rpm打包实战之Rocky Linux 9下打包protobuff

简介: 本教程介绍在Rocky Linux下使用RPM打包Protobuf的完整流程,涵盖rpmdevtools环境搭建、SPEC文件编写、rpmbuild构建及rpmlint规范检查,实现软件包的标准化制作与质量管控。

一、认识RPM与打包工具

RPM(Red-Hat Package Manager)是红帽系Linux发行版的软件包管理机制,Rocky Linux作为红帽系兼容发行版,完全继承了RPM的包管理体系。通过RPM打包,可将软件的安装、配置、卸载流程标准化,大幅提升软件在Rocky Linux环境下的部署效率与兼容性。

本教程核心用到的打包工具如下:

  • rpmbuild:核心打包工具,负责解析SPEC文件、执行构建流程、生成RPM包;

  • rpmdevtools:打包辅助工具集,包含rpmdev-setuptree(创建标准打包目录)、rpmdev-newspec(生成SPEC模板)等实用命令;

  • rpmlint:RPM包检查工具,用于检测打包过程中出现的规范问题(如文件路径错误、依赖缺失等),保障RPM包质量。

二、搭建打包环境

Rocky Linux 9及以上版本默认使用dnf作为包管理器,以下步骤均基于dnf命令完成环境搭建,无需适配其他包管理工具。

(一)安装基础RPM工具

Rocky Linux 9及以上可能已预装部分基础RPM工具,执行以下命令确保完整安装:


dnf install rpmdevtools rpm-build rpmlint -y

验证安装:

  • 执行rpmbuild --version,若输出版本信息则说明安装成功。
  • 执行rpmdev-setuptree --help,若输出帮助信息则rpmdevtools安装成功;
  • 执行rpmlint --version,若输出版本信息则rpmlint安装成功。

(二)安装Protobuf打包依赖包

根据Protobuf的SPEC文件要求,需安装gcc-c++、cmake等构建依赖。在Rocky Linux 9及以上环境中,直接执行以下命令一键安装(如已安装请略过):


sudo dnf install -y gcc-c++ cmake make autoconf libtool pkgconfig

说明:abseil-devel在Rocky Linux 9的官方源中已收录,但版本太低,可下载20250127.1版打成rpm包或者编译protobuff时会自行下载并编译。

三、rpmdevtools工具使用

(一)用rpmdev-setuptree创建标准打包目录

RPM打包需要遵循固定的目录结构,手动创建繁琐,通过rpmdev-setuptree可一键生成标准结构:


rpmdev-setuptree

执行完成后,会在当前用户家目录下生成rpmbuild目录,其内部结构及作用如下:

  • ~/rpmbuild/SOURCES/:存放软件源代码包(.tar.gz等)、补丁文件等;

  • ~/rpmbuild/SPECS/:存放SPEC文件(打包核心配置文件);

  • ~/rpmbuild/BUILD/:打包过程中的临时构建目录;

  • ~/rpmbuild/RPMS/:存放最终生成的二进制RPM包(会按架构分目录,如x86_64);

  • ~/rpmbuild/SRPMS/:存放生成的源代码RPM包(.src.rpm)。

(二)用rpmdev-newspec生成SPEC模板并适配Protobuf

SPEC文件是打包的核心,包含软件信息、构建步骤、安装规则等配置。先通过rpmdev-newspec生成基础模板,再基于提供的Protobuf SPEC内容修改:

  1. 进入SPECS目录:cd ~/rpmbuild/SPECS

  2. 生成模板:rpmdev-newspec protobuf.spec,此时会生成一个空白的protobuf.spec模板文件;

  3. 替换模板内容:将用户提供的Protobuf SPEC文件内容完整复制到protobuf.spec中,覆盖原有模板内容。

