解读C/C++应用包管理的Why和How-Github架构师

一、背景
本文整理自Johannes Nicolai在JFrog 2019用户大会上的讲演《DevOps for Non-Hipsters(aka C/C++ programmers)》。

Johannes Nicolai是Github的解决方案架构师,主要负责德语区的用户。他和很多制造业的用户(多数使用C/C++)交流,询问他们在DevOps或持续交付方面的挑战,通常会得到如下的描述:

在嵌入式C/C++领域,花费几十个小时完成一个完整的DevOps流水线并不少见。为某一个提交运行单独的构建和测试几乎是不可能的,通常每次构建都包含了几百个同事所有的提交。而构建时间长的主要原因在于交付包包含了大量的依赖包,而每次构建这些依赖包都需要从头开始重新构建。上述的描述并不限于德语区,Johannes询问了美国制造业的用户,也得到了类似的反馈。
从业界的发展来看,声明式包管理能够很好的解决上述的问题。在交付包中通过声明描述所需的依赖包,在构建时根据声明从包管理系统中获取相应的依赖包,这样能够大大缩短构建时间。Java或JavaScript的开发者很熟悉这样的方式。

对于像Java或JavaScript这样的开发语言,包管理的实现相对简单,包的每一个版本只对应一个二进制文件。而在C/C++中,由于操作系统、架构、编译器等的不同,包的每一个版本会对应多个不同的二进制文件,彼此之间还并不兼容。这也就导致了C/C++的包管理一直是业界公认的难题。
当然,针对C/C++的开发,现在也出现了像Conan这样比较成熟的包管理解决方案。Johannes在本次讲演中首先分析了为什么要在DevOps中引入包管理,然后通过演示介绍了Conan如何通过方便的包管理和开发方式,帮助C/C++程序员实现简洁、高效的DevOps流水线。

二、为什么要在DevOps中引入包管理

现在业界大都在推行敏捷,而在敏捷提出的12条原则中,其中一条就是:通过早期和持续型的高价值工作交付满足“客户”。
通过持续性的交付,首先能够快速发现问题,从而尽早解决问题,而不是每次发布前都要积累大量的问题,从而导致过长的修复时间和交付质量的下降。

其次,用户可能一开始并不是特别清楚自己的需求。通过持续性的交付,用户可以不断的试用来渐进明晰地明确自己的实际需求,从而保证了交付的有效性。

要实现敏捷原则所要求的持续性的交付,我们必须实现持续性、可重复的DevOps流水线。而为了实现这样的DevOps,一个基本原则是要做到“只构建一次二进制文件”。

也就是说,每一个版本的交付包,我们只构建一次。获得其对应的二进制文件后,在DevOps的后续阶段、不同环境中,都应该用且只用这同一个二进制文件。

然而,针对C/C++的应用来说,各种不同的目标环境导致同一个版本的交付包,必然会对应多个互不兼容的二进制文件。在这种情况,要做到仅一次构建,无疑需要借助于良好的包管理解决方案。

通过引入包管理系统,可以为C/C++包的每一个版本预编译好多个与之对应的面向不同目标环境的二进制包,再通过语义化版本及兼容环境的描述,在构建过程中直接获取对应的二进制包,从而能够大大节省构建的时间,保证DevOps流水线的一致性和可重复性。同时,当发现某些问题,如安全漏洞或开源许可证错误时,也可以通过对依赖关系的管理,迅速定位问题的影响范围,提升问题的解决效率。

对于C/C++开发常用的子模块的方式,并不能满足上述DevOps的要求。子模块的方式不能解决构建时间长的问题,不能保证所依赖的库的不可变性,对版本的依赖关系缺乏灵活的定义和管理,对兼容性的分析和处理也缺乏内置的解决方案。

类似的,通过Git LFS来管理C/C++的包也不是一个好的方式。Git LFS缺乏对版本依赖关系的灵活定义和管理,缺乏对兼容性分析和处理的内置解决方案,同样不能解决构建时间长的问题。
因此,要提升C/C++应用的DevOps效率和质量,我们需要引入与Java、JavaScript等类似的包管理解决方案。而目前这一领域发展最快、最受业界关注的就是Conan。

三、Conan——C/C++的包管理方案

