duanjigang 发表于 2012-12-16 18:19

Linux平台软件管理系统设计与规划-进阶篇(2)-rpm生成:rpmbuild 和 spec文件剖析

本帖最后由 duanjigang 于 2012-12-22 22:47 编辑

转载请保留作者信息和来自CU的原站
在第一篇文章中,我们介绍了 rpm 文件的基本概念,协议格式等基础知识。最近几周一直在断断续续的谋划第二篇的内容,终于定下来:以 RPM 文件的制作为使用情景,
主要介绍 rpm 生成工具 rpmbuild 和 rpm 定义文件 spec 文件。

其中 rpmbuild 部分针对rpmbuild 的使用方法,如何使用该命令来制作rpm文件,step by step.
另外,大多数内容以 spec 文件的语法为主,只有彻底掌握spec 中的各种玄机,才能对 rpm 的生成掌握牢固。
废话不多,让我们开始!

duanjigang 发表于 2012-12-16 18:22

本帖最后由 duanjigang 于 2012-12-16 18:31 编辑

在演讲PPT<<2012系统架构师大会-Linux平台软件管理系统设计与规划.pptx>>有这样一幅图,是说明 rpm 是如何产生的。:wink:


从图中我们可以看到,rpm 的制作过程跟美食的制作工艺很相仿,我们的源代码其实就是要熬粥的大米,豆子等原料。另外,食谱会告诉你,大米放多少,水放多少,豆子放多少,rpm制作中的 spec 文件也是类似功能,记录了如何制作rpm,用什么制作rpm等,然后,原料和食谱准备好了,还需要工具,熬粥的砂锅~~~,要烹制 rpm 这道菜,也需要工具,那就是rpmbuild工具(当然其它生成rpm文件的命令也可以)。

砂锅按照食谱上的规范把大米和豆子加工成美味的粥。
rpmbuild按照spec文件中的规范把源码加工成功能强大的rpm包。
:m01:

duanjigang 发表于 2012-12-16 18:37

本帖最后由 duanjigang 于 2012-12-17 09:37 编辑

从 wget 的 rpm 制作开始

借鉴了 IBM 开发社区的文章,我们的话题也从一个例子 rpm 的制作展开。这个例子软件是wget,版本时1.14。
对于大多数从事开发的同学来说,安装 wget 的方法很可能是直接下载源码,解压缩,configure,make,make install 就OK了。
我们在这里会介绍如果用源码包制作标准的二进制 rpm 和 源码 rpm.

首先,看看系统提供的rpm制作环境是什么样的,大多数从事系统管理的同学都知道,linux 系统自带的rpm 生成环境在 /usr/src/redhat 目录下,
包含的目录以及作用是:
BUILD:rpmbuild 命令在这个目录进行代码编译
RPMS: rpmbuild 命令会把最终生成的 rpm 文件存储在这个目录。
SOURCES: 制作 rpm 的源码都应该放在这个目录中。
SPECS:制作rpm时用到的spec 文件应该放在这个目录。
SRPMS: rpmbuild 生成的 源码rpm包会存储在这个目录下。
几个月前用openssl的srpm做的rpm就是这样流程,先 rpm 安装 openssl 的源码包,openssl 和众多patch文件都被安装到
/usr/src/redhat/SOURCES/
目录下了,对应的spec文件也被安装到
/usr/src/redhat/SPECS
目录下了。
我们要做的就是一条命令
rpmbuild -ba /usr/src/redhat/SPECS/openssl.spec
即可完成 rpm 的制作,生成的 rpm 存储路径是:
/usr/src/redhat/RPMS/i386/openssl-0.9.8b-8.3.i386.rpm
本文要说的,是在自定义目录下通过非root用户来制作rpm,而不是使用root帐号,在系统默认工作目录下制作rpm,为什么建议不要用root用户来编译生成rpm,在后面的内容中会涉及到,在此先不说了。

duanjigang 发表于 2012-12-16 19:04

