RPM 打包入门(基于openEuler)

主要参考内容(均为官方文档):

https://rpm-packaging-guide.github.io/#building-rpms
https://docs.redhat.com/zh_hans/documentation/red_hat_enterprise_linux/8/html/packaging_and_distributing_software/introduction-to-rpm_packaging-and-distributing-software#introduction-to-rpm_packaging-and-distributing-software

本文的环境:WSL2 + Qemu + OpenEuler24.03
提到的所有示例,均在该环境下测试

一、快速了解

RPM Package Manager (RPM)是一个运行在 Red Hat Enterprise Linux (RHEL)、CentOS 和 Fedora 上的软件包管理系统。您可以使用 RPM 为任何这些操作系统所创建的软件进行分发、管理和更新。

在 Red Hat Enterprise Linux 中,RPM 完全集成到更高级别的软件包管理软件中,如 YUM 或 PackageKit。虽然 RPM 提供了自己的命令行界面,但大多数用户只需要通过这个软件与 RPM 进行交互。但是,在构建 RPM 软件包时,您必须使用 RPM 工具,如 rpmbuild (8) 。

具体来说,RPM 软件包包含以下部分:

  • GPG 签名:GPG 签名用于验证软件包的完整性。
  • 标头(软件包元数据):RPM 软件包管理器使用此元数据来确定软件包依赖项、安装文件的位置及其他信息。
  • payload:有效负载是一个 cpio 归档,其中包含要安装到系统的文件。
    RPM 软件包有两种类型。这两种类型都共享文件格式和工具,但内容不同,并实现不同的目的:
  • 源 RPM(SRPM):SRPM 包含源代码和 spec 文件,它描述了如何将源代码构建为二进制 RPM。另外,SRPM 可以包含源代码的补丁。
  • 二进制 RPM:一个二进制 RPM 包含了根据源代码和补丁构建的二进制文件。
    安装 rpmdevtools 软件包:

openEuler 中使用 dnf,其他系统中可能使用 yum 安装:

dnf install rpmdevtools*

二、前置知识

这里仅简要罗列,更详细的内容可从文章开头的参考链接中查看
可以选择跳过,直接查看第三章的示例

1、源代码
源代码是人类可读的计算机指令,其描述了如何执行计算。源代码是使用编程语言表达的。

2、机器码
源代码转换为机器码方法:

  • 原生编译软件
    原生编译的软件是独立软件、原生编译的 RPM 软件包是特定于架构的,例如 C 语言
  • 使用语言解释器或语言虚拟机解释软件,可以使用原始解释或字节编译软件
    完全使用解释编程语言编写的软件不是特定于架构的。因此,生成的 RPM 软件包在其名称中有 noarch 字符串
    • 原始解释的软件:不需要编译这类软件,原始解释的软件由解释器直接执行
    • 字节编译的软件:必须首先将这类软件编译成字节码,然后由语言虚拟机执行

3、构建方式
在软件构建过程中,源代码被转换为可以使用 RPM 打包的软件工件

  • 原生编译的代码构建软件,使用以下方法之一将使用编译语言编写的软件构建成可执行文件:
    • 手动构建(使用 gcc 命令)
    • 自动化构建(使用 Makefile 文件与 make 命令)
  • 将解释编程语言编写的源代码转换为机器码:
    • 字节编译
    • 原始解释(例如 Shell 脚本)
      Python 支持原始解释、字节编译两种方式,字节编译的版本速度更快。因此,RPM 软件包程序更喜欢将字节编译的版本打包,来分发给最终用户。

4、修复软件(打补丁)
在打包软件时,可能需要对原始源代码进行某些更改,如修复 bug 或更改配置文件。在 RPM 打包中,可以将原始源代码保持不变,并在其上应用补丁。
补丁是更新源代码文件的一段文本。补丁具有 diff 格式,因为它代表文本的两个版本之间的区别。可以使用 diff 实用程序创建补丁,然后使用 patch 实用程序将补丁应用到源代码。