Protobuf SPEC文件关键字段说明(适配Rocky Linux 9+):

  • Version: 33.2(软件版本,需与源代码包版本一致);

  • Release: 1%{?dist}(发布版本,%{?dist}会自动适配Rocky Linux的发行标识,如el9);

  • BuildRequires: 列出的依赖包均为Rocky Linux 9+官方源可直接安装的包;

  • %install段:指定安装路径为/usr和/usr/lib64,符合Rocky Linux 64位系统的库文件存放规范。

四、rpmbuild工具详解

rpmbuild的基本使用语法为:
rpmbuild [选项] SPEC文件路径

以下是rpmbuild最常用的选项参数:

选项参数 功能说明(翻译+补充) 使用示例 说明
-bb 英文原文:Build binary packages only.(仅构建二进制RPM包)补充:不生成源代码包(.src.rpm),仅输出可直接安装的二进制包,适合日常部署场景。 rpmbuild -bb protobuf.spec 最常用选项,构建结果默认存放在~/rpmbuild/RPMS/x86_64/目录(64位系统)
-bs 英文原文:Build source package only.(仅构建源代码RPM包)补充:生成的.src.rpm包包含源代码和SPEC文件,可用于二次编译或分发打包配置。 rpmbuild -bs protobuf.spec 结果存放在~/rpmbuild/SRPMS/目录,适合需要共享打包流程的场景
-ba 英文原文:Build both binary and source packages.(同时构建二进制包和源代码包)补充:一次执行生成两种类型的包,兼顾部署和分发需求。 rpmbuild -ba protobuf.spec 需确保源代码包和二进制包的依赖均满足,否则构建失败
-bp 英文原文:Prepare source for building (unpack and apply patches).(仅执行预处理步骤,解压源码并应用补丁)补充:不进行后续编译和安装,仅完成%prep段定义的操作,用于调试预处理流程。 rpmbuild -bp protobuf.spec 预处理后的源码存放在~/rpmbuild/BUILD/目录,可进入该目录检查源码是否正确解压
-bc 英文原文:Build (compile) the sources.(执行预处理和编译步骤)补充:完成%prep和%build段操作,不执行安装(%install),用于调试编译过程中的错误。 rpmbuild -bc protobuf.spec 编译产物存放在~/rpmbuild/BUILD/下的对应源码目录,适合排查编译依赖缺失问题
-bi 英文原文:Build and install the sources into the build root.(执行预处理、编译、安装步骤)补充:完成%prep、%build、%install段操作,将产物安装到临时构建目录(%{buildroot}),不生成最终RPM包,用于调试安装配置。 rpmbuild -bi protobuf.spec 临时安装目录为~/rpmbuild/BUILDROOT/,可检查文件安装路径是否符合预期
--nodeps 英文原文:Ignore build dependencies.(忽略构建依赖检查)补充:强制跳过BuildRequires字段定义的依赖检查,仅在确认依赖已手动安装但rpmbuild未识别时使用。 rpmbuild -bb --nodeps protobuf.spec 谨慎使用!Rocky Linux 9+中依赖管理严格,忽略依赖可能导致编译失败
--define 英文原文:Define an RPM macro.(定义RPM宏)补充:可临时覆盖SPEC文件中的宏定义(如版本号、安装路径等),灵活适配不同构建场景。 rpmbuild -bb --define "version 33.2" protobuf.spec 适合临时测试不同版本或不同安装路径的构建需求,无需修改SPEC文件

五、rpmlint工具使用

rpmlint可检查生成的RPM包是否符合红帽系(含Rocky Linux)的打包规范,避免因包结构问题导致安装失败或运行异常。

(一)检查生成的Protobuf RPM包

进入RPM包所在目录,执行rpmlint检查:


cd ~/rpmbuild/RPMS/x86_64/
rpmlint protobuf-*.rpm

(二)检查结果解读与修复

rpmlint的输出信息分为不同级别(警告W、错误E),常见问题及修复方法:

  • 警告“unused-direct-shlib-dependency”:可忽略,部分动态库依赖为正常现象;

  • 错误“file-not-in-%_datadir”:若存在文件路径错误,需修改SPEC文件的%files段,确保文件路径符合Rocky Linux规范(如库文件放/usr/lib64,头文件放/usr/include);

  • 错误“missing-dependency”:若提示依赖缺失,需检查SPEC文件的Requires或BuildRequires字段,补充对应的依赖包名称(Rocky Linux 9+中依赖包名称可通过dnf search 依赖关键词查询)。

