I Ubuntu, I am learning about cmake and make, and just trying a simple example. I have two directories: src
and build
. In src
, I have two files: main.cpp
, and CMakeLists.txt
, which has (only) the following text:
add_executable(test main.cpp) link_directories(/usr/lib/x86_64-linux-gnu) target_link_libraries(test protobuf)
In /usr/lib/x86_64-linux-gnu
, there is a shared library called libprotobuf.so
, which I want to link against. My main.cpp
uses functions in this library, by including the releveant header file, #include <google/protobuf/message.h>
.
Now, in my build
directory, I run cmake ../src
, and then make
. However, I then get linker errors telling me that there are undefined references to some of the functions in the protobuf library. If I do a search through all the files and subdirectories in build
, there is not mention of anything related to protobuf.
However, if I remove the link_directories
line in my CMakeLists.txt
file, and instead write the full path to the library when specifying the executable, i.e. target_link_libraries(test /usr/lib/x86_64-linux-gnu/libprotobuf.so)
, it compiles and links fine.
Why is link_directories
not allowing cmake to find this library?
Do not use link_directories
like this in CMake.
This is a common beginner's mistake, as many other build environments work like this, but in CMake it's just asking for trouble. Even the manpage specifically advises against it:
Note that this command [
link_directories
] is rarely necessary. Library locations returned byfind_package()
andfind_library()
are absolute paths. Pass these absolute library file paths directly to thetarget_link_libraries()
command. CMake will ensure the linker finds them.
So instead, always pass absolute paths to target_link_libraries
and use find_library
to resolve the link directory:
find_library(PROTOBUF_LIBRARY protobuf HINTS /usr/lib/x86_64-linux-gnu) target_link_libraries(test PUBLIC ${PROTOBUF_LIBRARY})
This has the huge benefit that you will probably get a diagnostic at CMake configure time if the expected library cannot be found, instead of a random linker error at compile time. Also, this allows the user to specify a library location via the GUI if the target machine has a non-standard directory layout.
So if it doesn't work right away, be sure to check the result of the find_library
call and consult the manpage to track down why it doesn't find your library as intended.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With