当前位置: 首页 > news >正文

使用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声明子包并设置其独立属性

http://www.cnnetsun.cn/news/49261.html

相关文章:

  • Windows更新后RDPWrap失效修复指南:快速恢复多用户远程桌面功能
  • GPU和TPU差异之联网
  • 解决 Oracle 监听外网 IP 及腾讯云防火墙配置
  • ORACLE解析游标生成JSON
  • AMD GPU并行通信技术:突破性性能优化实战指南
  • Everywhere AI助手:跨平台智能对话系统深度解析
  • 考古学开放数据中的Paradata研究——CAPTURE项目与文献综述解读
  • 论文解读|将1930年前所有阿拉伯期刊添加到Wikidata——学术众包项目Jarāʾid向数字公共领域的迁移
  • 5分钟掌握UpSetR:超越维恩图的集合交集可视化神器
  • 机构洗盘拼合指标绝无未来 源码分析
  • Android项目架构完整指南:模块化开发与Kotlin最佳实践
  • Horovod Process Sets:让千亿参数模型训练触手可及
  • 5步掌握Loco+Tauri:构建高性能跨平台桌面应用的终极指南
  • 如何在Zephyr RTOS中制定最佳编译策略?
  • 专业实验室改造,必须避开的5大坑
  • 千万注意!实验室装修这5个关键点不容忽视
  • 关于指纹浏览器
  • ModelScope 模型一键上线?FunModel 让你 5 分钟从零到生产
  • 云服务器与传统服务器
  • Step-Audio 2:颠覆性多模态音频AI如何重新定义人机交互?
  • 3步掌握OpenUSD在Blender中的高效应用方法
  • HeyGem.ai视频生成超时终极解决方案:从卡顿到流畅的完整优化指南
  • AI智能体测试终极指南:构建可靠质量保障体系
  • 通信基站抛物面天线检测--基于RPN与FPN的改进算法实现
  • CosyVoice ONNX模型部署终极指南:5大实战技巧快速掌握
  • 字节跳动开源Bamboo-mixer:AI驱动电解液研发革命,周期缩短60%
  • 后端学习笔记
  • Gitea权限管理:构建安全高效的代码访问控制体系
  • AI视频生成终极指南:从零开始快速上手WAN2.2-14B-Rapid-AllInOne
  • Ascend C 编译器内幕与自动调优实战:从手写 Kernel 到 AI 驱动的性能优化