(三)rpmlint配置

默认配置已适配Rocky Linux 9+,若需自定义检查规则,可修改/etc/rpmlint/config文件,例如添加忽略特定警告的配置:


echo "addFilter('unused-direct-shlib-dependency')" | sudo tee -a /etc/rpmlint/config

六、完整实战


# 软件基础信息定义
Name:           protobuf  # 软件名称,需与包名保持一致,Rocky Linux中需符合命名规范(字母、数字、连字符)
Version:        33.2      # 软件版本号,必须与源代码包版本(v33.2)完全匹配
Release:        1%{?dist} # 发布版本号,1为首次发布;%{?dist}是RPM宏,自动填充Rocky Linux发行标识(如el9)
Summary:        Protocol Buffers - Google's data interchange format  # 软件简短描述
License:        BSD       # 软件许可证类型,Protobuf使用BSD许可证,需与源代码LICENSE文件一致
URL:            https://github.com/protocolbuffers/protobuf  # 软件官方地址,便于用户溯源
Source0:        https://github.com/protocolbuffers/protobuf/archive/refs/tags/v33.2.tar.gz  # 源代码包URL,rpmbuild会自动从该地址下载(也可手动放入SOURCES目录)

# 构建依赖定义:打包过程中需要的编译工具、库文件等,Rocky Linux 9+可通过dnf直接安装
BuildRequires:  gcc-c++ cmake make autoconf libtool abseil-devel

# 运行依赖定义:软件安装后运行所需的依赖包,此处指定与主包同版本的libs子包
Requires:       %{name}-libs = %{version}-%{release}

# 主包描述:详细说明软件功能
%description
Protocol Buffers are a way of encoding structured data in an efficient
yet extensible format.  # Protobuf核心功能:高效可扩展的结构化数据编码格式

# 定义libs子包:用于存放运行时依赖的共享库,独立分包便于其他软件依赖
%package libs
Summary:        Libraries for %{name}  # libs子包描述:Protobuf的运行时库文件
# 无需额外指定Requires,继承主包基础依赖

%description libs
Libraries for %{name}.  # 明确子包内容:包含Protobuf运行所需的各类共享库

# 定义devel子包:用于存放开发相关文件(头文件、静态库、pkgconfig配置等),供其他软件编译依赖
%package devel
Summary:        Development files for %{name}  # devel子包描述:Protobuf的开发文件
Requires:       %{name}-libs = %{version}-%{release}  # 开发包依赖同版本的libs包,确保编译与运行库版本一致

%description devel
Development files for %{name}.  # 明确子包内容:包含头文件、编译配置等开发必需文件

# 全局宏定义:禁用调试包生成(调试包通常命名为xxx-debuginfo,本场景无需生成,减少包体积)
%global debug_package %{nil}

# 预处理阶段:解压源代码、应用补丁等操作
%prep
# autosetup是RPM宏,自动解压Source0指定的源代码包,-n指定解压后的目录名为protobuf-33.2(%{name}-%{version})
%autosetup -n %{name}-%{version}

# 构建阶段:编译源代码生成可执行文件和库文件
%build
# 创建构建目录(避免源码目录混乱)并进入
mkdir -p build && cd build
# cmake配置
cmake .. \
  -DCMAKE_INSTALL_PREFIX=/usr \          # 指定安装根目录为/usr(Rocky Linux标准安装路径)
  -DCMAKE_INSTALL_LIBDIR=/usr/lib64 \    # 指定库文件安装目录为/usr/lib64(Rocky Linux 64位系统标准库路径)
  -Dprotobuf_BUILD_TESTS=OFF \           # 禁用测试编译(加快打包速度,生产环境无需测试代码)
  -DCMAKE_VERBOSE_MAKEFILE=ON \          # 开启makefile详细输出(便于调试打包错误)
  -DCMAKE_LINK_VERBOSE=ON \              # 开启链接过程详细输出(便于排查链接错误)
  -DCMAKE_POSITION_INDEPENDENT_CODE=ON \ # 生成位置无关代码(共享库必需)
  -DBUILD_SHARED_LIBS=ON                 # 构建共享库(生成.so文件,而非静态库.a,减少内存占用)
