How to write SPEC file
How to write SPEC file
如果说《SPEC 基础知识》解决“能打包”,这一篇解决的是“如何把 SPEC 写得可维护、可扩展、可发布”。
1. 先建立一个正确心智模型
打包过程可以拆成三层:
- 上游构建系统(
configure/Makefile)决定“会生成哪些文件”。 - SPEC 的
%install决定“这些文件安装到%{buildroot}的哪个路径”。 - SPEC 的
%files决定“最终哪些文件进入哪个 RPM 包”。
核心结论:SPEC 不负责创造文件,只负责组织和选择文件。
2. 从 Makefile 安装路径到 %files 的映射
假设上游项目里有:
1 | scriptdir = $(libexecdir)/mydaemon/scripts |
执行 make install DESTDIR=%{buildroot} 后,文件会进入:
1 | %{buildroot}%{_libexecdir}/mydaemon/scripts/ |
在 SPEC 中就应该声明:
1 | %files |
这就是“构建产物 -> 安装路径 -> 打包清单”的完整闭环。
3. 单包与多子包(%package)
默认一个 SPEC 生成一个主包。
当你需要拆分能力(例如主程序、sudo 规则、systemd 集成)时,使用子包:
1 | %package sudoers |
实践建议:
- 把“可选能力”拆成子包,避免主包依赖过重。
- 把“运行时配置”与“核心二进制”分开,升级更稳。
4. BuildRequires 与 Requires 的边界
BuildRequires:构建机需要(编译器、pkgconfig、devel 包)。Requires:用户安装后运行需要。
常见写法:
1 | BuildRequires: gcc, make, pkgconfig(systemd) |
注意 %{?_isa}:让依赖和架构绑定,更适合多架构场景。
5. systemd 脚本建议用官方宏
不要手写复杂脚本,优先用宏(可读性高、行为一致)。
1 | %post |
验证方法:
1 | rpm --scripts -qp mydaemon.rpm |
你会看到宏展开后的实际 shell 脚本。
6. %files 精细控制:配置文件与权限
6.1. 配置文件策略
%config:升级时可能覆盖并保留旧配置为.rpmsave。%config(noreplace):尽量保留用户改动,新配置写成.rpmnew。
一般建议:业务配置用 %config(noreplace),减少升级时覆盖风险。
6.2. 权限与归属
1 | %files |
7. 循环依赖怎么拆
原文提到的典型问题:A 依赖 B,B 又依赖 A。
这种场景不要硬写依赖,应该拆层:
core:核心能力,不依赖对方。integration/plugin:集成层,依赖 core + 对端。
示例:
mydaemon-core:只放 daemon 核心。api-gateway-core:只放 gateway 核心。mydaemon-api-integration:依赖前两者。
这样可以打破循环依赖并保持安装顺序可解。
8. 利用 .pc 暴露能力给其他包
如果你要给其他模块提供“编译期发现能力”,建议提供 pkg-config 文件:
1 | prefix=/usr |
其他包就可以写:
1 | BuildRequires: pkgconfig(mydaemonplugin) |
优势是:路径变化时,依赖方不需要硬编码路径。
9. 架构与调试包控制
1 | ExcludeArch: aarch64 |
说明:
ExcludeArch用于明确不支持的平台。- 关闭 debug 包要谨慎,建议只在确实不需要或上游策略明确时使用。
10. 交付前检查清单
每次发版前建议跑这几步:
1 | # 查看包头 |
另外建议本地安装一次验证:
- 新装(
rpm -ivh) - 升级(
rpm -Uvh) - 卸载(
rpm -e)
重点观察配置文件、systemd 服务、脚本副作用是否符合预期。
11. 我的实战建议
- 先做“最小可用主包”,再拆子包,不要一开始过度设计。
%install与%files对不上,是 SPEC 问题里最常见的根源。- 遇到依赖泥团,优先做“分层拆包”,不要用硬冲突规则互相压制。
- 把检查命令写进 CI(
qpi/qpl/scripts),让问题在合并前暴露。
当你能稳定回答“这个文件为何在这个包里、这个依赖为何是 BuildRequires 而不是 Requires”,SPEC 基本就进入工程化阶段了。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 因受!
评论