RPM制作
2.1 基本步骤
1) 取回软件的源代码和相关的补丁
2) 测试所需的补丁,以便于顺利的构建整个程序
3) 编辑spec文件
4) 把文件放到正确的位置
5) 使用RPM构建rpm包
2.2 目录结构
/usr/src/redhat/BUILD             编译时的临时目录
/usr/src/redhat/RPMS           存放RPM包
/usr/src/redhat/SOURCES  存放源代码和补丁
/usr/src/redhat/SPECS 存放控制文件--spec文件
/usr/src/redhat/SRPMS              存放源代码包
2.3编辑spec文件
要想制作一个RPM格式的软件包,需要编写软件包描述文件。其标准命名格式为:软件名-版本号-释出号.spec,这个文件,详细描述了有关该软件包的诸 多信息,如软件名,版本,类别,说明摘要,创建时要执行什么指令,安装时要执行什么操作,以及软件包所要包含的文件等等。有了这个文件,RPM就可以制作 出相应的包裹文件来。
2.4打包过程
下面总结一下运行 rpm -ba filename.spec 时,RPM 都做些什么:
1)读取并解析 filename.spec 文件
2)运行 %prep 部分来将源代码解包到一个临时目录,并应用所有的补丁程序。
3)运行 %build 部分来编译代码。
4)运行 %install 部分将代码安装到构建机器的目录中。
读取 %files 部分的文件列表,收集文件并创建二进制和源 RPM 文件。 源 RPM 文件简单地捆绑了 spec 文件和构建软件包用到的所有源文件和补丁文件。如果您选择分发它,则其他人可以很容易地用它重建您的软件。二进制 RPM 文件仅包含已编译的软件和如何安装的信息。
5)运行 %clean 部分来除去临时构建目录。

Spec文件的编辑
注释行
它以#号开头,起注解作用,可帮助用户理解所写的内容,但对软件包的生成不起任何作用。注释行可位于描述文件的任何位置。
文件头
文件头描述软件包的基本信息,它包含若干个域,其中有必选的域,也有可选的域。一个域占用一行,其描述格式为:
域名 : 域值
注意: 域名不分大小写,并且域值不能为空。
文件头必选域:
共有6个。
1. Name :
此域定义软件名。
2. Version :
此域定义版本号。仅当软件较以前有较大改变时才增加版本号。注: 版本号中不能含减号(-)字符。
3. Release :
此域定义释出号。若软件较以前改变较小,则仅增加释出号,不改变版本号。注: 释出号中亦不能含减号(-)字符。
RPM利用上述的Name(软件名),Version(版本号),Release(释出号)及体系号来命名软件包,如本例输出的包裹文件名为sip-2.4.3-1.i386.rpm。
4. Summary :
此域定义软件包简介。
5.  Group :
此域定义软件所属类别,本例的Developmet/Tools表示本软件属"开发/工具"类。
6. License :
此域定义软件适用的许可证或版权规则。该域也可用Copyright(版权)来定义,二者同意。许可证具体有: GPL(通用公共许可证,自由软件适用),BSD,MIT,Public Domain(公共域),Distributable(贡献),Commercial(商业),Share(共享)等。

Name:      sipVersion:    2.4Release:    3Summary:  This is a spec of sipGroup:      Development/ToolsLicense:     GPL


文件头可选域
下面介绍一些实用的可选域:
1. Requires :
此域定义软件包所需的功能,可重复多行。其描述格式为:
Requires : 功能1 [比较符1 [序列号1:]版本号1[-释出号1]]  ...
其中:
* []所括为可选项;
*   比较符可使用<(小于),>;(大于),=(等于),>;=(大于等于)或<=(小于等于);
*  序列号不选时,RPM默认为0;
*  功能之间的逗号可选,也可使用空格进行分隔。
例子:
Requires: aaa, bbb >;= 3.0, ccc < 2:5.0-1
注: 本例定义生成的包在安装时需要系统有如下功能:
(1) aaa(系统中已安装aaa包,或者已安装软件包中有软件包提供aaa虚包);
(2) bbb包已安装且版本要求大于等于3.0;
(3) ccc包已安装且版本要求小于序列号为2,版本号为5.0且释出号为1。
RPM在进行版本比较时,执行比较的顺序是; 先版本号,再释出号,最后比较序列号。通过比较,确定哪个版本较新,哪个版本较老。
2. Conflicts :
此域定义有哪些功能与本软件包相冲突(不能共存)。此域亦可在描述文件中书写多次。其描述格式形同Requires域,为:
Conflicts : 功能1 [比较符1 [序列号1:]版本号1[-释出号1]]
其含义同上。
举个例子:
Conflicts : xxx=1:2.0 yyy>;=3.0
注: 本例阐明生成的包冲突的功能有:
当系统中xxx包版本等于序列号为1且版本号为2.0时;
当系统中yyy包版本大于等于3.0时。

