如何链接从cmake中的add_subdirectory创建的静态库?

时间:2019-05-19 17:14:18

标签: c++ cmake linker dependencies

我正在尝试使用cmake构建依赖于第三方库的程序。该第三方库包含一个CMakeLists.txt文件,因此我要做的是将第三方库的源代码保留在我的项目目录中,并使用add_subdirectory(path / to / lib)进行构建,然后将目标链接到第三方库生成的静态库。

我的CMakeLists.txt:

cmake_minimum_version(VERSION 3.10)
project(my_project)

add_subdirectory("${CMAKE_SOURCE_DIR}/extern/somelib")

# my-code:
# somelib CMakeLists.txt file has a project name: SOMELIB
# which lets me access the directory where the files are built
# on windows it builds to /Release, on mac and linux it just builds
# to the binary dir
set(SOMELIB_LIBS "${SOMELIB_BINARY_DIR}/Release")
add_executable(my_program my_main.cpp)
target_link_libraries(my_program "${SOMELIB_LIBS}/SOMELIB.lib" "${SOMELIB_LIBS}/SOMELIBmain.lib")

然后我创建一个构建目录,然后从该目录中进行操作:

cmake -G "Visual Studio 15 2017" ..
cmake --build .

build命令失败,并显示“ LINK:致命错误LNK1181:无法打开输入文件'extern / somelib / Release / SOMELIBmain.lib'...”

我现在的解决方法是注释掉“#my-code”部分,首先构建somelib依赖关系,该依赖关系会生成静态库,然后取消注释my-code并再次构建,然后才能正常工作。 / p>

如何告诉CMake首先构建子目录,然后链接到它生成的静态库?

1 个答案:

答案 0 :(得分:1)

简短的回答:告诉CMake,其目标之间存在依赖性。

target_link_libraries(my_program PRIVATE SOMELIB SOMELIBmain)

CMake将为您评估SOMELIB的位置,并将my_programSOMELIB [1] 链接到SOMELIBmain。适用于Debug和Release配置以及Linux。

您不必担心CMake在哪里放置构建文件 [2] ,这就是所谓的“现代CMake”正在尝试实现的目标。我将在这里仅作简短描述,但请查看答案底部的链接 [3]

无论如何,关键概念是每当您创建库/可执行文件(目标)时,您都要列出其用法+构建要求以及对其他目标的依赖关系。您使用target_link_libraries(<your_lib> KEYWORD <dependencies>)声明依赖关系。这样的行不仅使<you_lib>链接到列出的依赖项,还将继承它们的使用要求(通常是公共包含目录),并命令CMake在<your_lib>之前构建依赖库。

它的优点在于,即使SOMELIB不遵循现代CMake的想法(没有声明构建/使用要求),您仍然应该可以仅用这一行来完成。

[1] 我假设CMake目标的名称与输出库名称相同,但这不是强制性的。对于OP而言,事实证明静态库目标后缀为-static,因此他不得不编写SOMELIB-static SOMELIBmain-static

[2] 不幸的是,使用Windows上的共享库(DLL)并不是那么容易

[3] 我将从此博客条目开始:https://pabloariasal.github.io/2018/02/19/its-time-to-do-cmake-right/