Issue
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)
Solution
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
Answered By - Gunther Answer Checked By - Dawn Plyler (WPSolving Volunteer)