I am working on centos. I installed boost version 1.45.0 on my system. The programs are compiled correctly but whenever I type command to see output it gives following error:
./a.out: error while loading shared libraries:
libboost_thread.so.1.45.0: cannot open shared object file: No such
file or directory
In addition to the other answers, you can also set the DT_RPATH elf tag when linking your executable
-Wl,-rpath,/path/to/boost/libraries -L /path/to/boost/libraries -lboost_whatever
This way you don't have to remember to set your LD_LIBRARY_PATH if the libraries are installed in a non-standard location.
How did you install the boost libraries?
The problem you're likely having is that the linker can not find the libraries, and when you built your program, you had to manually specify additional library paths to search for libraries.
A quick fix you can do is to set LD_LIBRARY_PATH to include the directory where the boost thread library is:
export LD_LIBRARY_PATH=/path/to/boost/libs:$LD_LIBRARY_PATH
./runExecutable
You need to set the LD_LIBRARY_PATH environment variable to include the path to the Boost libraries (they're possibly in /usr/local/lib, etc).
In bash, this is simply
export LD_LIBRARY_PATH=/path/to/boost:$LD_LIBRARY_PATH
Related
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.
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.
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.
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/).
I have some CMake packages that depend on Protobuf v2.5, and one that depend on Protobuf v3.4. I have v2.5 installed system-wide in /usr, whereas v3.4 is only used in a single package. Therefore, I put the headers for v3.4 in a 3rdparty subdirectory inside the package where it is being used, and then I call include_directories(3rdparty) in my CMakeLists.txt so it can be found.
As for the shared libraries, the .so files for v2.5 are present in /usr/lib/x86_64-linux-gnu, and I installed the .so files for v3.4 to /usr/lib. In short, this is what the directory structure looks like:
v2.5:
headers: /usr/include
libraries: /usr/lib/x86_64-linux-gnu
v3.4:
headers: <MY_PACKAGE_SRC_DIRECTORY>/3rdparty
libraries: /usr/lib
Now, the problem arises when I try to link against v3.4. To simplify things, I don't use any CMake module files to find protobuf v3.4, rather I just add a hard-coded path /usr/lib/libprotobuf.so to the list of libraries to link against when creating a target. But even so, when I run ldd my_target_executable, the result is:
libprotobuf.so.8 => /usr/lib/x86_64-linux-gnu/libprotobuf.so.8
meaning that it is linking against the libraries for v2.5 in /usr/lib/x86_64-linux-gnu, even though I added a hard-coded path to the correct .so file in /usr/lib in the call to target_link_libraries when building this executable.
What is worth noting is that if I remove the .so files in /usr/lib/x86_64-linux-gnu, then it does link against the correct .so file in /usr/lib, so it appears that for some reason, CMake searches in /usr/lib/x86_64-linux-gnu before using the library path that I provide it. How can I change this behavior, or fix this problem in any other way?
UPDATE
The library file for v3.4 /usr/lib/x86_64-linux-gnu/libprotobuf.so is a link to /usr/lib/x86_64-linux-gnu/libprotobuf.so.14 which in turn is a link to the actual file /usr/lib/x86_64-linux-gnu/libprotobuf.so.14.0.0.
Now, if I change the hard-coded path that I give in target_link_libraries from /usr/lib/x86_64-linux-gnu/libprotobuf.so to either the second symlink /usr/lib/x86_64-linux-gnu/libprotobuf.so.14, or to the actual file /usr/lib/x86_64-linux-gnu/libprotobuf.so.14.0.0, then my executable correctly links againt v3.4. It appears that the name of the provided symlink has some effect on CMake's behavior.
This isn't cmake specifically but also how things work on Linux with gcc and shared libraries.
http://www.yolinux.com/TUTORIALS/LibraryArchives-StaticAndDynamic.html
When you specify target_link_libraries( target /usr/lib/x86_64-linux-gnu/libprotobuf.so) this sets up linking as -lprotobuf. In this case it should just use any version of the library it finds first.
target_link_libraries( target /usr/lib/x86_64-linux-gnu/libprotobuf.so.14) adjusts the cmake generated link line to use a specific library version. This seems to tell gcc to link against that version which will change what happens at run-time and library searches.
target_link_libraries
There are some cases where CMake may ask the linker to search for the library (e.g. /usr/lib/libfoo.so becomes -lfoo), such as when a shared library is detected to have no SONAME field. See policy CMP0060 for discussion of another case.
I'm using omake to build a native binary executable. After it links and i try to run it, it fails to run giving the following error:
error while loading shared libraries: libprotobuf-c.so.1: cannot open shared object file: No such file or directory
Is there a way, at compile time, to tell the executable to pick up the static version: libprotobuf-c.a and not the shared on?
I'm not familiar with omake but I believe flag to ocamlc you are looking for is dllpath:
-dllpath dir
Adds the directory dir to the run-time search path for shared C libraries. At link-
time, shared libraries are searched in the standard search path (the one corresponding
to the -I option). The -dllpath option simply stores dir in the produced executable
file, where ocamlrun(1) can find it and use it.
If you can configure omake to pass the appropriate -dllpath argument to ocamlc, you should be good to go.
Under the hood I believe this is using the rpath feature (runtime library search path) of ld, the GNU linker. See https://linux.die.net/man/1/ld . There is also a chrpath utility to change the rpath of an already-built executable.
Another option is running your executable with LD_LIBRARY_PATH set so that the shared library is on the load path. You could also install the shared library system wide if appropriate. A final option is to load the library manually when your application boots using dlopen.
The correct choice depends on how you will distribute this and to who you will distribute this, if at all. Keep in mind if you use rpath/dllpath the end user is unlikely to have protobuf installed in the same location you do.
There doesn't seem to be a global flag that can be passed to ld, the linker, that enforces the linker prefer static libraries to dynamic ones when available. In my case, I set the library name explicitly like so:
OCAML_LINK_FLAGS += -cclib -l:libprotobuf-c.a
I am working on centos. I installed boost version 1.45.0 on my system. The programs are compiled correctly but whenever I type command to see output it gives following error:
./a.out: error while loading shared libraries:
libboost_thread.so.1.45.0: cannot open shared object file: No such
file or directory
In addition to the other answers, you can also set the DT_RPATH elf tag when linking your executable
-Wl,-rpath,/path/to/boost/libraries -L /path/to/boost/libraries -lboost_whatever
This way you don't have to remember to set your LD_LIBRARY_PATH if the libraries are installed in a non-standard location.
How did you install the boost libraries?
The problem you're likely having is that the linker can not find the libraries, and when you built your program, you had to manually specify additional library paths to search for libraries.
A quick fix you can do is to set LD_LIBRARY_PATH to include the directory where the boost thread library is:
export LD_LIBRARY_PATH=/path/to/boost/libs:$LD_LIBRARY_PATH
./runExecutable
You need to set the LD_LIBRARY_PATH environment variable to include the path to the Boost libraries (they're possibly in /usr/local/lib, etc).
In bash, this is simply
export LD_LIBRARY_PATH=/path/to/boost:$LD_LIBRARY_PATH
I pulled out an application that I wrote in C++ using the sfml library, but I'm having trouble setting up the library in Eclipse. I specified the include path, the lib path and included all the necessary .so libraries to link to. the application compiles fine but it complains at runtime about missing libraries. Why is this happening? Didn't I include the path to the libraries in the project settings already? I have even tried to place all the .so's in the executable directory with no luck.
There is only the name of the shared lib stored in the executable. At program startup the dynamic linker then searches for the specified libs in its search paths. You can add/specify search paths by placing them colon separated in the environment variable LD_LIBRARY_PATH or by specifying them in /etc/ld.so.conf (at least if you use some unix based OS). On windows the whole PATH environment variable is used when searching for dynamic-link libraries (DLL).
To see the paths of shared libraries used by a given application run ldd applicationPath.