CMake 并使用 git-submodule 进行依赖项目

CMake and using git-submodule for dependence projects

考虑以下三个项目。

ProjectA 没有任何依赖关系,其顶层的 CMakeLists.txt 如下所示,

cmake_minimum_required(VERSION 2.8.4)
project(A CXX)
add_library(a ${PROJECT_SOURCE_DIR}/liba.cpp)

ProjectB 依赖于 ProjectA,我将 ProjectA 添加为 git-子模块,因此其结构如下所示,

ProjectBCMakeLists.txt如下所示

cmake_minimum_required(VERSION 2.8.4)
project(B CXX)
add_subdirectory(ProjectA)
add_library(b ${PROJECT_SOURCE_DIR}/libb.cpp)
target_link_libraries(b a)

到目前为止一切正常。

现在假设它是 ProjectC。它取决于 ProjectAProjectB。假设我不知道 ProjectB 已经依赖于 ProjectA(例如,我之前没有创建这两个。或者认为 ProjectC 实际上有很多依赖关系,我不会被迫找出它们之间的确切依赖树)。

无论如何,我在 ProjectC 中添加了 ProjectAProjectB 作为 git 子模块。所以它有如下结构,

它有以下 CMakeLists.txt.

cmake_minimum_required(VERSION 2.8.4)
project(C CXX)
add_subdirectory(ProjectA)
add_subdirectory(ProjectB)
add_library(c ${PROJECT_SOURCE_DIR}/libc.cpp)
target_link_libraries(c a b)

现在,如果我尝试 运行 cmake for ProjectC,我会收到以下错误。

add_library cannot create target "a" because another target with the same
name already exists....

我明白这个错误的原因。这是因为 ProjectA 被添加为子目录两次,并且 add_library 创建的所有目标都是 Global。对于这种特殊情况,我可以通过删除 ProjectC/CMakeLists.txt 中的 add_subdirectory(ProjectA) 来修复它。但是,考虑 ProjectC 有很多依赖关系的情况,它们之间可能存在依赖关系,也可能不存在依赖关系。从ProjectC的开发者的角度来看,他应该不需要关心自身依赖之间的相互依赖关系。

在这种情况下,让 ProjectC 包含其依赖项的最佳方法是什么?将 ProjectAProjectB 作为源代码形式的 git 子模块是必须的。我知道我可以简单地在某处安装 ProjectAProjectB,而 ProjectC 只需要在某处找到已安装的文件。但是,如果可能的话,我想避免这种解决方案(例如,如果安装是使用与 ProjectC 使用的 ABI 不同的 ABI 构建的,则会出现不兼容问题)。我希望所有三个项目都构建在 ProjectC.

的构建树中

你可以在调用add_subdirectory之前检查目标a是否已经存在:

if (NOT TARGET a)
  add_subdirectory(ProjectA)
endif ()

这样它只会为您的整个 CMake 项目添加一次子目录。