5、LICENSE
软件许可证文件(LICENSE)告知用户他们可以使用源代码做什么和不能做什么。
没有源代码许可证意味着您保留此代码的所有权限,任何人都不能从源代码复制、分发或创建衍生工作。
GPLv3 LICENSE 示例:

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

6、源代码存档(归档文件)
归档文件是带有 .tar.gz 或 .tgz 后缀的文件。将源代码放入存档中是发布软件以稍后打包为分发的常用方法。
注意:补丁 文件不随程序一起在存档中分发。构建 RPM 时,RPM 软件包管理器应用补丁。补丁将与 tar.gz 存档一起放在 ~/rpmbuild/SOURCES/ 目录中。
LICENSE 和源代码是一起归档的,而 patch 不和源代码一起归档,即 .tar.gz 归档文件中包含 LICENSE 和源代码,patch 和 .tar.gz 并列存放在 ~/rpmbuild/SOURCES 目录下

# 源代码文件夹
mkdir cello-1.0
mv cello.c cello-1.0/
mv Makefile cello-1.0/
mv LICENSE cello-1.0/# 进行压缩打包,创建存档
tar -cvzf cello-1.0.tar.gz cello-1.0# 移动到 ~/rpmbuild/SOURCES/ 目录中, 存储用于构建软件包的源文件的默认目录
# 对于需要 patch 的软件包,将所需的 patch 也移动到 ~/rpmbuild/SOURCES/ 目录中
mv cello-1.0.tar.gz ~/rpmbuild/SOURCES/

三、打包 Hello World 示例

0、设置工作区

# 1. 安装 rpmdevtools 软件包
dnf install rpmdevtools
# 2. 执行 rpmdev-setuptree 程序
rpmdev-setuptree
# 默认在 ~ 目录下创建 rpmbuild 文件夹
tree ~/rpmbuild/

RPM 打包工作区目录:

1、spec 文件

spec 文件是一个文件,其中包含 rpmbuild 实用程序用来构建 RPM 软件包的指令。此文件通过在一系列部分中定义指令,为构建系统提供必要信息。这些部分在 spec 文件的 Preamble 和 Body 部分中定义:

  • Preamble 部分包含一系列在 Body 部分中使用的元数据项。
  • Body 部分代表指令的主要部分。

列举了 Preamble 部分关键的指令:
暂时无法在飞书文档外展示此内容
列举 Body 中部分重要的项目:
暂时无法在飞书文档外展示此内容

2、BuildRoots

在 RPM 打包上下文中,buildroot 是 chroot 环境。构建工件通过使用与最终用户系统中将来层次结构相同的文件系统层次结构放在此,buildroot 充当根目录。构建工件的放置必须遵循最终用户系统的文件系统层次结构标准。
buildroot 中的文件稍后放入 cpio 存档,后者成为 RPM 的主要部分。当在最终用户的系统中安装 RPM 时,这些文件将提取到 root 目录中,保留正确的层次结构。

# 对于不熟悉的宏,可以使用 rpm --eval 查看内容
rpm --eval %{_bindir}
# 输出:/usr/bin

3、使用 spec 文件

要打包新软件,必须创建一个 spec 文件。通过以下任一方法创建 spec 文件:

  • 从头开始手动编写新的 spec 文件。
  • 使用 rpmdev-newspec 工具。这个工具会创建一个未填充的 spec 文件,其中会填写必要的指令和字段。
cd ~/rpmbuild/SPECS# 创建空的 spec 文件
rpmdev-newspec bello    # hello world     Bash版本
rpmdev-newspec cello    # hello world     C版本
rpmdev-newspec pello    # hello world     python版本

