【问题标题】:Setting up build process for dependent projects and multiple developers为依赖项目和多个开发人员设置构建过程
【发布时间】:2012-05-10 07:17:37
【问题描述】:

我对自动化构建流程和持续集成还很陌生,并且正在为一个小型开发团队设置构建流程/服务器。我们正在使用 SVN、CMake 和 Jenkins 构建服务器。源语言为 C++。

假设我们有两个项目,library(一个 dll)和executableexecutable 链接到 library,因此要构建 executable,您需要来自 library 的 .lib 和 .h 文件。要运行executable,您需要library 的.dll(可能还有调试符号文件)。

在构建整个东西时,它相当简单,您从存储库中获取最新源并构建library 然后executable

但是,我们有多个开发人员,每个开发人员通常一次处理一个项目。我们的 CMake 脚本允许您选择要构建的项目,因此 John 的设置可能仅构建 executable,而 Bob 仅构建 library。放弃这不是一种选择。

所以如果Boblibrary 进行更改并提交源代码,John 将需要获取已编译的 .lib 和 .dll 文件(因为他没有编译 library)。

现在,二进制文件在 svn 中。在每次编译期间,CMake 将 src/bin 复制到 build/bin 作为预编译步骤,然后编译选择的任何项目(替换 build/bin 中的适当二进制文件),最后 CMake 将 build/bin 复制到 src/bin

这意味着当Bob 进行更改时,他不仅会提交源文件,还会提交编译后的二进制文件,当John 更新他的工作副本时,他会获得适当的二进制文件,而不必这样做任何手动文件替换。

这已经有一段时间了,但我真的不喜欢它有几个原因。是否有更少的黑客方式来设置这样的东西? (实际上有4个开发者,大概有12个项目,有些是不依赖任何东西的库,有些是依赖其他库的库,还有一些是依赖其他库的可执行文件。)

编辑:这是我正在考虑的过程:

使用 Artifactory 或 Nexus 等工件跟踪系统在构建后存储二进制文件以及用于生成这些二进制文件的头文件

在 CMake 中,每个项目都被标记为已编译或预编译。编译的项目是从常规存储库生成的。如果预编译的项目二进制文件和标头已过期,则会从 Nexus 下载它们,并且 CMake 会适当地链接和包含。标题也与工件一起保存,以防止我在对 Dave Bacher 的回答的评论中描述的竞争条件。

我唯一不喜欢的是我必须做一些 CMake-foo 来检查工件是否过时并下载它们,但我想没有真正的替代方案,因为显然我我正在尝试设置是如此不标准。

【问题讨论】:

  • 为什么不是每个开发人员都有自己的构建版本?在您的示例中,在 Bob 的更改之后,John 为什么不在结帐时重建他需要的库?
  • 部分是因为它给 VS 的解决方案资源管理器和构建输出增加了很多混乱,并且在每次编译期间增加了一点时间接触所有项目。但主要是因为这已经有一段时间了,而且权力已经决定了它不会改变:-\

标签: svn build-process cmake jenkins build-automation


【解决方案1】:

我不喜欢您将开发人员的构建作为其他人构建的规范参考进行签入。它很脆弱,您最终可能会得到在他们的环境中对一个人有用的糟糕构建,但对其他人却失败了。或者有人进行了更改,但忘记签入文件,突然间,他们是唯一可以构建项目的一部分的人。

至少,您应该将 Jenkins 设置为构建库和可执行文件的地方,并让您的开发人员只签入源代码。 Jenkins 有几个插件(例如SVN Publisher),可用于在标准构建环境中构建库和可执行文件后发布它们。

根据我的经验,在构建机器上安装 Jenkins 并为每个项目设置构建非常简单。这让您开始验证每个项目是否已构建的第一步。然后努力让 Jenkins 发布其输出,而不是依赖开发人员发布他们的构建。

【讨论】:

  • “我不喜欢你在检查开发人员的构建”——这也是我对系统最大的问题,也是我为什么要对其进行返工的原因。 “至少,你应该将 Jenkins 设置为构建库和可执行文件的地方” - 这就是我想要设置的地方,但我遇到的问题是,然后我们开发了一个竞争条件,如果有人提交了对源的更新,而其他人在编译新工件之前更新了他们的工作副本,那么他们将链接到可能与标头不匹配的过时二进制文件。
  • 实际上,我可以让 Jenkins 将带有二进制文件的标题提交到与常规标题不同的目录中。如果使用预编译的二进制文件,则包含预编译的头文件,否则包含来自源的常规头文件。
【解决方案2】:

看起来当前的系统在修改可执行文件和库的人之间总是存在竞争条件。我建议您不要专注于如何为所有开发人员解决竞态条件,而是使用 CI 来捕捉竞态条件中可能出现的问题。

由于您刚刚开始,我会保持简单,并专注于创建一个 Jenkins 作业,该作业在将某些内容签入存储库时构建整个事物。假设库和可执行文件保存在同一个 SVN 存储库中,作业的操作应该是这样的:

  1. 查看存储库
  2. 执行 CMake 构建库
  3. 对库进行任何单元测试(有一些,对吗?)
  4. 执行 CMake 以针对库构建可执行文件
  5. 对可执行文件进行任何单元测试(有一些,对吗?)
  6. 将构建结果通知开发人员。

虽然这看起来微不足道,但这会让开发人员得到反馈,就像他们因更改而破坏事物一样,而不必强迫他们记住更新他们的副本。这也将帮助他们轻松地进入使用 CI 工作的范式转变。

[顺便说一句,开发人员可能遇到的一个问题是他们是否习惯于一次检入 SVN 文件。逐个文件更改将启动多个构建,只有在最后一个文件最终签入时才会成功。多个文件的签入需要作为一次对多个文件的原子操作来完成。这也是一个很好的 SCM 实践,因为它将更改组合成一个可以跟踪和(如果需要)回滚的东西。]

范式转变一开始似乎无法克服,但确实会发生。我目前正在从事的项目是从习惯于与上述非常相似的过程的开发人员开始的。当我们开始运行 CI 时,每周检查一次以上的代码会遇到一些阻力。 8 个月后,如果我必须对 Jenkins 构建进行任何维护,我会立即被问到为什么 Jenkins 不可用以及“如果人们不能立即获得构建结果,我该如何工作? "

【讨论】:

    猜你喜欢
    • 2012-10-19
    • 2017-02-11
    • 1970-01-01
    • 2018-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-30
    • 2013-05-11
    相关资源
    最近更新 更多