如果您遵循我下面的建议(我多年来一直这样做),您将能够:
-- 将每个项目放在源代码管理中的任何位置,只要保留项目根目录下的结构即可
-- 以最小的风险和最少的准备在任何地方、任何机器上构建每个项目
-- 完全独立地构建每个项目,只要您有权访问其二进制依赖项(本地“库”和“输出”目录)
-- 构建和使用任意项目组合,因为它们是独立的
-- 构建并使用单个项目的多个副本/版本,因为它们是独立的
-- 避免生成的文件或库弄乱源代码控制存储库
我推荐(这是牛肉):
定义每个项目以生成单个主要可交付成果,例如 .DLL、.EXE 或 .JAR(Visual Studio 的默认设置)。
将每个项目构建为具有单个根的目录树。
为根目录中的每个项目创建一个自动构建脚本,该脚本将从头开始构建它,不依赖于 IDE(但如果可行,不要阻止它在 IDE 中构建)。
考虑将 nAnt 用于 Windows 上的 .NET 项目,或基于您的操作系统、目标平台等的类似项目。
使每个项目构建脚本从单个本地共享“库”目录引用其外部(第 3 方)依赖项,每个此类二进制文件均由版本完全标识:%DirLibraryRoot%\ComponentA-1.2.3.4.dll
, %DirLibraryRoot%\ComponentB-5.6.7.8.dll
.
使每个项目构建脚本将主要可交付成果发布到单个本地共享“输出”目录:%DirOutputRoot%\ProjectA-9.10.11.12.dll
, %DirOutputRoot%\ProjectB-13.14.15.16.exe
.
使每个项目构建脚本通过“库”和“输出”目录中的可配置且完全版本化的绝对路径(见上文)引用其依赖项,而不是其他地方。
永远不要让一个项目直接引用另一个项目或其任何内容——只允许引用“输出”目录中的主要可交付成果(见上文)。
使每个项目构建脚本通过可配置且完全版本化的绝对路径引用其所需的构建工具:%DirToolRoot%\ToolA\1.2.3.4
, %DirToolRoot%\ToolB\5.6.7.8
.
让每个项目构建脚本通过相对于项目根目录的绝对路径引用源内容:${project.base.dir}/src
, ${project.base.dir}/tst
(语法因构建工具而异)。
始终需要项目构建脚本通过绝对的可配置路径引用每个文件或目录(以可配置变量指定的目录为根):${project.base.dir}/some/dirs
or ${env.Variable}/other/dir
.
永远不要允许项目构建脚本引用任何具有相对路径的内容,例如.\some\dirs\here
or ..\some\more\dirs
,始终使用绝对路径。
切勿允许项目构建脚本使用没有可配置根目录的绝对路径引用任何内容,例如C:\some\dirs\here
or \\server\share\more\stuff\there
.
对于项目构建脚本引用的每个可配置根目录,定义将用于这些引用的环境变量。
尝试最大程度地减少配置每台计算机时必须创建的环境变量的数量。
在每台计算机上,创建一个定义必要的环境变量的 shell 脚本,该环境变量特定于该计算机(并且可能特定于该用户,如果相关)。
不要将特定于机器的配置 shell 脚本放入源代码管理中;相反,对于每个项目,在项目根目录中提交脚本的副本作为模板。
要求每个项目构建脚本检查其每个环境变量,如果未定义,则中止并显示有意义的消息。
要求每个项目构建脚本检查其每个依赖的构建工具可执行文件、外部库文件和依赖的项目可交付文件,如果这些文件不存在,则中止并显示有意义的消息。
抵制将任何生成的文件提交到源代码管理的诱惑——没有项目可交付成果、没有生成的源代码、没有生成的文档等。
如果您使用 IDE,请尽可能生成项目控制文件,并且不要将它们提交到源代码管理(这包括 Visual Studio 项目文件)。
建立一个服务器,其中包含所有外部库和工具的正式副本,以便在开发人员工作站和构建机器上复制/安装。备份它以及您的源代码控制存储库。
建立一个没有任何开发工具的持续集成服务器(构建机器)。
考虑使用一个工具来管理外部库和可交付成果,例如 Ivy(与 Ant 一起使用)。
不要使用 Maven——它一开始会让你高兴,最终会让你哭泣。
请注意,这些都不是 Subversion 特有的,而且大多数都是针对任何操作系统、硬件、平台、语言等的项目所通用的。我确实使用了一些特定于操作系统和工具的语法,但仅用于说明- -我相信您会翻译成您选择的操作系统或工具。
关于 Visual Studio 解决方案的附加说明:不要将它们置于源代码管理中!使用这种方法,您根本不需要它们,或者您可以生成它们(就像 Visual Studio 项目文件一样)。但是,我发现最好将解决方案文件留给各个开发人员根据他们认为合适的方式创建/使用(但不签入源代码管理)。我保留一个Rob.sln
我的工作站上的文件,我从中引用了当前的项目。由于我的项目都是独立的,因此我可以随意添加/删除项目(这意味着没有基于项目的依赖项引用)。
请不要使用 Subversion 外部组件(或其他工具中的类似组件),它们是反模式,因此没有必要。
当您实施持续集成时,甚至当您只想自动化发布过程时,请为其创建一个脚本。制作一个 shell 脚本:获取项目名称(如存储库中列出的)和标签名称的参数,在可配置的根目录中创建临时目录,检查给定项目名称和标签名称的源(通过构造适当的 URL(如果是 Subversion)到该临时目录,执行干净的构建,运行测试并打包可交付成果。该 shell 脚本应该适用于任何项目,并且应该作为“构建工具”项目的一部分签入源代码管理。您的持续集成服务器可以使用此脚本作为构建项目的基础,或者它甚至可能提供它(但您仍然可能需要自己的脚本)。
@VonC:当你的构建脚本中断时,你不想一直使用“ant.jar”而不是“ant-a.b.c.d.jar”,因为你在不知不觉中使用不兼容版本的Ant运行它。这在 Ant 1.6.5 和 1.7.0 之间尤其常见。概括而言,您总是想知道正在使用的每个组件的具体版本,包括您的平台 (Java A.B.C.D) 和构建工具 (Ant E.F.G.H)。否则,您最终会遇到错误,而您的第一个大问题将是跟踪所涉及的各个组件的版本。最好提前解决这个问题。