rpm檔的包裝

簡介

rpm檔主要是他有一個主控制檔在/etc/rpmrc, 這主要設定rpm的一些環境,不是要包裝package的資訊。 想要知道目前rpm所屬系統狀態,例如build的platform用
# rpm --showrc
	
不過這個目前先不管它了,有些內定值已經都設好了。

rpm真正的像debian的control這種information檔,是在一個叫xxxx.spec的檔 這個才是我們真正要準備的。 通常命名是packagename-versionnumber-releasenumber.spec, 通常是放在/usr/src/redhat/SPECS下。

rpm檔建立時是連source binary package一起建立的, 所以要把source code, patch檔案等等準備好。 /usr/src/redhat/下有5個目錄
      SOURCES  source code, patch檔放在這  .tar.gz的形式
      SPECS    這就是放資訊檔xxx.spec的的地方
      BUILD    source code會在這裡被解開並且compile與make
      RPMS     binary package最後在這裡產生
      SRPMS    source package最後在這裡產生
	

建立package檔實例

以eject-2.0.2-1.spec為例子
 Summary: A program that ejects removable media using software control.
 Name: eject
 Version: 2.0.2
 Release: 3
 Copyright: GPL
 Group: System Environment/Base
 Source: http://metalab.unc.edu/pub/Linux/utils/disk-management/eject-2.0.2.tar.gz
 Patch: eject-2.0.2-buildroot.patch
 URL:
 Vendor: ComC Software Corporation
 Packager: Santa Claus < sclaus@northpole.com>
 BuildRoot: /var/tmp/%{name}-buildroot
 Requires: libc >= 2.2


 %description
 The eject program allows the user to eject removable media
 (typically CD-ROMs, floppy disks or Iomega Jaz or Zip disks)
 using software control. Eject can also control some multi-
 disk CD changers and even some devices' auto-eject features.

 Install eject if you'd like to eject removable media using
 software control.

 %prep
 %setup
 %patch -p1 -b .buildroot

 %build
 configure --prefix=$RPM_BUILD_ROOT
 make RPM_OPT_FLAGS="$RPM_OPT_FLAGS"

 %install
 rm -rf $RPM_BUILD_ROOT
 mkdir -p $RPM_BUILD_ROOT/usr/bin
 mkdir -p $RPM_BUILD_ROOT/usr/man/man1
 install -s -m 755 eject $RPM_BUILD_ROOT/usr/bin/eject
 install -m 644 eject.1 $RPM_BUILD_ROOT/usr/man/man1/eject.1

 %clean
 rm -rf $RPM_BUILD_ROOT

 %files
 %defattr(-,root,root)
 %doc README TODO COPYING ChangeLog
 %attr(-, root, root) /usr/local/bin/cdplay
 /usr/bin/eject

/usr/man/man1/eject.1

 %pre
 if test; then cmd1; fi  #pre-install script code
 %post
 %preun
 %postun 

 %changelog
 * Sun Mar 21 1999 Cristian Gafton < gafton@redhat.com>
 - auto rebuild in the new build environment (release 3)

 * Wed Feb 24 1999 Preston Brown < pbrown@redhat.com> 
 - Injected new description and group.
	

其中比較要說明的有: GROUP很像debain的Section分類用的,在/usr/doc/rpm/GROUP找的到。 BuildRoot:這個就是假的root,等下在%build與%install時,有個 $RPM_BUILD_ROOT, 這個內定環境變數就是這個設定值。 Requires:是手動設定dependency。rpm可以自動幫你找 dependency,不過也可以手動指定。

%prep這邊是prepare準備build的動作 通常是你download的source code需要做一些你自己做的patch, 要作untar等動作。例如
%prep
rm -rf $RPM_BUILD_DIR/cdplayer-1.0
zcat $RPM_SOURCE_DIR/cdplayer-1.0.tgz | tar -xvf -
	
其中$RPM_SOURCE_DIR $RPM_BUILD_DIR是rpm跑起來時設定的環境變數。 不過由於這樣的動作幾乎已經是公式化的動作,所以有人把他寫好成一個 macro%setup, prep下有兩個常用的macro,%setup與%patch,可以只給下面的%prep就好。
%prep
%setup
%patch
	

