2017-05-03 112 views
2

考虑以下三个项目。CMake和使用Git子模块的依赖项目

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-子模块,所以它的结构会像下面,

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

和的ProjectBCMakeLists.txt外观立ke以下

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子模块。因此,它具有以下结构,

  • ProjectC
    • CMakeLists.txt
    • libc.cpp
    • ProjectA(GIT子模块)
      • CMakeLists.txt
      • liba.cpp
    • ProjectB(GIT子模块)
      • CMakeLists.txt
      • libb.cpp
      • ProjectA(子模块ProjectB的GIT中的子模块)
        • 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) 

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

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

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

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

+1

的可能的复制[如何处理使用Git子模块和CMake的传递依赖冲突?(http://stackoverflow.com/questions/42978414/how-to-handle-a-transitive-dependency-conflict-using- GIT-子模块和 - cmake的) – Tsyvarev

回答

2

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

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

,以便它只会增加子目录一次为您的整个CMake的项目。