Why the installed program has error when loading s

2019-03-03 02:49发布

问题:

I have a question related to how to install a built executable program with cmake when it relies on some external libraries. Suppose my executable is abc, and it relies on two external libraries: lib1.so and lib2.so. The structure of the codes are as follows:

-.........
  |----bin (lib1.so lib2.so)
  |----include(lib1.h lib2.h)
  |----src(main.cpp)

When the executable program is installed using the following cmake commands:

INSTALL(TARGETS ${Exe_Name}
    RUNTIME DESTINATION Path to bin
    LIBRARY DESTINATION Path to bin)

I expect that the executable program will be in the same directory with lib1.so and lib2.so. However, when I execute the built program in the installation folder, I met the following error:

error while loading shared libraries: lib1 can not open shared object file No such file or directory

If I use ldd to check the executable, I found lib1.so and lib2.so not found. After searching for possible solutions, I found if I call the executable in this way, then it worked:

LD_LIBRARY_PATH=./ ./my_program_run

Then my question is how I can let my executable program knows the locations of the shared libraries with cmake when it is installed? Thanks.

回答1:

If the application is to be cleanly installed to a standard linux distribution, then you should either install the supporting shared libraries into a standard location (/usr/lib), or you should add the libraries location to the ld.so config, by create an /etc/ld.so.conf.d/myprogram.conf file containing the name of the directory the libraries are in.

If the installation is temporary or more ad-hoc, then a script to set the LD_LIBRARY_PATH is suitable.



回答2:

This is best solved this with the RPATH of the final executable. RPATH is a hardcoded search path for the executable itself, and allows the use of the string $ORIGIN, which expands to the location of the executable at runtime. See this reference: http://man7.org/linux/man-pages/man8/ld.so.8.html

CMake strips the rpath of a binary at installation time, to avoid the binary picking up libraries littered around your development tree. But it also provides a simple way to modify the installation rpath for exactly this reason. Here's the short answer:

IF(UNIX)
  SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_RPATH}:\$ORIGIN/../bin:\$ORIGIN")
ENDIF()

This particular example appends to the existing rpath, and adds . and ../bin to the search path, all relative to the location of the binary.

Some developers claim that adjusting the RPATH of the binary is not a good idea. In the ideal world, all the libraries would live in the system library directories. But if you take this to the extreme, you end up with Windows (at least the older ones), where c:\windows\system32 is full of junk that came from who knows where, and may or may not conflict with other software, etc. Using rpath and installing everything in one place seems like a great solution.



回答3:

The libraries are searched in the predefined locations which includes standard library paths configured with ld.so.conf and LD_LIBRARY_PATH. You can also try to compile your app with -rpath, but it is not recommended by some developers. I suggest you to create a wrapper script which will set LD_LIBRARY_PATH and run the real application like that:

"theapp" script:

#!/bin/sh
dir="`dirname \"$0\"`"
export LD_LIBRARY_PATH=${LD_LIBRARY_PATH:+$LD_LIBRARY_PATH:}"$dir"
exec "$dir/theapp.real" # your real application

The application, script and libraries should be in the same location (under bin/).



标签: c++ linux cmake