CMAKE:如何引用和构建单独的 CMAKE 项目依赖项?



我有一个交叉编译器cmake项目,它依赖于一个单独项目的库,该项目恰好也使用cmake:

/myProject/CMakeLists.txt (uses cross-compiler)
/anotherProject/CMakeLists.txt (platform-agnostic)

另一个项目可以完全独立地构建。 它完全不了解我的项目。

现在,另一个项目有许多我需要的模块,例如:

anotherProject/A/CMakeLists.txt (produces static lib A.a)
anotherProject/B/CMakeLists.txt (produces static lib B.a)
etc

当我构建myProject时,我想构建并链接到另一个Project/A和另一个Project/B,以生成共享的lib myproject.so。 如果可能的话,我想利用另一个项目的现有cmake-ness,而不是从myProject手动通解其各种源代码集。

使用 cmake 实现这一目标的正确方法是什么? 我觉得我错过了一些明显的东西。

如果,比如说,myProject只是另一个项目下的一个子目录,或者如果有一个顶级CMakeLists.txt可以同时引用myProject和另一个Project,那将是很简单的;但两者都不是我所追求的。 我知道我可以构建另一个项目并将其库导出到一个众所周知的位置,然后从 myProject 引用导出目录 - 但我也想避免这种设置。

解决方案是使用 CMake 包。

基本上,在另一个项目中,你创建一个CMake配置文件,在其中设置myProject要使用的变量(例如,包括目录,库列表,编译标志...),甚至是目标。

然后,在 myProject 中,使用find_package()机制,以便 CMake 查找此配置文件并导入当前项目中的变量/目标。

CMake wiki上有一个教程。

根据您的要求,我能想到的唯一替代设置是允许您的主(依赖)项目使用find_package发现另一个(依赖)项目。

在你的主项目CMakeLists.txt中,你应该添加这样的东西:

find_package(anotherProject CONFIG)
if(anotherProject_FOUND)
message(STATUS "Found project dependency: anotherProject")
else
# change WARNING to FATAL_ERROR if the dependency is NOT optional
message(WARNING "package anotherProject was not found")
endif()

关于CONFIGMODULE模式之间的差异,请查看文档和此链接。

然后假设您的主项目创建了一个可执行文件,您可以像这样挂接发现的依赖项:

add_executable(myProject ${SOURCES})
[...]
if(anotherProject_FOUND)
target_link_libraries(myProject PUBLIC anotherProject)
endif()

这也应该处理所需的包含文件和定义。


现在,在依赖项项目中CMakeLists.txt您应该执行以下操作:

set(PRJ_NAME "anotherProject")
string(TOLOWER ${PRJ_NAME} PRJ_NAME_LOWER)
set(ANOTHERPROJECT_EXPORT_NAME "${PRJ_NAME}")
install(TARGETS ${PRJ_NAME} EXPORT ${ANOTHERPROJECT_EXPORT_NAME}
RUNTIME DESTINATION .)
install(EXPORT ${ANOTHERPROJECT_EXPORT_NAME} DESTINATION "share/cmake")

这会将导出与目标相关联,然后安装导出。

现在,如果您检查该导出文件,它希望找到某些内容并included,这可能特定于您的项目。为了使它尽可能灵活,您可以使用configure功能从模板生成它们,然后从构建目录中install
因此,在名为share/cmake的子目录下的项目中,您可以有一个名为config.cmake.in的文件,其中包含以下内容:

include(${CMAKE_CURRENT_LIST_DIR}/@PRJ_NAME@.cmake)

在主项目的CMakeLists.txt中,您需要添加以下内容以从该模板生成文件:

configure_file(${CMAKE_CURRENT_SOURCE_DIR}/share/cmake/config.cmake
${CMAKE_CURRENT_BINARY_DIR}/share/cmake/${PRJ_NAME_LOWER}-config.cmake)
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/share/
DESTINATION share)

请注意,我使用了PRJ_NAME,因为您可能会在add_executable命令中重用它来命名实际的可执行文件。如果导出的目标与生成的目标具有相同的名称,则在精神上有所帮助。

这是一个更通用的版本,可以容纳本教程的多个子项目。

最新更新