2009-03-22

rpm包的spec文件

下面通过制作一个rpm包来简单解释一下spec文件
先看一个简单的spec文件
name: whereami
Summary: Tell you where am I
Version: 1.0.0
Release: 1
Source0: %{name}.tar.gz
LIcense: GPL
Group: Development/Tools
%description
This tool can be used to test the binary search path
%prep
echo *************in prep************
%setup -q
%build
echo *************in build************
%install
echo *************in install**********
install -p whereami /bin
%files
%defattr(-,grep,grep)
/bin/whereami


其中提到的whereami作用是输出它所在的目录,代码如下
#!/bin/bash
dirname $0

spec文件的第一部分是关于rpm包的一些信息
Name是软件的名字;
Summary是关于软件的一句简单概述;
Version是软件的版本;
Release是spec文件的"版本号";
Source0是软件压缩包的名字,其中的%{name}是spec的宏的语法,意思是引用上面定义的Name,在这里,经过宏扩展后,Source0即whereami.tar.gz. 还可以用Source1,Source2....来指定更多的软件压缩包.在ubuntu里,默认情况下,用来制作rpm包的命令rpmbuild -ba 会在/usr/src/rpm/SOURCES这个目录查找这个压缩包.所以,在这里的这个例子里,把whereami打包压缩以后,就要把生成的压缩包放到/usr/src/rpm/SOURCES这个目录下
grep@ubuntu:~$ ls whereami-1.0.0/
whereami
grep@ubuntu:~$ tar -czf whereami.tar.gz whereami-1.0.0/
grep@ubuntu:~$ sudo cp whereami.tar.gz /usr/src/rpm/SOURCES/
[sudo] password for grep:
grep@ubuntu:~$ ls /usr/src/rpm/SOURCES/
whereami.tar.gz
grep@ubuntu:~$

最后,License是软件是使用的许可证
以上各种信息在spec文件里不区分大小写,例如,License可以写成LIcense;它们之间也不区分顺序,例如Name可以写在第二行,也可以写在第一行

然后,%description是对软件的更详细的描述.注意这里它虽然以%开头,但是它和上面说到的宏是不一样的

再下面的,%prep,%build,%install是嵌入到spec文件里的shell脚本
%prep负责把Source0等的文件解压.最简单的情况,只要用%setup -q(-q可以让它少输出一些信息. 注意虽然这里的setup和prep都是用%开头,但是它们是不同的东西,要注意区分)就可以了,这样,它会把Source0等解压到/usr/src/rpm/BUILD目录下,解压完以后,它就会自动进入到%{name}-%{version}这个目录,例如我们这个例子,它就会进入到whereami-1.0.0.0,然后继续工作. %prep这一部分相当于手工安装软件的tar -xzf XXXX

%build负责编译. rpm是不会自动编译的.一般会在这里调用
./configure
make

但是,这里的例子只是一个普通的shell脚本,所以这部分留空

%install. 前面做这些多工作,可以说,都是为了这一步吧. 这一步用于把各种文件安装到适当的地方.适当的意思是,让后面的%files部分列出来的文件可以被正确地找到. 通常在这里放置一行
make install
我觉得这一步特别的迷惑人.我以为,原来rpm也不会自动安装,它也要经历tar,configure,make,make install几步,这样和把这个命令写成一个简单的shell脚本有什么区别呢? 与写成脚本文件相比, rpm还有统一管理软件的功能,它维护着一个数据库,通过这个数据库,用户可以统一地查询,删除,升级软件. 还有一点就是,%instal这一步的安装,主要是为了让rpmbuild -ba能够找到在%files列出的文件,然后把这些文件打包进rpm包里. 在用rpm -i 来安装rpm包的时候,应该(个人猜测,因为使用ubuntu来做试验,所以未验证过)不会执行这个部分.