填充 spec 文件流程:

  1. 打开 rpmdev-newspec 创建的 ~/rpmbuild/SPECS/.spec 文件
  2. 填充 spec 文件的 Preamble 部分的指令:
    • Name:已指定为 rpmdev-newspec 的参数
    • Version:设置为与源代码的上游版本匹配
    • Release:自动设置为 1%{?dist},它最初是 1
    • Summary:软件包的单行说明
    • License:与源代码关联的软件许可证
    • URL:上游软件网站的 URL,为实现一致性,请使用 %{name} RPM 宏变量,并使用 https://example.com/%{name} 格式
    • Source:上游软件源代码的 URL,直接链接到被打包的软件版本
    • BuildRequires:指定软件包的构建时依赖项
    • Requires:指定软件包的运行时依赖项
    • BuildArch:指定软件架构
  3. 填充 spec 文件 Body 部分中的以下指令:可以将这些指令视为部分标题,因为这些指令可以定义多行、多结构或脚本化任务
    • %description:软件的完整描述
    • %prep:一系列命令来准备软件以进行构建
    • %build:用于构建软件的一系列命令
    • %install:一系列命令:用于指示 rpmbuild 命令如何将软件安装到 BUILDROOT 目录中
    • %files:指定在系统上安装的 RPM 软件包提供的文件列表
    • %changelog:软件包的每个 Version-Release 的 datetamped 条目列表
      从 %changelog 部分的第一行开始,带有星号(*)字符,后跟 Day-of-Week Month Day Year Name Surname - Version-Release
      对于实际更改条目,请遵循这些规则:
      • 每个更改条目都可以包含多个项目,每个代表一个改变。
      • 每个项目在新行中开始。
      • 每个项目以连字符(-)字符开头。

4、分析 bello 的 spec 文件

Bello 是使用 bash 写的 hello world,spec 文件如下

Name:           bello
Version:        0.1                --> 软件版本
Release:        1%{?dist}          --> 发布版本
Summary:        Hello World example implemented in bash scriptLicense:        GPLv3+
URL:            https://www.example.com/%{name}    --> 软件上游网站 url
Source0:        https://www.example.com/%{name}/releases/%{name}-%{version}.tar.gz # 软件的 urlRequires:       bash              --> 运行时依赖 bashBuildArch:      noarch            --> 与机器的体系结构无关%description
The long-tail description for our Hello World Example implemented in
bash script.%prep                               --> 准备阶段:例如解压缩源代码存档
%setup -q%build                              --> 构建阶段:bash 脚本不需要构建%install                            --> 安装阶段mkdir -p %{buildroot}/%{_bindir}install -m 0755 %{name} %{buildroot}/%{_bindir}/%{name}    --> 安装到指定路径%files
%license LICENSE                      --> LICENSE
%{_bindir}/%{name}                    --> /usr/bin/bello%changelog                            --> 改变日志
* Tue May 31 2016 Adam Miller <maxamillion@fedoraproject.org> - 0.1-1
- First bello package
- Example second item in the changelog for version-release 0.1-1
  • BuildRequires 指令指定软件包的 build-time 依赖项已被删除,因为没有可用于 bello 的构建步骤。Bash 是原始解释编程语言,文件仅安装到其系统上的位置。
  • Requires 指令指定软件包的运行时依赖项,它只包括 bash,因为 bello 脚本只需要 bash shell 环境才能执行。
  • %build 部分指定如何构建软件为空,因为不需要构建 bash 脚本。
  • %setup 对源代码存档进行解压

install:是Linux系统中用来复制文件和设置权限的命令,-m 0755:这个选项指定了安装文件的权限。0755是一个八进制数,表示文件所有者有读写执行权限(7),组用户和其他用户有读取和执行权限(5),没有写权限。
所以,整个 install 命令的作用是将名为%{name}的可执行文件复制到%{buildroot}/%{_bindir}目录下,并设置其权限为0755。在RPM打包过程中,%{buildroot}目录下的内容最终会被打包到 RPM 文件中,当用户安装RPM包时,这些文件会被安装到实际的文件系统路径上。
rpmbuild 常用的参数:
暂时无法在飞书文档外展示此内容

# 进入 SPEC 文件夹中
cd ~/rpmbuild/SPECS# 以构建 bello 的 RPM 包为例(其他的类似)
rpmbuild -bb bello.spec

可以使用 --noclean 留下构建的过程文件,在 BUILD/BUILDROOT 中可以看到 build 时做了什么
默认在构建好 rpm 包时,BUILD/BUILDROOT 下的内容会被清理

5、分析 pello 的 spec 文件

Pello 是使用 python 写的 hello world 程序

