If you use the command target_link_libraries in cmake, when linking the linker will search for libraries which name match some criteria. For instace:
Using following command:
target_link_libraries(some_target some_lib)
In Linux the linker will search for: libsome_lib.so while in Windows the linker will search for some_lib.lib (in Windows I'm compiling a VS project generated from the cmake project).
Due to deployment requirements of my application the libraries have no extension and have to be called the same in both OS (e.g some_lib).
How can I tell cmake that search for such library?
I suppose that entering the full path will do the trick, but, there is another any way to do this?
Edit: Specifying the full path to the library does not work.
I didn't ever test that, but the CMake Wiki Docs refer these variables to specify library extensions:
CMAKE_FIND_LIBRARY_SUFFIXES
CMAKE_IMPORT_LIBRARY_SUFFIX
Windows-specific. Appears to be read-only. Use SET_TARGET_PROPERTIES.
CMAKE_LINK_LIBRARY_SUFFIX
Windows-specific.
CMAKE_SHARED_LIBRARY_SUFFIX
Appears to be read-only. Use SET_TARGET_PROPERTIES.
CMAKE_STATIC_LIBRARY_SUFFIX
Appears to be read-only. Use SET_TARGET_PROPERTIES.
Related
I'm developing a shared library, and on my machine there could be two copies of the same shared library:
the one I installed to the system path: /usr/lib/libmyproject.so
the one I built in my workspace during my development: /home/ziqi.liu/workspace/myproject/build/src/libmyproject.so
So during my development, there're some executables under /home/ziqi.liu/workspace/myproject/build. I want them to use the dynamic library in /home/ziqi.liu/workspace/myproject/build/src/libmyproject.so, however it turns out that they're actually using /usr/lib/libmyproject.so when I use ldd to check the link library.
Is there anyway to specify which dynamic library to use when there are multiple? It would be better if I can specify this for all executables under "this project", since it's very intuitive to link the dynamic library in the same repo I just built, instead of the one installed to the system path.
UPDATED:
I've found this post: Where do executables look for shared objects at runtime?
It seems that the dynamic library searching has something to do with
the rpath and LD_LIBRARY_PATH environment variables.
What I want is to search for rpath first, and then LD_LIBRARY_PATH.
According to rpath wiki, the rpath is named DT_RPATH, however when I objdump that executable, the only thing I can find is RUNPATH section. I'm not sure if this is a compiler-specific behavior... (I'm running g++ (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0)
Is there anyway to specify which dynamic library to use when there are multiple?
The best way to achieve this is to use the special $ORIGIN tag in the executable.
Assuming you have $D/build/exe and you want that exe to use $D/build/src/libmyproject.so, link your exe with: -rpath '$ORIGIN/src'.
This would allow you to have several build directories (e.g. "release" and "debug" builds), and each binary will pick up the library from its own build tree.
It would also allow you to not install libmyproject.so into /usr/lib at all -- you can keep the binary and the all the required libraries in e.g. /usr/local/$project/{bin/exe,lib/libmyproject.so} and have it all just work(TM).
See also this answer.
Just modify LD_LIBRARY_PATH and put your home folder first, like
export LD_LIBRARY_PATH=/home/ziqi.liu/workspace/myproject/build/src/:${LD_LIBRARY_PATH}
Then it should be fine.
I working on a C++ application running on Linux. The project uses CMake.
It use a third party shared library. Unfortunately, the third party library doesn't end with .so.
And the CMake command find_library can't find the library.
Does anyone now how to force CMake to find libraries with a custom file extension? Or at least, how to configure GCC (through CMake) for linking with the library ending with a custom extension?
Thanks for any hint!
You can set the CMAKE_FIND_LIBRARY_SUFFIXES variable. From the documentation:
This specifies what suffixes to add to library names when the
find_library() command looks for libraries. On Windows systems this is
typically .lib and .dll, meaning that when trying to find the foo
library it will look for foo.dll etc.
Adding the custom suffix to it should do the trick.
Usually, open source packages will have cmake to check if some headers or libraries exists or not, I wish my own project has this same functionality.
So I wish to know if cmake provides some command to check if some ".so"/".a"/".h" files exists in the current linux system or not, if not cmake will give me some hint to install them?
How does cmake support this?
Usually one would use the find_package(ABC REQUIRED) and then refer to it in your project. This will ensure that the dependent library is installed and cmake will fail if it is not.
You can find lot's of example on how this works in your cmake installation, for example C:\Program Files\CMake\share\cmake-3.13\Modules\FindZLIB.cmake will search for the zlib library by looking in the file system for normal places where this library would be installed and if it finds it will set these variables accordingly:
# ZLIB_INCLUDE_DIRS - where to find zlib.h, etc.
# ZLIB_LIBRARIES - List of libraries when using zlib.
# ZLIB_FOUND - True if zlib found.
To achieve this header files are found using the cmake command find_path, and libraries (static and shared) are found using find_library.
To search for arbitrary library you can use find_library() command. Same task for headers is accomplished by find_file(). You can also search for executables with find_program().
As #Damian said in his naswer, many libraries provide "config" files, like FindBoost.cmake. Such libraries can be found by calling find_package(Boost) command. This command would locate and load config file and set corresponding variables.
You need to provide -config.cmake files to tell other projects where your libraries and headers are. Here, you will found what are you looking for.
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