CMake(C++):将一个项目链接到另一个已构建的项目或库

CMake (C++): Link one project to another, already built, project or library

提问人:DGRK 提问时间:11/10/2023 更新时间:11/12/2023 访问量:142

问:

嗨,我是使用 CMake 的新手,最近接管了一个具有以下文件系统设置的 C++ 项目:

MyProject
|- proj_folder1 (functionality)
|---- files/subdirectories
|-----CMakeLists
|- proj_folder2 (functionality)
|---- files/subdirectories
|-----CMakeLists
|- proj_folder3 (functionality)
|---- files/subdirectories
|-----CMakeLists
|- 3rd_party_dependencies
|---- Subdirectories for various dependencies (googletest, abseil-cpp, simdjson, etc)
|---- CMakeLists
|- CMakeLists

需要注意的一些事项:

在我的项目的顶层,除了设置各种标志和环境变量外,CMakeLists.txt 文件还包括以下内容,这是对此文件中项目中子目录的唯一引用:

add_subdirectory(3rd_party_dependencies)
add_subdirectory(proj_folder1)
add_subdirectory(proj_folder2)
add_subdirectory(proj_folder3)

在第三方依赖项目录中,根 CMakeLists 仅包含对其依赖项的大量调用(例如 .我没有触及这些依赖项目录中的任何文件,并且由于我使用的是各种第三方库和项目,因此对于它们的构建、编译或链接方式没有固定的模式。但是,目前,我的项目目录中的 CMakeLists 确保我的项目中的所有内容都能正常工作,并链接到正确的依赖项。add_subdirectory()add_subdirectory(libhv))

另外值得注意的是,我正在使用 Ninja 构建工具来运行我的项目。

我的问题:

由于这些第三方依赖项很少更改,因此我被要求修改我的项目,以便所有这些第三方依赖项都与项目的其余部分分开构建。我应该将这些工件存储在可从服务器中的任何位置访问的位置,然后修改我的项目,以便每当我编译我的项目时,它都会找到我所有第三方依赖项的工件并针对它们的链接。我一直在搜索论坛和 wiki,但我很迷茫,找不到任何有用的描述如何链接两个单独构建的 c++ 项目。谁能提供关于如何实现这一目标的任何见解?提前致谢!


我使用以下命令从我的项目目录的根目录将我的第三方依赖项构建到服务器上的另一个位置:

cmake -GNinja -B /location_to_store_artifacts ./3rd_party_dependencies

这成功地创建了生成项目以及 CMakeCache.txt、cmake_install.cmake 和 compile_commands.json 文件。到目前为止,我还没有取得任何进展,因为我一直在尝试研究 cmake,而我看到的任何页面或博客文章都与我的情况有关。

C++ CMake 叮当

评论

0赞 drescherjm 11/10/2023
https://cmake.org/cmake/help/latest/command/target_link_libraries.html 是你想要关注的,以获得一个目标链接到一个库和/或库依赖项。文件夹结构并不那么重要。CMake 允许您使用所需的文件夹结构。
0赞 DGRK 11/10/2023
鉴于我的项目的 CMakeLists.txt 没有像 add_executable() 或 add_library() 这样的命令,并且第三方依赖项不会创建共享库文件,我必须进行哪些更改(尽可能具体或尽可能宽泛)?
0赞 drescherjm 11/10/2023
鉴于我的项目的 CMakeLists.txt 没有像 add_executable() 或 add_library() 这样的命令我希望你的项目和3rd_party_dependencies都有几个。我想我不明白你不寻常的项目类型。

答:

0赞 Sergey Vlasov 11/12/2023 #1

您可能需要导入的目标:

add_library(foo STATIC IMPORTED)
set_property(TARGET foo PROPERTY
             IMPORTED_LOCATION "/path/to/libfoo.a")

https://cmake.org/cmake/help/latest/guide/importing-exporting/index.html

0赞 JATothrim 11/12/2023 #2

CMake 具有用于构建、导出、安装和导入目标的实用程序。通常,第三方库会做类似的事情(这里以 GLFW 项目为例):

install(TARGETS glfw
EXPORT glfwTargets
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}")

这允许 GLFW 项目导出其目标以包含在其他项目中。软件打包商也将其用作打包软件以进行分发的一种方式。 仅标头库也可以执行此导出,即使它们不生成任何用于链接的二进制文件。

项目中的直接选择是使用从这些第三方依赖项生成的目标导入文件,一旦它们通过 ..cmakecmake --install <binarydir> --install-prefix <installprefix>

生成的目标导入文件提供的不仅仅是库文件的路径:已安装以将确切的依赖项导入到使用者项目中。导入的目标具有适当的依赖关系图,用于链接、编译器标志和已设置的包含路径。include().cmake

如果指定了依赖项的安装位置,则 CMake 也适用于已安装的目标导入文件。但请注意,它可能会忽略您的提示。find_package()

您可能想要的是构建第三方依赖项并将其安装到前缀中。有多种方法可以对此进行存档。我见过的最新消息是通过 CMake :FetchContent()

include(FetchContent)
FetchContent_Declare(googletest URL "download url")
FetchContent_MakeAvailable(googletest)

在内部,这是使用 CMake 模块来构建和安装依赖项。还可以直接使用 ExternalProject 模块来更好地控制生成过程和依赖项的安装位置。ExternalProject

https://cmake.org/cmake/help/v3.27/guide/using-dependencies/index.html#guide:Using%20Dependencies%20Guide