RPM 包的构建 - 实例
RPM 系列文章:
打包目录
rpm 打包目录有一些严格的层次上的要求。
rpm 的版本 <=4.4.x,rpmbuid 工具其默认的工作路径是 /usr/src/redhat。因为权限的问题,普通用户不能制作 rpm 包,制作 rpm 软件包时必须切换到 root 身份才可以。
rpm 从 4.5.x 版本开始,将 rpmbuid 的默认工作路径移动到用户家目录下的 rpmbuild目录里,即 $HOME/rpmbuild ,并且推荐用户在制作 rpm 软件包时尽量不要以 root 身份进行操作。
本文所在环境:
- RPM 版本:rpm-4.11.3-32.el7.x86_64版本。
- CentOS 7
如果想发布 rpm 格式的源码包或者是二进制包,就要使用 rpmbuild 工具( rpm 最新打包工具)。如果我们已经根据本地源码包的成功编译安装而写了 spec 文件(该文件要以 .spec 结束),那我们就可以建立一个打包环境,也就是目录树的建立,一般是在 ~/rpmbuild 目录下建立 5 个目录。它门分别是:
- BUILD:目录用来存放打包过程中的源文件,就是来源于- SOURCE
- SOURCE:用来存放打包是要用到的源文件和 patch,主要是一些- tar包
- SPEC:用来存放 spec 文件
- SRPM:存放打包生成的 rpm 格式的源文件
- RPM:二进制文件
SPEC 阶段与目录的对应关系
| 阶段 | 读取的目录 | 写入的目录 | 具体动作 | 
|---|---|---|---|
| %prep | %_sourcedir | %_builddir | 读取位于 %_sourcedir 目录的源代码和 patch 。之后,解压源代码至 %_builddir 的子目录并应用所有 patch。 | 
| %build | %_builddir | %_builddir | 编译位于 %_builddir 构建目录下的文件。通过执行类似 ./configure && make 的命令实现。 | 
| %install | %_builddir | %_buildrootdir | 读取位于 %_builddir 构建目录下的文件并将其安装至 %_buildrootdir 目录。这些文件就是用户安装 RPM 后,最终得到的文件。注意一个奇怪的地方: 最终安装目录 不是 构建目录。通过执行类似 make install 的命令实现。 | 
| %check | %_builddir | %_builddir | 检查软件是否正常运行。通过执行类似 make test 的命令实现。很多软件包都不需要此步。 | 
| bin | %_buildrootdir | %_rpmdir | 读取位于 %_buildrootdir 最终安装目录下的文件,以便最终在 %_rpmdir 目录下创建 RPM 包。在该目录下,不同架构的 RPM 包会分别保存至不同子目录, noarch 目录保存适用于所有架构的 RPM 包。这些 RPM 文件就是用户最终安装的 RPM 包。 | 
| src | %_sourcedir | %_srcrpmdir | 创建源码 RPM 包(简称 SRPM,以.src.rpm 作为后缀名),并保存至 %_srcrpmdir 目录。SRPM 包通常用于审核和升级软件包。 | 
安装工具
RPM打包使用的是 rpmbuild 命令,来自 rpm-build 包:
yum install -y rpm-build
也可以安装 rpmdevtools,这个工具部包含一些其他工具,依赖 rpm-build,所以直接安装会将 rpm-build 装上:
yum install -y rpmdevtools
Python 的编译打包工具是 setuptools。
工具使用
rpmbuild 命令使用一套标准化的「工作空间」 ,生成 %_topdir 工作目录 ~/rpmbuild,以及配置文件 ~/.rpmmacros:
rpmdev-setuptree
rpmdev-setuptree这个命令就是安装 rpmdevtools 带来的。可以看到运行了这个命令之后,在 $HOME 家目录下多了一个叫做 rpmbuild 的文件夹,里边内容如下:
$ tree rpmbuild
rpmbuild
├── BUILD
├── RPMS
├── SOURCES
├── SPECS
└── SRPMS
rpmdev-setuptree 命令在当前用户 home/rpmbuild 目录里自动建立上述目录。
如果没有安装  rpmdevtools 的话,其实用 mkdir 命令创建这些文件夹也是可以的:mkdir -p ~/rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS}。
| 默认位置 | 宏代码 | 名称 | 用途 | 
|---|---|---|---|
| ~/rpmbuild/SPECS | %_specdir | Spec 文件目录 | 保存 RPM 包配置(.spec)文件 | 
| ~/rpmbuild/SOURCES | %_sourcedir | 源代码目录 | 保存源码包(如 .tar 包)和所有 patch 补丁 | 
| ~/rpmbuild/BUILD | %_builddir | 构建目录 | 源码包被解压至此,并在该目录的子目录完成编译 | 
| ~/rpmbuild/RPMS | %_rpmdir | 标准 RPM 包目录 | 生成/保存二进制 RPM 包 | 
| ~/rpmbuild/SRPMS | %_srcrpmdir | 源代码 RPM 包目录 | 生成/保存源码 RPM 包(SRPM) | 
| ~/rpmbuild/BUILDROOT | %_buildrootdir | 最终安装目录 | 保存 %install 阶段安装的文件 | 
rpmbuild 默认工作路径的确定,通常由在 /usr/lib/rpm/macros  这个文件里的一个叫做 %_topdir 的宏变量来定义。如果用户想更改这个目录名,rpm 官方并不推荐直接更改这个目录,而是在用户家目录下建立一个名为 .rpmmacros 的隐藏文件(Linux下隐藏文件,前面的点不能少),然后在里面重新定义 %_topdir,指向一个新的目录名。这样就可以满足某些用户的差异化需求了。.rpmmacros 文件里内容,比如:
 michael@localhost  ~  cat .rpmmacros