本帖最后由 duanjigang 于 2012-12-17 10:26 编辑

wget 源码包制作rpm

首先下载wget 的源码包wget-1.14.tar.gz,然后在个人目录下建立 RPM 的工作目录:
/home/jigang.djg/lessons/rpmbuild_dir
然后建立对应的几个目录:
$mkdir BUILDRPMSSOURCESSPECSSRPMS
$ls /home/jigang.djg/lessons/rpmbuild_dir
BUILDRPMSSOURCESSPECSSRPMS
把源码挪到 SOURCES目录下.
然后编写 wget.spec 文件。

参考
http://www.ibm.com/developerworks/library/l-rpm1/
这里的例子,编写的 spec 文件内容如下:

SPECS/wget.spec
# This is a sample spec file for wget
%define _topdir   /home/jigang.djg/lessons/rpmbuild_dir
%define namewget
%define release1
%define version1.14
%define buildroot %{_topdir}/%{name}-%{version}-root

BuildRoot:%{buildroot}
Summary:   GNU wget
License:   GPL
Name:    %{name}
Version:   %{version}
Release:   %{release}
Source:   %{name}-%{version}.tar.gz
Prefix:   /usr
Group:    Development/Tools

%description
The GNU wget program downloads files from the Internet using the command-line.

%prep
%setup -q

%build
./configure
make

%install
make install prefix=$RPM_BUILD_ROOT/usr

%files
%defattr(-,root,root)
#这也是wget默认的安装目录
/usr/bin/wget
#文档的安装路径也要根据wget的默认路径写,否则可能出错,如果你不自己写 --prefix=xx的话
#如果有报错的话,就根据wget-1.14-root里面的列表进行spec文件校准

%doc %attr(0444,root,root) /usr/share/man/man1/wget.1.gz
然后进行rpm的编译:
rpmbuild -v -bb SPECS/wget.spec
并没有完美的生成rpm,而是报了一堆错误。

部分信息如下:
error: Installed (but unpackaged) file(s) found:
   /usr/etc/wgetrc
   /usr/share/info/wget.info.gz
   /usr/share/locale/be/LC_MESSAGES/wget.mo
   /usr/share/locale/bg/LC_MESSAGES/wget.mo
根据提示,分析下出错的原因。

因为在用 wget 的源码编译安装时 make install 会把很多文件(wget-1.14-root下面的所有文件)都安装到目标目录,而我们在 $install 段写的脚本也正好是是 make install(或者你可以逐行的写 install 安装单个文件)。但是在%file 段却没有把所有 make install 到 wget-1.14-root 下的文件都写出来,因此 rpmbuild 在封装包时会报错,他提示我们: “找到了install 却没有 packaged 的文件”,这个提示是正确的。

解决这个问题有以下三个方法:

其一:也是最简单的做法,就是把 “installed but unpackaged” 的文件补充到spec 文件的 files 列表当中去。
其二: 从常理思考,虽然build出了一大堆文件,但是只把一部分封装到rpm文件中,这个做法应该是可以接受的,因为某些时候,我们就只需要一部分重要的文件,别的man文件或许暂时不需要。然后该怎么做呢?人性化的配置是好的软件不和缺少的,rpm 当然自带了这个参数的配置项。

在文件:
/usr/lib/rpm/macros
中有一个配置项:
# Should unpackaged files in a build root terminate a build?
#
# Note: The default value should be 0 for legacy compatibility.
%_unpackaged_files_terminate_build 1
从字面意思应该能看懂,“是否应该在build root 目录发现未封装进包的文件时终止编译?”
系统默认这个值为 1,因此我们的编译会被终止。

然后将它改为0,再次 build,发现还是报错?
原因又何在呢?

查看帮助手册
man rpmbuild
能够看到 rpmbuild 使用的宏定义文件的路径:
/usr/lib/rpm/macros
       /usr/lib/rpm/redhat/macros
       /etc/rpm/macros
       ~/.rpmmacros