# 执行编译:VERBOSE=1输出详细编译信息;%{?_smp_mflags}自动适配CPU核心数并行编译(Rocky Linux多核优化)
VERBOSE=1 make %{?_smp_mflags}

# 安装阶段:将编译产物安装到临时目录(%{buildroot}),后续会打包该目录下的文件
%install
cd build
# 执行安装,DESTDIR指定临时安装根目录(避免直接安装到系统目录,污染系统环境)
make install DESTDIR=%{buildroot}

# libs子包文件清单:明确该子包包含的文件,仅列出运行时必需的共享库
%files libs
/usr/lib64/libprotobuf.so.*        # Protobuf核心共享库(版本化命名,如libprotobuf.so.33.2.0)
/usr/lib64/libprotobuf-lite.so.*   # 轻量版Protobuf共享库(版本化)
/usr/lib64/libprotoc.so.*          # Protobuf编译器共享库(版本化)
/usr/lib64/libprotobuf.so          # 共享库软链接(指向最新版本,便于用户直接引用)
/usr/lib64/libprotobuf-lite.so     # 轻量版共享库软链接
/usr/lib64/libprotoc.so            # 编译器共享库软链接
/usr/lib64/libutf8_range.so        # UTF8范围处理共享库(Protobuf依赖)
/usr/lib64/libutf8_range.so.33.2.0 # UTF8范围处理共享库(版本化)
/usr/lib64/libutf8_validity.so     # UTF8有效性校验共享库(Protobuf依赖)
/usr/lib64/libutf8_validity.so.33.2.0 # UTF8有效性校验共享库(版本化)