最后一部分是%files,这里列出了要rpm放进rpm包里的文件.这里只有一个文件/bin/whereami. 这个文件就是就是由%install生成的. 我一直想不明白,为什么制作rpm包的时候,要"预安装"一次,而且这部分使我一直不明白rpm是怎么工作的. 现在觉得是,因为%files这部分的文件列表既在制作rpm包的时候使用,又在安装rpm包的时候使用吧.如果不用"预安装"的方法,就要有两个文件列表,一个是制作rpm包里使用的本地文件,另一个是安装rpm包时指定文件安装到哪里的列表.
下面是一个详细的操作过程
grep@ubuntu:~$ ls /usr/src/rpm/RPMS/i386/
grep@ubuntu:~$ ls /usr/src/rpm/SRPMS/
grep@ubuntu:~$ ls *.spec
whereami.spec
grep@ubuntu:~$ ls /bin/wh*
/bin/which
grep@ubuntu:~$ sudo rpmbuild -ba *.spec
Executing(%prep): /bin/sh -e /var/tmp/rpm-tmp.23001
+ umask 022
+ cd /usr/src/rpm/BUILD
+ echo *************in prep************
*************in prep************
+ cd /usr/src/rpm/BUILD
+ rm -rf whereami-1.0.0
+ /bin/gzip -dc /usr/src/rpm/SOURCES/whereami.tar.gz
+ tar -xf -
+ STATUS=0
+ [ 0 -ne 0 ]
+ cd whereami-1.0.0
+ exit 0
Executing(%build): /bin/sh -e /var/tmp/rpm-tmp.58860
+ umask 022
+ cd /usr/src/rpm/BUILD
+ cd whereami-1.0.0
+ echo *************in build************
*************in build************
+ exit 0
Executing(%install): /bin/sh -e /var/tmp/rpm-tmp.58860
+ umask 022
+ cd /usr/src/rpm/BUILD
+ cd whereami-1.0.0
+ echo *************in install**********
*************in install**********
+ install -p whereami /bin
+ /usr/lib/rpm/brp-compress
+ /usr/lib/rpm/brp-strip
+ /usr/lib/rpm/brp-strip-static-archive
+ /usr/lib/rpm/brp-strip-comment-note
Processing files: whereami-1.0.0-1
Requires(rpmlib): rpmlib(CompressedFileNames) <= 3.0.4-1 rpmlib(PayloadFilesHavePrefix) <= 4.0-1
Requires: /bin/bash
Checking for unpackaged file(s): /usr/lib/rpm/check-files %{buildroot}
Wrote: /usr/src/rpm/SRPMS/whereami-1.0.0-1.src.rpm
Wrote: /usr/src/rpm/RPMS/i386/whereami-1.0.0-1.i386.rpm
grep@ubuntu:~$ ls /usr/src/rpm/RPMS/i386/
whereami-1.0.0-1.i386.rpm
grep@ubuntu:~$ ls /usr/src/rpm/SRPMS/
whereami-1.0.0-1.src.rpm
grep@ubuntu:~$ ls /bin/wh*
/bin/whereami /bin/which
grep@ubuntu:~$ sudo rm /bin/whereami
grep@ubuntu:~$ ls /usr/src/rpm/RPMS/i386/
whereami-1.0.0-1.i386.rpm
grep@ubuntu:~$ ls
Desktop filehole Pictures Templates Videos whereami.tar.gz
Documents filehole.c Public test whereami-1.0.0 whereami.tar.gz~
Examples Music share tmp.txt whereami.spec win
grep@ubuntu:~$ mv whereami-1.0.0 whereami-1.0.0~
grep@ubuntu:~$ sudo alien /usr/src/rpm/RPMS/i386/whereami-1.0.0-1.i386.rpm
whereami_1.0.0-2_i386.deb generated
grep@ubuntu:~$ ls
Desktop filehole.c share Videos whereami.tar.gz
Documents Music Templates whereami-1.0.0~ whereami.tar.gz~
Examples Pictures test whereami_1.0.0-2_i386.deb win
filehole Public tmp.txt whereami.spec
grep@ubuntu:~$ ls /bin/wh*
/bin/which
grep@ubuntu:~$ sudo dpkg -i whereami_1.0.0-2_i386.deb
(Reading database ... 98036 files and directories currently installed.)
Preparing to replace whereami 1.0.0-2 (using whereami_1.0.0-2_i386.deb) ...
Unpacking replacement whereami ...
Setting up whereami (1.0.0-2) ...
grep@ubuntu:~$ ls /bin/wh*
/bin/whereami /bin/which

生成的whereami-1.0.0-1.src.rpm好像安装不了,不知道和ubuntu有没有关系

最后讲一下几个乱七八糟的目录.
从上面的操作看,必须有root的权限才能进行操作,因为要对/usr/src/rpm进行写操作,而且%install还会把文件安装到/bin目录.
通过定义BuildRoot的变量,然后修改make install为make DEST=$RPM_BUILD_ROOT install就可以让%install"预安装"到别的目录.其中的$RPM_BUILD_ROOT是rpm提供的,用来引用BuildRoot的一个shell变量.一般的BuildRoot可以定义为%{_builddir}/fake_root
至于对/usr/src/rpm写的问题,可以定义一个%_topdir来解决.

rpm --showrc | grep _topdir
rpm --showrc | grep _builddir
可以清楚地看到上面提到的各个宏和各个目录的关系


参考资料:
用 RPM 打包软件,第 1 部分
用 RPM 打包软件,第 2 部分
用 RPM 打包软件,第 3 部分



转载请注明出处 http://fornote.blogspot.com

没有评论:

发表评论