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

时间:2018-02-01 05:00:22

标签: c++ cmake

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

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

另一个项目可以单独完全独立构建。它根本不了解myProject。

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

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只是另一个项目下的子目录,或者如果有一个可以引用myProject和另一个项目的顶级CMakeLists.txt,那将是直截了当的;但是我所追求的也不是。我知道我可以构建另一个项目并将其库导出到一个众所周知的位置,然后从myProject引用导出目录 - 但我也想避免这种设置。

2 个答案:

答案 0 :(得分:1)

解决方案是使用CMake packages

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

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

CMake维基上有tutorial

答案 1 :(得分:0)

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

在您的主项目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模式之间的差异,请查看文档和link

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

add_executable(myProject ${SOURCES})
[...]

if(anotherProject_FOUND)
   target_link_libraries(myProject PUBLIC anotherProject)
endif()

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

现在在dependee项目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")

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

现在,如果您检查该导出文件,它会要求找到某些内容并include d,这可能是您的项目所特有的。为了使其尽可能柔和,您可以使用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命令中的实际可执行文件。如果导出的目标与生成的目标具有相同的名称,则在心理上有所帮助。

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