这篇文章是 极简 RPM 打包指南 的补充文档。
RPM 在打包时提供了大量的宏。每一个宏都定义了一个标准的系统路径,或者打包时的标准动作。这些宏确定了标准,让打包过程更规范、更容易正确、更容易维护、还能轻易的扩展到不同架构的系统上,避免了编写 shell 脚本时的各种神操作。
不能抄起脚本直接上,这让 RPM 打包的门槛大大提高。
RPM 打包过程中,所有的硬编码的路径都应该改用代表路径的宏,常见的 bash 命令,如果可以,也应该改用提供相同功能的宏。
变量宏
下面的宏都是一些变量,定义了标准路径和一些其他信息。
代表系统路径的宏
下表提供了 spec 文件编写过程中,非常常见的、代表系统路径的宏。它们的定义一般位于
/usr/lib/rpm/platform/x86_64-linux/macros
宏 | 定义 | 注释 |
---|---|---|
%{_sysconfdir} | /etc | |
%{_prefix} | /usr | can be defined to /app for flatpak builds |
%{_exec_prefix} | %{_prefix} | default: /usr |
%{_includedir} | %{_prefix}/include | default: /usr/include |
%{_bindir} | %{_exec_prefix}/bin | default: /usr/bin |
%{_libdir} | %{_exec_prefix}/%{_lib} | default: /usr/%{_lib} |
%{_libexecdir} | %{_exec_prefix}/libexec | default: /usr/libexec |
%{_sbindir} | %{_exec_prefix}/sbin | default: /usr/sbin |
%{_datadir} | %{_datarootdir} | default: /usr/share |
%{_infodir} | %{_datarootdir}/info | default: /usr/share/info |
%{_mandir} | %{_datarootdir}/man | default: /usr/share/man |
%{_docdir} | %{_datadir}/doc | default: /usr/share/doc |
%{_rundir} | /run | |
%{_localstatedir} | /var | |
%{_sharedstatedir} | /var/lib | |
%{_lib} | lib64 | lib on 32bit platforms |
下面的宏则只有在很老的包中才能见到,能不用就不用:
宏 | 定义 | 注释 |
---|---|---|
%{_datarootdir} | %{_prefix}/share | default: /usr/share |
%{_var} | /var | |
%{_tmppath} | %{_var}/tmp | default: /var/tmp |
%{_usr} | /usr | |
%{_usrsrc} | %{_usr}/src | default: /usr/src |
%{_initddir} | %{_sysconfdir}/rc.d/init.d | default: /etc/rc.d/init.d |
%{_initrddir} | %{_initddir} | old misspelling, provided for compatiblity |
代表打包路径的宏
rpmbuild 是 rpm 打包的工具,它工作在一棵标准的目录树上。目录树上的每一个目录都有属于自己的宏,这些宏在编写 spec 文件的%build 和%install 阶段时非常有用。
但是,在标准的打包过程中,只有%{buildroot}才会被经常用到,其他的路径一般都被 RPM 中提供动作的宏封装好了。只有 rpm 的标准打包动作不能满足需求时,你才应该直接在 bash 脚本中使用其他宏。
宏 | 定义 | 注释 |
---|---|---|
%{buildroot} | %{_buildrootdir}/%{name}-%{version}-%{release}.%{_arch} | same as $BUILDROOT |
%{_topdir} | %{getenv:HOME}/rpmbuild | |
%{_builddir} | %{_topdir}/BUILD | |
%{_rpmdir} | %{_topdir}/RPMS | |
%{_sourcedir} | %{_topdir}/SOURCES | |
%{_specdir} | %{_topdir}/SPECS | |
%{_srcrpmdir} | %{_topdir}/SRPMS | |
%{_buildrootdir} | %{_topdir}/BUILDROOT |
代表编译参数的宏
Fedora 系统中所有的二进制程序在打包是都会使用特定的编译参数和链接参数对软件进行加固。这些参数都被 rpm 标准动作封装好了,无需直接使用。但是有些时候,你可能依然需要在 spec 文件中直接调用 gcc,那么你就需要这些编译参数宏了。
这些宏定义在 /usr/lib/rpm/redhat/macros 文件中。
%{optflags} 包含了很多编译参数,比如 CFLAGS, CXXFLAGS, FFLAGS 等等。
我们可以直接查看 %{optflags}的内容:
$ rpm --eval "%{optflags}"
-O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fexceptions -fstack-protector-strong -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection
链接参数则包含在 %{build_ldflags}中,内容如下:
$ rpm -E "%{build_ldflags}"
-Wl,-z,relro -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld
这些资料主要来自 Fedora Packaging Guidelines - RPM Macros。
动作宏
%prep 阶段
宏 | 功能 |
---|---|
%setup | 接收参数,自动解压软件包 |
%patch | 接收参数,自动打补丁 |
%autosetup | 更加自动化的封装 |
%build 阶段
宏 | 功能 |
---|---|
%configure | 自动进行 ./configure 配置 |
%files 阶段
宏 |
功能 |
---|---|
%defattr |
设置文件权限 |
%doc |
指定 README、INSTALL 等文件 |
%attr |
对文件进行更精细的权限控制 |
%config |
指定配置文件,确保升级时不会被覆盖 |
%caps |
用于为文件分配 POSIX capabilities |
%lang |
处理 I18N 文件 |
%find_lang |
处理 I18N 文件,功能更强大 |
它们的具体用法,请参考下面的链接: