【问题标题】:CMake, C++ and Jenkins/Continuous integrationCMake、C++ 和 Jenkins/持续集成
【发布时间】:2016-02-27 16:47:35
【问题描述】:

我有一个 CMake 示例项目,我想在 Ubuntu 15.10 上运行的 Jenkins 上构建它。我已经安装了:

https://wiki.jenkins-ci.org/display/JENKINS/CMake+Plugin

并创建了两个构建步骤:

  1. 运行 CMake 生成 makefiles
  2. 从构建目录运行 ma​​ke all

效果很好:

[build] $ cmake -G "Unix Makefiles" -D CMAKE_BUILD_TYPE=Debug /var/lib/jenkins/workspace/cmake-test/cmake-gtest/src
-- Configuring done
-- Generating done
-- Build files have been written to: /var/lib/jenkins/workspace/cmake-test/cmake-gtest/build
[build] $ /usr/bin/make
[  4%] Built target libfoo
[  9%] Built target libbar
[ 14%] Built target myApp
[ 52%] Built target gmock
[ 90%] Built target gtest
[100%] Built target testfoo
[cmake-test] $ /bin/sh -xe /tmp/hudson1792271459427590561.sh
+ cd cmake-gtest/build
+ make all
[  4%] Built target libfoo
[  9%] Built target libbar
[ 14%] Built target myApp
[ 52%] Built target gmock
[ 90%] Built target gtest
[100%] Built target testfoo
Finished: SUCCESS

但这是在 CI/Jenkins 设置中使用 CMake 的推荐方法吗?

目前,我的 CMake/Jenkins 构建将在每次推送时进行; 1) 生成 makefile,2) 构建项目。

我有点担心第一步 1) 生成 makefile 会占用构建时间,而且在每次推送时执行此步骤似乎并不是最佳选择。特别是因为我不希望经常更改 CMakeLists.txt 文件,但是当它们更改新生成的文件时,当然应该使用。

上述方法是我必须习惯的常见做法还是我错过了什么?

【问题讨论】:

  • “生成makefile”是否需要足够的时间来担心?虽然它可能不会经常更改,但有一个单独的步骤或在有更改时弄乱构建确实不是一个好的解决方案......
  • 是的,这也是我关心的问题,比抱歉更安全,解决方案是确保在我的应用程序增长时将其分解为更小更快的部分。重新考虑上面的两个构建步骤,1)cmake/generate,2)运行 make all 作为代码生成步骤的一部分,有没有办法做到这一点?还是他们完全独立,应该这样对待?
  • 我不太确定你在问什么。总的来说,我的态度是“采用足以解决当前问题的最简单的解决方案”,在您真正有充分理由之前不要使事情复杂化。我在我的 Jenkins 系统(在家)上运行了三个不同的工作:“使用 clang++ 构建 + 运行所有测试”、“使用 g++ 构建 + 运行所有测试”——这些工作每 15 分钟检查一次 git repo 中的新提交,第三个就是下载 LLVM 的版本和我的代码,并根据项目中的构建脚本将它们一起构建 - 每晚一次。
  • 从上面的截图我有两个构建步骤:1:生成makefile,1:运行make。我只是想知道它是否可以一步完成,以及 cmake 是否有一些 post step 命令用于在生成 make 文件后进行实际构建。
  • 似乎很明智,无论如何你都需要这样做。拥有两个部分的唯一好处是,如果在测试完成之前开始另一个代码构建需要足够长的时间,或者类似的。

标签: c++ jenkins cmake


【解决方案1】:

是的,您可以一步完成。

例如,在我的 Jenkins 环境中,在构建 Ubuntu 作业时,我使用 CMake 插件进行整个编译,因为它允许多个构建工具调用。

我在这篇文章底部的屏幕截图是作业中的 CMake 步骤(我使用 Ninja 而不是 Unix Makefile,但效果是一样的)。

我使用两个构建调用:

  • 空白 - 相当于在 shell 中调用 ninjamake
  • 安装 - 相当于调用DESTDIR=. ninja install

如果我想从 makefile 构建额外的目标,我可以在这一步中添加额外的调用。

请注意,在您的屏幕截图中,配置中有一个空白调用。这已经调用了make,并且正如您的日志输出所证实的那样,您实际上正在编译您的项目两次,因为您在以下步骤中手动调用了make all

您可以删除您的 shell 步骤,您的项目仍将构建。


关于您关于最佳实践和重新生成 CMake 的问题,我建议您参阅 Jenkins Best Practices 上的这篇文章,其中指出:

为确保构建可重现,构建必须是完全从源代码控制构建的干净构建。这种做法还意味着所有代码(包括第三方 jar、构建脚本、发行说明等)都必须检查到源代码控制中。

请注意,我还在 CMake 步骤中选中了“Clean Build”,以便清除整个 CMake 工作区,并且每次构建都从头开始生成项目。这样可以确保不会出现由过时的缓存变量等引起的问题。

我的一项工作中的 CMake 步骤的屏幕截图:

【讨论】:

  • 我不明白为什么这不被接受(编辑:我戳了用户,而不是被接受的用户)。无论如何,什么是空白调用?帮我看看你在 OP 的截图中看到了什么...... :)
【解决方案2】:

我什至不确定你是否需要这个插件。 AFAIR 插件网页,它仅在您希望 Jenkins 使用特定的 CMake 版本,或者您想要一个您可能想要设置的 CMake 变量的 GUI 时才有用。我只是从命令行执行 CMake。

对于第二部分的问题,如果更改 CMakeLists.txt,Makefile 将自动重新运行 CMake,因此严格来说不必每次都运行 CMake。但另一方面,CMake 配置非常快,而且很可能比编译花费的时间更少。

【讨论】:

  • 这正是我的想法,但我不确定它是否正确,所以不赞成。当我们想要对 C++ 项目进行 CI 时,我们应该使用插件还是只是从命令行调用 make 或其他任何东西?如果您可以通过一些参考资料对此进行扩展,那就太好了。
猜你喜欢
  • 2020-06-29
  • 1970-01-01
  • 1970-01-01
  • 2017-09-09
  • 1970-01-01
  • 2011-08-04
  • 1970-01-01
  • 1970-01-01
  • 2016-08-28
相关资源
最近更新 更多