我是Ubuntu,我正在学习cmake和make,只是尝试一个简单的例子。我有两个目录:src
和build
。在src
中,我有两个文件:main.cpp
和CMakeLists.txt
,它们(仅)包含以下文字:
add_executable(test main.cpp)
link_directories(/usr/lib/x86_64-linux-gnu)
target_link_libraries(test protobuf)
在/usr/lib/x86_64-linux-gnu
中,有一个名为libprotobuf.so
的共享库,我想链接到该库。我的main.cpp
使用此库中的函数,包括相关的头文件#include <google/protobuf/message.h>
。
现在,在我的build
目录中,我运行cmake ../src
,然后make
。但是,然后我得到链接器错误,告诉我对protobuf库中的某些函数有未定义的引用。如果我搜索build
中的所有文件和子目录,则不会提及与protobuf相关的任何内容。
但是,如果我删除link_directories
文件中的CMakeLists.txt
行,而是在指定可执行文件时写入库的完整路径,即target_link_libraries(test /usr/lib/x86_64-linux-gnu/libprotobuf.so)
,则编译并链接正常
为什么link_directories
不允许cmake找到这个库?
答案 0 :(得分:53)
请勿在CMake中使用link_directories
这样的内容。
这是一个常见的初学者的错误,因为许多其他构建环境都是这样的,但在CMake中它只是在寻找麻烦。甚至the manpage也特别反对它:
请注意,此命令[
link_directories
]很少需要。库位置已返回find_package()
和find_library()
是绝对路径。通过这些 绝对库文件路径直接到target_link_libraries()
命令。 CMake将确保链接器找到它们。
相反,始终将绝对路径传递给target_link_libraries
并使用find_library
来解析链接目录:
find_library(PROTOBUF_LIBRARY protobuf HINTS /usr/lib/x86_64-linux-gnu)
target_link_libraries(test PUBLIC ${PROTOBUF_LIBRARY})
如果无法找到预期的库,而不是在编译时出现随机链接器错误,那么您可能会在CMake配置时获得诊断。此外,如果目标计算机具有非标准目录布局,则允许用户通过GUI指定库位置。
因此,如果它不能立即生效,请务必检查find_library
调用的结果,并查阅联机帮助页以查找无法按预期找到库的原因。
答案 1 :(得分:40)
确保您致电link_directories
的电话在致电之前发送至相关的add_executable
。
我错误地认为它只需要在调用target_link_libraries
之前,但事实并非如此。移动呼叫后,库已正确链接。
答案 2 :(得分:1)
确保顺序将是link_directories,设置PROJECT_LINK_LIBS,add_executable,然后是target_link_libraries。
下面是演示它的示例:
cmake_minimum_required(VERSION 2.8.9)
project (Logging)
include_directories(include)
file(GLOB LOGGINGSOURCES "libsrc/*.cpp")
file(GLOB SOURCES "src/*.cpp")
add_library(convertString SHARED ${LOGGINGSOURCES})
install(TARGETS convertString DESTINATION /root/Deepak/)
link_directories( /root/Deepak/ )
set(PROJECT_LINK_LIBS libconvertString.so)
add_executable(hello ${SOURCES})
target_link_libraries(hello ${PROJECT_LINK_LIBS} )