基于openEuler系统的RPM打包操作教程【原理+流程+问题解决】

RPM(RPM Package Manager)是一种用于在Linux系统上管理软件包的工具。它最初由Red Hat开发,现已成为许多Linux发行版(包括openEuler、CentOS、Fedora等)的标准包管理工具。RPM主要用于安装、卸载、更新和查询软件包。

本文章将基于openEuler24.03LTS操作系统完成对一个应用程序(feh)的RPM打包,涉及到RPM打包的相关概念、流程以及问题的发现与解决,适用于有一定LINUX操作命令与编程语言基础的读者朋友。

因本人水平及时间有限,文中难免有疏漏之处,请各位读者海涵并不吝指正。

注意:①# - 涉及到的commands需要sudo权限;

②$ - 涉及到的commands需要普通非特权用户权限;

③rpmbuild命令应在普通用户权限下执行,否则一点小错误可能危害整个操作系统,因此本文章建议在普通用户而非root用户界面完成;

④文章中出现的/egdoc或/zwy应替换为读者实际的用户名。

一、rpm building process涉及到的相关概念

安装、删除、更新(一句话,管理)软件是每个操作系统的基本任务。当包管理器还不存在时,安装程序的唯一方法是编译其源代码,并将生成的文件放在文件系统的适当位置。跟踪每段代码的依赖关系是非常困难和耗时的,在引入包管理器后一切都变得容易了。

如今,每个现代Linux发行版都有自己的包管理器:Debian及其衍生版本使用dpkg,而Red Hat系列发行版使用rpm。软件以包的形式提供预编译,包基本上是压缩的存档,包含有关软件版本、其依赖关系以及与其他包可能发生冲突的元数据。

在本文章中,我们将看到如何从应用程序源代码开始创建rpm包。我们将打包的应用程序是feh,它是一个简单的命令行图像查看器:它非常小,几乎没有依赖项。然而,在开始构建第一个包之前,我们应该掌握一些基本概念。

1. build environment相关

rpm构建环境树的根目录是rpmbuild目录,它包含6个子目录:BUILD、BUILDROOT、RPMS、SOURCES、SPECS和SRPMS。

在下文我们将看到如何通过启动一个简单的命令来生成这个环境,现在,我们只讨论这些目录的作用。下面是工作树的表示:

这些目录中的每一个在构建过程中都有其特定的作用:

BUILD目录是构建我们想要打包的程序的源代码的地方。

BUILDROOT目录是复制BUILD目录中软件编译所产生的文件的地方,反映了目标系统在包名称子目录中的结构:在我们的例子中,将安装在/usr/bin中的“feh”二进制文件将报告为BUILDROOT/feh-3.0-1.fc29.x86_64/usr/bin。

RPMS目录生成rpm包的地方:每个rpm将被放置在以其体系结构命名的子目录中,如果不是特定于体系结构(architecture),则放置在noarch目录中。(是的,这里的 architecture 指的是软件包(RPM)的目标硬件架构。在 Linux 系统中,不同的硬件架构需要不同版本的软件包,因为这些软件包是为特定的处理器架构编译的。)

SOURCES目录存放着我们想要打包的软件的压缩源代码,通常以压缩文件或压缩文件的形式存在。

SPECS目录是我们放置.spec文件的地方,其中包含构建包的指令:稍后我们将分析该文件的结构。

SRPMS目录相当于RPMS,但用于源RPMS。这个特殊的包包含应用程序的原始源代码、最终补丁和用于构建包的指定文件。

现在各位可能对每个目录内容仍有疑惑,不必担忧,在第二部分的具体操作过程中各位将对其有更深刻的理解。

2. .spec文件相关

定义构建rpm包所需的所有指令和信息的文件是.spec文件。一个specfile包含了build dependencies(构建依赖项,编译我们想要打包的程序所需的软件)、runtime dependencies(运行时依赖项,程序正确运行所需的库)和编译软件时应该执行的命令。

该文件由两个宏节组成:preamble(序言,绪论;前言,开场白)和body(主体部分)。

(1)preamble部分可以包含下列说明:

  • Name: The basename of the package (需要匹配 the spec file)
  • Version: The upstream version of the packaged software
  • Release: The release number of the package(第二章涉及到细节)
  • License: The license used for the software we want to package(第二章涉及到细节)
  • Url: The upstream URL of the software(资源的主页,可以是.org主页)
  • Source0: The direct URL or the path of the software’s compressed source code (tarball or zipped file)(直接源)
  • BuildArch: The architecture of the package: if no architecture is specified the one of the host system will be used
  • BuildRequires: The dependencies needed to build the software(构建依赖项)
  • Requires: The dependencies needed to run the software(运行依赖项)