# devel子包文件清单:明确该子包包含的开发文件
%files devel
/usr/include/google/protobuf/       # Protobuf核心头文件目录
/usr/include/upb/*                 # upb相关头文件(Protobuf依赖的轻量级解析库)
/usr/include/utf8_range.h          # UTF8范围处理头文件
/usr/include/utf8_validity.h       # UTF8有效性校验头文件
/usr/lib64/pkgconfig/protobuf.pc    # pkgconfig配置文件(便于其他软件通过pkg-config查找依赖)
/usr/lib64/pkgconfig/protobuf-lite.pc # 轻量版pkgconfig配置文件
/usr/lib64/cmake/protobuf/*        # CMake配置文件(支持CMake项目依赖Protobuf)
/usr/lib64/cmake/utf8_range/*      # UTF8范围处理库的CMake配置文件
/usr/bin/protoc*                   # Protobuf编译器(protoc),开发时需用其编译.proto文件
/usr/lib64/libupb.a                # upb静态库(开发时链接使用)
/usr/lib64/pkgconfig/upb.pc        # upb的pkgconfig配置文件
/usr/lib64/pkgconfig/utf8_range.pc # UTF8范围处理库的pkgconfig配置文件

# 变更日志:记录包的版本更新历史,便于追溯
%changelog
* Tue Dec 30 2025 mickeylan <mickeylan@163.com> - 33.2-1
- Initial package for Protobuf 33.2  # 首次打包Protobuf 33.2版本
  1. 执行打包:rpmbuild -bb protobuf.spec

命令说明:

  • 选择-bb选项是因为日常部署仅需二进制包,可减少构建时间和产物体积,如果还需要生成SRPM包,可使用-ba;
  • 执行过程中,rpmbuild会自动解析SPEC文件,依次执行%prep(解压源代码)、%build(编译构建)、%install(安装到临时目录)、%files(整理文件到RPM包)等步骤。
  1. 校验RPM包:cd ~/rpmbuild/RPMS/x86_64/ && rpmlint protobuf-*.rpm

  2. 安装测试(可选):sudo dnf install -y protobuf-libs-33.2-1.el9.x86_64.rpm protobuf-devel-33.2-1.el9.x86_64.rpm,安装完成后执行protoc --version验证。

相关文章
|
9月前
|
应用服务中间件 Linux Shell
RPM 打包 spec 文件全解析
本文系统讲解RPM打包核心——.spec文件的编写,涵盖软件标识、依赖管理、构建流程、文件配置及条件判断等关键内容,结合Bear、gRPC等实战场景,深入解析多架构与多发行版适配技巧,助力掌握自动化打包技能。
|
jenkins 持续交付
解决Sonarqube quality gate获取不到Sonarqube正确扫描结果的问题
在Jenkins pipeline中,一般都会用到Sonar-scanner来扫描代码,扫描完之后,把结果上传到SonarQube中,SonarQube把结果与质量阀进行对比,然后通过Sonarqube quality gate来判断这次扫描结果是成功还是失败。 不少同学都遇到过Sonarqube quality gate 获得的最后结果不正确,明明SonarQube中的结果是success,而Sonarqube quality gate判断的结果是pending。 这是怎么一回事呢?
3591 0
解决Sonarqube quality gate获取不到Sonarqube正确扫描结果的问题
|
缓存 开发者 CDN
CDN 刷新功能| 学习笔记
快速学习 CDN 刷新功能。
|
9月前
【麒麟Kylin】cmake-3.16.5 rpm包安装步骤详解 附常见问题
本文介绍在麒麟系统上安装CMake 3.16.5的完整步骤:从下载RPM安装包、确认文件位置,到使用终端通过rpm或yum命令安装,并验证版本。适用于初学者快速部署CMake环境。(238字符)
1188 2
|
存储 网络协议 Java
为什么王者荣耀、原神等游戏不使用微服务架构?
王者荣耀、原神作为家喻户晓的手游,能够支撑这么多人同时在线,其底层的架构自然令我们好奇,出乎意料的是,它并没有采用目前炙手可热的微服务架构,到底为什么会这样呢?本文结合知乎问答内容:https://www.zhihu.com/question/359630395撰写,本人其实也是个游戏迷,这次也是想深扒一下其底层的架构设计。
|
运维 安全 关系型数据库
​​国内 5 个最佳的控制面板,可轻松管理服务器
在当今数字化飞速发展的时代,Linux 服务器作为众多企业和开发者的核心基础设施,其管理的高效性和专业性成为了保障业务稳定运行的关键因素。对于专业的服务器运维人员和开发团队而言,理解这些面板的细节差异至关重要。这不仅关乎服务器管理的效率,更涉及到系统的稳定性、安全性以及对开源应用生态的适应性。期望本次全面的盘点能为您的 Linux 服务器管理策略提供坚实的理论依据和实践指导,确保服务器管理工作在技术迭代和业务发展的浪潮中保持高效、稳定且安全的运行状态。
​​国内 5 个最佳的控制面板,可轻松管理服务器
|
Ubuntu 网络安全 数据安全/隐私保护
搭建edk2编译环境
搭建edk2编译环境
1211 0
搭建edk2编译环境
|
Linux 调度 数据库
Django使用django-apscheduler实现定时任务
【7月更文挑战第8天】定时任务可以在后台定时执行指定的代码,避免了很多人为操作。下面是在Django项目中如何使用定时任务的具体操作流程
1543 1
|
人工智能 决策智能
【AI Agent系列】【阿里AgentScope框架】3. 深入源码:Pipeline模块如何组织多智能体间的数据流?- 顺序结构与条件分支
【AI Agent系列】【阿里AgentScope框架】3. 深入源码:Pipeline模块如何组织多智能体间的数据流?- 顺序结构与条件分支
742 2

热门文章

最新文章