而且生效顺序是从上往下的,这时可以理解,我们在/usr/lib/rpm/macros 文件中把
%_unpackaged_files_terminate_build 1
改为 %_unpackaged_files_terminate_build 0
后,在 /usr/lib/rpm/redhat/macros 文件中它还是 1,因为这个值被覆盖了。
为了能够生效,可以把这个配置写到
~/.rpmmacros
或者
/etc/rpm/macros
文件中,在此,我们写进 /etc/rpm/macros 文件中。
echo "%_unpackaged_files_terminate_build 0" >> /etc/rpm/macros
再次编译,果然通过,输出了 rpm 文件
Wrote: /home/jigang.djg/lessons/rpmbuild_dir/RPMS/i386/wget-1.14-1.i386.rpm
Wrote: /home/jigang.djg/lessons/rpmbuild_dir/RPMS/i386/wget-debuginfo-1.14-1.i386.rpm
然后我们看下rpm的信息:
rpm -qpl RPMS/i386/wget-1.14-1.i386.rpm
/usr/bin/wget
/usr/share/man/man1/wget.1.gz
能够看到,不纳入到 %files 中的文件确实是 installed but unpackaged 了,呵呵.

其三:就是把不想封装进包的文件从build输出的目录删掉。
http://blog.163.com/hui_san/blog/static/5710286720125272350508/

这里有个例子,如是说:
make install后删除这些文件:

rm -rf %{buildroot}
make INSTALL_ROOT=%{buildroot} install

rm -rf %{buildroot}/.channels/.alias/pear.txt %{buildroot}/.channels/.alias/pecl.txt %{buildroot}/.channels/__uri.reg %{buildroot}/.channels/pear.php.net.reg %{buildroot}/.channels/pecl.php.net.reg %{buildroot}/.depdb %{buildroot}/.depdblock %{buildroot}/.filemap %{buildroot}/.lock
可以借鉴上面的做法。

不过个人还是不建议这样做,最合适的做法就是把缺少的文件补充进去。
把 installed but unpackaged 的文件添加进spec 后,spec 文件如下:
# This is a sample spec file for wget

%define _topdir   /home/jigang.djg/lessons/rpmbuild_dir
%define namewget
%define release1
%define version1.14
%define buildroot %{_topdir}/%{name}-%{version}-root

BuildRoot:%{buildroot}
Summary:   GNU wget
License:   GPL
Name:    %{name}
Version:   %{version}
Release:   %{release}
Source:   %{name}-%{version}.tar.gz
Prefix:   /usr
Group:    Development/Tools

%description
The GNU wget program downloads files from the Internet using the command-line.

%prep
%setup -q

%build
./configure--with-ssl=openssl
make

%install
make install prefix=$RPM_BUILD_ROOT/usr