(2)body部分可以包含下列说明:

  • %description: An optionally multi-line description of the software packaged(描述)
  • %prep: The command(s) needed to prepare the source code (for example, the commands needed to extract a tarball)
  • %build: The command(s) needed to build the software
  • %install: The command(s) needed to copy the file resulting from the build process to the BUILDROOT directory
  • %files: The list of the files provided by the package, which will be installed on the system

另外,在zh/contributors/packaging.md · openEuler/community - Gitee.com中涉及到了软件拆分规则,感兴趣的读者可以参考学习。

“但是对于很多简单的软件来说,可以将libs包,devel包和主包合并,不单独拆分。目的是保持包的简洁,易于理解,不会将包的粒度做的过细而导致后续更新,维护困难,并且增加依赖关系的复杂性。”

由于本文章涉及到的软件不复杂,采用不单独拆分的形式。

3. .spec文件中的marcos(宏)的使用

为了简化我们的工作,在指定文件中,我们可以使用一些宏,这些宏允许我们引用许多有用的东西并自动执行某些任务。

首先,我们有RPM directory macros,它允许我们引用构建环境的目录;我们应该总是使用它们而不是直接路径(相当于将tree中直接路径定义好):

  • %{_topdir}: This macro references the rpmbuild directory
  • %{_builddir}: References the BUILD directory inside our build tree
  • %{_rpmdir}: References the path of the RPMS directory
  • %{_sourcedir}: This macro is evaluated to the path of the SOURCES directory
  • %{_specdir}: A macro which represents the path of the SPECS directory
  • %{_srcrpmdir}: References the path of SRPMS directory
  • %{_buildrootdir}: References the path of the BUILDROOT directory

不难看出,上述为工作树的上级目录rpmbuild以及下属的六个子目录的直接路径的宏。

还有一些宏可以让我们引用我们的操作系统中最重要的目录,例如:

  • %{_sysconfigdir}: The /etc directory
  • %{_prefix}: The /usr directory
  • %{_bindir}: The /usr/bin directory
  • %{_mandir}: The path to the /usr/share/man directory

在.spec文件的body部分,我们同样使用到了marcos,如:

(1)The %setup macro, is used in the %config section of the specfile,

基本上执行以下操作:

  1. ①提取我们要打包到BUILDDIR目录的程序的源代码
  2. ②切换到解压的目录
  3. ③在其中设置适当的文件权限

(2)The %{make_build} macro is used in the %build section of the specfile,基本上运行the make command with a predefined sets of options(一组预定义选项的make命令),来编译软件的源代码。

(3)The %{make_install} macro, instead, is used in the %install section of the file, and runs make install with the DESTDIR parameter, used to instruct the command to install the compiled files relatively to a given directory instead of the real system /(安装到指定的路径而不是根路径)

二、完成RPM打包的具体步骤及问题解决

在学习了包构建过程的基本概念后,接下来我们可以看到如何创建构建环境和第一个rpm包。

1. 安装构建依赖项(build dependencies)

首先,我们需要安装rpmdevtools,以及构建feh所需的依赖项

$ sudo dnf install rpmdevtools gcc make imlib2-devel libjpeg-devel libpng-devel libXt-devel libXinerama-devel libexif-devel  perl-Test-Command perl-Test-Harness libcurl-devel

命令中install后用空格分开的各项为并列关系,均需要安装,这些依赖项根据是.spec文件中的BuildRequires和Requires,对于不同的软件依赖项需要针对性调整,是一项比较重要的内容

问题:CENTOS系统(在该系统中同样进行了测试)中出现部分包不在仓库中的问题,通过启用 EPEL(Extra Packages for Enterprise Linux)仓库解决:

sudo yum install epel-release
sudo yum clean all
sudo yum makecache

安装这些包后,我们可以生成构建环境,运行以下命令:

$ rpmdev-setuptree

此时,应该在/home/user目录创建好了工作树的上级目录rpmbuild以及下属的五个子目录(无BUILDROOT)

(此时应暂时无BUILDROOT)

2. 编写.spec文件

命名为feh.spec,存放在~/rpmbuild/SPECS目录,以下为文件内容:

3. .spec文件分析

