如何使用Git子模块和CMake处理传递依赖冲突?
我们有许多Git仓库,其中一些包含我们自己的代码,一些仓库包含稍微修改的第三方库代码。 简化的依赖关系图如下所示:
executable_A
| |
| v
| library_B
| |
v v
library_C
所以可执行文件对library_C
有两个依赖关系,一个是直接的,另一个是可传递的。 我希望使用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不喜欢它,所以它抱怨:
library_C / CMakeLists.txt中的CMake错误:13(add_library):
add_library无法创建目标“library_C”,因为已存在另一个具有相同名称的目标。 现有目标是在源目录“... / library_B / library_C”中创建的静态库。
有关更多详细信息,请参阅策略CMP0002的文档。
我宁愿不删除的直接依赖executable_A
上library_C
,因为它是通过拉一个事实library_B
是一个实现细节library_B
不应加以依赖。 而且,只要我们添加像executable_A --> library_D --> library_C
这样的其他依赖项,这种方法就会崩溃。
(这个问题是我能找到的最接近的,但是更一般,仍然没有答案。)
有几种检测和丢弃项目的方法,已经包含在主项目的其他部分。
检查项目的目标存在
子项目单个包含的最简单模式是检查是否存在某个子项目的目标:
# When include 'C' subproject
if(NOT TARGET library_C)
add_subdirectory(C)
endif()
(在这里我们假定项目C
定义了目标库library_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()
链接地址: http://www.djcxy.com/p/95823.html
上一篇: How to handle a transitive dependency conflict using Git submodules and CMake?