I am building a library that I bundle with a few tests and example programs. The project is able to honor the cmake property BUILD_SHARED_LIBS, building a .so if it's on and building a .a file if it is off. The library depends on a few other dynamic libraries, which are supposed to be found using an environment variable, LIBLOC (their convention, not mine).
When I build the dynamic version of the library, I am able to set up the install rpath so that the libraries are found correctly. E.g.:
add_library(lib ${SRC})
set_target_properties(lib INSTALL_RPATH $LIBLOC)
install(TARGETS lib LIBRARY DESTINATION lib)
And then in each test/example program's CMakeLists.txt:
add_executable(test ${SRC})
target_link_libraries(test lib)
set_target_properties(test INSTALL_RPATH $ORIGIN/../lib)
install(TARGETS test RUNTIME bin)
When BUILD_SHARED_LIBS is on, the test program is happy:
$ lddtree bin/test
test => bin/test (interpreter => /lib64/ld-linux-x86-64.so.2)
liblib.so => /path/to/install/liblib.so
libdep.so => /path/to/dependency/libdep.so
We can find everything because the rpath in test is $ORIGIN/../lib, which finds liblib.so and then the rpath in liblib.so is $LIBLOC, which is set in my environment to /path/to/dependency.
I would have expected that, when installing the static library, cmake would read the INSTALL_RPATH property from my library and put it in the test program so that the rpath in test would be $ORIGIN/../lib;$LIBLOC. Instead, $LIBLOC does not end up in any rpath.
My current solution is dissatisfying: I condition my INSTALL_RPATH on BUILD_SHARED_LIBS in each example or test program, e.g.
if (BUILD_SHARED_LIBS)
set_target_properties(test INSTALL_RPATH "$ORIGIN/../lib")
else ()
set_target_properties(test INSTALL_RPATH "$LIBLOC")
endif ()
Now I have several targets, all of which have to be aware of their dependencies' dependencies. Plus a bunch of smelly if statements. Yuck!
Is there a nicer way in cmake to pass the install rpath "up" to the first ELF file produced when my libraries are compiled statically?