Homegrown destroot, maybe chroot?
This question isn't about using MacPorts but about how MacPorts does something that I want to do elsewhere. How does it do the destroot phase? I have some software I would like to build. It happens to be Graphviz. There are a dozen other packages on which Graphviz depends. Ultimately they need to go into a location under /usr/local which would require root access, but I would like to build them in a user- writable temporary location first. If I'm not mistaken, MacPorts accomplishes its destroot phase by using, usually make install DESTDIR=/foo where /foo is the destroot directory of the work directory. The software gets installed in /foo/opt/local/whatever. Then, later, during the install phase, everything from /foo gets merged with the real /opt/local. Right? Right. What if I have multiple packages I want to install in the temporary directory before installing? Say I want to install libpng, which depends on zlib. But if zlib is only in the temporary destroot directory, the libpng build won't find it there when I've told it the dependencies are to be found in /usr/local. And if I instead tell libpng to link with zlib in the temporary destroot, won't that be the location where libpng forever looks for zlib, even after I've tried to install everything in /usr/local? Is there a way to make this work? Maybe something I need to do in addition to setting DESTDIR during make install? Or is there a different option? It occurs to me to try to use a chroot, but I've never used one before. Does that sound like a good thing to try -- make a chroot which contains an empty /usr/local directory, links (hard links?) to /usr/bin, /usr/X11R6, /System, and other things the build is likely to need, and do the build in there, letting it think it's writing to the real /usr/local when it's really not? Any other suggestions for building multiple packages in a temporary directory before installation? Thanks for any insight you can offer. The ultimate goal, in case you're wondering, is that I would like to do a complete build of Graphviz -- from decompressing the source archives, all the way up to creating a disk image containing an installer package -- without requiring root access. Running the installer package would require root access, but I don't want the build system to require root.
There are two solutions for your library problem: 1. Export DYLD_LIBRARY_PATH before launching the software, so that the linker knows where to find the libraries 2. When building the libraries pass -install_name ${prefix}/lib/$outfile to the linker. ${prefix}/lib/$outfile is the final installation destination of the library. This approach requires patching the makefile. Hope this helps. Jann Ryan Schmidt wrote:
This question isn't about using MacPorts but about how MacPorts does something that I want to do elsewhere. How does it do the destroot phase?
I have some software I would like to build. It happens to be Graphviz. There are a dozen other packages on which Graphviz depends. Ultimately they need to go into a location under /usr/local which would require root access, but I would like to build them in a user-writable temporary location first.
If I'm not mistaken, MacPorts accomplishes its destroot phase by using, usually
make install DESTDIR=/foo
where /foo is the destroot directory of the work directory. The software gets installed in /foo/opt/local/whatever. Then, later, during the install phase, everything from /foo gets merged with the real /opt/local. Right? Right.
What if I have multiple packages I want to install in the temporary directory before installing? Say I want to install libpng, which depends on zlib. But if zlib is only in the temporary destroot directory, the libpng build won't find it there when I've told it the dependencies are to be found in /usr/local. And if I instead tell libpng to link with zlib in the temporary destroot, won't that be the location where libpng forever looks for zlib, even after I've tried to install everything in /usr/local?
Is there a way to make this work? Maybe something I need to do in addition to setting DESTDIR during make install? Or is there a different option? It occurs to me to try to use a chroot, but I've never used one before. Does that sound like a good thing to try -- make a chroot which contains an empty /usr/local directory, links (hard links?) to /usr/bin, /usr/X11R6, /System, and other things the build is likely to need, and do the build in there, letting it think it's writing to the real /usr/local when it's really not? Any other suggestions for building multiple packages in a temporary directory before installation?
Thanks for any insight you can offer.
The ultimate goal, in case you're wondering, is that I would like to do a complete build of Graphviz -- from decompressing the source archives, all the way up to creating a disk image containing an installer package -- without requiring root access. Running the installer package would require root access, but I don't want the build system to require root.
Hi, Jann. Thanks for your reply. On Mar 11, 2007, at 05:38, Jann Röder wrote:
There are two solutions for your library problem: 1. Export DYLD_LIBRARY_PATH before launching the software, so that the linker knows where to find the libraries
Do you mean: export DYLD_LIBRARY_PATH while compiling the other software, so it knows where to find its dependencies, and then everything will work normally when running the software later, or do you mean to export the variable in order to actually run the software later? If the latter, that won't do. I don't want to affect how end users use the software. I just want the build system to not require root access.
2. When building the libraries pass -install_name ${prefix}/lib/ $outfile to the linker. ${prefix}/lib/$outfile is the final installation destination of the library. This approach requires patching the makefile.
That sounds like a lot more work. Especially since you mention a specific outfile, but I don't know which files these packages install. Many packages install dozens of files, in lib, in include, in share, and so on. I don't want to have to figure out for each package which files it installs. Do you have any comment on whether or not my chroot idea could work? That's probably the solution I will try, unless anyone else has suggestions.
Each port destroots into a different folder, so you can't simply chroot the destroot and find the dependencies, since they won't be in the same folder. On Mar 11, 2007, at 10:58 PM, Ryan Schmidt wrote:
Do you have any comment on whether or not my chroot idea could work? That's probably the solution I will try, unless anyone else has suggestions.
-- Kevin Ballard http://kevin.sb.org eridius@macports.org http://www.tildesoft.com
Ryan Schmidt wrote:
Hi, Jann. Thanks for your reply.
On Mar 11, 2007, at 05:38, Jann Röder wrote:
There are two solutions for your library problem: 1. Export DYLD_LIBRARY_PATH before launching the software, so that the linker knows where to find the libraries
Do you mean: export DYLD_LIBRARY_PATH while compiling the other software, so it knows where to find its dependencies, and then everything will work normally when running the software later, or do you mean to export the variable in order to actually run the software later? If the latter, that won't do. I don't want to affect how end users use the software. I just want the build system to not require root access.
When building the software, the linker saves the path of the library it linked against in the binary. When the software is later run, the linker looks in that place first, if that doesn't work out it looks in the directories specified by DYLD_LIBRARY_PATH, and if that doesn't work it looks in the default locations (/lib, /usr/lib, ... ). So if you use that approach your users need to have DYLD_LIBRARY_PATH defined in order to run the software, but if you want to make it a double-clickabale application like theGimp.app you will have to do that anyway in some script. Sorry for being unprecise in my previous mail. I meant that the loader knows where to find the libraries, not the linker.
2. When building the libraries pass -install_name ${prefix}/lib/$outfile to the linker. ${prefix}/lib/$outfile is the final installation destination of the library. This approach requires patching the makefile.
That sounds like a lot more work. Especially since you mention a specific outfile, but I don't know which files these packages install. Many packages install dozens of files, in lib, in include, in share, and so on. I don't want to have to figure out for each package which files it installs.
Well usually the Makefile has a variable that spciefies how the linker is called. So it usually suffices to change that variable. Make will replace $outfile with the library it is currently building. This is the approach I used in one of my portfiles. The port built a dynamic library and then built a binary that linked against it. After installing the files in ${prefix} the binary couldn't find the library anymore, because the hardcoded path still pointed to the destroot destination, and the new library location (/opt/local/lib) wasn't specified in DYLD_LIBRARY_PATH. By giving the -install_name flag to the linker, you can change the path that is hardcoded in the binary when linking against the library.
Do you have any comment on whether or not my chroot idea could work? That's probably the solution I will try, unless anyone else has suggestions.
I have no experience with chroot, but I think it might work. Good luck. Jann
On Mar 12, 2007, at 03:40, Kevin Ballard wrote:
On Mar 11, 2007, at 10:58 PM, Ryan Schmidt wrote:
Do you have any comment on whether or not my chroot idea could work? That's probably the solution I will try, unless anyone else has suggestions.
Each port destroots into a different folder, so you can't simply chroot the destroot and find the dependencies, since they won't be in the same folder.
Well, I know MacPorts destroots into a different folder per port, but in my build system, I would have all software stage into the same destroot directory.
participants (3)
-
Jann Röder
-
Kevin Ballard
-
Ryan Schmidt