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 包:

  1. yum install -y rpm-build

也可以安装 rpmdevtools,这个工具部包含一些其他工具,依赖 rpm-build,所以直接安装会将 rpm-build 装上:

  1. yum install -y rpmdevtools

Python 的编译打包工具是 setuptools

工具使用

rpmbuild 命令使用一套标准化的「工作空间」 ,生成 %_topdir 工作目录 ~/rpmbuild,以及配置文件 ~/.rpmmacros

  1. rpmdev-setuptree

rpmdev-setuptree这个命令就是安装 rpmdevtools 带来的。可以看到运行了这个命令之后,在 $HOME 家目录下多了一个叫做 rpmbuild 的文件夹,里边内容如下:

  1. $ tree rpmbuild
  2. rpmbuild
  3. ├── BUILD
  4. ├── RPMS
  5. ├── SOURCES
  6. ├── SPECS
  7. └── 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 文件里内容,比如:

  1. michael@localhost ~ cat .rpmmacros
  2. %_topdir %(echo $HOME)/rpmbuild
  3. %_smp_mflags %( \
  4. [ -z "$RPM_BUILD_NCPUS" ] \\\
  5. && RPM_BUILD_NCPUS="`/usr/bin/nproc 2>/dev/null || \\\
  6. /usr/bin/getconf _NPROCESSORS_ONLN`"; \\\
  7. if [ "$RPM_BUILD_NCPUS" -gt 16 ]; then \\\
  8. echo "-j16"; \\\
  9. elif [ "$RPM_BUILD_NCPUS" -gt 3 ]; then \\\
  10. echo "-j$RPM_BUILD_NCPUS"; \\\
  11. else \\\
  12. echo "-j3"; \\\
  13. fi )
  14. %__arch_install_post \
  15. [ "%{buildarch}" = "noarch" ] || QA_CHECK_RPATHS=1 ; \
  16. case "${QA_CHECK_RPATHS:-}" in [1yY]*) /usr/lib/rpm/check-rpaths ;; esac \
  17. /usr/lib/rpm/check-buildroot

生成 SPEC 文件

最最最重要的 SPEC 文件,命名格式一般是“软件名-版本.spec”的形式,将其拷贝到 SPECS 目录下。

如果系统有 rpmdevtools 工具,可以用 rpmdev-newspec -o name.spec 命令来生成 SPEC 文件的模板,然后进行修改:

  1. [root@localhost ~]# rpmdev-newspec -o myapp.spec
  2. Skeleton specfile (minimal) has been created to "myapp.spec".
  3. [root@localhost ~]# cat myapp-0.1.0.spec
  4. Name: myapp
  5. Version:
  6. Release: 1%{?dist}
  7. Summary:
  8. License:
  9. URL:
  10. Source0:
  11. BuildRequires:
  12. Requires:
  13. %description
  14. %prep
  15. %setup -q
  16. %build
  17. %configure
  18. make %{?_smp_mflags}
  19. %install
  20. rm -rf $RPM_BUILD_ROOT
  21. %make_install
  22. %files
  23. %doc

如果没有安装 rpmdevtools,也可以自己手动创建一个 spec 文件。

打包命令

rpmbuild/SPECS 目录下执行打包编译,切换到该目录下执行打包编译命令。

rpmbuild 命令选项

rpmbuild 命令的选项 rpmbuild 命令有不少选项,用得比较多的有:

  1. -bp 只解压源码及应用补丁
  2. -bc 只进行编译
  3. -bi 只进行安装到%{buildroot}
  4. -bb 只生成二进制 rpm
  5. -bs 只生成源码 rpm
  6. -ba 生成二进制 rpm 包和源码 rpm
  7. --target 指定生成 rpm 包的平台,默认会生成 i686 x86_64 rpm 包,但一般我只需要 x86_64 rpm

只生成二进制格式的 rpm 包

  1. rpmbuild -bb 软件名-版本.spec

用此命令生成软件包,生成的文件会在刚才建立的RPM目录下存在。

只生成 src 格式的 rpm 包

  1. rpmbuild -bs 软件名-版本.spec

生成的文件会在刚才建立的SRPM目录下存在。

只需要生成完整的源文件

  1. rpmbuild -bp 软件名-版本.spec

源文件存在目录 BUILD 下。可能对这个命令不太明白,这个命令的作用就是把 tar 包解开然后把所有的补丁文件合并而生成一个完整的具最新功能的源文件。

完全打包

  1. rpmbuild -ba 软件名-版本.spec

软件包制作完成后可用 rpm 命令查询,看看效果。如果不满意的话可以再次修改软件包描述文件,重新运行以上命令产生新的 RPM 软件包。

实例

将所有用于生成 rpm 包的源代码、 shell 脚本、配置文件都拷贝到 SOURCES 目录里,注意通常情况下源码的压缩格式都为 *.tar.gz 格式。

下载源码

  1. cd ~/rpmbuild/SOURCES
  2. wget wget http://ftp.gnu.org/gnu/hello/hello-2.10.tar.gz

编辑SPEC文件

  1. cd ~/rpmbuild/SPECS
  2. vim hello.spec

打开发现已经有一些模版了,填入:

  1. Name: hello
  2. Version: 2.10
  3. Release: 1%{?dist}
  4. Summary: The "Hello World" program from GNU
  5. Summary(zh_CN): GNU "Hello World" 程序
  6. License: GPLv3+
  7. URL: http://ftp.gnu.org/gnu/hello
  8. Source0: http://ftp.gnu.org/gnu/hello/%{name}-%{version}.tar.gz
  9. BuildRequires: gettext
  10. Requires(post): info
  11. Requires(preun): info
  12. %description
  13. The "Hello World" program, done with all bells and whistles of a proper FOSS
  14. project, including configuration, build, internationalization, help files, etc.
  15. %description -l zh_CN
  16. "Hello World" 程序, 包含 FOSS 项目所需的所有部分, 包括配置, 构建, 国际化, 帮助文件等.
  17. %prep
  18. %setup -q
  19. %build
  20. %configure
  21. make %{?_smp_mflags}
  22. %install
  23. make install DESTDIR=%{buildroot}
  24. %find_lang %{name}
  25. rm -f %{buildroot}/%{_infodir}/dir
  26. %post
  27. /sbin/install-info %{_infodir}/%{name}.info %{_infodir}/dir || :
  28. %preun
  29. if [ $1 = 0 ] ; then
  30. /sbin/install-info --delete %{_infodir}/%{name}.info %{_infodir}/dir || :
  31. fi
  32. %files -f %{name}.lang
  33. %doc AUTHORS ChangeLog NEWS README THANKS TODO
  34. %license COPYING
  35. %{_mandir}/man1/hello.1.*
  36. %{_infodir}/hello.info.*
  37. %{_bindir}/hello
  38. %changelog
  39. * Sun Dec 4 2016 Your Name <youremail@xxx.xxx> - 2.10-1
  40. - Update to 2.10
  41. * Sat Dec 3 2016 Your Name <youremail@xxx.xxx> - 2.9-1
  42. - Update to 2.9

Group标签过去用于按照 /usr/share/doc/rpm-/GROUPS 分类软件包。目前该标记已丢弃,vim的模板还有这一条,删掉即可,不过添加该标记也不会有任何影响。

构建RPM包

  1. rpmbuild -ba hello.spec

OK,执行成功,看看结果:

  1. michael@localhost ~/rpmbuild tree *RPMS
  2. RPMS
  3. └── x86_64
  4. ├── hello-2.10-1.el7.x86_64.rpm
  5. └── hello-debuginfo-2.10-1.el7.x86_64.rpm
  6. SRPMS
  7. └── hello-2.10-1.el7.src.rpm
  8. 1 directory, 3 files

安装 RPM 包

  1. sudo rpm -ivh ~/rpmbuild/RPMS/x86_64/hello-2.10-1.el7.x86_64.rpm

运行:

  1. $ hello
  2. Hello, world!
  3. $ which hello
  4. /usr/bin/hello
  5. $ rpm -qf `which hello`
  6. hello-2.10-1.el7.centos.x86_64
  7. $ man hello

附录