%_topdir %(echo $HOME)/rpmbuild
%_smp_mflags %( \
    [ -z "$RPM_BUILD_NCPUS" ] \\\
        && RPM_BUILD_NCPUS="`/usr/bin/nproc 2>/dev/null || \\\
                             /usr/bin/getconf _NPROCESSORS_ONLN`"; \\\
    if [ "$RPM_BUILD_NCPUS" -gt 16 ]; then \\\
        echo "-j16"; \\\
    elif [ "$RPM_BUILD_NCPUS" -gt 3 ]; then \\\
        echo "-j$RPM_BUILD_NCPUS"; \\\
    else \\\
        echo "-j3"; \\\
    fi )
%__arch_install_post \
    [ "%{buildarch}" = "noarch" ] || QA_CHECK_RPATHS=1 ; \
    case "${QA_CHECK_RPATHS:-}" in [1yY]*) /usr/lib/rpm/check-rpaths ;; esac \
    /usr/lib/rpm/check-buildroot
生成 SPEC 文件
最最最重要的 SPEC 文件,命名格式一般是“软件名-版本.spec”的形式,将其拷贝到 SPECS 目录下。
如果系统有 rpmdevtools 工具,可以用 rpmdev-newspec -o name.spec 命令来生成 SPEC 文件的模板,然后进行修改:
[root@localhost ~]# rpmdev-newspec -o myapp.spec
Skeleton specfile (minimal) has been created to "myapp.spec".
[root@localhost ~]# cat myapp-0.1.0.spec
Name:           myapp
Version:
Release:        1%{?dist}
Summary:
License:
URL:
Source0:
BuildRequires:
Requires:
%description
%prep
%setup -q
%build
%configure
make %{?_smp_mflags}
%install
rm -rf $RPM_BUILD_ROOT
%make_install
%files
%doc
如果没有安装 rpmdevtools,也可以自己手动创建一个 spec 文件。
打包命令
在 rpmbuild/SPECS 目录下执行打包编译,切换到该目录下执行打包编译命令。
rpmbuild 命令选项
rpmbuild 命令的选项 rpmbuild 命令有不少选项,用得比较多的有:
-bp 只解压源码及应用补丁
-bc 只进行编译
-bi 只进行安装到%{buildroot}
-bb 只生成二进制 rpm 包
-bs 只生成源码 rpm 包
-ba 生成二进制 rpm 包和源码 rpm 包
--target 指定生成 rpm 包的平台,默认会生成 i686 和 x86_64 的 rpm 包,但一般我只需要 x86_64 的 rpm 包
只生成二进制格式的 rpm 包
rpmbuild -bb 软件名-版本.spec
用此命令生成软件包,生成的文件会在刚才建立的RPM目录下存在。
只生成 src 格式的 rpm 包
rpmbuild -bs 软件名-版本.spec
生成的文件会在刚才建立的SRPM目录下存在。
只需要生成完整的源文件
rpmbuild -bp 软件名-版本.spec
源文件存在目录 BUILD 下。可能对这个命令不太明白,这个命令的作用就是把 tar 包解开然后把所有的补丁文件合并而生成一个完整的具最新功能的源文件。
完全打包
rpmbuild -ba 软件名-版本.spec
软件包制作完成后可用 rpm 命令查询,看看效果。如果不满意的话可以再次修改软件包描述文件,重新运行以上命令产生新的 RPM 软件包。
实例
将所有用于生成 rpm 包的源代码、 shell 脚本、配置文件都拷贝到 SOURCES 目录里,注意通常情况下源码的压缩格式都为 *.tar.gz 格式。
下载源码
cd ~/rpmbuild/SOURCES
wget wget http://ftp.gnu.org/gnu/hello/hello-2.10.tar.gz
编辑SPEC文件
cd ~/rpmbuild/SPECS
vim hello.spec
打开发现已经有一些模版了,填入:
Name:     hello
Version:  2.10
Release:  1%{?dist}
Summary:  The "Hello World" program from GNU
Summary(zh_CN):  GNU "Hello World" 程序
License:  GPLv3+
URL:      http://ftp.gnu.org/gnu/hello
Source0:  http://ftp.gnu.org/gnu/hello/%{name}-%{version}.tar.gz
BuildRequires:  gettext
Requires(post): info
Requires(preun): info
%description
The "Hello World" program, done with all bells and whistles of a proper FOSS
project, including configuration, build, internationalization, help files, etc.
%description -l zh_CN
"Hello World" 程序, 包含 FOSS 项目所需的所有部分, 包括配置, 构建, 国际化, 帮助文件等.
%prep
%setup -q
%build
%configure
make %{?_smp_mflags}
%install
make install DESTDIR=%{buildroot}
%find_lang %{name}
rm -f %{buildroot}/%{_infodir}/dir
%post
/sbin/install-info %{_infodir}/%{name}.info %{_infodir}/dir || :
%preun
if [ $1 = 0 ] ; then
/sbin/install-info --delete %{_infodir}/%{name}.info %{_infodir}/dir || :
fi
%files -f %{name}.lang
%doc AUTHORS ChangeLog NEWS README THANKS TODO
%license COPYING
%{_mandir}/man1/hello.1.*
%{_infodir}/hello.info.*
%{_bindir}/hello
%changelog
* Sun Dec 4 2016 Your Name <youremail@xxx.xxx> - 2.10-1
- Update to 2.10
* Sat Dec 3 2016 Your Name <youremail@xxx.xxx> - 2.9-1
- Update to 2.9
Group标签过去用于按照 /usr/share/doc/rpm-/GROUPS 分类软件包。目前该标记已丢弃,vim的模板还有这一条,删掉即可,不过添加该标记也不会有任何影响。
构建RPM包
rpmbuild -ba hello.spec
OK,执行成功,看看结果:
 michael@localhost  ~/rpmbuild  tree *RPMS