%files
%defattr(-,root,root)
/usr/bin/wget
/usr/etc/wgetrc
/usr/share/info/wget.info.gz
/usr/share/locale/be/LC_MESSAGES/wget.mo
/usr/share/locale/bg/LC_MESSAGES/wget.mo
/usr/share/locale/ca/LC_MESSAGES/wget.mo
/usr/share/locale/cs/LC_MESSAGES/wget.mo
/usr/share/locale/da/LC_MESSAGES/wget.mo
/usr/share/locale/de/LC_MESSAGES/wget.mo
/usr/share/locale/el/LC_MESSAGES/wget.mo
/usr/share/locale/en_GB/LC_MESSAGES/wget.mo
/usr/share/locale/eo/LC_MESSAGES/wget.mo
/usr/share/locale/es/LC_MESSAGES/wget.mo
/usr/share/locale/et/LC_MESSAGES/wget.mo
/usr/share/locale/eu/LC_MESSAGES/wget.mo
/usr/share/locale/fi/LC_MESSAGES/wget.mo
/usr/share/locale/fr/LC_MESSAGES/wget.mo
/usr/share/locale/ga/LC_MESSAGES/wget.mo
/usr/share/locale/gl/LC_MESSAGES/wget.mo
/usr/share/locale/he/LC_MESSAGES/wget.mo
/usr/share/locale/hr/LC_MESSAGES/wget.mo
/usr/share/locale/hu/LC_MESSAGES/wget.mo
/usr/share/locale/id/LC_MESSAGES/wget.mo
/usr/share/locale/it/LC_MESSAGES/wget.mo
/usr/share/locale/ja/LC_MESSAGES/wget.mo
/usr/share/locale/lt/LC_MESSAGES/wget.mo
/usr/share/locale/nb/LC_MESSAGES/wget.mo
/usr/share/locale/nl/LC_MESSAGES/wget.mo
/usr/share/locale/pl/LC_MESSAGES/wget.mo
/usr/share/locale/pt/LC_MESSAGES/wget.mo
/usr/share/locale/pt_BR/LC_MESSAGES/wget.mo
/usr/share/locale/ro/LC_MESSAGES/wget.mo
/usr/share/locale/ru/LC_MESSAGES/wget.mo
/usr/share/locale/sk/LC_MESSAGES/wget.mo
/usr/share/locale/sl/LC_MESSAGES/wget.mo
/usr/share/locale/sr/LC_MESSAGES/wget.mo
/usr/share/locale/sv/LC_MESSAGES/wget.mo
/usr/share/locale/tr/LC_MESSAGES/wget.mo
/usr/share/locale/uk/LC_MESSAGES/wget.mo
/usr/share/locale/vi/LC_MESSAGES/wget.mo
/usr/share/locale/zh_CN/LC_MESSAGES/wget.mo
/usr/share/locale/zh_TW/LC_MESSAGES/wget.mo

%doc %attr(0444,root,root) /usr/share/man/man1/wget.1.gz

然后我们还是把%_unpackaged_files_terminate_build 改为1

重新rpmbuild,这次终于成功了。
rpm -qpl RPMS/i386/wget-1.14-1.i386.rpm
也能看到新添加进去的filelist.

至此,简单的RPM总算制作成功了,看下包的信息:
rpm -qpi RPMS/i386/wget-1.14-1.i386.rpm
Name      : wget                         Relocations: /usr
Version   : 1.14                              Vendor: (none)
Release   : 1                           Build Date: 2012年12月15日 星期六 14时32分31秒
Install Date: (not installed)               Build Host: localhost.localdomain
Group       : Development/Tools             Source RPM: wget-1.14-1.src.rpm
Size      : 2032997                        License: GPL
Signature   : (none)
Summary   : 一个使用 HTTP 或 FTP 协议来检索文件的工具。
Description :
GNU Wget 是一个文件检索工具,它既可以使用在
HTTP 协议上,也可以使用在 FTP 协议上。Wget
的功能包括:当您注消后在背景内运行的能力,
递归地目录检索,文件名通配符匹配,远程文件
时间戳贮存和比较,与 FTP 服务器一起使用 Rest
和与 HTTP 服务器一起使用 Range 来在缓慢和不
可靠的连接上检索文件,对代理服务器的支持,以及可配置性

send_linux 发表于 2012-12-17 09:23

非常不错,感谢原创!

duanjigang 发表于 2012-12-17 09:24

本帖最后由 duanjigang 于 2012-12-17 09:57 编辑

问题讨论:

lofeng410   2012-12-16 22:55
    关于你在“Linux平台软件管理系统设计与规划-进阶篇(2)-rpm生成:rpmbuild 和 spec文件剖析”的帖子
    请教个spec文件中语句的问题哈:
    我使用的kernel.spec中有这么一句:
    %if0%{?__debug_package:1},这个语句是什么意思呢?其中的0,?,:1分别起什么作用呢?
    google也没有找到相关说明,还请兄弟指点下哈

@lofeng410
能否把那段对应的spec 文件贴出来?

chinafenghao 发表于 2012-12-17 09:49

