[CMake] still having rpath problems on osxZ

clinton at elemtech.com clinton at elemtech.com
Thu Dec 31 20:07:04 UTC 2015



----- On Dec 31, 2015, at 1:41 AM, Boudewijn Rempt boud at valdyas.org wrote:

> I think I've finally figured out why I didn't get the results the cmake
> documentation suggested I should be getting... It's the extra-cmake-modules
> that I use, Krita being a KDE application. With these settings:
> 
>     set(KDE_SKIP_RPATH_SETTINGS 1)
>     set(CMAKE_MACOSX_RPATH 1)
>     set(BUILD_WITH_INSTALL_RPATH 1)
> 
> My libraries are built with an @rpath id, instead of an absolute path id. Now
> only the executable needs to have its rpath set correctly after install and
> after making a bundle, and all libraries are found and all plugins find the
> libraries, too.
> 
> Without KDE_SKIP_RPATH_SETTINGS, everything gets set to full, absolute paths on
> doing a make install. That might make sense on Linux, I guess... But no wonder
> that I was confused all the time.
> 
> So, to check that I really understand it:
> 
> On OSX, every library has an id. That id can be
> /abs/o/lute/path/to/library.dylib or library.dylib or @rpath/library.dylib.

Yes, there is an id.  @executable_path and @loader_path are a couple other that can used in addition to the list you provided.

> 
> The exectutable has a bunch of paths where it can look for libraries, and the
> path + library.dylib has to match the library id.

I'm not sure what you mean by that.

The library id is used only at link time, and not at runtime.  There is no matching to the library id at runtime.
At link time, the id is taken as-is and put into the executable as a dependency.
If you are familiar with SONAME on ELF platforms, think of the id in a dylib being similar.

> 
> so, if the executable has
> 
> @path = ../lib;../Frameworks
> 
> and links to
> 
> @path/library.dylib
> 
> and a library with that id is in ../lib (or ../Frameworks) from the executable's
> location, everything will be fine.

I think you have the idea there.  But just in case, let me enumerate how the runtime loader looks at these:

1. an exectuable with a /absolute/path/to/library.dylib dependency
  The library is searched for at the absolute path.
  If not found, library.dylib is searched in /usr/local/lib:/lib:/usr/lib
  environment variables such as DYLD_LIBRARY_PATH can override search locations.

2. an executable with a library.dylib dependency
  library.dylib is searched in /usr/local/lib:/lib:/usr/lib
  environment variables such as DYLD_LIBRARY_PATH can override search locations.

3. a binary with a @executable_path/library.dylib dependency
  The library is located in the same directory as the executable
  If the binary is another shared library, whether in another directory or not, library.dylib will be searched for in the same directory as the executable.
  If not found, a search is made in /usr/local/lib:/lib:/usr/lib
  environment variables such as DYLD_LIBRARY_PATH can override search locations.
  both exectuables and libraries can have @executable_path 

3. a binary with @loader_path/library.dylib dependency
  the library is located in the same directory as the binary (may be the same directory as the executable or not).
  If not found, a search is made in /usr/local/lib:/lib:/usr/lib
  environment variables such as DYLD_LIBRARY_PATH can override search locations.

4. a binary with @rpath/library.dylib dependency
  the binary can also have a list of rpaths embedded.  Each rpath is used to replace the "@rpath" portion of the dependency to locate the dependency.  For flexibility, rpaths may contain absolute paths, @executable_path or @loader_path.  For example, a binary can have an rpath @loader_path/../lib, and a dependency @rpath/library.dylib.
After substitution, you have: @loader_path/../lib/library.dylib.  With that, go see how @loader_path is handled.

  If not found, a search is made in /usr/local/lib:/lib:/usr/lib
  environment variables such as DYLD_LIBRARY_PATH can override search locations.


> 
> Which makes it easiest for me, I guess to have @rpath in the id for every
> library, and on make install set the exectables' rpath to where I install the
> libraries to, and on creating the bundle update the rpaths in the executable to
> the Frameworks folder. The only thing that won't work is running unittests
> without installing, but that's not a big problem, for me...
> 

I also find @rpath easiest for me.  I make sure all my 3rd party non-system dependencies use @rpath.
In my case, these libraries are built once and shared among multiple developers.  Using @rpath also allows multiple developers to place these libraries in their own home directories, and CMake's automatic rpath handling helps simplify things.  Then when I build my bundles or create packages, I don't need to do any "install_name_tool -change" work.  I do set the rpaths on exectuables during install, which is nearly identical to what I do on Linux.

I'm curious why the unit tests do not work.  Mine work just fine for me.  If you have a setting to skip rpaths in the build tree, I guess that would prevent them from working.

Clint


More information about the Kde-buildsystem mailing list