RPMS
└── x86_64
    ├── hello-2.10-1.el7.x86_64.rpm
    └── hello-debuginfo-2.10-1.el7.x86_64.rpm
SRPMS
└── hello-2.10-1.el7.src.rpm
1 directory, 3 files
安装 RPM 包
sudo rpm -ivh ~/rpmbuild/RPMS/x86_64/hello-2.10-1.el7.x86_64.rpm
运行:
$ hello
Hello, world!
$ which hello
/usr/bin/hello
$ rpm -qf `which hello`
hello-2.10-1.el7.centos.x86_64
$ man hello
附录
rpmbuild 目录结构
michael@localhost  ~/rpmbuild  tree . -L 3
.
├── BUILD
│   └── hello-2.10
│       ├── ABOUT-NLS
│       ├── aclocal.m4
│       ├── AUTHORS
│       ├── build-aux
│       ├── ChangeLog
│       ├── ChangeLog.O
│       ├── config.h
│       ├── config.in
│       ├── config.log
│       ├── config.status
│       ├── configure
│       ├── configure.ac
│       ├── contrib
│       ├── COPYING
│       ├── debugfiles.list
│       ├── debuglinks.list
│       ├── debugsources.list
│       ├── doc
│       ├── elfbins.list
│       ├── GNUmakefile
│       ├── hello
│       ├── hello.1
│       ├── hello.lang
│       ├── INSTALL
│       ├── lib
│       ├── m4
│       ├── maint.mk
│       ├── Makefile
│       ├── Makefile.am
│       ├── Makefile.in
│       ├── man
│       ├── NEWS
│       ├── po
│       ├── README
│       ├── README-dev
│       ├── README-release
│       ├── src
│       ├── stamp-h1
│       ├── tests
│       ├── THANKS
│       └── TODO
├── BUILDROOT
├── RPMS
│   └── x86_64
│       ├── hello-2.10-1.el7.x86_64.rpm
│       └── hello-debuginfo-2.10-1.el7.x86_64.rpm
├── SOURCES
│   └── hello-2.10.tar.gz
├── SPECS
│   └── hello.spec
└── SRPMS
    └── hello-2.10-1.el7.src.rpm
