news 2026/6/10 15:02:07

使用rpmbuild将源代码制成rpm包

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
使用rpmbuild将源代码制成rpm包

1 说明

因centos停止支持,需要将一些应用软件迁移到OpenEuler上。原本在centos上只需要直接安装官网提供的预编译rpm包即可,现在没有了现成的安装包,只能从源代码自行编译。如果只是少数机器,逐台编译尚可忍耐,对于大量机器需要安装的情况,显然还是制作成rpm更为合适。

本文内容整理自官网文档:https://rpm-packaging-guide.github.io/,将其中的一个实例进行了解释,供学习之用。

2 准备源代码

2.1 C语言程序

创建目录cello-1.0,在其中创建一个输出Hello World的C语言程序文件cello.c:

mkdir cello-1.0

cd cello-1.0

touch cello.c

cello.c内容如下:

#include <stdio.h>

int main(void) {

printf("Hello World\n");

return 0;

}

用gcc将该程序编译链接,即可直接运行:

yun install -y gcc

gcc -g -o cello cello.c

此时目录下会出现一个cello的可执行文件,直接使用./cello即可输出Hello World。

如果将该可执行文件放在PATH路径下,那么在任何目录都可以直接使用cello命令执行。

2.2 补丁文件

在cello-1.0目录下创建一个普通文件cello.conf,假设为配置文件,安装完成后准备放在/etc/cello/目录下,内容为“before” 。

echo "before" > cello.conf

这个文件内容计划在安装完成后被修改,因此需要用到补丁。创建内容为“after”的cello2.conf文件,并用diff命令生成补丁。生成后将cello2.conf文件删除,将补丁文件cello-patch.patch复制到上层目录下,后面另有用处,只保留原文件cello.conf。

echo "after" > cello2.conf

diff -Naur cello.conf cello2.conf > cello-patch.patch

rm -f cello2.conf

mv cello-patch.patch ..

可以用patch < cello-patch.patch进行补丁功能的测试。

2.3 说明文件

在cello-1.0目录下再创建一个README.md,假设为说明文件,安装完成后准备放在/usr/share/doc/cello-1.0/目录下,文件内容随意。

2.4 Makefile文件

除了用gcc直接编译、链接,使用make工具可以更方便、更规范的完成这个流程。首先确保已经安装了make工具:

yum install -y make

编写Makefile内容如下:

cello:

gcc -g -o cello cello.c

install:

mkdir -p $(DESTDIR)/usr/bin

install -m 0755 cello $(DESTDIR)/usr/bin/cello

clean:

rm -f cello

rm -f $(DESTDIR)/usr/bin/cello

运行make或者make cello命令,则会在当前目录下生成可执行文件cello。

运行make install命令,则会将cello文件复制到$(DESTDIR)/usr/bin/cello目录下,并赋予755的权限。这里的$(DESTDIR)是一个宏,可以人工指定(后面spec文件的%make_install部分会涉及),如果不指定则为根目录/。

运行make clean,则会将当前目录下的cello删除,同时将$(DESTDIR)/usr/bin/cello目录下的cello删除。

运行make distclean(本例中未涉及configure操作),除了同make clean外,还会将Makefile、config.log等文件一起删除,用于重新configure

2.5 总结

至此,源代码文件就准备好了。此时整个cello-1.0目录下,一共有4个文件:

└── cello-1.0

├── cello.c

├── cello.conf

├── Makefile

└── README.md

进入上层目录,将cello-1.0目录打包成tar.gz文件,以便进行下一步工作

cd ..

tar -zcvf cello-1.0.tar.gz cello-1.0/

3 制作rpm包

3.1 安装工具

yum install -y rpm-build

yum install -y rpmdevtools

3.2 构建工作空间

使用rpmdev-setuptree命令构建打包工作空间,该工作空间会创建在当前用户的家目录下,例如/root/rpmbuild,该目录结构如下:

└── rpmbuild

├── BUILD

├── RPMS

├── SOURCES

├── SPECS

└── SRPMS

各目录解释如下:

目录 内容

BUILD 主要是解压后的源代码

RPMS 如果制作的是RPM包,则存放在此

SOURCES 存放源代码包、补丁等

SPECS 制作时使用的spec文件

SRPMS 如果制作的是SRPM包,则存放在此

BUILDROOT 制作rpm包时才会生成,源代码会安装在此目录而非系统目录,以及放置文档、license等

3.3 编辑spec文件

将准备好的源代码文件cello-1.0.tar.gz和补丁文件cello-patch.patch放入SOURCES目录。

