答案 0 :(得分:6)
在我看来,依赖关系管理是项目组织的一个重要方面。您根据Mercurial的subrepos功能详细介绍了各种解决方案,并且我同意您提供的所有优点/缺点。
我认为SCM不太适合依赖管理。我更喜欢有专门的工具(这将是你的解决方案n°3)。
我目前的项目是Java。它是使用Apache Ant构建的,我首先将Apache Ivy设置为依赖项管理工具。最后,设置包括共享目录中的一些常春藤配置文件,以及列出项目每个模块的依赖项的一个XML文件。 Ivy可以被Ant目标调用,所以我在每个模块中添加了两个新动作:“解析依赖关系”和“部署构建的工件”。部署会在共享目录中添加buid(称为工件)的结果。依赖关系解析意味着可以传递地解析模块的依赖关系,并将已解析的工件复制到模块源的“lib”文件夹中。
此解决方案适用于C ++项目,因为Ivy并非特定于管理Java依赖项:工件可以是任何东西。在C ++中,模块生成的工件将是:
这不是一个完美的解决方案:常春藤不容易设置,你仍然必须告诉你的构建脚本使用什么依赖项,并且你没有直接访问依赖项的源代码以进行调试。但是你最终会得到独立的SCM存储库。
在我们的项目中,我们将表单Ant + Ivy切换到Apache Maven,它负责构建和依赖管理。工件部署在Apache Archiva而不是共享文件夹中。这是一个巨大的改进,但它只适用于Java项目。
答案 1 :(得分:2)
您要做的是让每个项目都在自己的目录中,如(1)所示。然后,您可以标记依赖项的工作版本,并将标记保存在某个文件中,以便构建如下:
App1/.dependencies: CommonLib1 tag-20100515 CommonLib2 tag-20100510 App2/.dependencies: CommonLib1 tag-20100510 CommonLib2 tag-20100510
然后使用构建脚本基于特定标记构建库,并将这些构建的库包含为应用程序的派生对象。如果构建时间存在问题,您可以使用预先构建并保存在某处的库中使用的标记版本。
注意(如果设计数据库模式,对象模型或产品构建,设计原则是相同的):
答案 2 :(得分:0)
我们使用subversion解决了类似的问题。
每个应用和每个Common Lib
都有自己的存储库。
每个应用都有一个目录Libs
,其中包含相关的dll。
因此,如果提供了一组新的dll,应用只会获得Common Lib
的更新。
然而,升级lib文件夹并不简单,因为依赖子dll必须匹配正确的版本。