02 打包软件
1. RPM 包⚓
有两种RPM包:
- source RPM (SRPM)
- binary RPM
两者的文件格式和工具是相同的,但有不同的内容,服务于不同的目的。SRPM包含源代码,可选的补丁和SPEC文件,它描述了如何将源代码构建为二进制RPM。二进制RPM包含从源码和补丁构建的二进制文件。
1.1 RPM 打包工具⚓
rpmdevtools
提供了一些打包工具,查看这些工具:
$ rpm -ql rpmdevtools | grep bin
1.2 RPM 打包工作区⚓
使用rpmdev-setuptree
设置目录布局,即RPM打包工作区:
$ rpmdev-setuptree
$ tree ~/rpmbuild/
/home/user/rpmbuild/
├── BUILD
├── RPMS
├── SOURCES
├── SPECS
└── SRPMS
5 directories, 0 files
目录 | Purpose |
---|---|
BUILD | 当创建包时,各种%buildroot 目录在这里创建。如果创建失败时,而日志输出又没有提供足够的信息,这将很有用处。 |
RPMS | 二进制 RPMs 在这里创建,子目录表示不同的架构, 比如 x86_64 和noarch 。 |
SOURCES | 压缩源码包和补丁存放地, rpmbuild 命令从这里寻找它们。 |
SPECS | SPEC文件存放地 |
SRPMS | rpmbuild 创建 SRPM 时, SRPM 在这里创建 |
1.3 SPEC 文件⚓
它通过在一系列章节中定义指令来告诉构建系统要做什么。
分为两个部分:Preamble(包含Body中使用的一系列元数据项。)和 Body(包含指令的主要部分)。
1.3.1 Preamble⚓
SPEC 指令 | 定义 |
---|---|
Name |
包的基础名,应该和 SPEC 文件名匹配。 |
Version |
软件的上游版本 |
Release |
此版本的软件发布的次数。 通常,设置初始值为1%{?dist} ,每次发布新的时候就增加它。当新的 Version 构建时重置为1 。 |
Summary |
包的在线简要介绍 |
License |
被打包软件的 license 。 |
URL |
关于软件的更多信息的完整 URL。 |
Source0 |
远端源代码的压缩存档的路径或 URL(未修补,修补程序在其他地方处理)。这应该指向存档的可访问和可靠的存储,例如上游页面,而不是打包的程序的本地存储。Path or URL to the compressed archive of the upstream source code (unpatched, patches are handled elsewhere). This should point to an accessible and reliable storage of the archive, for example, the upstream page and not the packager’s local storage. If needed, more SourceX directives can be added, incrementing the number each time, for example: Source1, Source2, Source3, and so on. |
Patch0 |
应用到源码的第一个补丁。 If needed, more PatchX directives can be added, incrementing the number each time, for example: Patch1, Patch2, Patch3, and so on. 使用方法举例:%patch0 -p1 |
BuildArch |
如果包不依赖架构,比如全部使用解释型编程语言编写,设置为 BuildArch: noarch 。如果不设置,包自动继承构建机器的架构,比如 x86_64 。 |
BuildRequires |
构建时用编译语言编写的程序所需的包列表。使用逗号或空格分隔。There can be multiple entries of BuildRequires , each on its own line in the SPEC file. |
Requires |
软件在安装后运行时所需的软件包。使用逗号或空格分隔。 There can be multiple entries of Requires , each on its own line in the SPEC file. |
ExcludeArch |
如果软件无法在特定处理器架构上运行,则可以在此处排除该体系结构。 |
1.3.2 Body⚓
SPEC 指令 | 定义 |
---|---|
%description |
RPM中打包的软件的完整描述。该描述可以跨越多行并且可以分成段落。 |
%prep |
用于准备要构建的软件的命令或一系列命令,例如,在Source0中解压缩归档文件。该指令可以包含shell脚本。主要动作(参考《鸟哥的linux私房菜》): 1. 进行软件的补丁 (patch) 等相关工作; 2. 寻找软件所需要的目录是否已经存在? 3. 事先建立你的软件所需要的目录,或者事先需要进行的任务; 4. 如果待安装的 Linux 系统内已经有安装的时候可能会被覆盖掉的文件时,那么就必需要进行备份(backup)的工作。 |
%build |
用于将软件构建为机器码(用于编译语言)或字节码(用于某些解释语言)的命令或一系列命令。 |
%install |
用于将所需构建工件从%builddir (构建发生的位置)复制到%buildroot 目录(包含要打包的文件的目录结构)的命令或一系列命令。通常意味着从~/rpmbuild/BUILD 复制文件到~/rpmbuild/BUILDROOT 并创建在~/rpmbuild/BUILDROOT 中的必需的目录。这只在创建包的时候运行,而不是最终用户安装包的时候。 See Working with SPEC files for details. |
%check |
测试软件的命令或一系列命令。通常包含单元测试。 |
%files |
将在最终用户的系统中安装的文件列表。 |
%changelog |
不同版本或发布版本之间的包发生的更改记录。记录的是打包的改变,而不是软件的改变。 |
1.4 BuildRoots⚓
充当在构建时最终用户的文件系统的根目录。构建文件的放置应符合最终用户系统的文件系统层次结构标准。
在buildroot
中的文件待会会被放到一个 cpio 的打包文件,将成为 RPM 的主要部分。当RPM安装之后,这些文件会被提取到根目录,并保留当前的目录结构。
1.5 RPM 宏⚓
rpm macro是直接文本替换。被这意味着可以让RPM为您执行文本替换。
若不知道某个宏的值,可以使用rpm --eval %{_MACRO}
查看:
$ rpm --eval %{_bindir}
/usr/bin
$ rpm --eval %{_libexecdir}
/usr/libexec
1.6 使用 SPEC 文件⚓
不必手动创建,可以使用rpmdev-newspec
工具创建未填写内容的 SPEC 文件。
$ rpmdev-newspec cello
下面举例说明三种源码的 SPEC 文件。
1.6.1 Natively Compiled Code⚓
Name: cello
Version: 1.0
Release: 1%{?dist}
Summary: hello world example implemented in C.
License: GPLv3
URL: http://www.sharkshark.xyz/%{name}
Source0: http://www.sharkshark.xyz/%{name}/release/%{name}-%{version}.tar.gz
Patch0: cello-output-first-patch.patch
BuildRequires: gcc make
%description
long description in C.
%prep
%setup -q
%build
make %{?_smp_mflags}
%install
%make_install
%files
%license LICENSE
%{_bindir}/%{name}
%changelog
* Tue Jul 23 2019 sharkshark <xxx@example.com> - 1.0-1
- First cello package
1.6.2 Raw Interpreted Code⚓
Name: bello
Version: 0.1
Release: 1%{?dist}
Summary: hello world programed in bash.
License: GPLv3
URL: http://www.sharkshark.xyz/%{name}
Source0: http://www.sharkshark.xyz/%{name}/release/%{name}-%{version}.tar.gz
BuildArch: noarch
Requires: bash
%description
assume there is a long description
%prep
%setup -q
%build
%install
mkdir -p %{buildroot}/%{_bindir}
install -m 0755 %{name} %{buildroot}/%{_bindir}/%{name}
%files
%license LICENSE
%{_bindir}/%{name}
%changelog
* Mon Jul 22 2019 sharkshark <xxx@example.com> - 0.1-1
- First bello package
- Example secod item in the changlog for version-release 0.1-1
1.6.3 Byte-Compiled Code⚓
Name: pello
Version: 0.1.1
Release: 1%{?dist}
Summary: Hello World example implemented in Python
License: GPLv3
URL: http://www.sharkshark.xyz/%{name}
Source0: http://www.sharkshark.xyz/%{name}/release/%{name}-%{version}.tar.gz
BuildRequires: python
Requires: python,bash
BuildArch: noarch
%description
assume this is a long description.
%prep
%setup -q
%build
python -m compileall pello.py
%install
mkdir -p %{buildroot}/%{_bindir}
mkdir -p %{buildroot}/usr/lib/%{name}
cat > %{buildroot}/%{_bindir}/%{name} <<-EOF
#!/bin/bash
/usr/bin/python /usr/lib/%{name}/%{name}.pyc
EOF
chmod 0755 %{buildroot}/%{_bindir}/%{name}
install -m 0644 %{name}.py* %{buildroot}/usr/lib/%{name}/
%files
%license LICENSE
%dir /usr/lib/%{name}/
%{_bindir}/%{name}
/usr/lib/%{name}/%{name}.py*
%changelog
* Tue Jul 23 2019 sharkshark <xxx@example.com> - 0.1.1-1
- First pello package
2. 构建 RPM 包⚓
2.1 Source RPMs⚓
为什么要构建源码包?
- 为了保存一个RPM包的某些源文件。包括 SPEC 文件、源码、所有的补丁。这对回溯历史和debug很有用。
- 为了能够在不同的硬件平台或架构上构建二进制包。
$ rpmbuild -bs _SPECFILE_
$ cd ~/rpmbuild/SPECS/
$ rpmbuild -bs bello.spec
warning: bogus date in %changelog: Mon Jun 22 2019 sharkshark <xxx@example.com> - 0.1-1
Wrote: /home/study/rpmbuild/SRPMS/bello-0.1-1.el7.src.rpm
2.2 Binary RPMS⚓
两种构建二进制RPM的方法:
- 使用
rpmbuild --rebuild
命令从SRPM重新构建 - 使用
rpmbuild -bb
命令从 SPEC 文件构建
2.2.1 从源码包构建⚓
rpmbuild --bs cello.spec
rpmbuild --rebuild ../SRPMS/cello-1.0-1.el7.src.rpm
调用rpmbuild --rebuild
包括以下几点:
-
安装SRPM的内容( SPEC 文件和源码)安装到
rpmbuild
目录 -
使用已安装的内容构建。
-
移除SPEC 文件和源码。如果想保留这两个文件,有下面两种方法:
-
使用
--recompile
选项代替--rebuild
。 -
使用
rpm -Uvh SRPM
命令安装源码包,这样两个文件又会重新出现在对应目录了。
-
2.2.2 从 SPEC 文件构建⚓
rpmbuild --bb bello.spec
3. 检查RPMs是否合理⚓
检查的是RPM包的质量,而不是软件本身的质量。主要使用rpmlint
工具,可以检查:RPMs、SRPMs、 SPEC 文件。
rpmlint的规则很严格,有时可以跳过一些错误和警告。
yum install -y rpmlint