精通RPM之--制作篇(中)
一个RPM的软件包描述文件,可以仅生成一个父包或一个子包,也可以生成一个父包和多个子包。通过设定子包选项,可以使生成的子包采用"软件名-子包名" 的标准命名,也可使生成的子包采用自己的名字。一个子包,通常是按照其包含的文件的用途或类型来归并文件进而打成包裹的。象前面的LZE描述文件很简单, 它将所有文件都包含进了父包中。我们也可以将文件分类作成子软件包,如可分成执行程序子包(lze-bin),配置文件子包(lze-config)和说明文档包(lze-doc)。我们还可以只分出一个配置文件子包(lze-config),其余文件均打入父包中(lze)。通过这样详细地分类,有助于用户管理软件包,避免安装多余的东西,同时也有助于升级。要想创建子软件包,必须描述以下内容:
1. %package :
用此段创建一个子包。其名字由子包选项控制。子包选项为"[-n] 子包名",不选-n时,生成的子包文件为"软件名-子包名-版本号-释出号.体系.rpm";选-n时,生成的子包文件为"子包名-版本号-释出号.体系.rpm"。其应用格式为:
%package 子包选项
2. Summary
此域必须在%package下面,它定义子包功能简介(一句话说明)。格式为:
Summary : 子包简介
3. Group
此域必须在%package下面,其定义子包所属软件类别(软件类别请参见<<精通RPM之五--查询篇>>)。格式为:
Group : 软件类别
4. %description :
此描述段的内容是较为详细的子包功能介绍,介绍为文本形式,格式不作要求,可任意换行或分段。格式为:
%description 子包选项
...介绍子包功能的内容...
5. %files :
此文件段的内容是子包所要包含的文件列表。文件列表中,一个文件占用一行,还可使用多种文件修饰符。(详见<<精通RPM之七--制作篇(上)>>)
段名应用格式为:
%files 子包选项 [-f 文件名]
注意: 上述%description与%files段所用的子包选项形式,必须与%package所用的子包选项形式一致,否则的话,它们定义的不是同一个子包,RPM检查时将报错退出。如定义过%package name后,描述段名须用%description name,文件段名须用%files name方可。而用%description -n name则不行,%files -n name也不行。
子软件包也可使用%pre,%post,%preun,%postun,%triggerin,%triggerun和%triggerpostun等七个可选的功能段,因为它们都可使用子包选项。当使用子包选项时,它们的段内容就是用来管理子软件包的脚本程序。要注意的是,这些段使用的子包选项形式也必须与%package段使用的子包选项形式一致。
条件语句的使用
在软件包描述文件中,可以灵活地使用条件语句,位置不限制。这些语句,用于当前体系与操作系统的判断,当条件为真或为假时,RPM均会引用其相应的描述内容。
条件语句有两种格式:
1. {%ifarch,%ifnarch,%ifos,%ifnos} 值1 [值2] ...
描述内容
%endif
注: {}所括内容必选其中之一,[]所括为可选项,各个值之间以空格分隔,%endif表示条件语句结束。
此语句的含义是:
1) 使用%ifarch时,表示如果当前体系为值1或值2...,则引用描述内容。
2) 使用%ifnarch时,表示如果当前体系不为值1或值2...,则引用描述内容。
3) 使用%ifos时,表示如果当前操作系统为值1或值2...,则引用描述内容。
4) 使用%ifnos时,表示如果当前操作系统不为值1或值2...,则引用描述内容。
如果想在LZE包描述文件的文件段增加只适用于sparc体系的文件/etc/sparc.lze和 /etc/sparc.ime,则可在文件段内加入如下语句:
%ifarch sparc
/etc/sparc.lze
/etc/sparc.ime
%endif
这样做以后,如果当前体系为sparc,则RPM在打包时会加入这两个文件。
2. {%ifarch,%ifnarch,%ifos,%ifnos} 值1 [值2] ...
描述内容1
%else
描述内容2
%endif
注: {}所括内容必选其中之一,[]所括为可选项,各个值之间以空格分隔,%else表示另外一种情况,%endif表示条件语句结束。
此语句的含义是:
1) 使用%ifarch时,表示如果当前体系为值1或值2...,则引用描述内容1,否则引用描述 内容2。
2) 使用%ifnarch时,表示如果当前体系不为值1或值2...,则引用描述内容1,否则引用描述内容2。
3) 使用%ifos时,表示如果当前操作系统为值1或值2...,则引用描述内容1,否则引用描述内容2。
4) 使用%ifnos时,表示如果当前操作系统不为值1或值2...,则引用描述内容1,否则引用描述内容2。
如果想根据当前操作系统来确定LZE包的名字,则可在描述文件头使用如下语句定义Name域:
%ifos linux
Name : lzeforlinux
%else
%ifos aix
Name : lzeforaix
%else
Name : lzeforothersys
%endif
%endif
本例中使用了嵌套的条件语句,它说明的情况是:如果操作系统为linux,则软件名定为lzeforlinux,如果操作系统为aix,则软件名定为lzeforaix,如果不是上述两个操作系统,则将软件名定为lzeforothersys。
如何在描述文件中使用宏(macros)
1. 宏是什么?
学过C语言的人都知道,宏是用来实现文本替换的,即定义了宏名与宏体后,文件中所有有宏名的地方在预处理时将被宏体替换掉。使用宏可以减少文字的录入量,方便了编程人员。在软件包描述文件中使用宏,也是基于这个目的,只不过这个宏与C语言的宏定义格式不同而已。
2. 宏的定义
描述文件中宏的定义格式为:
%define [(opts)]
注: []所括为可选项。为宏名,宏名可用字母,数字和下划线(_),并且其长度最小为3。opts为一个或多个选项,各选项之间无分隔,选项采用getopt函数要求的形式,即选项为单个字符,如果某个选项需要参数,则需要在这个选项后加个冒号(:)。为宏体,它周围的空字符将被删掉。宏体的内容须在一行上。
如没有选项的宏定义:
%define aaa "This is my software"
如仅有一个选项的宏定义:
%define xxx(p:Z) echo %{-p:%{-p*}} %{-Z}
3. 宏的使用
宏的使用格式为:
% [opt1] [opt2]... [arg1] [arg2]...
或
%{} [opt1] [opt2]... [arg1] [arg2]...
注: []所括为可选项;为所应用的宏名,宏名可以用{}括住;opt1,opt2...为选项,均须以减号(-)开头,并且如果选项需要参数,则必须提供一个选项参数;arg1,arg2...则为宏的参数。
如上面定义的xxx宏,可这样使用:
%xxx -p zhsoft hello world<
br>
例子中,xxx宏使用一个选项-p,zhsoft为-p选项的参数,还有两个宏的参数hello和world。
注意: 宏使用时最好多换一行(即宏下面空一行),因为宏在扩展后并不换行,这样如果不多换行,则下面一行若有内容的话,宏扩展后的内容将和下面一行的内容合并在一起,极容易出现错误。这也是笔者发现RPM宏的问题之一。还有一个问题,如果注释行上存在宏,则这个宏也将扩展,错矣!因为注释本来就是要忽略掉的,有宏也不必再扩展了。这两个问题都需要引起RPM开发者的注意,并切实加以解决。
4. 宏体专用的宏
宏体中可使用如下专用的宏:(类似SHELL形式的宏)
1) %0 : 表示所在宏的宏名;
2) %* : 表示宏的所有参数;
3) %# : 表示宏的参数个数;
4) %{-f} : 表示如果宏使用了-f选项,则它表示-f及其选项参数;
5) %{-f*} : 表示如果宏使用了-f选项,则它表示-f所带的参数;
6) %{-f:X} : 表示如果宏使用了-f选项,则它表示X;
7) %{!-f:Y} : 表示如果宏没有使用-f选项,则它表示Y;
8) %1,%2,... : 表示宏的参数1,参数2...
如,上例中xxx宏执行时,若宏体中有上述专用的宏,则专用宏将会扩展为:
1) %0扩展为xxx;
2) %*扩展为hello world;
3) %#扩展为2;
4) %{-p}扩展为-p zhsoft;
5) %{-p*}扩展为zhsoft;
6) %{-p:good}扩展为good;
7) %{!-Z:bad}扩展为bad; (因为xxx宏未使用-Z选项)
8) %1为hello,%2为world,没有其它参数。
5. 系统内置的宏
系统内置的宏可分如下三类:
5.1 定义类
1) %define ... : 定义一个宏;(原来,%define也是一个宏啊)
2) %undefine ... : 取消一个宏;(宏取消后,此语句下面的描述文件就不能再使用这个宏了,即使使用,该宏也不会被扩展了)
5.2 调试类
1) %trace : 打印宏扩展前后的调试信息;
2) %dump : 打印活动的宏(宏名及宏体);
3) %{echo:...} : 打印...到标准错误设备;
4) %{warn:...} : 打印...到标准错误设备;
5) %{error:...} : 打印...到标准错误设备,并且返回BADSPEC值;
5