*** 依赖关系的自动实现 ***
一般情况下,当RPM建立一个软件包时,它要执行/usr/lib/rpm目录下的两个小程序。一个是find-requires,用于查找软件包所需的 共享库,这些库将以虚包的形式加入到该软件包所需的功能(Requires)之中。另一个是find-provides,它用于查找软件包所提供的共享 库,这些库将以虚包的形式加入到该软件包所提供的功能(Provides)之中。这两个程序都是SHELL程序,代码量虽小,但确实帮了软件包制作者一个 大忙--不必劳心费神地自己写这样的依赖关系了,因为程序均自动完成了。
下面三个域用于指示RPM是否执行这两个程序。
3. Autoreq :
此域用于指示RPM是否自动查找软件所需的共享库。仅当域值为no或0时,RPM不执行find-requires程序,否则均执行该程序。
4. Autoprov :
此域用于指示RPM是否自动查找软件提供的共享库。仅当域值为no或0时,RPM不执行find-provides程序,否则均执行该程序。
5. Autoreqprov :
此域用于指示RPM是否自动查找软件所需的共享库与其提供的共享库。仅当域值为no
或0时,RPM不执行find-requires与find-provides两个程序。此域相当于同时设定Autoreq
与Autoprov域值为指定之值。
注: 上述三个域在描述文件中,它们之间因为顺序的不同而结果会有所不同,一般以最后一个为准。如:
Autoreq : yesAutoreqprov : noAutoprov : yes
注: 本例虽然第一行允许执行find-requires,但第二行又不允许find-requires与find-provides两个程序运行,而第三行允 许find-provides运行,所以依照执行顺序,结果为不允许执行find-requires,而允许执行find-provides。
又如:
Autoreq : noAutoreqprov : yesAutoprov : no
注: 本例的结果为允许执行find-requires,而不允许执行find-provides。
6. Prefix :
此域定义可重定位的目录前缀,可在描述文件中书写多次。其描述格式为:
Prefix : 目录前缀1 [目录前缀2] ...
各目录前缀之间均以空格分隔。例如:
Prefix : /usr /etc
它也可写作:
Prefix : /usr Prefix : /etc
RPM利用可重定位的目录前缀,实现了软件包的重定位安装,使软件中的文件不必固定在某个绝对位置,这种做法很好。这样,安装时就可将该包中在/usr目录下的文件重定位到用户指定的目录,如:
# rpm -i --prefix /tmp sip-3.2.4-1.i386.rpm
或者:
# rpm -i --relocate /usr=/tmp sip-3.2.4-1.i386.rpm
注: 此命令安装sip包,将其中含/usr重定位目录前缀的文件定位到/tmp目录。如包中的/usr/bin/sip文件安装后,因重定位而成了/tmp/bin/sip。
7. Buildroot :
此域定义的是软件包所包含的文件共有的根目录,此根目录仅供RPM建立软件包时使用。即当RPM建立软件包时,将设定此目录为根(调用chroot函数),提取所需文件,生成软件包。
例如: 当Buildroot设定为/tmp时,对于sip包描述文件中所包含的/usr/bin/sip文件,RPM实际打包的则是/tmp/usr/bin/sip,但对生成的包查询后可以发现:原文件名并未改变,还是/usr/bin/sip。
此域的描述格式很简单:
Buildroot : 目录
如,上例可定义为:
Buildroot : /tmp
8. Source :
此域定义RPM打包时要包含的程序源码文件。这些文件一般先用tar命令打包,然后再用gzip压缩。一个描述文件中可包含多个Source域,当有多个 这样的域时,需要进行编号:第1个编为Source0(也可直接用Source),第2个编为Source1,第3个编为Source2等等。此域的描述 格式为:
Source[编号] : 源码文件
具体用法如:
Source0 : lze-6.0-2.tar.gzSource1 : lzeime-wb-6.0-2.tar.gzSource2 : lzeime-py-6.0-2.tar.gzSource3 : lze-lib-6.0-2.tar.gz
注: 此域值可以采用URL(统一资源定位)的形式,如
Source0: http://zhsoft.myetang.com/lze-6.0-2.tar.gz
采用这种形式,主要是给其它用户提供该源码的位置信息。在RPM制作源包时,它提取的是最后的文件名lze-6.0-2.tar.gz,而不是http://zhsoft.myetang.com/lze-6.0-2.tar.gz(URL前面的内容被RPM忽略了)。
9. NoSource :
在上例中,假如在打包时不想包含Source1与Source2定义的文件,那该怎么办?
办法之一是将其所在行删除掉;
办法之二是将其所在行注释掉(即所在行前面加#号);
办法之三就是定义Nosource域,此域可重复。其描述格式为:
NoSource : 源码域编号
本例可写作:
NoSource : 1NoSource : 2
注: 其中的1与2为编号,表示Source1和Source2。
功能段
功能段是描述软件包的重要数据和操作指令的段落,它包括段名与段内容两部分。功能段的段名都是以百分号(%)开始的,占用一行。功能段的段内容范围是这样 界定的:它从该功能段段名下一行开始到下一个功能段段名的前一行或到描述文件结束。另外要注意的是,各个功能段的位置是自由的,可放在文件头以下的任何位 置,不必拘泥某一固定位置。
必选的功能段
描述文件中,必选的功能段有:
1. %description
本段是描述段,段的内容是对软件包进行较为详细的介绍,不象文件头的Summary域仅用一句话说明。介绍的文本形式自由,可任意换行,不受限制。
本段段名描述格式是:
%description This is ….
2. %files
本段是文件段,它定义的是软件包需要包含哪些文件。本段通常放在描述文件尾部,以便于添加文件名,便于编辑。本段段名描述格式为:
%files  [-f 文件名]
当没有任何选项时,本段内容定义的是要打包的文件列表;
当选择-f选项时,RPM除了从文件段读取打包文件列表外,还将从指定的文件中读取要打包的文件列表。指定的文件中,一个文件名占用一行。文件段的内容格式为:
[修饰符1 [修饰符2] ...] 文件名
其中:修饰符是可选的,一个文件可以有多个修饰符,文件名必须以/开头(绝对路径形式)。
修饰符有以下几个:
* %doc :
此修饰符设定文件类型为说明文档
* %config :
此修饰符设定文件类型为配置文件
* %attr :
此修饰符设定文件的属性信息,使用格式为:
%attr(权限,属主,属组)
注: 权限常用数字形式(八进制),属主和属组可以是数字,也可以是字符串。如果文件的权限,属主和属组想使用系统默认值,则可用减号(-)表示它。
如下例采用两个修饰符,定义/etc/funkey.def文件的权限为755,属主默认,属组为root,类型为配置文件:
%attr(755,-,root) %config /etc/funkey.def
* %docdir :
此修饰符定义说明文档前缀,这样,后面所有含指定文件名作为前缀的文件,RPM打包时会将其类型统一设定为说明文档。
例如某描述文件的文件段中有这么三行:
/root/readme%docdir /root/root/mydoc.txt
此例指明/root为说明文档的前缀,因为/root/mydoc.txt在%docdir的下一行,所以RPM打包时会设定此文件的类型为说明文档。而/root/readme文件则不做此设定,因为它在%docdir定义之前。
通过此修饰符,用户可以很方便地设定说明文档一类的文件,因为它们通常固定在某个目录下面,有着共同的前缀。
*%defattr。它设定默认的文件属性,而非特定的某个文件。它一般放在文件段内容的第一行。
其使用格式为:
%defattr (权限,属主,属组)
其中: 权限,属主和属组都可以使用减号(-)。使用减号的属性将由系统设定。例如:
%defattr(022,zzz,zhsoft)
设定其后的所有文件权限为022,属主为zzz,属组为zhsoft;又如:
%defattr(-,zzz,-)
则是设定其后的所有文件属主为zzz,权限与属组由系统设置。
可选的功能段
描述文件中,可选功能段的内容都是些脚本程序。可选的功能段的描述格式为:
功能段名
可选的功能段可分为如下三类:
1.1.1. 建包用功能段:
RPM通过源程序来建立一个软件包时,要执行预处理,编译,安装和清理四项操作,分别对应于%prep,%build,%install和%clean四个段。
下面按其执行顺序逐段进行说明:
1. %prep :
此为预处理段,其内容为预处理脚本程序。该程序完成以下任务:
* 建立软件编译用目录;
* 将源程序解压缩;
* 通过打补丁,升级源程序;
在此脚本程序中,可使用如下宏命令:
%setup
这个宏利用系统中的gzip与tar等命令,来解压源程序包。RPM会自动探测源程序包是否压缩,如果压缩,它会用gzip将其解压缩,否则直接用tar命令展开包中文件。其使用格式为:
%setup
这个宏用来解压默认的源程序包(由文件头Source或Source0域指定)。
2. %build :
此为编译段,其内容为编译脚本程序。该程序完成源程序的编译和连接。一个最简单的例子就是程序中仅有一个make命令。这适用于大部分情况,因为多数软件 均有自己的makefile,这样通过make命令就可实现编译与连接。如果没有makefile的话,需要软件包制作者自己在编译段书写上一系列的编译 连接命令。
3. %install :
此为安装段,其内容是安装脚本程序。该程序将已编译连接好的执行程序或其它文件存放到指定目录下,这些程序或文件供RPM打包时使用。一个最简单的例子就是程序中仅用一个make install命令,从而完成安装。
4. %clean :
此为清理段,其内容是清理脚本程序。此程序在RPM制作好软件包后才执行,它通常是删除那些编译连接时产生的临时文件或目录。
1.1.2. 管理用功能段:
此类段用于软件包自身的管理(安装,卸载和校验),包括%pre,%post,%preun,%postun等功能段。
1.  %pre :
该段内容为安装前脚本程序。它在软件包安装之前执行,通常是检测操作环境,建立有关目录,清理多余文件等等,为软件包的顺利安装做准备。本段很少使用。
其段名格式为:
%pre
2. %post :
该段内容为安装后脚本程序。它在软件包安装完成之后执行,常用来建立符号连接,修改系统配置文件,运行ldconfig程序等,以利软件的正常运行。
其段名格式为:
%post
3. %preun :
该段内容为卸载前脚本程序。它在软件包卸载之前执行,主要为卸载做准备。具体如,要卸载的软件包中某个程序当前正在运行时,此脚本程序必须杀掉它,否则无法正确卸载。
其段名格式为:
%preun
4. %postun :
该段内容为卸载后脚本程序。它在软件包卸载后执行,完成卸载的缮后工作,如将系统配置文件inetd.conf改回原来的样子,重新运行一下ldconfig命令,将已卸载的共享库从缓冲文件ld.so.cache中删除等等。
其段名格式为:
%postun
1.1.3. 其它功能段
其它功能段只有一个,即%changelog。这个段的内容是软件维护记录,它记录每次软件维护的时间,维护人及其EMAIL,维护的项目等。
%changelog段内容格式为:
* 星期 月份 日子 年份 维护人 EMAIL
- 维护内容1
- 维护内容2
注: 每个维护记录均以*开头,星期,月份均须为英文缩写。维护内容多时可分行编写,
每行开头最好以减号(-)开头。例如:
%changelog* Sun Mar 21 2002  wyx   weiyx@dawning.com.cn-rebuild in the new environment-new modules added