@duanjigang
强力支持段总。

duanjigang 发表于 2012-12-17 11:56

本帖最后由 duanjigang 于 2012-12-17 12:19 编辑

关于 rpmbuild 的用法可以参考 man 手册,在这里,我们着重对spec文件的语法细节进行说明。
SPEC 文件语法解析

一个spec 文件其实就是一个普通人类可读的文本文件,只不过这个文件由众多个 entry (entries)组成,每个不同的 entry 有不同的用法。构成spec 文件的entry 大致可以分为一下几类:
    Comments — 人类可读的字符串,会被RPM忽略,就是为了注释,备注而生,方便人们理解spec文件。
    Tags — 在spec 中定义数据

    Scripts — 脚本,在rpm生成,安装,升级,卸载等过程的一些时间点执行。

    Macros — 宏定义,主要是控制rpm的执行流程,为了执行不同的命令。

    %files— 定义 RPM 中将要包含的文件列表。

    Directives — (指令),在%files 中,使得rpm能够针对不同的file进行不同的处理。

    Conditionals — 条件,根据不同的操作系统,处理器架构,进行不同的配置,处理。
comments

comments 也就是常说的注释,在 spec 文件中导出都可以写,就为了方便阅读理解。rpm 生成时会过滤注释。
比如我们在 openssl.spec 中看到的注释:
# Install a makefile for generating keys and self-signed certs, and a script
# for generating them on the fly.
mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/pki/tls/certs
install -m644 %{SOURCE2} $RPM_BUILD_ROOT%{_sysconfdir}/pki/tls/certs/Makefile
install -m755 %{SOURCE6} $RPM_BUILD_ROOT%{_sysconfdir}/pki/tls/certs/make-dummy-cert

duanjigang 发表于 2012-12-17 12:19

本帖最后由 duanjigang 于 2012-12-17 12:33 编辑

Tags

Tags 数据或者标签定义。

Tage 一般都被定义在spec 文件的顶端,通过

Tag 名称: Tag取值
的方式来定义。Tag 不是大小写敏感的,要注意这点。
我们在Spec中常见的Tag 有:

vendor: 产生软件的机构名称

比如:
VeNdOr : White Socks Software, Inc.
vendor:White Socks Software, Inc.
VENDOR    :    White Socks Software, Inc.
上面三行对spec 文件来说是一样的。

包命名Tag: Name,Version和Release

比如:
Name: openssl
Version: 0.9.8e
Release: 22%{?dist}.4
描述Tags:

%description: 对包进行详细的描述。比如:
%description
The OpenSSL toolkit provides support for secure communications between
machines. OpenSSL includes a certificate management tool and shared
libraries which provide various cryptographic algorithms and
protocols.
还有:
summary
copyright
distribution
icon
vendor
url
group
packager
这些tags,都是对包的描述信息,基本上可以通过 rpm 的 -i 参数看到这些信息,比如:
rpm -qpi /usr/src/redhat/RPMS/x86_64/openssl-1.0.0i-1.x86_64.rpm
Name      : openssl                      Relocations: (not relocatable)
Version   : 1.0.0i                            Vendor: (none)
Release   : 1                           Build Date: Sat 21 Apr 2012 01:32:28 PM CST
Install Date: (not installed)               Build Host:test.localhost.mysite.com
Group       : System Environment/Libraries   Source RPM: openssl-1.0.0i-1.src.rpm
Size      : 3294837                        License: GPL
Signature   : (none)
Packager    : Damien Miller <djm@mindrot.org>
URL         : http://www.openssl.org/
Summary   : The OpenSSL toolkit
Description :
The OpenSSL toolkit provides support for secure communications between
machines. OpenSSL includes a certificate management tool and shared
libraries which provide various cryptographic algorithms and
protocols.

duanjigang 发表于 2012-12-17 14:19

本帖最后由 duanjigang 于 2012-12-17 20:20 编辑

Dependency (依赖性)TAGS:


