在 Linux 环境(尤其是 RHEL/CentOS/Fedora 等 RPM 系发行版)中,安装软件时常常面临选择:使用 SRPM(源 RPM 包)构建并安装,还是直接 ./configure && make && make install 从源码编译。

1. 基础概念
- SRPM(Source RPM)以
.src.rpm结尾的包,包含上游源码压缩包、补丁文件以及一个 .spec规范文件。可通过rpmbuild命令重建为二进制 RPM 包,再通过rpm或yum/dnf安装。它是 RPM 包管理体系中的“源码环节”。 - 从源码编译(直接编译)通常指手动下载
tar.gz源码,执行 ./configure(或cmake、meson等)、make、make install将文件直接复制到系统目录(如/usr/local)的过程。这种方式完全脱离包管理器。
2. 多维度对比
| 依赖管理 | spec 声明,dnf builddep 可自动安装。运行依赖在安装二进制包时由 RPM 自动解析。 | -devel 包。无自动运行依赖检查,容易出现缺库。 |
| 软件清单与可追溯性 | rpm -ql、rpm -qf 可精确查询。 | |
| 卸载与升级 | rpm -ednf remove 干净卸载。dnf update 可平滑升级到新版本或安全更新。 | make uninstall,或卸载不彻底。升级需要手动覆盖,极易残留旧文件,导致“文件污染”。 |
| 构建环境纯净度 | mock/koji 在干净 chroot 环境中构建,彻底避免宿主机“依赖泄漏”(即不小心依赖了未声明的库)。 | |
| 权限与安全 | rpmbuild 打包(安装时需 root)。包签名(GPG)可防篡改。 | make install |
| 定制化能力 | .spec 文件(增减补丁、改变编译选项、拆分子包)实现深度定制,且定制过程可版本控制、可重现。 | ./configure 参数直接定制,速度快,适合一次性测试,但操作不易复现和传承。 |
| 分发与部署 | .rpm 是标准交付物。可放入 Yum/DNF 仓库,批量部署到数百台服务器,享受增量更新、依赖自动解决。 | |
| 学习曲线与成本 | .spec 有一定学习成本,需要理解宏、分段(%prep, %build, %install, %files)等。 | |
| 标准合规性(FHS/LSB) | /usr),符合文件系统层级标准,能被其他工具正确找到。 | prefix=/usr/local 符合标准,但随意指定 prefix 可能导致 PATH、man、pkg-config 等路径混乱。 |
3. 最佳实践:何时用哪种方式
✅ 优先使用 SRPM(构建成 RPM 后安装)的场景
- 生产环境部署必须保证系统可维护、可审计、可平滑升级。RPM 数据库是所有运维自动化的基石。
- 需要在多台机器上重现安装构建一次 RPM,放入私有仓库,所有节点通过
dnf install统一安装,保证一致性。 - 需要定制软件,且希望定制内容可追溯拿到上游 SRPM,修改
spec添加补丁或编译选项,用 mock重建,生成的 RPM 可直接纳入版本管理。 - 系统关键组件或库避免
make install覆盖包管理器文件,防止“DLL 地狱”或文件冲突。 - 团队协作
.spec文件、补丁和 SRPM 是可共享的标准化“配方”,新人也能快速复现构建。
✅ 可以直接从源码编译的场景
- 快速尝鲜/开发调试只想临时运行一个工具的最新版,使用
./configure --prefix=$HOME/local安装到用户家目录,用完即删。 - SRPM 不可用或太旧,且仅需个人使用源码包只提供 tarball,没有现成 spec。可快速
make install到 /opt或/usr/local并做好文档记录。 - 开发过程中频繁修改源码直接在源码树中编译运行,无需反复打包。
- 容器镜像构建(低约束场景)某些极简容器内,为了减小尺寸,可能直接编译安装,但即使如此,也建议先用多阶段构建生成 RPM 再拷贝,或使用
checkinstall生成临时包。
4. 混合与过渡的最佳实践
如果必须经常从源码安装,但希望保留包管理的好处,可以遵循以下“温和改进”路线:
做法一:使用 checkinstall 快速生成简陋的 RPM/DEB
./configure --prefix=/usr/localmakesudo checkinstall -R # 自动监控 make install,生成 .rpm 并安装- 优点: 能记录文件清单,可卸载。
- 缺点: 不处理依赖,路径可能不符合发行版规范,不适合正式分发。
做法二:把常用编译动作“spec化”
即使不上传仓库,也可为自己常用的软件编写最小 spec,通过 rpmbuild -ba 生成包再安装。重复几次后就会发现,前期投入的学习成本远低于后期维护“手动编译孤儿文件”的成本。
做法三:始终使用隔离前缀或 stow(临时方案)
./configure --prefix=/usr/local/stow/myapp-1.0make && sudo make installcd /usr/local/stowsudo stow myapp-1.0 # 管理符号链接便于同时保留多版本,卸载只需删除目录和 stow 链接。但仍无法处理依赖。
5. 构建 SRPM 的标准化工作流(推荐)
如果你决定拥抱 SRPM 路线,推荐以下流程:
获取 SRPM
dnf download --source <package-name># 或从发行版 Git 仓库(如 CentOS Stream、Fedora)克隆,包含 spec 和补丁安装构建依赖
sudo dnf builddep <package-name>.src.rpm解包并定制(可选)
rpm2cpio <package-name>.src.rpm | cpio -idmv # 提取 spec 和源码# 或用 rpmbuild -rp 等标准方法修改 spec 文件:改版本、加补丁、调编译参数。
在干净环境中构建(强烈建议)
mock --rebuild <modified-package>.src.rpm # 自动创建 chroot,解决依赖,产出 RPM或使用
rpmbuild直接在本地构建(需小心环境泄漏)。- 安装并验证,将成品 RPM 推送到私有仓库。
6. 总结:
| 一切纳入 RPM 管理 | |
$HOME/local 或 /tmp,快速验证,不污染系统。 | |
make install。 | |
./configure --prefix=/opt。 |
核心理念:直接 make install 是一种即时满足但长期负债的操作。SRPM 让你对软件构建和部署过程拥有声明式、可重现、可分发的控制力。只要系统上运行着包管理器,就应尽力将所有软件纳入其管辖范围,而 SRPM 正是实现这一目标的桥梁。
夜雨聆风