tmlen
tmlen

Reputation: 9090

Linking shared libraries in same directory

I'm using CMake to build two shared libraries (.so files). They get built into separate directories, but on the install step they get copies into the same directory. One of them links with the other. And both get loaded dynamically from another process.

The first problem is that apparently CMake does not set an rpath on the .so files on OS X (not tested on other platforms). In CMakeLists.txt I have

set(CMAKE_INSTALL_PREFIX ../dist)
set(MACOSX_RPATH YES)
set(INSTALL_NAME_DIR YES)

And the CMakeLists.txt files for the two libraries get included using

add_subdirectory(./a "${CMAKE_BINARY_DIR}/a")
add_subdirectory(./b "${CMAKE_BINARY_DIR}/b")

But running otool -l on the resulting .so files shows no LC_RPATH entry.

Also, which path would need to be set in the RPath (of a) so that when the linker loads a.so, it can find b.so which is in the same directory (dist/). The executable from which a gets loaded is in a different place.

I've tried @executable_path/, @executable_path/../, @origin/../, but none seem to work.

Upvotes: 1

Views: 2276

Answers (1)

user2288008
user2288008

Reputation:

The first problem is that apparently CMake does not set an rpath

By default cmake does set rpath for target in build directory (see project):

> cmake -H. -B_builds -DBUILD_SHARED_LIBS=ON
> cmake --build _builds
> ls _builds/foo _builds/liba.dylib 
  _builds/foo
  _builds/liba.dylib
> otool -L _builds/foo 
_builds/foo:
  @rpath/liba.dylib (compatibility version 0.0.0, current version 0.0.0)
  ...
> otool -l _builds/foo | grep LC_RPATH -A2
      cmd LC_RPATH
  cmdsize 64
     path /.../_builds (offset 12)

I.e. library will load correctly if you run it from directory _builds:

> ./_builds/foo
a: 42

But running otool -l on the resulting .so files shows no LC_RPATH entry.

Also, which path would need to be set in the RPath

I've tried @executable_path/, @executable_path/../, @origin/../, but none seem to work.

It depends on where you want to install your library and your executable. For instance if destination directories are the same you can set just @executable_path:

set(CMAKE_INSTALL_RPATH "@executable_path")
install(TARGETS foo a DESTINATION bin)

See example project:

> cmake -H. -B_builds -DBUILD_SHARED_LIBS=ON -DCMAKE_INSTALL_PREFIX=_install
> cmake --build _builds --target install
> otool -L _install/bin/foo 
_install/bin/foo:
  @rpath/liba.dylib (compatibility version 0.0.0, current version 0.0.0)
  ...
> otool -l _install/bin/foo | grep LC_RPATH -A2
      cmd LC_RPATH
  cmdsize 32
     path @executable_path (offset 12)

You can test that library will load correctly from _install:

> ./_install/bin/foo
a: 42

Info

Upvotes: 1

Related Questions