rpmbuild 目录结构

  1. michael@localhost ~/rpmbuild tree . -L 3
  2. .
  3. ├── BUILD
  4.    └── hello-2.10
  5.    ├── ABOUT-NLS
  6.    ├── aclocal.m4
  7.    ├── AUTHORS
  8.    ├── build-aux
  9.    ├── ChangeLog
  10.    ├── ChangeLog.O
  11.    ├── config.h
  12.    ├── config.in
  13.    ├── config.log
  14.    ├── config.status
  15.    ├── configure
  16.    ├── configure.ac
  17.    ├── contrib
  18.    ├── COPYING
  19.    ├── debugfiles.list
  20.    ├── debuglinks.list
  21.    ├── debugsources.list
  22.    ├── doc
  23.    ├── elfbins.list
  24.    ├── GNUmakefile
  25.    ├── hello
  26.    ├── hello.1
  27.    ├── hello.lang
  28.    ├── INSTALL
  29.    ├── lib
  30.    ├── m4
  31.    ├── maint.mk
  32.    ├── Makefile
  33.    ├── Makefile.am
  34.    ├── Makefile.in
  35.    ├── man
  36.    ├── NEWS
  37.    ├── po
  38.    ├── README
  39.    ├── README-dev
  40.    ├── README-release
  41.    ├── src
  42.    ├── stamp-h1
  43.    ├── tests
  44.    ├── THANKS
  45.    └── TODO
  46. ├── BUILDROOT
  47. ├── RPMS
  48.    └── x86_64
  49.    ├── hello-2.10-1.el7.x86_64.rpm
  50.    └── hello-debuginfo-2.10-1.el7.x86_64.rpm
  51. ├── SOURCES
  52.    └── hello-2.10.tar.gz
  53. ├── SPECS
  54.    └── hello.spec
  55. └── SRPMS
  56. └── hello-2.10-1.el7.src.rpm
  57. 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. 8、路由 router

    路由:router 用户功能 /user ----> index.html /user/login ----> login.html /user/reg ----> reg.html ...

  2. 【C++ mid-term exerises】

    1. 用掷骰子方式,模拟班级每个学号被随机抽点的概率. (12分) 具体要求如下: (1)设计并实现一个骰子类Dice. ① 数据成员sides表示骰子面数.构造时,指定骰子是6面,8面,还是其它数值 ...

  3. Spark SQL 之 Join 实现

    原文地址:Spark SQL 之 Join 实现 Spark SQL 之 Join 实现 涂小刚 2017-07-19 217标签: spark , 数据库 Join作为SQL中一个重要语法特性,几乎 ...

  4. JavaScript基础知识(函数)

    函数的基础 函数: 把实现相同功能的代码放到一个函数体中,当想实现这个功能时,直接执行这个函数即可:减少了的冗余:高内聚,低耦合--> 函数的封装: 函数:引用数据类型: var a = 10; ...

  5. jquery chrome中取select 的值一就返回了

    在 <div class="controls"> <select class="span2" data-val="true" ...

  6. RabbitMQ的消息确认机制

    一:确认种类 RabbitMQ的消息确认有两种. 一种是消息发送确认.这种是用来确认生产者将消息发送给交换器,交换器传递给队列的过程中,消息是否成功投递.发送确认分为两步,一是确认是否到达交换器,二是 ...

  7. js篇-解析url链接里面的参数名和参数值

    项目背景是,链接为:https://paladin.pingan.com.cn/jf/?appId=PA00200000000_01_APP&id=123456#/fundRank 要求拿到: ...

  8. map函数和filter函数 zip函数

    1.map函数 接收一个函数f和一个可迭代对象(列表,字典等),并通过把函数f依次作用在li每个元素上,得到一个新的list并返回 # -*-coding:utf8 -*- import reques ...

  9. 【UML】-NO.45.EBook.5.UML.1.005-【UML 大战需求分析】- 通讯图(Communication Diagram)

    1.0.0 Summary Tittle:[UML]-NO.45.EBook.1.UML.1.005-[UML 大战需求分析]- 通讯图(Conmunication Diagram) Style:De ...

  10. Python Scrapy爬虫速成指南

    序 本文主要内容:以最短的时间写一个最简单的爬虫,可以抓取论坛的帖子标题和帖子内容. 本文受众:没写过爬虫的萌新. 入门 0.准备工作 需要准备的东西: Python.scrapy.一个IDE或者随便 ...