注:以下 spec 文件无法再 python3 上使用,python2 下应该是可以正确使用的【未验证】
在 python3 中,python -m compile 会将生成的pyc字节码文件放到 pycache 文件夹下,并且会修改命名,与该 spec 文件不匹配。而在 python2 中,生成的 pyc 字节码文件,可以按照以下 spec 描述进行。

Name:           pello
Version:        0.1.1
Release:        1%{?dist}
Summary:        Hello World example implemented in PythonLicense:        GPLv3+
URL:            https://www.example.com/%{name}
Source0:        https://www.example.com/%{name}/releases/%{name}-%{version}.tar.gzBuildRequires:  python        --> 构建生成 pyc 字节码时,需要使用 python 
Requires:       python        --> 运行时需要使用 python
Requires:       bash          --> 运行时需要 bashBuildArch:      noarch%description
The long-tail description for our Hello World Example implemented in Python.%prep                            --> 准备阶段:
%setup -q                        --> 解压源代码存档文件%build                            --> 构建阶段:python -m compileall %{name}.py   --> build 阶段, 对 py 进行编译, 得到字节码%install                                   --> 安装阶段:mkdir -p %{buildroot}/%{_bindir}               --> 递归创建目录
mkdir -p %{buildroot}/usr/lib/%{name}cat > %{buildroot}/%{_bindir}/%{name} <<EOF    --> 创建切入bash脚本,命名为 pello
#!/bin/bash
/usr/bin/python /usr/lib/%{name}/%{name}.pyc    --> 使用 python 执行 pyc
EOFchmod 0755 %{buildroot}/%{_bindir}/%{name}     --> 修改切入bash脚本的权限 install -m 0644 %{name}.py* %{buildroot}/usr/lib/%{name}/   --> 将源 py 文件安装到 /usr/lib 中%files
%license LICENSE                    --> LICENSE
%dir /usr/lib/%{name}/              --> /usr/lib/pello 目录
%{_bindir}/%{name}                  --> /usr/bin/pello 下的新建的切入脚本
/usr/lib/%{name}/%{name}.py*        --> /usr/lib/pello 目录下的 pyc 字节码文件%changelog
* Tue May 31 2016 Adam Miller <maxamillion@fedoraproject.org> - 0.1.1-1- First pello package
  • Requires 指令指定软件包的运行时依赖项,其中包括两个软件包:
    • 在运行时执行字节代码所需的 python 软件包。
    • 执行小入口点脚本所需的 bash 软件包。
  • BuildRequires 指令指定软件包的 build-time 依赖项,它只包括 python 软件包。pello 程序需要 python 执行字节型构建流程。
  • %build 部分指定如何构建软件,创建脚本的字节版本。请注意,在实际打包中,通常会根据所使用的发行版自动执行。
  • %install 部分与这个事实对应,您必须将字节文件安装到系统上的库目录中,以便可以访问它。
    创建打包程序脚本的示例显示了 spec文件本身可以脚本化。

7、分析 cello 的 spec 文件

cello 是使用 C语言编写的 hello world 示例程序,并且使用补丁 patch 进行修复

注:个人实验过程中,%prep 部分使用官方提供的示例,应用补丁会有错误,未进行解决
应用补丁的 cello 版本实验可能应用不成功

Name:           cello
Version:        1.0
Release:        1%{?dist}
Summary:        Hello World example implemented in CLicense:        GPLv3+
URL:            https://www.example.com/%{name}
Source0:        https://www.example.com/%{name}/releases/%{name}-%{version}.tar.gzPatch0:         cello-output-first-patch.patch        --> 需要使用的补丁BuildRequires:  gcc            --> 构建时需要 gcc
BuildRequires:  make           --> 自动化构建需要 make%description
The long-tail description for our Hello World Example implemented in
C.%prep                   --> 准备阶段:
%setup -q               --> 解压源码等%patch0                 --> 应用补丁到源码(属于准备阶段)%build                  --> 构建阶段:
make %{?_smp_mflags}    --> %{?_smp_mflags} 表示 -j4 等,加速编译%install
%make_install           --> 调用 make install%files
%license LICENSE        --> LICENSE
%{_bindir}/%{name}      --> 可执行文件%changelog
* Tue May 31 2016 Adam Miller <maxamillion@fedoraproject.org> - 1.0-1
- First cello package

