我对自动构建流程和持续集成相当新,并且正在为一小组开发人员设置构建流程/服务器。我们正在使用SVN,CMake和Jenkins构建服务器。源语言是C ++。
假设我们有两个项目,library
(一个dll)和executable
。 executable
的{{1}}链接,因此要构建library
,您需要executable
中的.lib和.h文件。要运行library
,您需要executable
的.dll(以及可能的调试符号文件)。
在构建整个事物时,它非常简单,您从存储库中获取最新的源代码并构建library
然后library
。
但是,我们有多个开发人员,每个开发人员通常一次只处理一个项目。我们的CMake脚本允许您选择要构建的项目,因此executable
可能只有John
的构建,而executable
只构建Bob
。提出这个问题不是一种选择。
因此,如果library
对Bob
进行更改并提交源代码,library
将需要获取已编译的.lib和.dll文件(因为他没有编译John
})。
现在,二进制文件位于svn中。在每次编译期间,CMake将library
复制到src/bin
作为预编译步骤,然后编译所选项目(替换build/bin
中的相应二进制文件),最后CMake副本{{1}到build/bin
。
这意味着当build/bin
进行更改时,他不仅会提交源文件,还会提交已编译的二进制文件,并且当src/bin
更新其工作副本时,他会获得相应的二进制文件,并且不会必须做任何手动文件更换。
这已经有一段时间了,但我真的不喜欢它有几个原因。是否有更少的黑客方式来设置这样的东西? (实际上有4个开发人员,大约12个项目,有些是不依赖于任何东西的库,有些是依赖于其他库的库,有些是依赖于其他库的可执行文件。)
编辑:这是我正在考虑的过程:
使用工件跟踪系统(如Artifactory或Nexus)在构建后存储二进制文件,以及用于生成这些二进制文件的头文件
在CMake中,每个项目都标记为已编译或预编译。编译的项目是从常规存储库生成的。预编译的项目二进制文件和标题是从Nexus下载的,如果它们已过期,并且CMake链接和包含适当。标题也与文物一起保存,以防止我在评论Dave Bacher的答案中描述的竞争条件。
我唯一不喜欢的是我必须做一些CMake-foo来检查这些文物是否已经过时并下载它们,但我想其实并没有真正的替代方案我试图设置是非常标准的。
答案 0 :(得分:2)
我不喜欢你在开发人员的构建中检查其他人将构建的规范引用。它很脆弱,你最终可能会遇到在他们的环境中为一个人工作的坏构建,但对其他人来说却是失败的。或者某人进行更改但忘记签入文件的情况,突然之间,他们是唯一可以构建项目一部分的人。
至少,您应该将Jenkins设置为构建库和可执行文件的位置,并让开发人员只检查源代码。 Jenkins有几个插件(例如SVN Publisher)可用于在标准构建环境中构建库和可执行文件之后发布它们。
根据我的经验,在构建计算机上安装Jenkins并为每个项目设置构建非常简单。这将帮助您开始验证每个项目的构建的第一步。然后努力让Jenkins发布其输出,而不是依赖开发人员发布他们的构建。
答案 1 :(得分:1)
看起来当前的系统在修改可执行文件和库之间总是存在竞争条件。我建议您使用CI来捕捉可能因竞争条件而产生的问题,而不是试图专注于如何解决所有开发人员的竞争条件。
由于您刚刚开始,我会保持简单并专注于创建一个Jenkins作业,无论何时将某些内容检入存储库,都会构建整个事物。假设库和可执行文件保存在同一个SVN存储库中,作业的操作应该是这样的:
虽然看起来微不足道,但如果他们通过改变破坏事物而不必强迫他们记住更新他们的副本,这将得到开发人员的反馈。它还将有助于他们进入与CI合作的范式转变。
[顺便说一句,开发人员可能遇到的问题是,他们是否习惯于一次检查SVN文件。逐个文件更改将启动多个构建,这些构建仅在最后一个文件最终签入时才会成功。多个文件的检查需要一次完成具有多个文件的原子操作。这也是一个很好的SCM实践,因为它将更改组合成一个可以跟踪并且(如果需要)回滚的东西。]
一开始,范式转变似乎无法克服,但可能会发生。我目前正在开展的项目始于开发人员,他们习惯于如上所述的非常类似的过程。当我们开始运行CI时,对代码检查的阻力比每周一次更多。 8个月之后,如果我必须对Jenkins版本进行任何维护,我会立即被问及为什么Jenkins不可用的问题,“如果他们无法立即获得构建结果,我怎么能指望人们工作? “