.spec文件来源于https://linuxconfig.org/how-to-create-an-rpm-package,在实际使用过程中出现一些问题,结合个人实践与查阅资料补充以下内容/问题解决方案:

#Release相关

使用1%{?dist}而非1的好处

#License相关

由于另一项目许可证涉及到GPLv3+,于是对该字段标准进行补充。

编写完成后可以使用rpmlint命令检查.spec文件。

关于%prep %build %install %files

%prep:提供%setup -q宏就足够了:如前所述,这个宏将运行解压缩源tarball所需的命令,并将解压缩的目录放入BUILD文件夹中。

%build:我们指定构建源代码时应该运行的命令。在这里,我们所要使用的也只是%{make_build}宏,它使用我们之前看到的选项将make命令运行到存放我们想要打包的应用程序的未打包源代码的目录中。

%install:我们使用了另一个宏%{make_install},它也提供了PREFIX参数,将其设置为%{_prefix},它将扩展到/usr。生成的命令将导致编译源代码生成的文件被放置在“假根”中,并使用宏中包含的DESTDIR参数进行设置。因为在%{make_install}宏中,“DESTDIR”被设置为/home/egdoc/rpmbuild/BUILDROOT/%{NAME}-%{VERSION}-%{RELEASE}。x86_64时,文件将安装在:/home/egdoc/rpmbuild/ buildroot /%{NAME}-%{VERSION}-%{RELEASE}.x86_64/usr下。

%files:a list of the files which will be installed by our package我们的包将要安装的文件列表。

#关于自动解压失败问题

在%prep阶段出现了自动解压失败问题

解决:手动解压 tar -xjvf ~/rpmbuild/SOURCES/feh-3.0.tar.bz2 -C /tmp注意选项对应压缩文件类型

tar -xjvf ~/rpmbuild/SOURCES/feh-3.0.tar.bz2 -C /tmp

该问题应该有更好的解决方法,后续将检查%prep内含命令使其可以自动化解压,mark。

#关于.debug文件的问题

第二行:/usr/lib/debug/usr/bin/feh-3.0-1.fc29.x86_64.debug(出现报错)

解决方法:取消手动创建文件,删去此行系统自动创建后问题解决。

4. 获取sources压缩包

下载“feh”的源代码tarball:不需要手动下载,因为我们可以使用spectool命令:

$ spectool -g -R ~/rpmbuild/SPECS/feh.spec

相当于Getting http://feh.finalrewind.org/feh-3.0.tar.bz2 to /home/zwy/rpmbuild/SOURCES/feh-3.0.tar.bz2

当spectool有问题时,可以考虑替代的手动下载命令curl/wget,如:

curl -o /home/zwy/rpmbuild/SOURCES/feh-3.0.tar.bz2 http://feh.finalrewind.org/feh-3.0.tar.bz2

上述命令将使用spec文件中的SOURCE0下载我们引用的源代码,下载到工作树的适当目录中:~/rpmbuild/SOURCES。

5. rpmbuild完成打包

我们所要做的就是启动rpmbuild命令,并提供指定文件的路径。当使用-bb选项启动时,rpmbuild将只构建一个二进制包,如果我们也想生成一个源rpm,我们必须使用-ba来代替。

以下为-bb 选项示例:

$ rpmbuild -bb ~/rpmbuild/SPECS/feh.spec

所执行操作的输出将打印在屏幕上,请注意rpmbuild操作可能会有各种各样的报错,但是报错提示是很详细的,可以根据报错提示逐步完善依赖项或修改.spec文件,或将一些自动化操作改为手动操作,希望读者可以顺利解决遇到的问题。

如果一切正常,rpm包将在RPMS目录中生成。

6. RPM包的安装与校验

执行以下命令将安装feh的rpm包:

sudo rpm -i RPMS/x86_64/feh-3.0-1.x86_64.rpm

man feh指令将显示feh的说明书:

为openEuler系统安装GNOME桌面环境,以运行feh-3.0 :

sudo dnf install gnome-shell gdm gnome-session gnome-terminal -y

root权限设置默认启动环境:

systemctl enable gdm.service
systemctl set-default graphical.target

重启后生效,运行feh打开一张图片:

至此本文章已将至尾声,作者也是正处于LINUX操作系统的学习阶段,文章可能有所纰漏,希望本文能对各位有所帮助,祝愿共同进步。

 refer:①https://linuxconfig.org/how-to-create-an-rpm-package

zh/contributors/packaging.md · openEuler/community - Gitee.com -源于openEuler开源社区

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值