我们都知道,一个软件不可能把所有功能都实现了,调用或者借助别的软件来实现自身功能是很常见的一种做法,比如,开发网络相关程序的同学会经常需要安装libpcap,做规则处理或者高速匹配应用的程序可能需要pcre库,做 mysql 数据库开发的需要libmysql或者 libmysql++,通讯程序的用libevent,ICE等等。

总之,在不同的应用范畴内,我们几乎都需要借助别的软件来实现自己软件要达到的功能。

对于 rpm 也存在这样的情况:安装B软件,它需要A软件的功能支持,因此,在安装B之前,需要把A安装成功;卸载C软件时,D软件还用到C软件的功能,因此不能直接卸载C,或者需要卸载掉D之后,再卸载C,或者为了D的正常运转,C就不能卸载掉。这是最常见的依赖。

因此,RPM 的 SPEC 语法中提供了 Dependency(依赖性)这个TAG,当然,SPEC 中的依赖性 TAG 设计的比较灵活,可以说是一个比较普适的Dependency 语法。这些会在介绍中看到。

为了详细说明 Dependency ,我们设计了两个例子包,一个叫 test-baby-1.1,另外一个叫 test-daday-1.1

首先看 provides:
provides: 主要是说明本包提供了什么,这里的provides 的取值可以是任何字符串,代表了一个虚拟的包,这个tag的最常用场景就是多个包提供了相同的功能,为了标识他们提供的相同功能可用,着多个包之间就可以provides 出来一个同名的虚拟 package,一旦任何一个包被安装了,只要虚拟的package可用,则依赖于这个功能的软件包就能够安装了。

看下三个包的spec 文件中的 Requires 和 Provides tag是怎么写的:

daddy.spec
#daddy.spec
Requires:                 baby-is-provided
baby.spec
Provides:                 baby-is-provided
girl.spec
Provides:                 baby-is-provided
然后编译生成三个rpm包。
RPMS/x86_64/test-baby-1.1-1.x86_64.rpm
RPMS/x86_64/test-daddy-1.1-1.x86_64.rpm
RPMS/x86_64/test-girl-1.1-1.x86_64.rpm
看下 test-daddy 的Require 和 test-girl 和 test-baby 的 Provides
rpm -qp RPMS/x86_64/test-daddy-1.1-1.x86_64.rpm --requires
/bin/sh
baby-is-provided
libc.so.6()(64bit)
libc.so.6(GLIBC_2.2.5)(64bit)
rpmlib(CompressedFileNames) <= 3.0.4-1
rpmlib(PayloadFilesHavePrefix) <= 4.0-1
rtld(GNU_HASH)

rpm -qp RPMS/x86_64/test-baby-1.1-1.x86_64.rpm --provides
baby-is-provided
test-baby = 1.1-1

rpm -qp RPMS/x86_64/test-girl-1.1-1.x86_64.rpm --provides
baby-is-provided
test-girl = 1.1-1
能够看到,test-girl 和 test-baby 都提供了 test-daddy 需要的 requires.
直接安装 test-daddy 看下:
rpm -ivh RPMS/x86_64/test-daddy-1.1-1.x86_64.rpm
error: Failed dependencies:
        baby-is-provided is needed by test-daddy-1.1-1.x86_64
提示: "baby-is-provided" 未被提供。

我们尝试安装 test-girl 或者 test-baby,然后再安装test-daddy
sudo rpm -i RPMS/x86_64/test-baby-1.1-1.x86_64.rpm
$ sudo rpm -i RPMS/x86_64/test-daddy-1.1-1.x86_64.rpm
rpm -qa test-daddy
test-daddy-1.1-1
这次确实能成功安装了。
sudo rpm -e test-baby
error: Failed dependencies:
        baby-is-provided is needed by (installed) test-daddy-1.1-1.x86_64
