osx: use relative linker paths
Submitted by Heinrich Fink
Link to original bug (#762140)
Description
There is often the need to bundle GStreamer into some other OSX bundle (framework or app). For this to work we have to use relative linker paths for all GST libs and also plugins.
At my company we achieved this through a (sort of hack-ish) custom cerbero tarball packager that just brute-force runs install_name_tool over all binaries before packing them into a tarball (not nice, but works, see http://paste.debian.net/hidden/a3156b37/, start reading at line 227). Ideally, the OSX (and iOS?) build-chain would deal with that earlier (maybe as libtool args so it could also be used for gst-uninstalled on OSX?), and IMO we should make this the default mode to build on OSX.
I will explain how we currently use a combination of @loader_path and @rpath to make this work. man dyld (i.e. @rpath and @loader_path) provides the background knowledge.
So this is how it currently looks like (I am shortening the output, i.e. skipping dependencies with similar/non-relevant paths to make this more concise):
otool -L bin/gst-inspect-1.0
gst-inspect-1.0:
/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation (compatibility version 150.0.0, current version 1241.11.0)
@rpath/libgstreamer-1.0.0.dylib (compatibility version 701.0.0, current version 701.0.0)
<skipping rest>
Now, gst-inspect-1.0 also has an rpath entry of "@loader_path/../lib", so when loading the library, dyld can find libgstreamer-1.0.0.dylib in the lib folder.
If you look at
otool -L lib/libgstreamer-1.0.0.dylib
lib/libgstreamer-1.0.0.dylib:
@rpath/libgstreamer-1.0.dylib (compatibility version 701.0.0, current version 701.0.0)
@rpath/libgobject-2.0.0.dylib (compatibility version 4601.0.0, current version 4601.2.0)
<skipping rest>
you will see that we also use @rpath here, and libgstreamer-1.0.0.dylib has an rpath set to @loader_path, so it can find its dependencies residing in the same folder.
For plugins, it looks like this:
otool -L lib/gstreamer-1.0/libgstcoreelements.so
lib/gstreamer-1.0/libgstcoreelements.so:
@rpath/libgstbase-1.0.0.dylib (compatibility version 701.0.0, current version 701.0.0)
<skipping rest>
We could also add an @rpath to each plugin to load from @loader_path/../lib, but @rpath's accumulate over the dependency chain, so this might not be necessary (we haven't, but probably should be done to be consistent). The whole point of @rpath is that - depending on your application/framework's layout - you can add multiple rpath that each will be used for an attempt to resolve a dependency. Setting DYLD_PRINT_RPATHS=1 can help to debug problems here (see man dyld).
So that's our story. If I'm not mistaken, the above approach applied earlier in the build process could automatically make the OSX frameworks re-locatable as well. And since iOS also supports dynamic linking for a while now, this might be useful there as well. Any ideas at which point this whole @rpath/@loader_path should best be applied to be as much re-usable as possible?
caveats: setuid process usage is prohibited on OSX when relative linker paths are used (e.g. the ptp-helper process shipping with GStreamer)