skip to Main Content

For using find_package( for another library that I am using (it is not supporting CMake), I have developed something like this (I am using gcc10 on CentOS 7 and CMake 3.20 with Ninja 1.10.2):

add_library(MyLib UNKNOWN IMPORTED)
target_include_directories(MyLib 
   INTERFACE "$ENV{MY_LIB}/include")

target_link_libraries(MyLib INTERFACE ${CMAKE_DL_LIBS})
set_property(TARGET MyLib PROPERTY
   IMPORTED_LOCATION "$ENV{MY_LIB}/lib/libmylib.so"
)

and in my project, I simply use find_package and link against it:

find_package(MyLib REQUIRED PATHS "${CMAKE_MODULE_PATH}" NO_DEFAULT_PATH)
target_link_libraries(myApp
   PUBLIC MyLib 
)

The strange behavior that I see with this code is that the linker puts the absolute path of libmylib.so in myApp target. In other words, if I copy/move my whole project into a new folder, it fails to load the library:

/data/projects/myApp/external/myLib/lib/libmylib.so: cannot open shared object file: No such file or directory

Can anyone tell me why the path to ‘libmylib.so’ is hard-coded?

Note: the LD_LIBRARY_PATH is already set and valid.

Update 1: If I run readelf -d myApp | head -20, I will see this result:

[user]$ readelf -d myApp | head -20

Dynamic section at offset 0x101588 contains 73 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [libsth1.so]
 0x0000000000000001 (NEEDED)             Shared library: [libsth2.so]
 0x0000000000000001 (NEEDED)             Shared library: [/data/projects/myApp/external/myLib/lib/libmylib.so]

Update 2: I have tried to unset these two variables, but nothing changes:

set(CMAKE_SKIP_BUILD_RPATH TRUE)
set(CMAKE_SKIP_RPATH TRUE)

2

Answers


  1. There are multiple ways how to get your executeable to work:

    (1) Edit LD_LIBRARY_PATH

    export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:"PATH_TO_SO"
    

    will allow the dynamic linker to find and link the shared object.

    (2) Edit RPATH

    # Make sure required .so files are found in the same folder as the shared library
    set_target_properties(myApp PROPERTIES
       BUILD_WITH_INSTALL_RPATH TRUE
       #INSTALL_RPATH_USE_LINK_PATH TRUE
       INSTALL_RPATH "$ORIGIN"
     )
    

    I would prefer (2) if you want to move your app around in the file system.

    Update explanation:

    cmake tries to get your build to work. Internally it usually uses absolute paths. Generated cmake projects are not copyable to other places in the filesystem, but have to regenerated.

    find_package() returns the absolute path to your library. Its the only assumption it can make. Just adding the library name without the full path could lead to using a similar named but wrong (incompatible, wrong version) shared object.

    It is your task to prepare everything in your CMakeLists install section. Those rules should describe what to copy and how to prepare encompanied shared object libraries.
    Packaging systems like rpm or dhbuild depend on it.

    I hope that is helpful.

    Bye Gunther

    Login or Signup to reply.
  2. I can`t comment so I will write it here.

    Pls, check if SONAME is present in your shared library.
    Details are here: Why does CMake links external library by relative path?

    After fixing SONAME my binary was added to the executable without an absolute path to it.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search