也能够看到 test-baby 通过的 “baby-is-provided” 被 test-daddy 使用着,不能卸载。
然后:
sudo rpm -i RPMS/x86_64/test-girl-1.1-1.x86_64.rpm
$ sudo rpm -e test-baby
这次,test-baby 能够卸载了,因为新安装的 test-girl 也提供了虚拟包 "baby-is-provided" 供 test-daddy 依赖。
到此,相信已经对 Provides 理解透彻了吧。


其次是 requirestag:
provides 提供了虚拟包或者实体的包,requires 表明自己需要哪些包为前提,只有requires 的包安装了,才能安装当前包
使用 requires 注意版本的书写,如果你的应用明确需要某个版本的第三方包的话,可以写上版本,如果没有特殊版本需要,建议还是不要写,因为很可能当你的程序从rhel4升级到rhle5或者rhel6时,require 的包版本也升级了,如果写 :
requires pkgname = 1.23
这样的,很可能在5u 或者 6u的 机器上就需要重现改写spec文件生成rpm了。
requires 支持包的版本运算符有5个。
requires: pkgname= 1.2-2
requires: pkgname> 1.2
requires: pkgname>= 1.2
requires: pkgname< 1.2
requires: pkgname<= 1.2-5
没有不等于运算符。


另外还有 conflicts

conflicts与requires 相反, Requires 说明 “我必须与这个包一起安装在这台机器上”,而 conflicts则表明:“我不能与这个(版本的)包共处一台机器上”。
我们稍微修改下 test-baby 的spec 文件:
rpm -qp RPMS/x86_64/test-girl-1.1-1.x86_64.rpm --provides
baby-is-provided
test-girl = 1.1-1
$ rpm -qa test-girl
test-girl-1.1-1
$ rpm -ivh RPMS/x86_64/test-baby-1.1-1.x86_64.rpm
error: Failed dependencies:
        baby-is-provided conflicts with test-baby-1.1-1.x86_64
能够看到, test-girl provides 了 “baby-is-provided”,而 test-baby conflicts with "baby-is-provided"
因此,当 test-girl 安装后, test-baby 的安装就会失败。


还有一个比较恶心的tag是 serial ,这个tag 专门是为了当版本比较不能够标明包的新旧时,用serial 的值来标识。
serial大的rpm 就是新包,从根本上不建议使用这个tag。当你用到这个tag区分版本时,说明你的rpm 已经管理的比较乱了。呵呵。

最后一个是不太用却比较重要的 Tag:autoreqprov

autoreqprov是用来自动产生 rpm 依赖的,它的取值为 yes 或者no, 1 或者 0,
当autoreqprov tag 打开时,在 rpm 包编译的时候,会执行以下操作:
(1):所有打包进rpm 的二进制程序需要的共享库都会被分析出来,然后打包进rpm 的requirements 中。
(2):所有该rpm 提供的 so 文件的名字都会被自动添加到该RPM的 provides 中。
以 test-baby 为例,没有配置 autoreqprov 时 autoreq 默认 为 1,看下它的Requires
$ rpm -qp RPMS/x86_64/test-baby-1.1-1.x86_64.rpm --requires
/bin/sh
libc.so.6()(64bit)
libc.so.6(GLIBC_2.2.5)(64bit)
rpmlib(CompressedFileNames) <= 3.0.4-1
rpmlib(PayloadFilesHavePrefix) <= 4.0-1
rtld(GNU_HASH)
加上: autoreq: 0
后,再看:
rpm -qp RPMS/x86_64/test-baby-1.1-1.x86_64.rpm --requires
/bin/sh
rpmlib(PayloadFilesHavePrefix) <= 4.0-1
rpmlib(CompressedFileNames) <= 3.0.4-1
很明显可以看到,对于 libc 的共享库的自动添加 requires 被取消了。provides 的自动添加,大家可以自己测试。
页: [1] 2 3 4 5
查看完整版本: Linux平台软件管理系统设计与规划-进阶篇(2)-rpm生成:rpmbuild 和 spec文件剖析