Conan(https://conan.io)是一个开源的解决方案,为C/C++应用提供了跨平台的包管理方式。而JFrog收购Conan后,通过结合其在制品管理方面产品和技术的优势,更提升了Conan对C/C++应用的支持能力

Conan具有良好的兼容性,能够与当前C/C++领域应用的各种构建系统和编译器配合使用。

Conan提供了完整的C/C++应用依赖关系管理能力,能够支持语义化版本描述、传递依赖的解析、依赖冲突的分析与解决,以及灵活的范围化版本描述等。

Conan还为C/C++应用的DevOps建设提供了丰富的工具支持:
?针对包仓库,提供了原生、开源的Conan Server,同时JFrog的Artifactory、Bintray也提供了功能更为丰富、全面的商业化产品支持;
?Conan的客户端,与各种构建系统对接,实现基于Conan的C/C++构建;
Conan提供与Jenkins、Travis CI等工具的对接,实现C/C++应用自动化的、可重复的DevOps流水线。

在Conan的解决方案中,包的每一个版本都根据目标环境的不同,如架构、操作系统、编译器等,预编译好与之对应的二进制包。构建时,Conan客户端只下载与当前目标环境兼容的二进制包,从而在保证一致性的同时,提升了构建的效率。
对于特殊环境,还没有对应的预编译二进制包的情况,Conan通过定义包的Recipe,描述了如何构建该包的二进制包的过程,Conan客户端可以即时构建出一个新的,匹配与当前特殊环境的新二进制包,供应用构建使用。同时,这个新二进制包也可以存回包仓库当中,供后续的构建直接引用。

综上所述,与Java、JavaScript等使用的类似,Conan为C/C++开发者提供了一个成熟的、功能完整、工具完备的包管理解决方案,能够辅助C/C++的开发者创建稳定、高效、一致、可重复的DevOps流水线。

四、如何在C/C++应用中使用Conan

Johannes在演讲中还通过演示,展示了如何基于Conan,实现便捷、高效的C/C++应用的构建。
Johannes所用的例子不是简单的“Hello World”,而是github上一个真实项目:

要使用Conan,我们只需为每一个C/C++应用增加一个conanfile.txt,用以描述其依赖关系:

利用“conan remote add”命令,可以将Conan客户端和Conan的包仓库建立关联,再执行“conan install”,就可以将符合目标环境需求的所有依赖二进制包下载在本地。

在编辑构建参数,如使用CMake构建,就修改CMakeLists.txt,加入conan的配置,就可以集成下载的依赖二进制包,完成C/C++应用的构建。

除了直接引用Conan仓库中已有的包及其二进制文件,利用Conan也可以创建自己开发的Conan包作为库,供其他C/C++应用依赖。Johannes还以github上的另一个项目演示了如何创建自己的Conan包:

要创建Conan的库包,需要为项目增加conanfile.py文件,如上图中的右半部分,改py文件就对应了之前提到的Conan包的Recipe,它除了描述了该包的基本信息之外,还通过函数定义了如何构建该库包得到二进制文件的过程。

通过执行“conan create”命令,我们就可以生成自定义的Conan包作为内部库,再执行“conan upload”将其上传到Conan包仓库,就可以被其他C/C++应用引用、依赖了。
此外,Conan还可以与Jenkins等工具集成,通过自动化、并行的方式,一次性构建出同一版本包,针对不同目标环境的所有二进制文件:

基于Conan的包管理方案,通过与GitHub、Jenkins、Artifactory、Bintray等工具对接,可以实现完整的C/C++应用的DevOps流水线:

通过演示可以看出,在C/C++应用中引入Conan的包管理,方式是直观、简便的,附加的工作负载并不多。而通过与各种工具的集成,可以基于Conan方便地创建C/C++应用的DevOps流水线,满足敏捷的需求。

五、总结

敏捷化是目前业界应用研发的发展方向。通过实施敏捷化,我们可以实现迅速的、持续的产品交付,从而尽早发现问题,尽早解决问题。而且,通过快速、持续的交付,我们也可以获得用户持续的反馈,渐进明细地挖掘和实现用户的真正需求。

对于C/C++应用及开发者来说,基于Conan的包管理方案,以及与DevOps领域工具的集成使用,可以创建便捷、高效、一致性、可重复的DevOps流水线,从而满足敏捷化的需求。

注:本文图片因平台原因不能上传,可关注“JFrog杰蛙DevOps”公众号,每周二在线课堂,干货分享~

原文地址:https://blog.51cto.com/jfrogchina/2430035

时间: 2024-10-24 15:31:24

解读C/C++应用包管理的Why和How-Github架构师的相关文章

Linux包管理工具(rpm/dpkg,yum/apt,alien)

概括: rpm/yum  redhat dpkg/apt  debian alien 转换 在 GNU/Linux( 以下简称 Linux) 操作系统中,RPM 和 DPKG 为最常见的两类软件包管理工具,他们分别应用于基于 RPM 软件包的 Linux 发行版本和 DEB 软件包的 Linux 发行版本.软件包管理工具的作用是提供在操作系统中安装,升级,卸载需要的软件的方法,并提供对系统中所有软件状态信息的查询.RPM 全称为 Redhat Package Manager,最早由 Red Ha

Linux包管理命令与Ubuntu下安装nginx的方法

rpm包和deb包是两种Linux系统下最常见的安装包格式,在安装一些软件或服务的时候免不了要和它们打交道.rpm包主要应用在RedHat系列包括 Fedora等发行版的Linux系统上,deb包主要应用于Debian系列包括现在比较流行的Ubuntu等发行版上. 二者对应的安装命令分别为rpm与dpkg. Ubuntu的软件包格式是deb,如果要安装rpm的包,则要先用alien把rpm转换成deb.alien安装与转换命令: sudo apt-get install alien #安装ali

linux--软件包管理工具

linux平台软件包管理: RPM/DPKG 两大阵营简介 在 GNU/Linux( 以下简称 Linux) 操作系统中,RPM 和 DPKG 为最常见的两类软件包管理工具,他们分别应用于基于 RPM 软件包的 Linux 发行版本(centos/suse/redhat)和 DEB 软件包的 Linux 发行版本(Ubuntu/debain).软件包管理工具的作用是提供在操作系统中安装,升级,卸载需要的软件的方法,并提供对系统中所有软件状态信息的查询. RPM 全称为 Redhat Packag

包管理工具rpm和yum的用法

包管理工具rpm和yum的用法 一.rpm的用法 rpm原本是Rde Hat Linux发行版专门用来管理Linux各项套件的程序,由于它遵循GPL规则且功能强大方便,因而广受欢迎.逐渐收到其他发行版的采用,RPM套件管理方式的出现,让Linux易于安装.升级,间接提升了Linux的适用性. rpm用法:rpm [OPTION...] 1.rpm安装软件包,后面需要跟上程序包文件的绝对路径或相对路径 常用选项: -v:显示指令的执行过程 -vv:详细显示指令执行过程,便于排错 -h:以#号显示程

学习笔记之Linux程序包管理rpm、yum、编译

无论是Windows系统还是Linux系统,我们用户想要在操作系统上获得更多的乐趣还是更多的功能的话,就需要在一个干净的系统上安装各式各样的软件程序,Linux上的是ELF格式的,目前比较常见的程序包管理器如: Redhat软件包管理器---rpm Debian软件包管理器---dpkg 一.1.RPM 安装:rpm {-i|--install} [install-options] PACKAGE_FILE... -v: verbose,详细信息 -vv: 更详细的输出 -h: hashmark

Linux之Redhat系列程序包管理

安装.升级和卸载应用软件是每个系统不可或缺的一部分:对于在企业使用越来越广泛的Linux操作系统而言,强大而简洁的程序包管理机制为工程师们带来了很大的便利:下文主要介绍在RedHat系列的系统上如何使用RPM/YUM/编译三种方式去管理程序包. 一.RPM程序包管理 PRM全称是Red Hat Package Manager(RedHat 包管理器).Linux RPM软件包的命名有一定的规律:名称-版本-修正版-类型.rpm 例如: RPM命令详解: 功能: 安装.卸载.升级.查询和数据库维护

windows安装python包管理工具pip

windows安装python包管理工具pip     pip 是一个Python包管理工具,主要是用于安装 PyPI 上的软件包,可以替代 easy_install 工具. 一.前期准备 首先确认windows机器上面是否已经安装好了python.在cmd中输入python --version和python看看是否有反应 如上面所示,表示已经在windows平台上面搭建好了python环境. 二.下载安装 1.到官网去https://pypi.python.org/pypi/pip#downl

Yocto tips (15): Yocto中的包管理器

使用包管理器 在local.conf中使能就可以: 然后编译后就会有rpm包了: 配置文件server 能够使用ngix和apache.可是我们也能够仅仅用使用python: python -m SimpleHTTPServer 打开浏览器能够看到: 在机器上面查看包的status smart status 在机器上面配置channel 对于rpm使用的smart工具,加入channel: smart channel --add all type=rpm-md baseurl=http://19

CentOS程序包管理器之rpm前端管理器

CentOS的程序包管理器: 首先,我们要来了解一下程序包(源代码包)的命名规则: software_name-VERSION.tar.gz VERSION:major.minor.release major:主版本号,通常代表重大功能改进的版本分支: minor:次版本号,通常代表在某个版本的分支中的某个功能发生变化: release:发行版本号,修复了某些bug或者对某段代码进行了优化: 例如:apache-tomcat-7.0.63.tar.gz 而rpm程序包命名规则为: 源码包:sou