制作篇(中)
一个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.3 特殊类
这类宏的默认值通常放在/usr/lib/rpm/macros文件中,用户通过编辑自己主目录(HOME)下的.rpmmacros文件(~/.rpmmacros),可重定义这类宏,改变其默认值,以供RPM在软件包制作,安装及查询时使用自己的定义。
这类宏的定义格式为:
%
注: 为宏名,为宏体。
1) %packager,%vendor,%distribution :
这三个宏用于定义描述文件中Packager,Vendor,Distribution三个可选域的默认的域值,即如果这三个域中有哪个未在描述文件中定义,且其相对应的宏有定义,则RPM会采用其对应的宏的宏体。
如我的~/.rpmmacros文件中有这样三行:
%vendor 纵横软件制作中心
%packager 雨亦奇
%distribution 小赵'2001
这样,软件包描述文件中再也不用定义那三个域了,由此制作出来的软件包在查询时,其打包者(Packager),销售商(Vendor)及发行版(Distribution)均自动搞定了,一劳永逸。
2) %buildroot,%_provides :
这两个宏定义软件包建包时用的根目录及软件包所提供的功能。它们在打包时不会象 上面那三个宏一样主动被RPM采用,而是必须在描述文件中写那么几行。即:
%vendor 纵横软件制作中心
%packager 雨亦奇
%distribution 小赵'2001
Buildroot : %buildroot
Provides : %_provides
3) %_topdir,%_builddir,%_rpmdir,%_sourcedir,%_specdir,%_srcrpmdir :
这六个宏都是RPM制作软件包时要用的,它们在/usr/lib/rpm/macros文件中的默认值为:
%_topdir %{_usrsrc}/dist
%_builddir %{_topdir}/BUILD
%_rpmdir %{_topdir}/RPMS
%_sourcedir %{_topdir}/SOURCES
%_specdir %{_topdir}/SPECS
%_srcrpmdir %{_topdir}/SRPMS
%_topdir宏定义的是RPM制作软件包时所用目录的顶层目录,一般为/usr/src/dist(%{_usrsrc} 宏的值为/usr/src)。在顶层目录下面,又有五个子目录:
编译连接源程序时用的目录,由%_builddir宏定义,常用BUILD;
生成的RPM执行程序包存放的目录,由%_rpmdir宏定义,常用RPMS;
软件源程序存放的目录,由%_sourcedir宏定义,常用SOURCES;
软件包描述文件存放的目录,由%_specdir宏定义,常用SPECS;
生成的RPM源程序包存放的目录,由%_srcrpmdir宏定义,常用SRPMS。 由于宏的递归特性,我们可以通过只定义%_topdir宏来达到改变%_builddir等五个宏的目的。(注意:%_builddir等五个宏的宏体如无特殊要求,尽量不要改变,它们是标准的定义,应该采用)这对于普通用户来说,意义非常重大。因为RPM默认的顶层目录/usr/src/dist并不是每个用户都可以随便使用的,普通用户更想在自己所有的目录下用RPM来制作些软件包。我也有这种想法,所以在~/.rpmmacros文件里加上这么一行:
%_topdir /usr/zzz/rpm
同时,在此宏定义的目录下面建立了RPM所需的子目录,使用命令为:
$ cd /usr/zzz
$ mkdir -p rpm/{BUILD,RPMS/i386,SOURCES,SPECS,SRPMS}
$
命令中的i386是RPM默认的体系名,RPM生成的执行程序包是存放在“RPMS/体系名”目录下面的。这么做以后,我就可以在自己的目录下制作RPM软件包了,象超级用户一样自由。
4)%_excludedocs,%_ftpport,%_ftpproxy,%_httpport,%_httpproxy,%_netsharepath :
这六个宏对RPM软件包的安装和查询起作用。
%_excludedocs : 如果其值定义为1,则RPM安装软件包时,对说明文档的默认作法是不安装;
%_ftpport : 此宏用于定义RPM默认的FTP端口;
%_ftpproxy : 此宏用于定义RPM默认的FTP代理服务器;
%_httpport : 此宏用于定义RPM默认的HTTP端口;
%_httpproxy : 此宏用于定义RPM默认的HTTP代理服务器;
%_netsharepath : 此宏用于定义RPM默认的网络共享目录,适用于网络文件系统(NFS)。 6. 一种特殊的宏
这种宏的用法是:
%(SHELL命令及其参数)
它的结果是取指定的SHELL命令的标准输出的结果作为描述文件内容的一部分。如软件包描述文件的某个部分需要加上当前日期,则可以用:
%(date +%Y-%m-%d)
执行后,该宏将扩展为类似2001-10-31的日期数据。用户不妨在自己的描述文件的预处理段(%prep)内加上这么两行试试:
%(date +%Y-%m-%d)
exit 1
注: exit 1用于中止RPM的执行。
描述文件模板
以下所有描述文件模板均以LZE软件包制作为例,以源程序现场编译后产生的文件为准生成软件包。描述文件中一般只描述必要的部分。另外,如果文件段的所有文件已存在于系统中,并且想直接利用打包,则可以去掉Source域,去掉RPM建包用功能段(%prep,%build,%install,%clean)。
1. 只有父包,没有任何子包:
此描述文件见<<精通RPM之七--制作篇(上)>>。此文件中还可以去掉几个可选的功能段, 如%pre,%post,%preun,%postun,%triggerin,%triggerun,%triggerpostun。这几个段在此文件中无实质用途,执行时仅显示RPM开始执行某个脚本程序的信息。此描述文件仅生成软件包lze-6.0-2.i386.rpm(父包)。
2. 有父包,也有子包:
描述文件如下:
1 # 文件名称: lze-6.0-2.spec1
2 # 文件功能: lze软件包描述信息
3 # 文件作者: 纵横软件制作中心雨亦奇 国防大学研究生二队赵建利
4 # 修改时间: 2001.10.31
5
6 Name: lze
7 Version: 6.0
8 Release: 2
9 Summary: 小赵全屏幕中英文多窗口多功能编辑器(LINUX/UNIX系统适用)
10 Group: Applications/Editors
11 License: Share
12 Source: http://zhsoft.myetang.com/lze-6.0-2.src.tgz
13
14 %description
15 小赵编辑器,是为使用SCO UNIX,LINUX多用户系统的广大用户专门设计的全屏幕多窗
16 口中英文多功能编辑器。
17 它主要有以下十大特点:1.全屏幕菜单操作。2.显示方式多样。3.块操作丰富。4.十
18 字制表功能强大。5.多窗口操作灵活自如。6.文件操作功能齐全。7.解释输出功能独具特
19 色。8.自带中文输入法(增强五笔和增强拼音),实用方便。9.十六进制编辑功能,如虎
20 添翼。10.即时翻译,按到即译。
21 总之,小赵编辑器会成为您在UNIX,LINUX系统上编制程序和书写一般性文稿的好帮手。
22 它将在工作中助您一臂之力,轻松上阵,游刃有余!
23
24 %prep
25 echo "预处理脚本程序(prep)开始执行"
26 %setup
27
28 %build
29 echo "编译连接脚本程序(build)开始执行"
30 make
31
32 %install
33 echo "安装脚本程序(install)开始执行"
34 make install
35
36 # 配置文件子包
37 %package config
38 summary : 小赵编辑器LZE的配置文件
39 group : Applications/Editors
40
41 %description config
42 小赵编辑器用配置文件包括功能键定义文件与
43 输入法控制文件,用户可根据实际情况加以修改。
44
45 %files config
46 %config /etc/funkey.def
47 %config /etc/inputme.def
48
49 # 说明文档子包
50 %package doc
51 summary : 小赵编辑器LZE的说明文档
52 group : Applications/Editors
53
54 %description doc
55 小赵编辑器说明文档,详细介绍了该编辑器的
56 命令行用法及内置的各项菜单的功能与操作,对用
57 户熟悉小赵编辑器有很大作用。
58
59 %files doc
60 %doc /usr/doc/lze-6.0/README
61 %doc /usr/doc/lze-6.0/LICENSE
62
63 # 父包文件段
64 %files
65 %defattr (-,root,root)
66 /usr/bin/lze
67 /usr/bin/lzeime.py
68 /usr/bin/lzeime.wb
69 /etc/wbzc.dat
70
此描述文件生成软件包有:lze-6.0-2.i386.rpm(父包),lze-config-6.0-2.i386.rpm(配置文件子包)和lze-doc-6.0-2.i386.rpm(说明文档子包)。
3. 没有父包,只有子包:
没有父包,意味着描述文件中可以没有父包的文件段(%files),请看下面的描述文件:
1 # 文件名称: lze-6.0-2.spec2
2 # 文件功能: lze软件包描述信息
3 # 文件作者: 纵横软件制作中心雨亦奇 国防大学研究生二队赵建利
4 # 修改时间: 2001.10.31
5
6 Name: lze
7 Version: 6.0
8 Release: 2
9 Summary: 小赵全屏幕中英文多窗口多功能编辑器(LINUX/UNIX系统适用)
10 Group: Applications/Editors
11 License: Share
12 Source: http://zhsoft.myetang.com/lze-6.0-2.src.tgz
13
14 %description
15 小赵编辑器,是为使用SCO UNIX,LINUX多用户系统的广大用户专门设计的全屏幕多窗
16 口中英文多功能编辑器。
17 它主要有以下十大特点:1.全屏幕菜单操作。2.显示方式多样。3.块操作丰富。4.十
18 字制表功能强大。5.多窗口操作灵活自如。6.文件操作功能齐全。7.解释输出功能独具特
19 色。8.自带中文输入法(增强五笔和增强拼音),实用方便。9.十六进制编辑功能,如虎
20 添翼。10.即时翻译,按到即译。
21 总之,小赵编辑器会成为您在UNIX,LINUX系统上编制程序和书写一般性文稿的好帮手。
22 它将在工作中助您一臂之力,轻松上阵,游刃有余!
23
24 %prep
25 echo "预处理脚本程序(prep)开始执行"
26 %setup
27
28 %build
29 echo "编译连接脚本程序(build)开始执行"
30 make
31
32 %install
33 echo "安装脚本程序(install)开始执行"
34 make install
35
36 # 配置文件子包
37 %package config
38 summary : 小赵编辑器LZE的配置文件
39 group : Applications/Editors
40
41 %description config
42 小赵编辑器用配置文件包括功能键定义文件与
43 输入法控制文件,用户可根据实际情况加以修改。
44
45 %files config
46 %config /etc/funkey.def
47 %config /etc/inputme.def
48
49 # 说明文档子包
50 %package doc
51 summary : 小赵编辑器LZE的说明文档
52 group : Applications/Editors
53
54 %description doc
55 小赵编辑器说明文档,详细介绍了该编辑器的
56 命令行用法及内置的各项菜单的功能与操作,对用
57 户熟悉小赵编辑器有很大作用。
58
59 %files doc
60 %doc /usr/doc/lze-6.0/README
61 %doc /usr/doc/lze-6.0/LICENSE
62
63 # 执行程序子包
64 %package bin
65 summary : 小赵编辑器LZE的执行程序
66 group : Applications/Editors
67
68 %description bin
69 小赵编辑器执行程序为lze,五笔输入法服务器执行程序
70 为lzeime.wb,拼音输入法服务器执行程序为lzeime.py。
71
72 %files bin
73 %defattr (-,root,root)
74 /usr/bin/lze
75 /usr/bin/lzeime.py
76 /usr/bin/lzeime.wb
77 /etc/wbzc.dat
78
此描述文件生成三个软件包:lze-config-6.0-2.i386.rpm(配置文件子包),lze-doc-6.0-2.i386.rpm(说明文档子包),lze-bin-6.0-2.i386.rpm(执行程序子包)。