Makefile 文件中指定如何编译、clean,以及 install

# cello 的 Makefile 文件
cello:gcc -g -o cello cello.cclean:rm celloinstall:mkdir -p $(DESTDIR)/usr/bin                       --> 递归创建目录install -m 0755 cello $(DESTDIR)/usr/bin/cello    --> 安装到指定路径

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/31866.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

WPF文本绑定显示格式StringFormat设置-特殊格式时间日期和多数据绑定

WPF文本绑定显示格式StringFormat设置 特殊格式设置日期/时间使用系统默认样式自定义格式&#xff1a; 绑定多个属性&#xff08;多重绑定&#xff09;多重绑定中的特殊字符示例&#xff1a; 特殊格式设置 在Textblock等文本控件中&#xff0c;我们经常要显示一些日期和时间&a…

【R语言】地理探测器模拟及分析(Geographical detector)

地理探测器模拟及分析 1. 写在前面2. R语言实现2.1 数据导入2.2 确定数据离散化的最优方法与最优分类2.3 分异及因子探测器&#xff08;factor detector&#xff09;2.4 生态探测器&#xff08;ecological detector&#xff09;2.5 交互因子探测器&#xff08;interaction dete…

Leetcode3184. 构成整天的下标对数目 I

Every day a Leetcode 题目来源&#xff1a;3184. 构成整天的下标对数目 I 解法1&#xff1a;遍历 统计满足 i < j 且 hours[i] hours[j] 构成整天的下标对 i, j 的数目。 构成整天的条件&#xff1a;(hours[i] hours[j]) % 24 0。 代码&#xff1a; /** lc applee…

推出RW610高度集成的低功耗无线MCU,带内置3频:1x1 Wi-Fi®6+ Bluetooth® Low Energy 5.4射频单元

RW610是一款高度集成的低功耗无线MCU&#xff0c;它集成了MCU和Wi-Fi6Bluetooth Low Energy (LE) 5.4射频单元&#xff0c;适用于多种应用&#xff0c;包括互联智能家居设备、游戏控制器、企业和工业自动化、智能配件和智能能源。 采用TFBGA145封装的系列器件&#xff1a;RW61…

大数据学习-环境准备

VMware 部分 网络设置 下载好 CentOS 7 的镜像文件 修改 VMware 的网络 把子网 ip 修改为 192.168.88.0&#xff0c;然后点击 NAT 设置&#xff0c;修改网关 IP 为 192.168.88.2 之后就确定即可 虚拟机安装 选择镜像文件&#xff0c;使用 VMware 的典型安装方法即可&#…

分解数据堆栈:存储和计算 2.0 的分解

在LinkedIn上&#xff0c;有一篇优秀的帖子在数据和数据库人群中流行。它由 Theory VC 合伙人 Tomasz Tunguz 撰写&#xff0c;讲述了我们自 2019 年以来讨论的趋势。 数据库正在成为高速查询引擎&#xff0c;并正在抛弃存储。这并不意味着存储不重要&#xff0c;相反&#xf…

Opencv学习项目5——pyzbar,numpy

上一次我们使用pyzbar进行解码二维码并将其内容显示在图像上&#xff0c;使用的是rect barcode.rect来获取图像的坐标&#xff0c;这次我们使用另一种方法来获取坐标进行画框。 Numpy介绍 NumPy 是一个用于科学计算的开源 Python 库&#xff0c;提供了对大量数值数据进行高效操…

MFC GDI绘制卡通人物

文章目录 主要代码完整visual studio工程下载主要代码 // DrawFrogView.cpp : implementation of the CDrawFrogView class //#include "stdafx.h" #include "DrawFrog.h"#include "DrawFrogDoc.h" #include "DrawFrogView.h"#includ…

5. Revit API: Application

