13

I am trying to get rid of setting LD_LIBRARY_PATH everytime time I run my program. After adding in the library and targeting my executable to the library, when I run it tells me it can not open shared object library, no such file or directory.

In my CMakeLists.txt I have:

add_library(heart SHARED ${HEART_FILES})
add_executable(run ${RUN_FILES})
target_link_libraries(run heart)
set(CMAKE_SKIP_BUILD_PATH FALSE)
set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
set(CMAKE_INSTALL_RPATH "~/person/target/usr/local/lib")
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)

I set an absolute link to my library folder to test out whether this would create an rpath to my library and it seems like there isn't. I have checked and made sure that the shared library is indeed in lib. libheart.so is the file that is being linked. What else am I missing?

TheBlueMan
  • 316
  • 1
  • 4
  • 27
  • 1
    Add [`SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)`](https://cmake.org/Wiki/CMake_RPATH_handling#Common_questions) – phoenix Mar 26 '18 at 11:43

3 Answers3

20

It is because you build heart and run from the same cmake project:

CMAKE_INSTALL_RPATH_USE_LINK_PATH is an interesting and very useful option. When building a target with RPATH, CMake determines the RPATH by using the directories of all libraries to which this target links. Some of these libraries may be located in the same build tree, e.g. libbar.so, these directories are also added to the RPATH. If this option is enabled, all these directories except those which are also in the build tree will be added to the install RPATH automatically. The only directories which may then still be missing from the RPATH are the directories where the libraries from the same project (i.e. libbar.so) are installed to. If the install directory for the libraries is not one of the systems default library directories, you have to add this directory yourself to the install RPATH by setting CMAKE_INSTALL_RPATH accordingly

You can try this:

SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")

More documentation here cmake rpath handling

EDIT:

Only this should work:

set(CMAKE_VERBOSE_MAKEFILE ON)
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)

add_library(heart SHARED ${HEART_FILES})
add_executable(run ${RUN_FILES})
target_link_libraries(run heart)

install(
  TARGETS heart run
  RUNTIME DESTINATION bin
  LIBRARY DESTINATION lib
)

Clean your build directory and then:

cmake -G "Unix Makefiles" -DCMAKE_INSTALL_PREFIX=/home/person/target/usr/local ..
make install

At the end of the g++ line Linking CXX executable run you should see like -Wl,-rpath,/home/person/target/usr/local/lib

If you want a fully relocatable package:

set(CMAKE_INSTALL_RPATH "$ORIGIN/../lib")

PS: are you sur that it is libheart.so that is not found ?

Anton Menshov
  • 2,266
  • 14
  • 34
  • 55
explo91
  • 530
  • 4
  • 11
  • I was reading the documentation and tried setting it to `${CMAKE_INSTALL_PERFIX}/lib"` and doesn't work. If `${CMAKE_INSTALL_PERFIX}` points to where CMakeLists.txt is, then I am sure I have the right file path. – TheBlueMan May 22 '15 at 18:52
  • `${CMAKE_INSTALL_PREFIX}` is used when you have a CMake command like `INSTALL (TARGETS run DESTINATION bin). Do you have a such command or do you try to run your program from the build tree ? – explo91 May 26 '15 at 08:16
  • I have a command like `install(TARGETS run DESTINATION bin)` then `set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib"`. It still says it cannot find the shared libraries. All my executables are installed into the ../bin folder and my object files are in the ../lib. After I set the variable I also install the object into my lib folder like so: `install(TARGETS heart DESTINATION lib)`. – TheBlueMan May 26 '15 at 13:12
  • See [this answer](https://stackoverflow.com/a/32470070) for the solution. `set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)` before `add_executable()` – phoenix Mar 26 '18 at 11:58
  • Cool! `set(CMAKE_INSTALL_RPATH "$ORIGIN")` does the trick if shared libs are installed in the same dir with executables :) – AntonK Sep 18 '22 at 12:44
6

In your CMake file, set the RPATH before defining the targets. The CMAKE_INSTALL_RPATH must be defined before calling add_executable(), otherwise it has no effect.

fgiraldeau
  • 2,384
  • 1
  • 19
  • 12
4

I had a similar issue as the original post. I created executables which linked to external shared libraries. This approach compiled and executed fine from the build directory. However, the executable that was installed to a separate directory could not find a shared library at runtime:

error while loading shared libraries: libxxxx.so.1: cannot open shared object file: No such file or directory

To solve, I

1) upgraded to CMake 3.17

2) used Craig Scott's recommended: set(CMAKE_INSTALL_RPATH $ORIGIN) as explained in his talk

3) set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) as directly mentioned to solve this error in the second common question in Kitware's documention

4) Put all this before adding the targets as mentioned in this post

5) Used the "$ORIGIN/../lib" syntax instead of Craig's Scott's mentioned $ORIGIN as mentioned by @explo91

In summary, and to my suprise, only the "$ORIGIN/../lib" before the target definition was necessary from above (I tested the other combinations which did not fix the cannot open shared object file runtime issue).

Anyway the solution I finally applied, which may be of better, fine-grained CMake style or at least may be helpful to others on their RPATH journey is:

set_target_properties(target_defined_above PROPERTIES INSTALL_RPATH "$ORIGIN/../lib")

kdmarrett
  • 43
  • 3
  • careful, one may need "$ORIGIN/../lib64" on some distros. or even $ORIGIN/../${CMAKE_INSTALL_LIBDIR} when using gnuInstallDirs – OznOg Dec 02 '20 at 10:56