ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

c – 如何使用Git子模块和CMake处理传递依赖冲突?

2019-09-23 21:14:16  阅读:675  来源: 互联网

标签:c cmake git-submodules


我们有许多Git存储库,其中一些包含我们自己的代码,一些包含稍微修改过的第三方库代码.简化的依赖关系图如下所示:

  executable_A
    |     |
    |     v
    |  library_B
    |     |
    v     v
   library_C

因此,可执行文件对library_C有两个依赖关系,一个是direct,一个是传递.我希望使用Git子模块和CMake将它们组合在一起,因此简化的目录结构如下所示:

executable_A/
  CMakeListst.txt
  library_B/
    CMakeLists.txt
    library_C/
      CMakeLists.txt
  library_C/
    CMakeLists.txt

如您所见,library_C存储库作为子模块包含两次.让我们假设两个子模块都指向同一个提交(关于如何强制执行的任何想法都是受欢迎的,但不是这个问题的主题).

我们使用add_subdirectory,target_link_libraries和target_include_directories来管理这些相互依赖性.很标准.

问题是如果你创建一个具有相同名称的目标两次,CMake不喜欢它,所以它会抱怨:

CMake Error at library_C/CMakeLists.txt:13 (add_library):
add_library cannot create target “library_C” because another target
with the same name already exists. The existing target is a static
library created in source directory “…/library_B/library_C”.
See documentation for policy CMP0002 for more details.

我宁愿不删除executable_A对library_C的直接依赖,因为它是通过library_B引入的,这是library_B的一个实现细节,不应该依赖它.此外,一旦我们添加了另一个依赖项,例如executable_A – >,这种方法就会崩溃. library_D – > library_C.

(This question是我能找到的最接近的,但是有点一般,但无论如何都没有答案.)

解决方法:

检测和丢弃项目的包含有几种方法,已经包含在主项目的其他部分中.

检查项目的目标存在

单个包含子项目的最简单模式是检查某个子项目的目标是否存在:

# When include 'C' subproject
if(NOT TARGET library_C)
    add_subdirectory(C)
endif()

(这里我们假设项目C定义了目标库_C.)

在有条件的包含之后,所有子项目的目标和功能将立即为呼叫者提供保证.

最好在所有地方(在executable_A和library_B中)使用此模式.这样改变executable_A中library_B和library_C的顺序并不会破坏正确性.

这个模式可以重新设计,供子项目本身使用:

# At the beginning of 'C' project
cmake_minimum_required(...)
if(TARGET library_C)
    return() # The project has already been built.
endif()

project(C)
...

检查项目是否存在

创建项目时,CMake为其定义了几个变量,其中包含<PROJECT-NAME>_BINARY_DIR个变量.请注意,此变量是缓存的,因此当第二次调用cmake时(例如,如果某些CMakeLists.txt已更改),该变量一开始就存在.

# When include 'C' subproject
if(NOT C_BINARY_DIR # Check that the subproject has never been included
    OR C_BINARY_DIR STREQUAL "${CMAKE_CURRENT_BINARY_DIR}/C" # Or has been included by us.
)
    add_subdirectory(C)
endif()

这个模式可以重新设计,供子项目本身使用:

# At the beginning of 'C' project
cmake_minimum_required(...)
if(NOT C_BINARY_DIR # Check that the project has never been created
    OR C_BINARY_DIR STREQUAL "${CMAKE_CURRENT_BINARY_DIR}" # Or has been created by us.
    project(C)
else()
    return() # The project has already been built
endif()

标签:c,cmake,git-submodules
来源: https://codeday.me/bug/20190923/1815807.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有