以前写的一篇文档,文章重点在于讲清如何快速上手和会碰到的问题。并不是软件文档的中文翻译,要看大全或faq的见参考文献

1. 概述连同难点
这里的概述仅仅是我的理解。假如要获得准确全面的信息,建议阅读“参考文献”一章。

研发者需要书写一个后缀名为spec的文本文档(简称spec文档),该文档提供了将应用程式打包(package)必须的配置信息。研发者在填写完这个配置文档(就是spec文档)后,只需要运行打包软件rpmbuild(通常是输入命令行"rpmbuild -ba your_application.spec),rpmbuild读入spec文档上的配置信息,自动生成rpm包。书写spec文档的内容是打包者的主要工作。

这里有个关键,理解这个关键是阅读并正确书写spec文档的前提。

关键在于,rpm是为开源软件设计的打包软件,他假设软件的打包者对于要打包的软件并不熟悉,例如打包者对他(她)要打包的软件的熟悉度,只是知道如何获得源代码包并解压缩源代码包,然后“./configure;make;make install”。即使这样,打包者也能够成功地制作rpm包。假如不理解这点,您可能会误会打包过程中的“install”(意义见后文),就是普通用户安装程式中的“安装”。实际上,打包过程中的install仅仅是处理源代码包的一个步骤而已。后文会周详解释这个问题。

和通常商业打包软件不同的是,在spec文档中,您*能够*提供(通过配置Source变量)软件的源代码包的完整文档名(注意:不是完整路径!具体原因见后文)。几乎任何的开源软件都提供源代码包的文档名(例如hello-1.0.0.tar.gz)。打包系统会根据且*仅*根据文档名(和文档名一起提供的路径自动被忽略)在并且*仅仅在*某个特定目录找到这个源代码包。这里的“特定目录”由%/SOURCES指定,_topdir是环境变量,能够输入命令行rpmbuild --showrc查看这个变量,在redhat linux系统中,%的值是/usr/src/redhat,具体细节参考RPM Tutorial和Maximum RPM。

打包系统找到这个源代码包后,他会解压缩源代码包(解压缩至%/BUILD目录中)并且将当前工作目录转换到解压缩后的源代码包根目录里(这个阶段能够认为是prepare阶段,在spec文档中简写为%prep),然后他开始编译源代码包(这个阶段是build阶段,在spec文档中简写为%build),然后他会将编译出的binary文档安装(这个阶段是install阶段,在spec文档中简写为%install)到用户指定的某个目录(能够由$RPM_BUILD_ROOT这个环境变量访问)。接着打包系统进入清理阶段,他会删除一些打包过程中产生的临时文档(这个阶段是clean阶段,在spec文档中简写为%clean)。最后他会输出binary rpm包到%/RPMS/i386中(子目录是i386还是i486,i586,取决于系统的architecture配置),输出source rpm包到%/SRPMS/中。

注意!以上描述中的主语始终是“打包系统”,也就是说,上段中的各个动作都是在打包过程中发生的动作。就是您运行“rpmbuild -ba your_application.spec”后打包系统的一些自动的动作。 即使是install阶段,也只是打包过程中的一个阶段(这个阶段移动了某些临时文档)而已。和最终用户安装rpm包中的“安装”根本是两回事!!!

在cos系统中的spec文档,没有上文所说的“prepare,build”两个阶段,而所谓install阶段,我理解只是例行公事地把编译好的二进制文档移动到$RPM_BUILD_ROOT目录中去。

2. 一个spec文档的例子
spec文档实际上很简单。一个spec文档能够划分为三个部分(我的理解):必要信息,shell脚本(shell scripts),要打包的文档清单(file list,在spec文档中用%files标示)。

所谓必要信息,就是诸如公司名,源代码包名,打包者的名字之类的杂七杂八的信息,为什么要提供这些信息是显而易见的。其中的Source变量指定了源代码包的来源,我的例子给出了源代码包的文档名,有些spec文档会给出源代码包的url,但是结果和我这里没什么区别。对于打包系统来说,他会忽略掉url,提取出源代码包的文档名。BuildRoot变量设定了$RPM_BUILD_ROOT的值。

shell脚本是在打包连同运行安装程式的过程中必须运行的一些脚本程式,例如删除文档,移动文档,创建目录等等。在%prep,%build,%install,%clean各section下(每个section对应打包过程中的一个阶段)都是一些常见的shell脚本或命令。%setup -q是个宏,对应解压缩源代码包,进入源代码包目录等几个动作,您能够不使用这个宏而自己写脚本命令。但是使用宏显然方便很多。%setup的细节请参考Maximum RPM。

要打包的文档清单部分在spec文档中用%files标示,例如:
%files
#defattr的定义请参阅RPM HOWTO
辠attr(-,root,root)
#hello文档放入最后生成的安装包中,其安装路径为/usr/local/bin
/usr/local/bin/hello

打包者应该在文档清单部分中指定放入于安装包中的二进制文档名,打包者也要指定运行安装包后该文档最终应被安装到哪里。

例如上例中的"/usr/local/bin/hello",说明了hello这个可执行程式(打包系统会在$RPM_BUILD_ROOT下的相应子目录寻找hello)应被放入安装包中,运行安装包后hello将最终被安装到/usr/local/bin目录下。

以下是个spec文档的例子,完整的源代码,脚本连同spec文档见附件(附件找不着了!) :
#--------------------hello-1.0.0-1.spec----------------begin
Summary: a simple "hello world" app
Name:hello
Version: 1.0.0
Release: 1
Copyright: Commercial
URL: http://www.kodak.com
Source: %-%.tar.gz
Vendor: Kodak Inc.
Packager: Jerry Chen <jerry.chen@kodak.com>
Group: Applications/Multimedia
#指定了$RPM_BUILD_ROOT的值
BuildRoot:/var/tmp/%-%-%-root


辳cription
a simple "hello world" app. you can do nothing useful with it.

%prep
#解压缩源代码包,进入源代码包目录
%setup -q

%build
#就是make了
make

%install
rm -rf $RPM_BUILD_ROOT
#编译好的二进制文档安装到环境变量$RPM_BUILD_ROOT所指定的目录中去。
make DESTDIR="$RPM_BUILD_ROOT" install

%clean
rm -rf $RPM_BUILD_ROOT

%files
辠attr(-,root,root)
#hello文档放入最后生成的安装包中,其安装路径为/usr/local/bin