一、认识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内容修改:
进入SPECS目录:
cd ~/rpmbuild/SPECS生成模板:
rpmdev-newspec protobuf.spec,此时会生成一个空白的protobuf.spec模板文件;替换模板内容:将用户提供的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版本
- 执行打包:
rpmbuild -bb protobuf.spec
命令说明:
- 选择
-bb选项是因为日常部署仅需二进制包,可减少构建时间和产物体积,如果还需要生成SRPM包,可使用-ba; - 执行过程中,rpmbuild会自动解析SPEC文件,依次执行%prep(解压源代码)、%build(编译构建)、%install(安装到临时目录)、%files(整理文件到RPM包)等步骤。
校验RPM包:
cd ~/rpmbuild/RPMS/x86_64/ && rpmlint protobuf-*.rpm安装测试(可选):
sudo dnf install -y protobuf-libs-33.2-1.el9.x86_64.rpm protobuf-devel-33.2-1.el9.x86_64.rpm,安装完成后执行protoc --version验证。