Cmake doesn't install RPATH when adding link_library with -L
When setting up link libraries like this
target_link_libraries (SOME_TARGET -L/somedir -lfoo)
cmake does not handle RPATH. Is "-L" and "-l" not best practice, or really wrong? When I create my own Find * .cmake I usually use find_library()
, but the find script I got doesn't do it and resorts to the above form using '-L' and '-l'.
The documentation doesn't really explain how the RPATHs are assembled, and also the documentation isn't really quite clear how it handles "-l" and "-L", the only pointer you get is
"Element names starting with - but not -l or -framework are considered linker flags."
Specifying toolchain-specific flags such as -l
and -L
is generally discouraged as it impairs portability and may have different effects than expected.
The correct way to specify the linker path is with a command link_directories
.
The idiomatic solution in CMake is to use find_library
to find the library and then pass the full path to the linker, so you don't need to worry about link directories at all.
Now RPATH is a different beast as it also defines where dynamic libraries can be located at runtime. Usually the default settings work quite well here. If you ever find yourself in a sad situation where this is not the case, there are a number of CMake target properties and variables that affect this:
There are several properties used to specify RPATH rules. INSTALL_RPATH a semicolon-separated list of rpath to use for the stated target (for platforms that support it). INSTALL_RPATH_USE_LINK_PATH a boolean value that, if true, will add directories in the linker search path and outside the project to INSTALL_RPATH. SKIP_BUILD_RPATH - A Boolean value that indicates whether to automatically skip the generation of the rpath, which allows the target to be run from the build tree. BUILD_WITH_INSTALL_RPATH Boolean indicating whether to bind the target in the build tree using INSTALL_RPATH. This takes precedence over SKIP_BUILD_RPATH and avoids the need to re-link the mount. INSTALL_NAME_DIR - string defining the directory part of the 'install_name' fieldshared libraries in Mac OSX to use for established purposes. When the target is created, the values โโof the variables CMAKE_INSTALL_RPATH, CMAKE_INSTALL_RPATH_USE_LINK_PATH, CMAKE_SKIP_BUILD_RPATH, CMAKE_BUILD_WITH_INSTALL_RPATH and CMAKE_INSTALL_NAME_DIR are used to initialize these properties.
(From the set_target_properties
documentation )
Also you may need to look at the CMake wiki page for RPATH handling .
The whole RPATH business is unfortunately quite complex and it will take a lot more space to explain in detail than is appropriate for Stack Overflow's answer, but I hope this is enough to get you started.
Mostly you are using it target_link_libraries()
wrong. According to the documentation , you should provide target, libraries, and possibly some CMake specific binding flags.
For example, something like this:
target_link_libraries(my_build_target somedir/foo.so)
If you are using your own developed solutions Find*.cmake
, it is usually done as follows:
find_library(foo)
//build main target somewhere here
//now link it:
target_link_libraries(my_build_target ${FOO_LIBRARIES})
NOTE. ... I am assuming your generated files Find*.cmake
follow these guidelines and populate CMake variables like SOMELIB_LIBRARIES
, and / or SOMELIB_INCLUDE_DIRS
, etc.
NOTE 2: for my personal opinion, target_link_directories()
this is a pain in the butt and you should avoid using it unless you really need it. This is difficult to maintain and uses paths relative to the current source directory.