Tho*_*mas 16 c++ cmake git-submodules
我们有许多Git存储库,其中一些包含我们自己的代码,一些包含稍微修改过的第三方库代码.简化的依赖关系图如下所示:
executable_A
| |
| v
| library_B
| |
v v
library_C
Run Code Online (Sandbox Code Playgroud)
所以可执行文件有两个依赖项library_C
,一个是直接的,一个是传递的.我希望使用Git子模块和CMake将它们组合在一起,因此简化的目录结构如下所示:
executable_A/
CMakeListst.txt
library_B/
CMakeLists.txt
library_C/
CMakeLists.txt
library_C/
CMakeLists.txt
Run Code Online (Sandbox Code Playgroud)
如您所见,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
on 的直接依赖library_C
,因为它被拉入via的事实library_B
是一个library_B
不应该依赖的实现细节.而且,一旦我们添加了另一个依赖项,这种方法就会崩溃executable_A --> library_D --> library_C
.
Tsy*_*rev 12
检测和丢弃项目的包含有几种方法,已经包含在主项目的其他部分中.
单个包含子项目的最简单模式是检查某个子项目的目标是否存在:
# When include 'C' subproject
if(NOT TARGET library_C)
add_subdirectory(C)
endif()
Run Code Online (Sandbox Code Playgroud)
(这里我们假设项目C
定义了目标library_C
.)
在有条件的包含之后,所有子项目的目标和功能将立即为呼叫者提供保证.
最好在所有地方(in executable_A
和library_B
)使用此模式.这种方式改变的顺序library_B
和library_C
在executable_A
不破的正确性.
这个模式可以重新设计,供子项目本身使用:
# At the beginning of 'C' project
cmake_minimum_required(...)
if(TARGET library_C)
return() # The project has already been built.
endif()
project(C)
...
Run Code Online (Sandbox Code Playgroud)
创建项目时,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()
Run Code Online (Sandbox Code Playgroud)
这个模式可以重新设计,供子项目本身使用:
# 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()
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1170 次 |
最近记录: |