17 directories, 37 files
configure、make、make install 命令的区别
- configure它是个- shell脚本,- ./configure那么就是运行这个 shell 脚本啦!- ./configure是用来检测你的安装平台的目标特征的。比如它会检测你是不是有- CC或- GCC,
 并不是需要- CC或- GCC。这一步一般用来生成- Makefile,为下一步的编译做准备。 可以通过在- configure后加上参数来对安装进行控制。例如,- ./configure --prefix=/usr。意思是将该软件安装在- /usr下面,执行文件就会安装在- /usr/bin(如果不指定,默认的路径是- /usr/local/bin),
 资源文件就会安装在- /usr/share(而不是默认的- /usr/local/share)。可以通过- ./configure --help察看详细的说明帮助。之前就写过一篇文章 CentOS 源码编译安装 Python3
- make是用来编译的,它从- Makefile中读取指令,然后编译。如果 在 make 过程中出现 error ,你就要记下错误代码(注意不仅仅是最后一行),然后你可以向开发者提交 bugreport(一般在 INSTALL 里有提交地址),或者你的系统少了一些依赖库等,这些需要自己仔细研究错误代码。
- make install就是把编译出来的二进制文件,库,配置文件等等放到相应目录下
- make uninstal是卸载,不加参数就是默认的进行源代码编译。
- make clean清除编译结果
make 是 Linux 开发套件里面自动化编译的一个控制程序,他通过借助 Makefile 里面编写的编译规范(语法很多,类似一个可以运行的脚本程序。反正我是看不懂,所以你也别问我怎么编写)。进行自动化的调用 gcc 、ld 以及运行某些需要的程序进行编译的程序。
一般情况下,他所使用的 Makefile 控制代码,由 configure 这个设置脚本根据给定的参数和系统环境生成。
Makefile是什么东东?有什么用?怎么用?
makefile 是用于自动编译和链接的,一个工程有很多文件组成,每一个文件的改变都会导致工程的重新链接--但是不是所有的文件都需要重新编译,makefile 能够纪录文件的信息,决定在链接的时候需要重新编译哪些文件。
cc 和 gcc 又是什么?
从名字上看,老的 Unix 系统的 CC 程序叫做 C Compiler 。但 GCC 这个名字按 GNU 的说法叫做 Gnu Compiler Collection ,注意这是一个编译器集合,不仅仅是 c 或 c++。gcc 包含很多编译器(C, C++, Objective-C, Ada, Fortran,and Java) 。所以它们是不一样的,一个是一个古老的 C 编译器,一个是编译器的 Gnu 的编译器的集合(Gcc里的 C 编译器比 CC 强大太多了,所以你没必要用 CC)。
cc 是 gcc 的连接。cc 来自于昂贵的 Unix 系统,cc 是商业软件,gcc 是编译器。
GCC 可以用来编译 C/C++、FORTRAN、JAVA、OBJC、ADA等语言的程序,可根据需要选择安装支持的语言。
参考
- 开源中国-RPM包的制作 对构建目录介绍的比较仔细
- RPM打包原理、示例、详解及备查 很详细,有示例
- 如何构建 RPM 包 Linux 中国的文章,赞
- Fedora-WIKI-How to create an RPM package/zh-cn 中文介绍
- JIN-YANG-RPM 包制作 总结很全,还介绍了签名
- CSDN-RPM构建 - RPM构建 - 简单实例 该博主,总共围绕 RPM 构建写了几篇文章的
- 月与灯依旧-linux rpm包编译过程(spec文件和spec宏 ) 这个博主的文章看到过不止一次,赞
两份英文资料:
make gcc 命令了解的参考:
RPM 包的构建 - 实例的更多相关文章
- RPM 包的构建 - SPEC 基础知识
		spec 文件 制作 rpm 软件包并不是一件复杂的工作,其中的关键在于编写软件包的 spec 描述文件. 要想制作一个 rpm 软件包就必须写一个软件包描述文件 spec.这个文件中包含了软件包的诸 ... 
