一、安装和构建项目
$ yum install -y rpm-build rpmdevtools
$ rpmdev-setuptree
$ tree rpmbuild/
rpmbuild/
├── BUILD 源码解压并编译的临时目录
├── BUILDROOT 最终安装目录,保存 %install 阶段安装的文件
├── RPMS 最终生成二进制 RPM 安装包
├── SOURCES 所有源码包(.tar.gz)及需要的补丁文件
├── SPECS 配置文件,定义 rpmbuild 在构建时的所有操作
└── SRPMS 最终生成的源码rpm包
二、spec 说明
宏 |
名称 |
默认位置 |
用途 |
%{_specdir} |
Spec 文件目录 |
~/rpmbuild/SPECS |
保存 RPM 包配置(.spec)文件 |
%{_sourcedir} |
源代码目录 |
~/rpmbuild/SOURCES |
保存源码包(如 .tar 包)和所有 patch 补丁 |
%{_builddir} |
构建目录 |
~/rpmbuild/BUILD |
源码包被解压至此,并在该目录的子目录完成编译 |
%{_buildrootdir} |
最终安装目录 |
~/rpmbuild/BUILDROOT |
保存 %install 阶段安装的文件 |
%{_rpmdir} |
标准 RPM 包目录 |
~/rpmbuild/RPMS |
生成/保存二进制 RPM 包 |
%{_srcrpmdir} |
源代码 RPM 包目录 |
~/rpmbuild/SRPMS |
生成/保存源码 RPM 包(SRPM) |
名称 |
宏 |
说明 |
Name |
%{name} |
软件包名,与spec的文件名保持相同。 |
Version |
%{version} |
版本号 |
Release |
%{release} |
发行编号,初始值为 1%{?dist},后期制作新版本时,递增该值。若Version发布新版本,该值重新设置为1。 |
Summary |
|
软件包介绍(简洁)。 |
License |
|
软件授权协议。 |
URL |
|
该软件包的项目主页 |
Sources |
%{source} |
源码包名称,若有多个源码包,增加标签Sources1、Sources2... |
BuildRequires |
|
编译软件包所需的依赖包列表,以逗号分隔 |
Requires |
|
安装软件包时所需的依赖包列表,以逗号分隔 |
宏 |
对应目录 |
说明 |
%{_bindir} |
/usr/bin |
二进制目录:保存可执行文件 |
%{_builddir} |
~/rpmbuild/BUILD |
构建目录:软件在 build 的子目录被编译。参考 %buildsubdir |
%{buildroot} |
~/rpmbuild/BUILDROOT |
Build root:%install 阶段中,将 %{_builddir} 子目录下的文件复制到 %{buildroot} 的子目录(之前,%{buildroot} 使用的位置为 "/var/tmp/") |
%{buildsubdir} |
%{_builddir}/%{name} |
构建子目录:%build 阶段中,文件会在 %{_builddir} 的子目录中编译。此宏在 %autosetup 之后设置 |
%{_datadir} |
/usr/share |
共享数据目录 |
%{_defaultdocdir} |
/usr/share/doc |
默认文档目录 |
%{dist} |
.fcNUMBER |
发行版名称+版本号(例如 ".fc33") |
%{fedora} |
NUMBER |
Fedora 发行版本号(例如 "33") |
%{_includedir} |
/usr/include |
程序头文件目录 |
%{_infodir} |
/usr/share/info info |
手册目录 |
%{_initrddir} |
/etc/rc.d/init.d |
init 脚本目录 |
%{_libdir} |
/usr/lib |
共享库目录 |
%{_libexecdir} |
/usr/libexec |
仅由系统调用执行该目录中的命令 |
%{_localstatedir} |
/var |
保存缓存/日志/lock等信息的目录 |
%{_mandir} |
/usr/share/man |
man 手册目录 |
%{name} |
|
软件包名称,通过 Name: tag 设置 |
%{_sbindir} |
/usr/sbin |
保存管理员可执行命令 |
%{_sharedstatedir} |
/var/lib |
保存程序运行所处理的文件 |
%{_sysconfdir} |
/etc |
配置文件目录 |
%{version} |
|
软件包版本,通过 Version: tag 设置 |
阶段 |
说明 |
%prep |
读取位于 %_sourcedir 目录的源代码和 patch 。之后,解压源代码至 %_builddir 的子目录并应用所有 patch。 |
%build |
编译位于 %_builddir 构建目录下的文件。通过执行类似 "./configure && make" 的命令实现。 |
%install |
读取位于 %_builddir 构建目录下的文件并将其安装至 %_buildrootdir 目录。这些文件就是用户安装 RPM 后,最终得到的文件。注意一个奇怪的地方: 最终安装目录 不是 构建目录。通过执行类似 "make install" 的命令实现。 |
%pre |
rpm 安装前执行 |
%post |
rpm 安装完成后执行 |
%preun |
rpm 卸载前执行的脚本 |
%postun |
rpm 卸载后执行的脚本 |
%check |
检查软件是否正常运行。通过执行类似 "make test" 的命令实现。很多软件包都不需要此步。 |
%files |
表示为所有要被打包的文件清单 |
宏 |
说明 |
%doc |
文档 |
%config |
配置文件 |
%attr |
文件属性,包括许可、用户和用户组 |
%defattr |
文件默认属性分别(文件权限,属主,属组,目录权限) 例如 %defattr (-,root,root,-) : - 表示默认值,由umask决定,通常对文本文件是0644,可执行文件是0755 |
%ghost |
文件包含在包中,但不进行安装 |
%verify |
验证文件的各种属性以保证完整性 |
三、打包命令 rpmbuild
参数 |
说明 |
-bp |
只作准备 (解压与打补丁) |
-bc |
准备并编译 |
-bi |
编译并安装 |
-bl |
检验文件是否齐全 |
-ba |
编译后做成*.rpm和src.rpm |
-bb |
编译后做成*.rpm |
-bs |
只做成*.src.rpm |
参数 |
说明 |
--buildroot <root> |
构建包时,以值 root 覆盖标签 BuildRoot 的值。 |
--clean |
清除软件包构建目录。 |
--nobuild |
不执行任何构建阶段,用于测试 spec 文件。 |
--noprep |
不执行 %prep 构建阶段。 |
--noclean |
不执行 %clean 构建阶段。 |
--nodebuginfo |
不产生调试信息包。 |
--nodeps |
不验证构建依赖。 |
--rmsource |
构建后移除源码包,也可以单独使用,比如 rpmbuild --rmsource foo.spec。 |
--rmspec |
构建后移除 spec 文件,同 --rmsource。 |
--with <option> |
使能选项 option。 |
--without <option> |
禁止选项 option。 |
--showrc |
显示 rpmbuild 当前使用的所有的宏。 |
四、rpm
常用命令
$ rpm -ivvh 包
$ rpm -qa
$ rpm -q 包名
$ rpm -e 包名
$ rpm -qR 包名
五、示例 将 Python 打包成 rpm
1. 打包 python 为可执行脚本
使用 PyInstaller 工具
注意:打包不同操作系统的可执行文件,需要到对应的操作系统中进行打包
# 安装
$ pip install PyInstaller
# 打包
$ Python -m PyInstaller -F test.py
$ cd disk
$ ls
test 打包后的可执行程序
2. 打包 rpm
创建 rpm 工作目录
$ rpmdev-setuptree
$ cd SPECS
$ vim test.spec
test.spec
Name: test
Version: 1.0
Release: 0%{?dist}
Summary: Configure the kvm environment and install pylon and drone
License: GPLv3+
URL: http://www.cetccloud.com
Source0: test-1.0.tar.gz
BuildRequires: gettext
# 在 %post 中执行命令时使用 bash
Requires(post): bash
%description
描述
%prep
# 主要作用是解压 %{source} 指定的源码包
# 参数
# -n <dir> 指定自动进入目录名称。用于当源码解压后目录名不规范。
# -c 解压之前先创建默认目录,用于压缩文件未包含在一个顶层目录下。
# -q 抑制输出,可以减少日志的输出。
# -D 解压前不删除目录。
# -T 不执行默认解压动作。
# -b <num> 切换目录前,解压 %{source<num>} 指定的包。
# -a <num> 切换目录后,解压 %{source<num>} 指定的包。
%setup -c n test
# 编译源码包
%build
echo "aaaaaaaa"
# 在构建rpm包时执行。注意这个不会再安装rpm包时执行
%install
# 在根据路创建保存脚本的目录
mkdir -p %{buildroot}/pytest/
# 将可执行文件放入到创建的目录中
install %{name}-%{version}/test %{buildroot}/pytest/test1.0
# rpm 包安装完成后执行
%post
# 执行python可执行文件
/pytest/test1.0
# 为所有要被打包的文件清单
%files
# 文档
%doc
/pytest/install_rpm/*
/pytest/test1.0
%changelog
* Thu Dec 23 2021 Ma Chao <machao_ma@qq.com> - 1.0
- asdf
3. 打包 rpm
$ rpmbuild -bb SPEC/test.spec
4. 安装 rpm
$ rpm -ivvh test-1.0-0.rpm