【问题标题】:Cmake cannot find library using "link_directories"Cmake 找不到使用“link_directories”的库
【发布时间】:2015-10-04 23:54:39
【问题描述】:

我是 Ubuntu,我正在学习 cmake 和 make,只是尝试一个简单的例子。我有两个目录:srcbuild。在src 中,我有两个文件:main.cppCMakeLists.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 相关的内容。

但是,如果我在我的CMakeLists.txt 文件中删除link_directories 行,而是在指定可执行文件时写入库的完整路径,即target_link_libraries(test /usr/lib/x86_64-linux-gnu/libprotobuf.so),它可以正常编译和链接。

为什么link_directories 不允许 cmake 找到这个库?

【问题讨论】:

  • cmake 手册中提到了 link_libraries “该命令仅适用于调用后创建的目标。”目标是用 add_executable() 命令创建的吗?也许您需要将 add_executable() 命令移到 link_directories() 之后。
  • 如果我这样做,我会收到错误Cannot specify link libraries for target "test" which is not built by this project.
  • 请确定:您的命令顺序现在是 1) link_directories()、2) add_executable() 和 3) target_link_libraries()?
  • 使用find_package(Protobuf) 而不是直接尝试定位。请参阅cmake.org/cmake/help/v3.3/module/FindProtobuf.html 了解更多信息。
  • 如果 find_package() 对你不起作用,下一个最佳选择是 find_library(PROTOBUF protobuf /usr/lib/x86_64-linux-gnu) 然后在你的 target_link_libraries 中使用 ${PROTOBUF} () 命令。环顾网络,您会看到很多人建议(有时强烈)反对使用 link_directories()。甚至 CMake 文档似乎也建议使用 find_library() 。

标签: c++ cmake makefile


【解决方案1】:

不要在 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 调用的结果并查阅手册页以找出它没有按预期找到您的库的原因。

【讨论】:

  • ... 但是,为什么它不起作用?我知道不建议这样做,但它不应该仍然有效吗?
  • 如果您使用 pkg_check_modules 查找库,您已经拥有所需的所有信息,使用 pkg_check_modules 是有意义的。
  • @aardvarkk 医生说The command will apply only to targets created after it is called.
  • FYI on Windows 我发现如果库位于子目录中,您可能需要将/* 添加到提示中
【解决方案2】:

确保您对link_directories 的呼叫发生在在您致电到相关的add_executable 之前。

我错误地认为它只需要在调用target_link_libraries 之前,但事实并非如此。移动调用后,库已正确链接。

【讨论】:

  • 感谢您的回答!我有一个使用 link_directories 的 FindSomething.cmake 文件,实际上,当在静态库上使用 target_link_libraries 将其与库“Something”链接然后将该静态库与二进制程序链接时,链接器无法链接库,因为没有采用 link_directories在帐户中...
  • 这是问题的正确答案。这里的关键字是before your call ...
【解决方案3】:

确保顺序是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} )

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-09-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-25
    • 2015-07-12
    • 2011-12-26
    相关资源
    最近更新 更多