%build就是當你要從source來build binary時要打的命令。 通常就是
configure --prefix=$RPM_BUILD_ROOT
make
	
不過由於rpm是跨平台的, 在/usr/lib/rpm/rpmrc有一些定義了的變數, make可以這樣比較有彈性, make CFLAGS="$RPM_OPT_FLAGS" LDFLAGS=-s。 %install就是我們常在source上用的
make install
        
%clean通常是把我們剛剛創造的build檔案清除掉。 其實在%build與%install可以光打我們熟悉的 configure; make; make install這樣就好, 這樣會真的把東西裝到source的Makefile內定的地方,通常就是/usr/local下。 %prep %build %install %clean會真的run一次我們熟悉的從source code編譯成 binary的步驟,而且如果我們沒有用個假的root的話, 會真的裝東西到目前系統上,通常這是不好的作法,最好還是設定假root。

%files才是真正告訴package是要裝到那裡的files list, %doc裡的檔會被裝到/usr/doc/$NAME-$VERSION-$RELEASE, %attr是設定安裝時檔案的權限,
%attr(mode, user, group)
        
mode如果不指定0755而只指定-的話表示, 不寫%attr話用%defattr,或者用root的權限。

如果有用BuildRoot的話,rpm自動知道要到相對應的假 root,下去把~fakeroot/usr/bin/ 根據%files指定的檔放到package的正確/usr/bin/。

rpm的pre- post- install與remove 不像solaris或debian的另寫真正的額外shell script檔, 而是把shell script含進spec檔內的%pre %post %preun %postun下。

寫完後到存到/usr/src/redhat/SPECS下並且給命令
# rpm -ba eject-2.0.2-1.spec
	
就會把該做的事與檔案放進去package, 最後去/usr/src/redhat/RPMS找binary package, /usr/src/redhat/SRPMS找source package。

從maximum rpm下抄一個例子出來
# rpm -ba cdplayer-1.0.spec
* Package: cdplayer
Executing: %prep
+ cd /usr/src/redhat/BUILD
?
+ exit 0
Executing: %build
+ cd /usr/src/redhat/BUILD
+ cd cdplayer-1.0
?
+ exit 0
+ umask 022
Executing: %install
+ cd /usr/src/redhat/BUILD
+ cd cdplayer-1.0
+ make ROOT=/tmp/cdplayer install
install -m 755 -o 0 -g 0 -d /tmp/cdplayer/usr/local/bin/
install -m 755 -o 0 -g 0 cdp /tmp/cdplayer/usr/local/bin/cdp
ln -s ./cdp /tmp/cdplayer/usr/local/bin/cdplay
install -m 755 -o 0 -g 0 -d /tmp/cdplayer/usr/local/man/man1/
install -m 755 -o 0 -g 0 cdp.1 /tmp/cdplayer/usr/local/man/man1/cdp.1
+ exit 0
Executing: special doc
+ cd /usr/src/redhat/BUILD
+ cd cdplayer-1.0
+ DOCDIR=/tmp/cdplayer//usr/doc/cdplayer-1.0-1
+ rm -rf /tmp/cdplayer//usr/doc/cdplayer-1.0-1
+ mkdir -p /tmp/cdplayer//usr/doc/cdplayer-1.0-1
+ cp -ar README /tmp/cdplayer//usr/doc/cdplayer-1.0-1
+ exit 0
Binary Packaging: cdplayer-1.0-1
Finding dependencies...
Requires (2): libc.so.5 libncurses.so.2.0
usr/doc/cdplayer-1.0-1
usr/doc/cdplayer-1.0-1/README
usr/local/bin/cdp
usr/local/bin/cdplay
usr/local/man/man1/cdp.1
93 blocks
Generating signature: 0
Wrote: /usr/src/redhat/RPMS/i386/cdplayer-1.0-1.i386.rpm
+ umask 022
+ echo Executing: %clean
Executing: %clean
+ cd /usr/src/redhat/BUILD
+ cd cdplayer-1.0
+ exit 0
Source Packaging: cdplayer-1.0-1
cdplayer-1.0.spec
cdplayer-1.0.tgz
82 blocks
Generating signature: 0
Wrote: /usr/src/redhat/SRPMS/cdplayer-1.0-1.src.rpm