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

Yan*_*hou 3 cmake git-submodules

考虑以下三个项目。

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

cmake_minimum_required(VERSION 2.8.4)
project(A CXX)
add_library(a ${PROJECT_SOURCE_DIR}/liba.cpp)
Run Code Online (Sandbox Code Playgroud)

ProjectB取决于ProjectA,我将其添加ProjectA为git-submodule,因此其结构如下所示,

  • ProjectB
    • CMakeLists.txt
    • libb.cpp
    • ProjectA (git子模块)
      • CMakeLists.txt
      • liba.cpp

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)
Run Code Online (Sandbox Code Playgroud)

到目前为止,还好。

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

无论如何,我都将ProjectAProjectB作为git子模块添加到中ProjectC。因此,它具有以下结构,

  • ProjectC
    • CMakeLists.txt
    • libc.cpp
    • ProjectA (git子模块)
      • CMakeLists.txt
      • liba.cpp
    • ProjectB (git子模块)
      • CMakeLists.txt
      • libb.cpp
      • ProjectA(子模块的git子模块ProjectB
        • CMakeLists.txt
        • liba.cpp

并且具有以下内容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)
Run Code Online (Sandbox Code Playgroud)

现在,如果我尝试运行cmakeProjectC,我得到了下面的错误。

add_library cannot create target "a" because another target with the same
name already exists....
Run Code Online (Sandbox Code Playgroud)

我了解此错误的原因。这是因为ProjectA两次被添加为子目录,并且创建的所有目标add_library都是Global。对于这种特殊情况,我可以通过add_subdirectory(ProjectA)在中删除来解决ProjectC/CMakeLists.txt。但是,请考虑ProjectC具有许多依赖性的情况,并且它们之间可能有也可能没有依赖性。从的开发人员的角度来看ProjectC,他不需要关心自己依赖关系之间的相互依赖关系。

在这种情况下,ProjectC包括其依赖项的最佳方法是什么?必须具有ProjectAProjectB作为源形式的git-submodule。我知道我可以简单地安装ProjectAProjectB显山露水,ProjectC只需要在某个地方找到安装文件。但是,如果可能的话,我想避免这种解决方案(例如,如果安装时使用的ABI与安装的ABI不同,则会ProjectC出现不兼容的问题)。我希望所有三个项目都在的构建树中构建ProjectC

oLe*_*Len 7

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

if (NOT TARGET a)
  add_subdirectory(ProjectA)
endif ()
Run Code Online (Sandbox Code Playgroud)

因此,它只为整个CMake项目添加一次子目录。