我是Git子模块的忠实粉丝。我希望能够跟踪依赖关系及其版本,以便您可以回滚到项目的先前版本,并具有相应版本的依赖关系,以安全,干净地进行构建。此外,将我们的库作为开放源代码项目发布更容易,因为库的历史记录与依赖于它们的应用程序的历史记录是分开的(并且不会公开)。
我正在为工作中的多个项目设置工作流程,我想知道如果我们采用这种方法有点极端,而不是拥有一个整体项目会怎么样。我很快意识到,在真正使用子模块时,可能存在蠕虫病毒。
假设有一对应用程序:studio
和player
,以及依赖库core
,graph
和network
,其中依赖关系如下:
core
是独立的graph
取决于core
(的子模块./libs/core
)network
依赖于core
(的子模块./libs/core
)studio
取决于graph
和network
(位于./libs/graph
和的子模块./libs/network
)player
取决于graph
和network
(位于./libs/graph
和的子模块./libs/network
)
假设我们正在使用CMake,并且每个项目都有单元测试和所有工作。每个项目(包括studio
和player
)都必须能够独立编译以执行代码指标,单元测试等。
事情是,递归的git submodule fetch
,然后您将获得以下目录结构:
studio/
studio/libs/ (sub-module depth: 1)
studio/libs/graph/
studio/libs/graph/libs/ (sub-module depth: 2)
studio/libs/graph/libs/core/
studio/libs/network/
studio/libs/network/libs/ (sub-module depth: 2)
studio/libs/network/libs/core/
注意core
在studio
项目中克隆了两次。除了浪费磁盘空间之外,我还有一个构建系统问题,因为我要构建core
两次,并且有可能获得的两个不同版本core
。
题
如何组织子模块,以便获得版本化的依赖关系和独立的构建,而无需获取公共嵌套子模块的多个副本?
可能的解决方案
如果库依赖关系只是一个建议(例如,以“已知可与版本X一起使用”或“仅正式支持版本X”的方式),并且潜在的依赖应用程序或库负责使用其喜欢的任何版本进行构建,则我可以想象以下情形:
- 让构建系统知道
graph
并network
告诉他们在哪里core
(例如,通过编译器包含路径)。定义两个构建目标:“独立”和“依赖”,其中“独立”基于“依赖”,并添加包含路径以指向本地core
子模块。 - 引入额外的依赖性:
studio
上core
。然后,studio
建立core
,设置包括它自己的拷贝路径core
子模块,然后建立graph
与network
在“依赖”模式。
生成的文件夹结构如下所示:
studio/
studio/libs/ (sub-module depth: 1)
studio/libs/core/
studio/libs/graph/
studio/libs/graph/libs/ (empty folder, sub-modules not fetched)
studio/libs/network/
studio/libs/network/libs/ (empty folder, sub-modules not fetched)
但是,这需要一些构建系统的技巧(我很确信这可以使用CMake来完成)以及版本更新方面的一些手动工作(更新graph
可能还需要更新core
并network
获得core
所有项目中的兼容版本) 。
有什么想法吗?