C 和 C ++ 目前被应用在操做系统、嵌入式系统、财务、科研、汽车、机器人、游戏等很是重要的行业。主要缘由是 C 和 C++ 相比于其余技术来讲拥有很高的性能。但一样,C/C ++ 生态系统也面临一些巨大的挑战:web
巨石应用 -- 拥有数百万甚至更多行代码,在不使用现代工具的状况下很难管理项目。架构
应用程序二进制接口(ABI)不兼容 -- 为了保证库与其余库和应用程序的兼容性,须要控制不一样的配置(如操做系统,体系架构和编译)。运维
编译时间慢 -- 因为包含头文件和预处理器扩大,再加上上述挑战,须要特别注意优化过程并仅重建须要重建的库。分布式
代码连接和内联 -- 静态 C/C++ 库能够嵌入来自相关库的头文件。另外,共享库能够嵌入一个静态库。在这两种状况下,当它们的依赖关系发生变化时,都须要管理库的重建。ide
不一样的生态系统 -- 针对不一样的平台、目标和用途,有许多不一样的编译器和生成系统。工具
本文将展现如何使用 Jenkins CI,Conan C/C++ 包管理器和 JFrog Artifactory 通用工件存储库实现 DevOps C/C++ 开发的最佳实践。性能
Conan 的诞生就是为解决这些痛点。测试
Conan 使用了 Python,描述了如何经过显式调用任何构建系统来构建库,还描述了用户所需的信息(包括目录,库名等)。Conan 使用“Settings”(操做系统,架构,编译器等)管理不一样的配置和 ABI 的兼容性。当一个设置被改变时,Conan 为同一个库生成一个不一样的二进制版本。优化
构建后的二进制文件能够上传到 JFrog Artifactory 或 Bintray,与团队或整个社区共享。 团队中的开发人员不须要从新编译库,Conan 将从配置好的远程库(分布式模型)中仅提取匹配用户配置所需的二进制包。 可是还有更多的挑战须要解决:ui
如何管理 C/C++ 项目的开发和发布过程?
如何分发你的 C/C++ 库?
如何测试你的 C/C ++ 项目?
如何为不一样的配置生成多个包?当其中一个更改时,如何管理库的重建?
Conan 生态系统正在快速发展,使用 C/C++ 的 DevOps 如今已经成为现实:
JFrog Artifactory 管理完整的开发和发布周期。
JFrog Bintray 是通用的分发中心。
Jenkins 自动执行项目测试,生成 Conan 软件包的不一样二进制配置,并自动重建库。
提供 Conan DSL,是比较通用但有效的从 Jenkins 流水线脚本调用 Conan 的方法。
使用 Artifactory 实例管理远程配置,隐藏认证详细信息。
收集从 Conan 操做(安装/上传包)的工件来生成 Buildinfo 而且发布到 Artifactory。 BuildInfo 对象是很是有用的,例如,将建立的 Conan 包推广到不一样的存储库并对 Jenkins 构建具备完整的可追溯性:
下面是带有 Artifactory 插件的 Conan DSL 的一个例子。首先咱们配置 Artifactory 存储库,而后检索依赖关系并最终构建它:
在上面的例子中你能够看到 Conan DSL 是很是明确的。它对经常使用操做有很大的帮助,并且也容许强大的自定义集成。这对于 C/C++ 项目很是重要,由于每一个公司都有一个很是具体的项目结构,自定义集成等。
正如咱们在本文开始时看到的那样,在构建 C/C++ 项目时节省时间相当重要。 如下是几种优化流程的方法:
只从新构建须要重建的库。 有些库已经被一个依赖库的改变而影响了。
若是可能,并行构建。 当项目关系图中两个或多个库之间没有关系时,能够并行构建它们。
并行构建不一样的配置(操做系统,编译器等)。
咱们来看一个使用 Jenkins 流水线功能的例子
上图显示了咱们的项目 P 及其依赖关系(A-G)。咱们但愿分发两个不一样的体系结构,x86 和 x86_64。
若是咱们改变库 A 会发生什么?
若是咱们碰到 A(v1)的版本没有问题,咱们能够更新 B 的要求,也能够将版本升级到 B(v1)等等。完整的流程以下:
将A(v1)版本推送到 Git,Jenkins 将构建 x86 和 x86_64 二进制文件。Jenkins 会把全部的包上传到 Artifactory。
手动将 B 更改成 v1,如今取决于 A1,推送到 Git,Jenkins 将使用从 Artifactory 检索到的新 A1 来为 x86 和 x86_64 构建 B(v1)。
对 C,D,F,G 和咱们的项目重复相同的过程。
可是,若是咱们在开发库中开发咱们的库,咱们可能依赖于最新的 A 版本,或者将在每次 Git 推送时重写 A(v0)软件包,而且咱们但愿在这种状况下自动重建受影响的库 B,D,F ,G 和 P。
Jenkins 流水线会怎么作
首先咱们须要知道哪些库须要从新构建。“conan info --build_order”命令会标识在咱们的项目中被更改的库,而且还告诉咱们哪些能够并行从新构建。
因而,咱们建立了两个 Jenkins 管道任务:
创建每一个单一库的 SimpleBuild 任务。相似于使用 Jenkins Artifactory 插件使用 Conan DSL 的第一个示例。这是一个参数化的任务,接收须要构建的库。
MultiBuild 任务,在可能的状况下并行的协调、启动“ SimpleBuild”任务。
咱们也有一个 Yml 配置的仓库。 Jenkins 任务将使用它来了解每一个库的配置,以及要使用的不一样配置文件。在这种状况下,它们是 x86 和 x86_64。
这意味着咱们须要开始构建 B,而后咱们能够并行构建 D 和 F,最后构建 G。请注意,库 C 不须要重建,由于它不受 A 库变化的影响。
“MultiBuild”任务的 Jenkins 流水线脚本将对“SimpleBuild”任务的并行调用,最后并行启动组。
最终,这将会发生什么:
两个 SimpleBuild 任务将被触发,都是用于构建库 B,一个用于 x86 仍是另外一个用于 x86_64 体系结构
一旦“A”和“B”被构建,将触发“F”和“D”,4个工做将同时运行“SimpleBuild”任务(x86,x86_64)
最后将构建“G”。因此2个工做将平行运行。
Jenkins Stage 视图:
MultiBuild
SimpleBuild
咱们能够在不一样节点(Windows,OSX,Linux ...)中配置“ SimpleBuild ”任务,并控制 Jenkins 配置中可用的执行程序的数量。
对于 C/C++ 来讲,落地 DevOps 仍然是许多公司须要作的事情。 这须要大量的时间投入,但从长远来看能够节省不少的时间在开发阶段而且释放生命周期。 并且它提升了 C/C++ 产品的质量和可靠性。
上面的 Jenkins 示例演示了如何并行控制库构建,只是经过 Groovy 代码和一个自定义的方便的 Yml 文件。 关于它的伟大的事情不是例子或代码自己。 最重要的是能够定义本身的流水线脚本以适应特定的工做流程,这要归功于 Jenkins Pipeline,Conan 和 JFrog Artifactory。
原文连接:https://jenkins.io/blog/2017/07/07/jenkins-conan/
JFrog 中国研发工程师,曾在惟品会担任研发工程师,擅长Java,参与过多个互联网平台的研发和运维工做,现专一于Devops 落地,持续集成、持续交付领域。
欢迎转载,但转载请注明做者与出处。谢谢!