【问题标题】:CMake: Link a library to libraryCMake:将库链接到库
【发布时间】:2013-01-06 06:44:26
【问题描述】:

我对 cmake 有疑问。比如说,我有一个 CMakeLists1,它有一个 CMakeLists2 所在的子目录。

在 CMakeLists2 中,我的目标是一个静态库。我想将它链接到外部库。 我已经做到了:

link_directories ("path_to_library")
add_library (project2 ${sources})
target_link_libraries (project2 "name_of_external_lib")

然后,我想在我的 project1 中使用这个 project2 中的一个类。我是这样做的:

add_executable (project1 ${sources})
target_link_libraries (project1 project2)

但这根本行不通。首先,project2 没有链接到外部库。只是为了检查,我通过vs10项目属性添加了这个库,并且大小不同。第二件事,不知何故 project1 看到了那个外部库(它在这个项目的库依赖项中),当然找不到它。

有什么问题?

【问题讨论】:

  • 这看起来像 *.com/questions/14199708/… 的副本,请检查我的答案。
  • 嗯,这实际上有点类似于我的问题。但是如果一个库是外部的并且不是目标,我该如何使用这个命令呢?
  • “name_of_external_lib”是共享库还是静态库?
  • @Ov3r1oad 您只需用库的名称替换$<TARGET_FILE:lib2> 位。理想情况下,您使用find_library 来定位库并将名称存储在变量中。该变量将代替第二个 $<TARGET_FILE:x> 事物。

标签: cmake


【解决方案1】:

我认为不将 project2 链接到外部库是 CMake 的默认行为, 但是要将两个库链接到可执行文件。 摘自《精通 CMake》一书。

由于静态库不链接到它们所依赖的库,它是 对 CMake 跟踪库很重要,因此可以在 正在创建的可执行文件的链接行。

您可以尝试在 CMakeLists2 中使用绝对路径:

add_library (project2 ${sources})
target_link_libraries (project2 "path to ext lib"/"name of ext lib")

或者你可以添加

link_directories ("path_to_library")

到 project1 的 CMakeLists 文件。

如果你真的想在 Visual Studio 中做类似的事情,你可以使用这个answer 中给出的命令在 CMake 中构建一个 custom_command。 它可能看起来像这样(我没有测试它)。

set(EXT_LIB "path_to_library/name_of_external_lib") 
set(BIG_LIB "path_to_big_lib/name_of_big_lib")
add_library (project2 ${sources})
get_property(PROJ2_LOC TARGET project2 PROPERTY LOCATION)

add_custom_command(OUTPUT ${BIG_LIB} 
                   DEPENDS ${EXT_LIB} project2
                   COMMAND "lib.exe /OUT:${BIG_LIB} ${EXT_LIB} ${PROJ2_LOC} )

然后你可以用 ${BIG_LIB} 链接你的可执行文件。

你必须考虑的一些事情:

  • 也许你必须使用LOCATION_CONFIGCMake docs,我在this answer找到了get_property命令)
  • link.exe 必须在您的路径中
  • 如果您想在其他 CMakeLists.txt 中使用 BIG_LIB 变量,请注意它的范围

【讨论】:

  • 显然,这些是唯一的选择。我只是不明白,为什么我可以在 VS10 中使用“附加库依赖项”来实现它?而且在cmake中没有办法做到这一点。
  • 如果您使用SHARED 构建共享库,然后target_link_libraries 可以将它们链接到外部库。 @Ov3r1oad
【解决方案2】:

我猜问题可能在于 *name_of_external_lib* 不正确,因此无法找到。

我会选择:

find_library(
    LIB_I_NEED name_of_external_lib
    HINTS "path_to_library"
)

if(${LIB_I_NEED} STREQUAL "LIB_I_NEED-NOTFOUND")
    message(FATAL_ERROR "Couldn't find the 'external_lib' library)
endif()

message(STATUS "Found 'external_lib' at: ${LIB_I_NEED}")

add_library (project2 ${sources})
target_link_libraries (project2 ${LIB_I_NEED})

如果这没有帮助,请快速阅读 cmake 文档中的示例:

http://www.cmake.org/cmake/help/v2.8.8/cmake.html#command:target_link_libraries

其中提到的一件事是:

虽然一次重复通常就足够了,但病态目标文件 和符号排列可能需要更多。可以通过以下方式处理此类案件 手动重复最后一个 target_link_libraries 中的组件 打电话

所以我想说的另一件事可能是在 project2 中:

set(PROJECT_2_LIBS project2 "name_of_external_lib" PARENT_SCOPE)

然后在exe中:

target_link_libraries (project1 ${PROJECT_2_LIBS})

这将在两个地方重复“external_lib”链接,并为您提供更多工作机会;)

【讨论】:

  • 虽然,我现在在想,如果它没有找到,那么编译器可能会在某个时候抱怨呃......嗯...... - 无论如何希望答案有所帮助。
  • 是的,cmake 找到了这个库,但不幸的是问题仍然存在。