[MacPorts] #74261: Symlinked prefix and Python ports

MacPorts noreply at macports.org
Wed Jul 29 12:33:55 UTC 2026


#74261: Symlinked prefix and Python ports
-------------------------+--------------------
 Reporter:  RJVB         |      Owner:  (none)
     Type:  enhancement  |     Status:  new
 Priority:  Normal       |  Milestone:
Component:  contrib      |    Version:
 Keywords:               |       Port:
-------------------------+--------------------
 I've been using MacPorts with the standard `$prefix` a symlink pointing to
 a different partition since I started using MacPorts (a long time ago),
 despite the fact that it was never supported. For the most part this has
 worked without problems (I apply a small patch  to "base" so that `port
 provides` works 99.9% of the time). I can install prebuilt binary packages
 thanks to how Unix handles symlinks. Building packages from source of
 course creates binaries with the actual path to dependencies hardcoded,
 thanks to Darwin's annoyingly unavoidable path normalisation, but that's
 not an issue as long as I don't plan to distribute my builds.

 I see that the "officially unsupported" policy has changed a bit since or
 because of e.g. issue #69327, which is why I thought I'd come out of the
 closet and create this ticket.

 A recent update to the Python PG and/or Python's own code for installing
 packages introduced a nuisance. Somewhere, the normalised `$prefix` is
 injected as the install location and I thus end up with a `$destroot`
 containing, in my case, `/Volumes/Debian/MP9` instead of `/opt/local`.
 Which of course raises a warning about a layout violation.

 It would of course be nice to fix the issue at the source (it seems like
 something that upstream might consider a bug, and I would in fact not be
 surprised that it's related to what caused #69327). That would require
 knowing where the issue arises though, and I have no idea how to triage
 that.

 Avoiding the consequences via a mod of the Python PG turned out to be
 deceptively simple though ''(for a `$prefix` where the symlink is the last
 path component)'', and might be a workaround that could evolve into a more
 generic modification for "base" itself. The idea is to recreate the actual
 configuration at the start of the destroot phase, and then standardise
 that back at the end of the phase.

 So I added this at the start of the existing `pre-destroot`:
 {{{
     # See if we have a symlinked $prefix, and if so replicate the set-up
 under $destroot
     if {[file type ${prefix}] eq "link" && [file type
 ${destroot}${prefix}] eq "directory"} {
         set realprefix [realpath ${prefix}]
         if {![file exists ${destroot}${realprefix}]} {
             xinstall -m 755 -d ${destroot}[file dirname ${realprefix}]
             # ${destroot}${prefix} will have been populated by now, and we
 want to preserve that tree.
             # So rename it to the actual name it's supposed to have (this
 should all be on the same FS!)
             file rename ${destroot}${prefix} ${destroot}${realprefix}
             # we should now have a directory ${destroot}[file dirname
 ${prefix}] !
             ln -sf ${destroot}${realprefix} ${destroot}${prefix}
             ui_warn "\t had to make \$destroot${prefix} a symlink to
 \$destroot${realprefix}"
         }
     }
 }}}

 and this at the start of the existing `post-destroot`:
 {{{
             # See if we have to restore the correct $prefix
             if {[file type ${prefix}] eq "link" && [file type
 ${destroot}${prefix}] eq "link"} {
                 set realprefix [realpath ${prefix}]
                 file delete ${destroot}${prefix}
                 file rename ${destroot}${realprefix} ${destroot}${prefix}
                 ui_warn "\t restored the symlink-to-be \$destroot${prefix}
 from \$destroot${realprefix}"
             }
 }}}

 Problem solved ...

 As said, this was designed for a `$prefix` where the last component (i.e.
 `local`) is a symlink, but I *think* that the implementation will work for
 any `$prefix` that has a symlink somewhere in its path. During the
 workaround, the symlinked `${destroot}${prefix}` is there only for ports
 that also install files to that expected `${destroot}${prefix}` path (IIRC
 `port:py-cython` does).
 So all that might be needed to generalise this workaround could be to
 replace the initial `[file type ${prefix}] eq "link"` check with
 `[realpath ${prefix}] ne ${prefix}`.


 ----
 Ahhh, if only Darwin had a proper "bind mount" feature, allowing any
 directory to be mounted elsewhere...!

-- 
Ticket URL: <https://trac.macports.org/ticket/74261>
MacPorts <https://www.macports.org/>
Ports system for macOS


More information about the macports-tickets mailing list