进入SPECS目录,创建新spec文件

cd SPECES

rpmdev-newspec

会生成一个新的spec文件newpackage.spec,本例中修改为cello.spec,内容如下:

Name: cello

Version: 1.0

Release: 1%{?dist}

Summary: test

License: GPLv3+

Source0: %{name}-%{version}.tar.gz

Patch0: cello-patch.patch

BuildRequires: gcc, make

%description

test-1

%prep

%setup -q

%patch0

%build

make %{?_smp_mflags}

%install

%make_install

mkdir -p $RPM_BUILD_ROOT/%{_sysconfdir}/%{name}

install -m 0644 %{name}.conf $RPM_BUILD_ROOT/%{_sysconfdir}/%{name}/%{name}.conf

%files

%doc README.md

%attr(0755, vmuser, vmuser) %{_bindir}/%{name}

%attr(0644, vmuser, vmuser) %{_sysconfdir}/%{name}/%{name}.conf

%postun

if [ "$1" = "0" ]; then

rmdir %{_sysconfdir}/%{name}

fi

spec文件主要构成有:

Preamble Items

包含了包的元数据,这些项可以作为宏在spec文件中使用,以提高文件的可移植性。

关键字 说明

Name 包的名称

Version 包的版本

Release release版本

Summary 简要说明

License 遵循的License

Source0 使用的源代码包,如果有多个可以有Source1、 Source2……,由于使用了宏,替换后这里的源代码包即为cello-1.0.tar.gz

Patch0 使用的补丁,可以有多个:Patch1、Patch2……

BuildRequires build时需要的包

Requires 运行时需要的包,本例中无

Body Items

用于编译过程中的阶段控制。为提高文件的可移植性,文件中使用了一些宏,可参考下一小节。

关键字 说明

%description 说明描述

%prep 准备阶段,%setup -q意为将源代码压缩包(即cello-1.0.tar.gz)解压,并限制输出

%build 构建阶段,make %{?_smp_mflags}意为调用多处理器并行构建

%install 安装阶段,%make_install意为调用make install命令,此时$(DESTDIR)不为系统跟目录,而是该工作空间的$RPM_BUILD_ROOT目录,实际为/BUILDROOT/cello-1.0-1.el7.x86_64/。再应用install命令将conf文件复制到%{_sysconfdir}/%{name}/%下,即/etc/cello/下

%files 文件声明,将$RPM_BUILD_ROOT下的文件复制到系统的根目录/下。本例中是将README复制到/usr/shar/doc/cello-1.0/下(默认);cello可执行文件复制为%{_bindir}/%{name},实际为/usr/bin/cello,权限755;cello.conf复制到%{_sysconfdir}/%{name}/%{name}.conf,实际为/etc/cello/cello.conf,权限644

%postun 卸载后操作,本例中会保留一个空目录%{_sysconfdir}/%{name},即/etc/cello,因此需要删除

SPEC文件中使用的宏,除了如%{name}、%{version}等关键字外,还有rpm定义的宏,例如%{_sysconfdir}和%{_bindir},这些宏具体说明可以在 /usr/lib/rpm/macros 文件中查看。

常用的rpm宏例如:

宏 说明

% bin目录,默认为/usr/bin

% sbin目录,默认为/usr/sbin

% 配置目录,默认为/etc

% 数据目录,默认为/usr/share

此类宏可以用rpm --eval %{_bindir}命令输出具体值。

3.4 创建rpm包

至此,rpmbuild目录结构如下:

└── rpmbuild

├── BUILD

├── BUILDROOT

├── RPMS

├── SOURCES

│ └── cello-1.0.tar.gz

│ └── cello-patch.patch

├── SPECS

│ └── cello.spec

└── SRPMS

应用命令rpmbuild -bb SPECS/cello.spec即可进行rpm包的创建,其中bb为选项之一:

选项 说明

-bp build prep,只执行spec的%pre段

-bc build compile,只执行spec的%pre和%build段

-bi build install,只执行spec的%pre、%build和%install段

-bl 检查spec中的%file段

-ba 同时做成rpm和src.rpm文件

-bb build binary,只做成rpm文件

-bs build source,只做成srpm文件

创建rpm成功后,会默认清空BUILDROOT目录,如果再加上--noclean选项,则会保留,便于进行调试。

本例的完整结构如下,可以对照查看:

├── BUILD

│ └── cello-1.0

│ ├── cello

│ ├── cello.c

│ ├── cello.conf

│ ├── debugfiles.list

│ ├── debuglinks.list

│ ├── debugsources.list

│ ├── elfbins.list

