1

I'm working on a project with the following structure -

app:
- CMakeLists.txt
- lib/
  - CMakeLists.txt
- main/
  - CMakeLists.txt
  - main.cpp
- build/

The files in lib depend on Boost C++ libraries (which are not present in default ld search paths) and are configured to compile into a shared library and linked with object file compiled from main.cpp into the final binary main. Relevant parts of cmake files -

Top-level CMakeLists.txt

project(app)

# the RPATH to be used when installing, but only if it's not a system directory
LIST(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${CMAKE_INSTALL_PREFIX}/lib" isSystemDir)
IF("${isSystemDir}" STREQUAL "-1")
   SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
ENDIF("${isSystemDir}" STREQUAL "-1")

add_subdirectory(lib)
add_subdirectory(main)

lib/CMakeLists.txt

file(GLOB src "*.cpp")
add_library(app SHARED ${src})
target_link_libraries(app PUBLIC "-L${BOOST_LIBRARYDIR} -lboost_program_options -lboost_filesystem -lboost_system")
target_include_directories(app PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
install(TARGETS app
        LIBRARY DESTINATION lib
        ARCHIVE DESTINATION lib/static
        RUNTIME DESTINATION bin)

main/CMakeLists.txt

add_executable(main main.cpp)

link_directories(${CMAKE_BINARY_DIR}/src)
target_link_libraries(main LINK_PUBLIC "app")
target_include_directories(main PUBLIC ${PROJECT_SOURCE_DIR}/lib)
install(TARGETS main
        RUNTIME DESTINATION bin)

I run the following command to build and install the project from within the build directory -

cmake .. \
  -DBOOST_LIBRARYDIR=<path to boost lib dir> \
  -DCMAKE_INSTALL_RPATH_USE_LINK_PATH:BOOL=FALSE \
  -DCMAKE_INSTALL_PREFIX=<path to install dir> && make install

The issue is that the final main binary in build and install directories are not configured with correct path to the Boost libraries -

$ ldd <install prefix>/bin/main 
    libapp.so => <install prefix>/lib/libapp.so (0x00007f03b970f000)
    libboost_program_options.so.1.61.0 => not found
    libboost_system.so.1.61.0 => not found
    libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f03b9386000)
    libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f03b916e000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f03b8d7d000)
    libboost_program_options.so.1.61.0 => not found
    libboost_filesystem.so.1.61.0 => not found
    libboost_system.so.1.61.0 => not found

The output is similar for the binary in the build directory. I'm not sure why the boost libraries appear twice here and why does it not set the proper path for the Boost libraries.

What changes do I need to make to my cmake project for it to set proper rpaths?

EDIT: If I explicitly set add the path to Boost libraries to LD_LIBRARY_PATH and build the project, they are set properly in the final executable, but I'm looking for a way around this.

EDIT: Additional information upon request

$ ldd <INSTALL PREFIX>/lib/libapp.so 
    linux-vdso.so.1 (0x00007fff73f63000)
    libboost_program_options.so.1.61.0 => not found
    libboost_filesystem.so.1.61.0 => not found
    libboost_system.so.1.61.0 => not found
    libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007fcb3c284000)
    libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fcb3c06c000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fcb3bc7b000)
    libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fcb3ba77000)
    libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fcb3b858000)
    libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fcb3b4ba000)
    /lib64/ld-linux-x86-64.so.2 (0x00007fcb3cd14000)

Following commands have empty output

$ objdump -p <INSTALL PREFIX>/lib/libapp.so | grep RPATH
$ objdump -p <INSTALL PREFIX>/bin/main | grep RPATH
nsane
  • 1,715
  • 4
  • 21
  • 31
  • 1
    `target_link_libraries(app PUBLIC` which mean app depends on it but since it's public main binary will also depends on it directly thus they appear twice in ldd. * ldd main depends on app then recursively libapp.so depends on boost, and * since they are PUBLIC in app CMake also add boost as direct deps of bin/main – Mizux Jan 03 '20 at 08:39
  • why don't using set_target_properties(main PROPERTIES INSTALL_RPATH "$ORIGIN/../lib") ? – Mizux Jan 03 '20 at 12:15
  • what is the output of `ldd libapp.so` and the output of `objdump -p lib/libapp.so | grep RPATH` and `objdump -p main | grep RPATH` ? – Mizux Jan 03 '20 at 12:19
  • Why don't adding "${BOOST_LIBRARYDIR}" to libapp.so rpath ? (and main rpath if you use an older bintutils package see https://github.com/Mizux/SecondaryDependency for explaination – Mizux Jan 03 '20 at 12:21
  • Thanks @Mizux! I did not know what `PUBLIC` really did because cmake documentation is not very descriptive. I've updated my question with the output you requested. Meanwhile I will try setting `INSTALL_RPATH` property like you mentioned. – nsane Jan 03 '20 at 17:54
  • according to your objdump i would say rpath is empty for libapp.so and the main binary. you can try to add `set_target_properties(app PROPERTIES INSTALL_RPATH "${BOOST_LIBRARYDIR}")` ps: you can use `objdump -p XXX.so | grep "NEEDED\|RPATH"` to see the NEEDED dependencies too – Mizux Jan 04 '20 at 14:13
  • Make sure to grep for `PATH` instead of `RPATH` when checking the binary's dynamic tags. On some distributions the linker will put things in the `RUNPATH` tag instead, unless you use `-Wl,--disable-new-dtags`: https://stackoverflow.com/a/52020177 – Nicolas Capens Aug 28 '20 at 13:46

0 Answers0