RPM 系列文章:

打包目录

rpm 打包目录有一些严格的层次上的要求。

rpm 的版本 <=4.4.xrpmbuid 工具其默认的工作路径是 /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 是用来检测你的安装平台的目标特征的。比如它会检测你是不是有 CCGCC

    并不是需要 CCGCC。这一步一般用来生成 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等语言的程序,可根据需要选择安装支持的语言。

参考

两份英文资料:

make gcc 命令了解的参考:

RPM 包的构建 - 实例的更多相关文章

  1. RPM 包的构建 - SPEC 基础知识

    spec 文件 制作 rpm 软件包并不是一件复杂的工作,其中的关键在于编写软件包的 spec 描述文件. 要想制作一个 rpm 软件包就必须写一个软件包描述文件 spec.这个文件中包含了软件包的诸 ...

  2. 全面学习 Python 包:包的构建与分发

    首发于公众号:Python编程时光 1. 为什么需要对项目分发打包? 平常我们习惯了使用 pip 来安装一些第三方模块,这个安装过程之所以简单,是因为模块开发者为我们默默地为我们做了所有繁杂的工作,而 ...

  3. RPM包制作方法

    一.RPM介绍 RPM 前是Red Hat Package Manager 的缩写,本意是Red Hat 软件包管理,顾名思义是Red Hat 贡献出来的软件包管理:现在应为RPM Package M ...

  4. 安装软件包的三种方法、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工 ...

  5. Linux下基于官方源代码RPM包构建自定义MySQL RPM包

    rpmbuild时不要以root用户执行! 方法一: 1.首先安装rpmbuild #yum install rpm-build gcc gcc-c++ cmake bison ncurses-dev ...

  6. RPM包构建

    参考资料 https://docs-old.fedoraproject.org/en-US/Fedora_Draft_Documentation/0.1/html-single/RPM_Guide/i ...

  7. 自制mysql的rpm包

    MySQL安装一般使用RPM或者源码安装的方式.RPM安装的优点是快速,方便.缺点是不能自定义安装目录.如果需要调整数据文件和日志文件的存放位置,还需要进行一些手动调整.源码安装的优点是可以自定义安装 ...

  8. 部分rpm包总结描述

    acl-2.2.51-15.el7.x86_64 Commands for Manipulating POSIX(可移植操作系统接口 of unix) Access Control Lists.有ge ...

  9. RPM包的制作

    RPM包的制作 前言 按照其软件包的格式来划分,常见的Linux发行版主要可以分为两类,类ReadHat系列和类Debian系列,这两类系统分别提供了自己的软件包管理系统和相应的工具. 类RedHat ...

随机推荐

  1. D - Windows Message Queue

    来源hdu1509 Message queue is the basic fundamental of windows system. For each process, the system mai ...

  2. PHP7.1安装xdebug

    一.前言1. Xdebug 简介Xdebug 是一个开放源代码的 PHP 程序调试器(即一个Debug工具),可以用来跟踪,调试和分析PHP程序的运行状况.当前最新版本为 Xdebug 2.5.0. ...

  3. 山东13年省赛 Aliceand Bob

    Problem F: Alice and Bob Description Alice and Bob like playing games very much.Today, they introduc ...

  4. sql中join与left-join图解区别

      select a.* from YG_BRSYK a left join(SELECT DISTINCT SYXH, STUFF((SELECT '.'+MS FROM #lsb where SY ...

  5. socket 编程中。 服务端用到多线程

    客户端连接服务端之后, 服务端会生成与客户端交换信息的socket. 在服务端实现多线程: 为每个连接创建一个线程进行信息交换. import threading from socket import ...

  6. [No0000C6]Visual Studio 2017 函数头显示引用个数

    Visual Studio 2017  函数头显示引用个数

  7. 从光盘安装ubuntu系统

    参考博客: https://www.jianshu.com/p/7929e4911206

  8. 【English】【托业】【四六级】写译高频词汇

    大家都知道,四六级翻译每次考的话题不可能原句直接重复,但是,在研究了近几年的四六级真题后,我们惊奇地发现: 写译词汇在重复考! 写译词汇在重复考! 写译词汇在重复考! 因此,小编为大家整理了四六级写译 ...

  9. byte转bit

    由于项目需要,传过来的数据是高位到低位的Byte,需要输出低位到高位的bool数组. public static bool[] getBits(byte[] byt) { bool[] ret = n ...

  10. Linux常用总结

    CentOS 7.0中一个最主要的改变,就是切换到了systemd.它用于替代红帽企业版Linux前任版本中的SysV和Upstart,对系统和服务进行管理.systemd兼容SysV和Linux标准 ...