本文只是简单的介绍一个Linux下为一个新的项目,创建自己的RPM 安装包, 里面包含RPM 一些基本术语和基本概念的介绍. 作为入门级的参考使用
创建rpm build 环境
rpmbuild的默认创建目录为$HOME/rpmbuild 目录, 可以通过如下命令创建:
rpmdev-setuptree
这个默认工作路径通常在 /usr/lib/rmp/macros 这个文件中通过宏变量 %_topdir 定义的, 如果想更改这个路径,一般不建议直接修改这个配置文件.而是在自己的用户目录下面创建一个 .rpmmacros 隐藏文件,然后在里面重新定义 %_topdir 的路径, 如下:
%_topdir /home/devinxa/rpmbuild_demo/
使用 rpmdev-setuptree 命令创建 build 环境后,会生成5个标准的子目录 BUILD, RPMS, SOURCES, SPECS 和 SRPMS, 另外在打包过程还会需要 BUILDROOT 这个目录, 这6个目录就是rpm build的所需要的所有目录,父级目录为%_topdir,他们的作用如下:
创建 spec 文件
最简单的方式是从别处copy一份功能类似的spec文件直接修改,但是这种case经常是可遇不可求的.所有我们从创建一个新的 spec 模板文件说起.
rpmdev-newspec -o name-version.spec
通过上面的命令我们就可以创建一个新的 spec 模板文件, 这个文件可以分为 前言 和 主体 两个部分, 分别解释如下:
#前言部分
Name: myapp-1.0.0 #软件包的名字,建议和spec文件名字中的name一致
Version: #软件包的版本,建议和spec文件名字中的version一致
Release: 1%{?dist} #软件的发布序号
Summary: #软件包的摘要描述
License: #软件的授权方式
URL: #源码的对应的路径或者软件所有公司的网址之类
Source0: #源代码包的名称(默认时rpmbuid回到SOURCES目录中去找), 如果有其他配置或脚本则依次用Source1、Source2等等往后增加
BuildRequires: #编译rpm包时需要的依赖软件包,每个依赖之间以逗号分隔。假如,要求编译myapp时,gcc的版本至少为4.4.2,则可以写成 gcc >= 4.2.2
Requires: #编译好的rpm在运行时的依赖软件包,各个依赖也以逗号分隔
#主体部分
%description #软件包的详细说明,最多为80个英文字符
%prep #将%_sourcedir目录下的源代码解压到%_builddir目录下。如果有补丁的需要在这个阶段进行打补丁的操作
%setup -q #解压操作
%build #在%_builddir目录下执行源码包的编译,一般是执行./configure和make指令
%configure #宏常量,会自动将 %{_prefix}设置成/usr
make %{?_smp_mflags} #自动将软件安装时的路径设置成如下约定:
# 1. 可执行程序放在/usr/bin
# 2. 依赖的动态库放在/usr/lib或者/usr/lib64
# 3. 二次开发的头文件放在 /usr/include
# 3. 文档及手册放在/usr/share/man
%install # 将需要打包到rpm软件包里的文件从%_builddir下拷贝%_buildrootdir目录下, 当用户最终用rpm -ivh name-version.rpm安装软件包时,这些文件会安装到用户系统中相应的目录里
rm -rf $RPM_BUILD_ROOT # $RPM_BUILD_ROOT 内置变量,就是 %_buildrootdir的值
%make_install
%clean #编译后的清理工作,这里可以执行make clean以及清空 %_buildroot 目录等
#下来就是制作 rpm 包阶段, 这个阶段是自动完成的,所以在SPEC文件里面是看不到的,这个阶段会将%_buildroot目录的相关文件制作成rpm软件包最终放到%_rpmdir目录里
#rpm制作阶段会引用下面的 %files 阶段, %file 阶段主要用来说明会将 %_buildrootdir 目录下的哪些文件和目录最终打包到rpm包里
%files #所有需要打包到rpm包的文件和目录都在这个地方列出, 需要注意,文件列表必须以 "/" 开头, 否则会报错(自己也可以尝试一下)
@defatrr(-,root,root,-) #%defattr(文件权限,用户名,组名,目录权限),如果不牵扯到文件、目录权限的改变则一般用%defattr(-,root,root,-)这条指令来为其设置缺省权限
%doc #可以指定那些在编译过程中没有从 %_builddir 放入到 %_buildrootdir 的文件,如一些README,LICENSE之类的文件
%changelog #记录的每次打包时的修改变更日志,为打包 rpm 的最后一个阶段, 格式不对,或报错失败,格式一般如下:
# * date +"%a %b %d %Y" 修改人 邮箱 本次版本x.y.z-p
# - 本次变更修改了那些内容
另外主体部分还可以定义其他一些 阶段 的脚本片段如: %pre, %post, %preun 和 % postun. 这里不在具体介绍,如果碰到需要的case,请参考如下文章:
- https://www.golinuxhub.com/2018/05/how-to-execute-script-at-pre-post-preun-postun-spec-file-rpm/
- https://docs.fedoraproject.org/en-US/packaging-guidelines/Scriptlets/
实战演练
示例程序很简单, 有两个目录, 每个目录下面存在一个文件,然后需要将这个程序打包成rpm,安装到机器的 /opt/myapp 目录下面:
- 在 /tmp 目录下面创建如下目录和文件
- 使用 rpmdev-setuptree 生成 rpmbuild 环境如下(我自定义了 %_topdir 目录):
- 打包整个程序目录为 myapp-1.0.0.tar.gz 放入 SOURCES 目录中,如下
- 使用 rpmdev-newspec -o myapp-1.0.0.spec 生成spec文件,并修改内容如下,放入 SPECS 目录中,如下
- 使用 rpmbuild -ba SPECS/myapp-1.0.0.spec 生成rpm包, 如下,忽略那个debuginfo的包.
- 安装 myapp-1.0.0-1.x86_64.rpm 包,查看安装结果,如下: