1. 应用程序打包技术之一(源代码篇)
2. 应用程序打包技术之二(deb篇)
3. 应用程序打包技术之三(rpm 篇)
4. 应用程序打包技术之四(exe篇)
rpm 是 RedHat 系 Linux 使用的软件包格式。流行的 Linux 发行版:Fedora, RHEL, OpenSUSE, Oracle 包括国产的红旗 Linux,都采用 rpm 来管理软件包。
我不是很喜欢 rpm 软件包格式,原因主要有两个,一个是它的依赖关系很难处理,另一个是控制文件比较复杂。但是 rpm 包有着非常广泛的应用,也是一个提高生产力的重要工具。
像前一篇文章提到的一样,checkinstall 也可以用来打 rpm 包,但我不是很熟悉这个软件。这里我仅仅介绍如何使用原始的 rpm(rpmbuild) 工具来打 rpm 软件包。
和前面 deb 包使用 fakeroot 一样,rpmbuild 也是利用沙盒的方式来构建软件包,除了控制文件比较繁琐,过程可能还更自动一些。构建 rpm 包的工作目录默认是 /usr/src/redhat,如果您在 Debian 下安装了 rpm 这个软件包,它可能是 /usr/src/rpm。您可以使用 rpm --eval %_topdir 查看自己的 rpm 工作目录。
$ tree `rpm --eval %_topdir`
/usr/src/redhat
|-- BUILD
|-- RPMS
| |-- athlon
| |-- i386
| |-- i486
| |-- i586
| |-- i686
| `-- noarch
|-- SOURCES
|-- SPECS
`-- SRPMS
我们可以看到,/usr/src/redhat/ 下有几个子目录:SOURCES 用来存放源代码包,SPECS 用来存放 spec 控制文件,BUILD 用来解压源代码包和构建软件,RPMS 里存放的是打好的二进制应用程序 RPM 包,SRPMS 里存放的是打好的源代码 RPM 包。但是,我们应该知道 _topdir 是可以在 spec 文件中修改的,否则我们只能用 root 才能在默认的工作目录 /usr/src/redhat 下创建文件和执行命令。我们可以先把工作目录树拷贝到用户自己的目录中:
$ cp -r /usr/src/redhat ~/rpm
这样,我们就可以在用户目录 ~/rpm 下打 rpm 包了。打 rpm 包之前的准备工作只有两件:1. 准备好源代码包并放置在 SOURCES 目录下;2. 准备好 spec 控制文件并放在 SPECS 目录下。如何打源代码包我们已经在 《源代码篇》中介绍过,下面我们主要来介绍 spec 文件的格式。下面是一个实例 spec 文件。
$ more ~/rpm/SPECS/casnet.spec
%define _topdir /home/solrex/rpm
Name: casnet
Version: 1.3
Release: 1
License: GPL
Packager: Solrex Yang
Summary: CASNET Client
Group: Network
Source: %{name}-%{version}.tar.gz
URL: http://share.solrex.org/casnet/
Prefix: /usr%description
CASNET is a gui client for ip gateway of GUCAS(Graduate University of Chinese
Academy of Sciences), which is written in Python and PyGtk.%prep
%setup -q%build
%install
make -e PREFIX=%{prefix} install%files
%{prefix}/bin/casnetconf
%{prefix}/bin/casnet
%{prefix}/bin/casnet-gui
%{prefix}/share/casnet/casnetconf.py
%{prefix}/share/casnet/casnet.py
%{prefix}/share/casnet/casnet-gui.py
%{prefix}/share/casnet/pics/*.png
%{prefix}/share/applications/casnet.desktop
%{prefix}/share/icons/casnet.png
我们可以看到,spec 文件与 deb 包的 control 文件有很多相似之处:Name, Version, Release, License, Packager, URL 是软件的名称、版本、小版本、使用的协议、维护者和网址;Summary 和 %description 是软件的信息;Group 是软件所归类别。剩下的就有些不同了:Source 是指软件的源代码包名称,rpm 会到 SOURCES 目录下找这个包;Prefix 是软件的默认安装位置;%prep、%build、%install 下分别是软件的预处理、编译和安装命令;%files 是所有需要被打包进去的文件。
因此,作者需要将 spec 文件中的各个域填写正确。%prep 下的 %setup 宏一般是用来将源代码 tar 包释放到 BUILD 目录下;%build 下可以添加 %configure 宏和 make 命令,如果您的软件需要编译的话;%install 下是您的安装命令;%files 下是您程序运行所需要的全部文件,其路径即为您安装完软件后它应该在的位置。%{name} 可以用来指代 Name: 域的内容,%{version } 指代 Version: 域的内容,以此类推。
需要注意的是,rpmbuild 使用 BUILD/%{name}-%{version} 作为您的源代码包释放后的目录,进入其进行编译。因此当您使用 tar 打源代码包时,tar 包的顶层目录名应该为 %{name}-%{version} 而不是仅仅是 %{name},比如:
$ tar czvf casnet-1.3.tar.gz casnet-1.3
$ mv casnet-1.3.tar.gz ~/rpm/SOURCES
现在我们在 ~/rpm/SOURCES 下有了 casnet-1.3.tar.gz,在 ~/rpm/SPECS 目录下有了 casnet.spec,那么我们就可以使用下面的命令生成 rpm 包了。如果您的安装位置 Prefix 选择的是一个系统目录,比如 /usr, /usr/local 之类,您也许需要使用 root 权限来运行 rpmbuild 命令。
$ rpmbuild -ba ~/rpm/SPECS/casnet.spec
这样我们就能在 ~/rpm/RPMS/i386 目录下获得我们生成的 rpm 软件包了。rpmbuild 命令的执行过程是这样的:首先根据 spec 文件定位源代码包,然后将源代码包释放到 BUILD 目录下,使用 spec 文件中给出的命令编译和安装,然后将 spec 中列的文件提取出来,按照包信息打出来 rpm 包。
我们可以使用 rpm -qpi 命令来查看 rpm 包的信息,rpm -qpl 命令来查看 rpm 包所包含的文件列表:
$ rpm -qpi ~/rpm/RPMS/i386/casnet-1.3-1.i386.rpm
Name : casnet Relocations: /usr
Version : 1.3 Vendor: (none)
Release : 1 Build Date: Thu 26 Feb 2009 08:03:50 PM CST
Install Date: (not installed) Build Host: laptop
Group : Network Source RPM: casnet-1.3-1.src.rpm
Size : 40883 License: GPL
Signature : (none)
Packager : Solrex Yang
URL : http://share.solrex.org/casnet/
Summary : CASNET Client
Description :
CASNET is a gui client for ip gateway of GUCAS(Graduate University of Chinese
Academy of Sciences), which is written in Python and PyGtk.$ rpm -qpl ~/rpm/RPMS/i386/casnet-1.3-1.i386.rpm
/usr/bin/casnet
/usr/bin/casnet-gui
/usr/bin/casnetconf
/usr/share/applications/casnet.desktop
/usr/share/casnet/casnet-gui.py
/usr/share/casnet/casnet.py
/usr/share/casnet/casnetconf.py
/usr/share/casnet/pics/casnet.png
/usr/share/casnet/pics/offline.png
/usr/share/casnet/pics/online.png
/usr/share/icons/casnet.png
如果您想了解更详细的内容,您可以进一步参考 Jake's RPM Build Tutorial 这篇文章。