5. Revit API: Application 前言 上一篇中&#xff0c;讲到了UI篇的Ribbon&#xff08;界面&#xff09;&#xff0c;并提到要创建 RibbonPanel&#xff0c;需要使用UIControlledApplication.CreateRibbonPanel(..)方法&#xff0c;还在结尾说到要写“UI”开头的那些个类&…

碳钢酸洗线送酸槽蒸汽冷凝水PH计测量装置改进方法

碳钢酸洗线送酸槽蒸汽冷凝水PH计测量装置改进方法 一、项目提出前状况 1)立项背景 轧钢退火酸洗生产线的酸洗过程需要使用大量的硫酸、盐酸、硝酸、氢氟酸等酸液对钢带的表面进行清洗,酸洗过后产生较多的酸洗废水,酸洗废水需要经过处理达到污水排放标准后才能排放。其中酸…

【linux】内核源码TCP->IP->L2层函数调用继续摸索中

日志打印的时候&#xff0c;把行数也打印了&#xff1a; 登录 - Gitee.comhttps://gitee.com/r77683962/linux-6.9.0/commit/b847489a9910f68b9581fd8788807c697c82cdbd 上回基于应用层wget操作找到TCP调用的一些接口&#xff0c;并且已经到IP层的一些接口&#xff0c;当前基…

昇思25天学习打卡营第3天|数据集Dataset

一、简介&#xff1a; 数据是深度学习的基础&#xff0c;高质量的数据输入将在整个深度神经网络中起到积极作用。有一种说法是模型最终训练的结果&#xff0c;10%受到算法影响&#xff0c;剩下的90%都是由训练的数据质量决定。&#xff08;doge&#xff09; MindSpore提供基于…

Docker常用操作和命令

文章目录 1、卸载旧版本 2、yum安装Docker CE&#xff08;社区版&#xff09; 3、添加镜像加速器 4、docker --version 查看docker版本 5、docker info 或 docker system info 显示 Docker 系统的详细信息&#xff0c;包括容器、镜像、网络等 6、docker search 搜索镜像 …

仙讯畅通无阻:探索MQ阵法的强大功能

MQ起源 IBM MQ&#xff1a;IBM MQ是IBM推出的一系列消息导向中间件产品&#xff0c;最初在1993年12月发布。它最初被称为MQSeries&#xff0c;2002年更名为WebSphere MQ&#xff0c;以加入WebSphere产品系列。2014年4月&#xff0c;它被重新命名为IBM MQ。Apache ActiveMQ&…

永辉超市:胖东来爆改,成色几何?

单日业绩暴涨14倍。来&#xff0c;看看&#xff0c;这是被胖东来爆改后重新开业后的门店&#xff0c; 不出意外的流量爆炸。胖东来爆改&#xff0c;真是解决实体商超困境的灵丹妙药吗&#xff1f; 今天我们聊聊——永辉超市 最近两年实体商超日子都不好过&#xff0c;去年13家…

cron.timezone

系统 date 数据库 show timezone插件 show cron.timezonealter system set cron.timezonePRC;show cron.timezone

【odoo】常用的基本视图类型

概要 在Odoo中&#xff0c;有几种基本视图类型&#xff0c;每种视图类型用于不同的目的和场景。这些视图类型包括表单视图&#xff08;form view&#xff09;、树视图&#xff08;tree view&#xff09;、看板视图&#xff08;kanban view&#xff09;、图表视图&#xff08;gr…

研究人员描述了如何判断ChatGPT是否在虚构

研究人员描述了如何判断ChatGPT是否在虚构 这是世界上最不为人知的秘密之一&#xff0c;大型语言模型对查询给出了明显错误的答案&#xff0c;并自信地这样做&#xff0c;与它们正确的时候没有区别。这有很多原因。人工智能可能已经接受了错误信息的训练;答案可能需要从LLM无法…

Flutter【组件】富文本组件

简介 flutter 富文本组件。 github地址&#xff1a; https://github.com/ThinkerJack/jac_uikit pub地址&#xff1a;https://pub.dev/packages/jac_uikit 使用方式 运行 flutter pub add jac_uikit组件文档 使用方式&#xff1a; HighlightedTextWidget.builder(text: &…