- 全面学习 Python 包:包的构建与分发
		首发于公众号:Python编程时光 1. 为什么需要对项目分发打包? 平常我们习惯了使用 pip 来安装一些第三方模块,这个安装过程之所以简单,是因为模块开发者为我们默默地为我们做了所有繁杂的工作,而 ... 
- RPM包制作方法
		一.RPM介绍 RPM 前是Red Hat Package Manager 的缩写,本意是Red Hat 软件包管理,顾名思义是Red Hat 贡献出来的软件包管理:现在应为RPM Package M ... 
- 安装软件包的三种方法、RPM包介绍、rpm、yum工具用法、yum搭建本地仓库
		第5周第3次课(4月18日) 课程内容: 7.1 安装软件包的三种方法7.2 rpm包介绍7.3 rpm工具用法7.4 yum工具用法7.5 yum搭建本地仓库 7.1 安装软件包的三种方法 rpm工 ... 
- Linux下基于官方源代码RPM包构建自定义MySQL RPM包
		rpmbuild时不要以root用户执行! 方法一: 1.首先安装rpmbuild #yum install rpm-build gcc gcc-c++ cmake bison ncurses-dev ... 
- RPM包构建
		参考资料 https://docs-old.fedoraproject.org/en-US/Fedora_Draft_Documentation/0.1/html-single/RPM_Guide/i ... 
- 自制mysql的rpm包
		MySQL安装一般使用RPM或者源码安装的方式.RPM安装的优点是快速,方便.缺点是不能自定义安装目录.如果需要调整数据文件和日志文件的存放位置,还需要进行一些手动调整.源码安装的优点是可以自定义安装 ... 
- 部分rpm包总结描述
		acl-2.2.51-15.el7.x86_64 Commands for Manipulating POSIX(可移植操作系统接口 of unix) Access Control Lists.有ge ... 
- RPM包的制作
		RPM包的制作 前言 按照其软件包的格式来划分,常见的Linux发行版主要可以分为两类,类ReadHat系列和类Debian系列,这两类系统分别提供了自己的软件包管理系统和相应的工具. 类RedHat ... 
随机推荐
- 七牛 qshell 全命令实践
			七牛API服务的命名行测试工具,参考文档 七牛开发者中心 命令行工具(qshell) 实践目的 安装 account 设置ak.sk stat 查看文件状态 buckets/listbucket/do ... 
- 教你如何用笔记本设置超快WIFI
			以win7为例 1.在主菜单运行框输入 cmd------->以管理员的身份运行 2.命令提示符中输入:netsh wlan set hostednetwork mode=allow ssid ... 
- 剑指offer——python【第29题】最小的K个数
			题目描述 输入n个整数,找出其中最小的K个数.例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,. 思路 先排序后取数,排序可以用冒泡,插入,选择,快排,二分法等等, ... 
- Python学习之旅(十)
			Python基础知识(9):函数(Ⅰ) Python中函数的定义:是逻辑结构和过程化的一种编程方法 定义方法: def test(x): #def:定义函数的关键字 test:函数名 x:形参,也可以 ... 
- 使用强类型DataSet增加数据并获取自动增长的ID
			使用强类型的DataSet可以方便的操作数据库:有时候我们会对表的ID设置为自动增长,并且需要在插入数据后获取新插入数据的ID,按以下方法即可达到目的: 一. 首先建立一个表,id为自动增加, ... 
- shop_z 一套非常适合二次开发的php后台管理系统
			QQ群:247823727 如果你需要定制某些功能开联系群主,价格实惠,后期交接完善,有上手培训 shop_z基础thinkphp5 php7上开发运行,速度杠杠的 地址:https://gitee ... 
- ML.NET 0.10特性简介
			IDataView被单独作为一个类库包 IDataView组件为表格式数据提供了非常高效的处理方式,尤其是用于机器学习和高级分析应用.它被设计为可以高效地处理高维数据和大型数据集.并且也适合处理属于更 ... 
- [No0000D1]WPF—TreeView无限极绑定集合形成树结构
			1.如图所示:绑定树效果图 2.前台Xaml代码: <Window x:Class="WpfTest.MainWindow" xmlns="http://schem ... 
- Java-idea-常用插件
			一.插件安装 settings→plugins→直接搜索框搜索,没有选择Browse Respositories→找到需要安装的插件,install即可 二.常用插件 插件名称 简介 地址 备注 ... 
- Windows 下运行Makefile文件
			下载并安装Microsoft Visual Studio2017 配置环境变量: 计算机右击-属性-高级系统设置-环境变量-选择Path编辑-添加nmake的路径: D:\Microsoft Visu ... 