│ ├── Makefile

│ └── README.md

├── BUILDROOT

│ └── cello-1.0-1.el7.x86_64

│ ├── etc

│ │ └── cello

│ │ └── cello.conf

│ └── usr

│ ├── bin

│ │ └── cello

│ ├── lib

│ │ └── debug

│ │ └── usr

│ │ └── bin

│ │ └── cello.debug

│ ├── share

│ │ └── doc

│ │ └── cello-1.0

│ │ └── README.md

│ └── src

│ └── debug

│ └── cello-1.0

│ └── cello.c

├── RPMS

│ └── x86_64

│ ├── cello-1.0-1.el7.x86_64.rpm

│ └── cello-debuginfo-1.0-1.el7.x86_64.rpm

├── SOURCES

│ ├── cello-1.0.tar.gz

│ └── cello-patch.patch

├── SPECS

│ └── cello.spec

└── SRPMS

3.5 安装rpm包

构建完成后,可以用:

rpm -ivh xxx.rpm:安装rpm包

rpm -qa:查看已安装的rpm包

rpm -e xxx.rpm:卸载rpm包

卸载rpm包时,如果%preun或者%postun写的不正确,会出现无法卸载的情况,此时可以加上--noscripts跳过两个阶段强制卸载,相应的残留文件需要手工删除

3.6 使用src.rpm包

src.rpm包也可以使用rpm -ivh命令安装,但是并不会实际安装软件,而是解压出源代码压缩包、补丁、spec文件以及其他普通文件。网络资料显示源代码会接到到 /usr/src/redhat/ 或 /usr/src/packages/ 目录下,但是实际文件出现在了~/rpmbuild/目录下。

也可以使用rpm2cpio package.src.rpm | cpio -idmv命令将源代码接到到当前目录下。

笔记

常用宏

宏 含义 示例

% 无条件宏展开:如果宏已定义,则替换为对应值;如果未定义,则报错。多为用户自定义宏或非路径类系统宏 %

% 无条件展开。以下划线开头,通常为系统预定义的路径宏,用于表示标准目录或系统环境变量 %{_bindir} → 展开为/usr/bin

% 当宏已定义且非空时展开为x,否则替换为空字符串 %{?alphatag:%{?alphatag}.},如果alphatag已定义,则展开

% 当宏未定义时执行冒号后的操作 %{!?build_agent: %global build_agent 1},如果build_agent未定义,则全局置为1

常用Body Items

Body Items 含义

%package 定义子包,。当需要从一个 spec 文件生成多个 RPM 包时,可通过%package声明子包并设置其独立属性

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/10 14:50:23

深入理解 Linux Namespace:隔离技术的基石

Linux 容器技术&#xff08;如 Docker&#xff09;的强大能力并非来自魔法&#xff0c;而是源于 Linux 内核提供的一项核心功能&#xff1a;Namespace。它提供了对系统资源的隔离&#xff0c;是容器能够实现轻量级、便携且安全运行的基石。本文将深入浅出地探讨 Namespace 是什…

作者头像 李华
网站建设 2026/6/9 21:31:42

AutoGPT项目安装常见问题及解决方案汇总

AutoGPT项目安装常见问题及解决方案汇总 在AI从“被动响应”迈向“主动思考”的今天&#xff0c;像AutoGPT这样的自主智能体正逐步走出实验室&#xff0c;进入开发者的本地终端。它不再等待用户一步步下达指令&#xff0c;而是能自己拆解目标、调用工具、反复试错&#xff0c;…

作者头像 李华
网站建设 2026/6/10 13:32:02

《极品家丁七改版》终极珍藏完整版:一键下载无雷精校全本资源

《极品家丁七改版》终极珍藏完整版&#xff1a;一键下载无雷精校全本资源 【免费下载链接】极品家丁七改版珍藏七改加料无雷精校全本资源下载介绍 《极品家丁&#xff08;七改版&#xff09;》是一部广受欢迎的经典小说&#xff0c;此版本经过精心校对与优化&#xff0c;保留了…

作者头像 李华
网站建设 2026/6/9 16:00:01

静态博客迁移实战:从WordPress卡顿到Gridea极速体验

你是否经历过这样的场景&#xff1a;在WordPress后台编辑文章时&#xff0c;页面加载缓慢得让人焦躁&#xff1b;每个月都要为服务器续费而心疼钱包&#xff1b;还要时刻担心网站被恶意攻击的风险&#xff1f;如果你正在寻找一种更轻量、更快速、更安全的博客解决方案&#xff…

作者头像 李华