RPM Packaging Guide (rpm-packaging-guide.github.io)
Creating RPM packages :: Fedora Docs (fedoraproject.org)
How RPM packages are made: the spec file - Fedora Magazine
需要了解的概念
什么是RPM?
RPM包简单来说也是一个文件,该文件包含系统所需的其他文件和有关这些文件的信息的文件。具体来说,RPM包由包含文件的cpio归档和包含包的元数据的RPM头组成。rpm包管理器使用此元数据确定依赖项、文件安装位置和其他信息。有两种类型的RPM包:
- source RPM (SRPM)
- binary RPM
SRPM 和 binary RPM 拥有相同的文件格式和工具,但是内容不同、目的不同。
SRPM 包含了源码,可选的补丁包,以及SPEC文件。SPEC文件指导如何将源码编译为binary RPM。
Binary RPM 包含了从源码和补丁编译的二进制文件。
一、准备工作
- 安装依赖
yum install gcc rpm-build rpm-devel rpmlint make python bash coreutils diffutils patch rpmdevtools
- 执行命令
rpmdev-setuptree
生成目录框架,默认目录~/rpmbuild/
[root@VM-99-33-centos ~]# tree ~/rpmbuild/
/root/rpmbuild/
|-- BUILD
|-- RPMS
|-- SOURCES
|-- SPECS
`-- SRPMS
5 directories, 0 files
目录 | 用途 | 备注 |
---|---|---|
BUILD | 生成包时,将在此处创建各种%buildroot 目录。可用于编译失败,而日志又没有提供足够的信息的检查。 |
|
RPMS | Binary RPMs will land here in subdirectories of Architecture. For example: noarch and x86_64 | |
SOURCES | Compressed source archives and any patches should go here, this is where the rpmbuild command will look for them. | |
SPECS | SPEC files live here. | |
SRPMS | When the correct arguments are passed to rpmbuild to build a Source RPM instead of a Binary RPM, the Source RPMs (SRPMS) will land in this directory. |
二、创建spec文件
在SPECS目录下执行rpmdev-newspec $specfilename
创建spec文件。可以创建多个spce文件。
[root@VM-99-33-centos rpmbuild]# cd SPECS/
[root@VM-99-33-centos SPECS]# rpmdev-newspec bello
bello.spec created; type minimal, rpm version >= 4.11.
[root@VM-99-33-centos SPECS]# ls
bello.spec
[root@VM-99-33-centos SPECS]# cat bello.spec
Name: bello
Version:
Release: 1%{?dist}
Summary:
License:
URL:
Source0:
BuildRequires:
Requires:
%description
%prep
%setup -q
%build
%configure
make %{?_smp_mflags}
%install
rm -rf $RPM_BUILD_ROOT
%make_install
%files
%doc
%changelog
说明1、preamble-items
SPEC Directive | Definition |
---|---|
Name |
包名,与SPEC文件名匹配。 |
Version |
软件的上游版本号。 |
Release |
初始值通常是 1%{?dist} ,随着包的release增长。如果是新版本,则重置为1。 |
Summary |
概况,一条述。 |
License |
授权。 |
URL |
项目网址。 |
Source0 |
源码网址。可以多个,比如:Source1, Source2, Source3。 |
Patch0 |
所必要的第一个补丁名称。可以多个,比如:Patch1, Patch2, Patch3。 |
BuildArch |
如果不依赖处理器架构,比如以解释型语言编写,则为BuildArch: noarch 。否则会继承运行编译主机的处理器架构。 |
BuildRequires |
编译程序所需的包的列表,以逗号或空格分隔。可以有多个条目,每条一行。 |
Requires |
安装软件后运行所需的包的列表,以逗号或空格分隔。可以有多个条目,每条一行。 |
ExcludeArch |
如果某个软件无法在特定的处理器体系结构上运行,可以在此排除它。 |
2、body-items
SPEC Directive | Definition |
---|---|
%description |
RPM打包软件的完整描述,可能会占用多行代码,并分成多个段落。 |
%prep |
编译软件所需的一条或一组命令。范例是解压缩Source0 中的归档文件。可以是shell脚本。 |
%build |
编译软件所执行的一条或一组命令。 |
%install |
实际安装各种制品到FHS中目标位置的一条或一组命令。注意,这是在%buildroot 的相对上下文中完成的。 |
%check |
“测试”软件的命令或一系列命令。通常是单元测试之类。 |
%files |
列表中的文件将安装于目标系统上下文的将resting place ^^。 |
%changelog |
不同Version或Release的变更记录。 |
三、修改spec文件
修改spec文件如下:
Name: bello
Version: 0.1
Release: 1%{?dist}
Summary: Hello World example implemented in bash script
License: GPLv3+
URL: https://example.com/%{name}
Source0: https://example.com/%{name}/release/%{name}-%{version}.tar.gz
BuildRequires:
Requires: bash
BuildArch: noarch
%description
The long-tail description for our Hello World Example implemented in
bash script
%prep
%setup -q
%build
%install
mkdir -p %{buildroot}/%{_bindir}
install -m 0755 %{name} %{buildroot}/%{_bindir}/%{name}
%files
%license LICENSE
%{_bindir}/%{name}
%changelog
* Tue May 31 2016 Adam Miller - 0.1-1
- First bello package
- Example second item in the changelog for version-release 0.1-1
%description
,比Summary
更长、更全面的关于包的描述。可以多段。%build
,指示系统如何编译包。范例不需要编译,所以留白。%install
,指示rpmbuild
如何安装编译号的软件到BUILDROOT
,并且我们需要构建目录层次结构,以便我们在指定位置安装软件。RPM Macros 帮助我们解决该问题,无需我们对路径硬编码。范例中,为了将bello
安装到该环境,我们唯一要做的事就是为bash script创建目标目录,然后将文件安装到该目录。我们通过install
命令实现,但是略有更改,因为在SPEC文件中我们使用%{name}
宏变量来保持一致性。%files
, RPM安装文件的列表,以及文件安装的位置。注意,这与%{buildroot}
无关,而是与文件的完整路径有关,因为安装后文件将存在于最终系统中。 因此,bellow file的安装列表是%{_bindir}/%{name}
,如果不使用宏那就配置成/usr/bin/bello
。
有时还需要一个内置宏来提供文件的上下文。可用于系统管理员和最终用户通过rpm查询包信息。我们在这里使用的内置宏是%license,它将告诉rpmbuild这是包文件清单元数据中的软件许可证文件。%changelog
, 与包的特定版本相关的带日期戳的列表。这并非记录软件的变化,而是打包的变化。例如,如果软件包中的软件需要修补,或者%build部分中列出的构建过程中需要更改,则信息将显示在此处。每个更改条目可以包含多个项目,并且每个项目应以新行开始,并以-
字符开头。
注意格式,时间戳以*
符号开头,然后是周、月、日、年,RPM Packager联系人信息。然后,在Version-Release之前,我们有一个-
字符,约定俗成,不是规定。最后是Version-Release。
四、编译RPM包
源码准备
上传bello-0.1.tar.gz到~/rpmbuild/SOURCES/
目录,不用解压编译
rpmbuild -bs 编译成SRPM
rpmbuild -bb 编译成 BINARY RPM
[root@VM-99-33-centos rpmbuild]# rpmbuild -bb SPECS/bello.spec
Executing(%prep): /bin/sh -e /var/tmp/rpm-tmp.1wvHwU
+ umask 022
+ cd /root/rpmbuild/BUILD
+ cd /root/rpmbuild/BUILD
+ rm -rf bello-0.1
+ /usr/bin/tar -xf -
+ /usr/bin/gzip -dc /root/rpmbuild/SOURCES/bello-0.1.tar.gz
+ STATUS=0
+ '[' 0 -ne 0 ']'
+ cd bello-0.1
+ /usr/bin/chmod -Rf a+rX,u+w,g-w,o-w .
+ exit 0
Executing(%build): /bin/sh -e /var/tmp/rpm-tmp.Crik0Z
+ umask 022
+ cd /root/rpmbuild/BUILD
+ cd bello-0.1
+ exit 0
Executing(%install): /bin/sh -e /var/tmp/rpm-tmp.pYTCv5
+ umask 022
+ cd /root/rpmbuild/BUILD
+ '[' /root/rpmbuild/BUILDROOT/bello-0.1-1.el7.x86_64 '!=' / ']'
+ rm -rf /root/rpmbuild/BUILDROOT/bello-0.1-1.el7.x86_64
++ dirname /root/rpmbuild/BUILDROOT/bello-0.1-1.el7.x86_64
+ mkdir -p /root/rpmbuild/BUILDROOT
+ mkdir /root/rpmbuild/BUILDROOT/bello-0.1-1.el7.x86_64
+ cd bello-0.1
+ mkdir -p /root/rpmbuild/BUILDROOT/bello-0.1-1.el7.x86_64//usr/bin
+ install -m 0755 bello /root/rpmbuild/BUILDROOT/bello-0.1-1.el7.x86_64//usr/bin/bello
+ /usr/lib/rpm/find-debuginfo.sh --strict-build-id -m --run-dwz --dwz-low-mem-die-limit 10000000 --dwz-max-die-limit 110000000 /root/rpmbuild/BUILD/bello-0.1
/usr/lib/rpm/sepdebugcrcfix: Updated 0 CRC32s, 0 CRC32s did match.
+ '[' noarch = noarch ']'
+ case "${QA_CHECK_RPATHS:-}" in
+ /usr/lib/rpm/check-buildroot
+ /usr/lib/rpm/redhat/brp-compress
+ /usr/lib/rpm/redhat/brp-strip-static-archive /usr/bin/strip
+ /usr/lib/rpm/brp-python-bytecompile /usr/bin/python 1
+ /usr/lib/rpm/redhat/brp-python-hardlink
+ /usr/lib/rpm/redhat/brp-java-repack-jars
Processing files: bello-0.1-1.el7.noarch
Executing(%license): /bin/sh -e /var/tmp/rpm-tmp.Q1LfDb
+ umask 022
+ cd /root/rpmbuild/BUILD
+ cd bello-0.1
+ LICENSEDIR=/root/rpmbuild/BUILDROOT/bello-0.1-1.el7.x86_64/usr/share/licenses/bello-0.1
+ export LICENSEDIR
+ /usr/bin/mkdir -p /root/rpmbuild/BUILDROOT/bello-0.1-1.el7.x86_64/usr/share/licenses/bello-0.1
+ cp -pr LICENSE /root/rpmbuild/BUILDROOT/bello-0.1-1.el7.x86_64/usr/share/licenses/bello-0.1
+ exit 0
Provides: bello = 0.1-1.el7
Requires(rpmlib): rpmlib(CompressedFileNames) <= 3.0.4-1 rpmlib(FileDigests) <= 4.6.0-1 rpmlib(PayloadFilesHavePrefix) <= 4.0-1
Requires: /bin/bash
Checking for unpackaged file(s): /usr/lib/rpm/check-files /root/rpmbuild/BUILDROOT/bello-0.1-1.el7.x86_64
Wrote: /root/rpmbuild/RPMS/noarch/bello-0.1-1.el7.noarch.rpm
Executing(%clean): /bin/sh -e /var/tmp/rpm-tmp.sUCUko
+ umask 022
+ cd /root/rpmbuild/BUILD
+ cd bello-0.1
+ /usr/bin/rm -rf /root/rpmbuild/BUILDROOT/bello-0.1-1.el7.x86_64
+ exit 0
- 测试安装
[root@VM-99-33-centos noarch]# rpm -ivh bello-0.1-1.el7.noarch.rpm
Preparing... ################################# [100%]
Updating / installing...
1:bello-0.1-1.el7 ################################# [100%]
[root@VM-99-33-centos noarch]#
[root@VM-99-33-centos noarch]#
[root@VM-99-33-centos noarch]# rpm -qa |grep bello
bello-0.1-1.el7.noarch
[root@VM-99-33-centos noarch]# rpm -ql bello-0.1-1.el7.noarch
/usr/bin/bello
/usr/share/licenses/bello-0.1
/usr/share/licenses/bello-0.1/LICENSE
附件一、BuildRoots
术语 buildroot 有多个定义。但是,在RPM软件包的生态中,是一个chroot环境,这样可以在一个新的虚拟根目录中创建文件系统,然后可以将这些内容放在实际的文件系统上,而不会破坏其完整性。
就类似于将tarball解压,在现有系统的根(/)目录中展开,这就是RPM在安装事务中的某个部分所做的事情。最终,从二进制RPM包解压,并放入 cpio 归档。
cpio 是什么?
一个非常古老的归档工具。
附件二、RPM Macros
RPM 宏是一种纯文本替换,在使用某些内置功能时,可以根据可选值有条件地赋值。这意味着RPM可以执行文本替换,无需我们干涉。
这对于RPM打包非常有用,如果我们想在SPEC文件中多次引用正在打包的软件版本,但只想定义一次。我们可以使用%{version}
宏,它将被在SPEC的version字段中定义的实际版本号替换。
rpm --eval
快速解析宏
[root@VM-99-33-centos ~]# rpm --eval %{_bindir}
/usr/bin
[root@VM-99-33-centos ~]# rpm --eval %{_libexecdir}
/usr/libexec
[root@VM-99-33-centos ~]# rpm --eval %{?dist}
.el7