1. 程式人生 > >RPM打包探索(rpm-max翻譯整理)

RPM打包探索(rpm-max翻譯整理)

1. %global 和 %define 的區別?
這是內建巨集,%define用來定義巨集,%global用來定義一個全域性可見的巨集(在整個spec檔案中可見)
2. %{!?macro-name} 和 %{?!macro-name} 的區別?


3. rpmbuild 巨集定義檔案都有哪些?載入順序如何?


4. AutoReqProv 的作用?


5. 巨集定義 %define kernel_variant_post(v:r:) 中 v:r: 的意思?


####
1. Shell 指令碼


2. Makefile




rpm包的構建
rpm有一個比較官方的網站解釋一系列和rpm包有關的的文件;我主要從第10章開始學習。
參考網站: http://www.rpm.org/max-rpm/index.html


第一部分:


1.如何建立一個spec檔案?
  我們管理RPM構建過程的方式是建立spec檔案,規範檔案包含八個不同的部分,其中大部分是必需的。
  下面我們瀏覽每個部分並建立一個例項包cdplayer作為我們的規範檔案。
  
  The Preamble(我們暫時理解為序言吧!!) 
  前序:
序言中包含了大量的關於構建包的資訊以及構造者。下面是cdplayer包的序言:


====================================================================
#
# Example spec file for cdplayer app...
#
Summary: A CD player app that rocks!
Name: cdplayer
Version: 1.0
Release: 1
Copyright: GPL
Group: Applications/Sound
Source: ftp://ftp.gnomovision.com/pub/cdplayer/cdplayer-1.0.tgz
URL: http://www.gnomovision.com/cdplayer/cdplayer.html
Distribution: WSS Linux
Vendor: White Socks Software, Inc.
Packager: Santa Claus <

[email protected]>


%description
It slices!  It dices!  It's a CD player app that
can't be beat.  By using the resonant frequency
of the CD itself, it is able to simulate 20X
oversampling.  This leads to sound quality that
cannot be equaled with more mundane software...
======================================================================


一般來說,序言由條目,每行一個開始標記,後跟一個冒號,然後是一些資訊。
例如,每行從“Summary:”開始給了一個簡短的可以被RPM顯示的描述。
當然每行的順序並不重要,只要他們出現在序言中。


下面我麼來一睹每一行的作用:
---Name  
#name這行的定義實際會被呼叫。總的來說,這樣做比較好因為軟體的名稱也將包含在包標籤,和包的檔名。


---Version
#設定軟體包的版本號,將被包含在包的標籤和包檔名中。


---Release
#Release 是一種用於表示軟體(目前的版本已經打包的)被髮布次數的數量,
你可以認為它是包的版本號。Release也包標籤和包檔名的一部分。


---Copyright
# 表示版權資訊


---Group
#Group行是用於儲存一串字串,它定義了應該如何分組打包軟體與其他包。
字串包含了一系列的單詞用斜槓隔開。從左到右,這句話描述的打包軟體更加明確一些。
上面我們分組cdplayer應用程式,因為它是一個應用程式,然後與聲音有關的應用程式。


---Source
#Source這一行主要有兩個作用:
   --記錄包的來源和給出包名(廢話!!)
---URL
#和Source有點像


---Distribution
#Distribution行包含產品的名稱,是軟體的一部分。在Linux世界中,作業系統通常是
打包成一個“distribution”,所以因此而得名!!!


---Vendor
##供應商表示,個人使用者可以省略!!


---Packager
#打包者的資訊,具體人或者責任人。


---Description
#Description行由一個百分號'%'開始,這實際上是spec巨集定義的方式。
在後面我們知道spec檔案的巨集定義是百分號'%' 開頭的。和其他行不同的是這裡可以是多行,
來提供更具體的描述資訊相較於Summary


---A Comment on Comments --註解
#在spec檔案的開始以‘#’開頭的是解釋,這可以讓檔案更加容易理解!!




---The %prep Section
---準備部分
#在序言部分,我們提供了豐富的資訊。大多數的這些資訊是給人來看的。
只有名稱、版本、釋出以及源和包構建過程有直接關係。
然而,在%prep部分重點是指導RPM準備軟體構建(%build)的過程。


%prep階段,建立軟體的構建環境,開始刪除任何之前的構建留下的殘餘。在這之後,擴充套件原始檔。
下面是一個例項%prep部分:
=========================================================================
            %prep
            rm -rf $RPM_BUILD_DIR/cdplayer-1.0
            zcat $RPM_SOURCE_DIR/cdplayer-1.0.tgz | tar -xvf -
=========================================================================


   %prep部分看起來酷似一個指令碼,為什麼呢?因為本來就是指令碼!!!這裡可以使用任何shell指令碼,
包括一些環境變數(比如RPM的一些內建巨集$RPM_BUILD_DIR ),和管道命令等。


在這一階段,我們在構建目錄中執行遞迴刪除任何舊的構建。然後我們將gzip tar檔案解壓縮,
並提取其內容到構建目錄中。


通常,原始檔可能需要打patch。%prep部分是打補丁最合適的地方,但是在本例中我們沒有看到補丁,
因為暫時不需要補丁。別擔心,哈哈!!後面我們會討論和補丁以及它的“驕傲”哈哈。
在較為複雜一點的包構建時。


---Making Life Easier With Macros 
---巨集,讓你的生活變得更簡單!!!
我們已經在是你在上面描述的巨集%prep並不難理解,巨集可以有效降低編譯一些複雜包的難度,下面
我們將介紹巨集%setup。


平均來講使用tar來歸檔解壓檔案是%setup巨集的主要營生。就像像之前我們將的%prep巨集部分,在
這一階段%setup巨集將clean掉之前的構建樹以及解壓提取所需檔案從原始檔中。
當然%setup巨集還有一些選項,我們將在後面的章節來描述。
      ===================
      | %prep
      | %setup
      ====================
上面是一個非常簡單的%prep部分,我們也使用%setup來替代那些指令碼。%setup巨集還有很多的選項來
處理不同的情形,關於更多的這個巨集的描述我們將在後面說明。
在我們的例子中,關於%prep部分描述就到這裡,下面我們將介紹實際的構建build。


----The %build Section
----%build部分
一點也不奇怪,下面這部分就是spec檔案負責構建的部分---%build sectio;就像前面的%prep巨集部分,
這部分也是一段普通的shell指令碼。不同的是,這裡沒有巨集。原因是軟體的build過程是非常簡單的或者
高複雜度的。在後一種情況下巨集幫不上什麼忙。在我們例子中build的過程是很easy的。
       ================
       | %build
       |  make
       ================
先和make的實用說聲謝謝!!!我們只需要一個命令就可以構建cdplayer應用。
在應用程式的build部分比較難搞的情況下,build 部分才比較有意思(這不是我說的@)!!!


-----The %install Section
----- %install 部分
這部分就是執行相關的shell指令碼,和前面的%prep和%setup類似。如果應用程式在build的時候
makefile中就install這個‘target’的話,%install部分將會萬里無雲的般的順暢。我們例子就是。
==================
| %install
| make install
==================
但是如果應用程式沒有自動安裝的本事,還需要麻煩你去寫個指令碼來做這件事情。指令碼放在%install下就OK了!




-----The %files Section
-----%files部分
嗯,%files部分和其他部分稍有不同的是,在files中包含了包的一部分。記住了--如果沒在檔案列表
裡的檔案將不會被放進軟體包中。
=======================
%files
%doc README
/usr/local/bin/cdp
/usr/local/bin/cdplay
/usr/local/man/man1/cdp.1
=======================
上面%doc開頭的行表示RPM處理不同檔案的型別。我們可以猜到,%doc代表文件相關的。
這裡將被用於標記這檔案的是文件。在上面的例子中,EADME檔案將被放到指定的目錄
中,關於具體在哪裡要看Makefile檔案中的指定。這裡詳細的解釋會在後面繼續說明。。


怎麼來建立file list呢??
雖然從各方面來看RPM是一個自動化軟體安裝,很容易迷糊的是你會覺得RPM將為你大包大攬
做了所有事情。不是這樣地!!建立file list仍然是一個手動的過程,雖然它似乎乍一看,
它可以自動從某種意義上講,它實際上比看起來更困難的問題。


因為很多應用的files是被Makefile來安裝的,RPM沒有在build中起作用,但是不能判斷哪些檔案
是包的一部分。有人嘗試使用修改版本的logs名來安裝每個檔案???
但是也不是所有的Makefile都是用install,就算有,也很少使用。


Another approach tried was to obtain a list of every file on the build system, 
immediately before and after a build, and use the differences as the file list. 
While this approach will certainly find every file that the application installed, 
it can also pick up extraneous files, such as system logs, files in /tmp, and the like. 
The only way to begin to make this approach workable would be to do nothing else on the build system, 
which is highly inconvenient. This approach also precludes building more than one package on the system at any given time.
上面我還沒有明白??


現如今,建立file list最好的辦法就是閱讀Makefile檔案,看哪些檔案將被install,核實這些檔案的安裝在構建系統上,並建立列表。


*****The Missing Spec File Section
***** 還有那些部分在spec檔案中??
上面的那個例子實在是有點簡單了,所以我麼漏掉了兩個部分,這兩部分在一些較為
複雜的情況下可能會用到。後面lou一眼,跟多詳細的部分在後面專門討論!!


------The Install/Uninstall Scripts
------安裝和解除安裝指令碼
這兩個指令碼將被執行在下面的情況下:
#包被安裝之前
#包被安裝之後
#包被解除安裝之前
#包被解除安裝之後
我們會在後面看到這些指令碼的使用;


-----The %clean Section
-----%clean 部分
另一個被忘記的部分就是這裡,這部分可以用來清理任何檔案不屬於正常構建的應用程式的區域。
比如一些/tmp下的臨時檔案。


NOTE:更多關於環境變數相關的使用可以看構建時的指令碼。




第二部分:
2.開始構建---Starting the Build


************待完善!!!




第三部分:
這些內容根據對max-rpm-snapshot的理解整理而來;
------------rpmbuild的引數說明-------------
1. rpmbuild -b<stage> options file1.spec … fileN.spec
 ---在使用這個命令的過程中我們可以先rpmbuild --help瞭解一下具體有哪些引數,根據這引數在不通過
 階段的使用以及對這一過程中相關除錯的輔助選項的理解。
 
 --我們知道在構建rpm包的過程中有5大部分,rpmbuild命令為我們提供引數選項可以針對你指定的某一部分
 後者幾個部分來執行構建命令。如下面的選項和解釋所示:
 ---------------------------------------------------------------------
 -------<stage>-----------
 p Execute %prep  只執行prep部分;
 c Execute %prep, %build   執行prep和build部分但沒有install等部分;
 i Execute %prep, %build, %install, %check
 b Execute %prep, %build, %install, %check, package (bin)--相對‘-a’引數,少了構建原始碼包
 a  Execute %prep, %build, %install, %check, package (bin, src)
 l Check %files list
 注意事項:check階段在很多實用中不為常用;
 ---------------------------------------------------------------------
 #以上為<stage>引數選項的說明,下面對options作了說明;
 我們從上面的描述可以知道,我們可以指定引數對構建的具體階段部分,我們也可以用在這一基礎上
 實用一些選項來更加方便的為我們的包構建部分服務;
 
 -------------------------------------------------------------------------------------
 ****************Options********************
 --short-circuit Force build to start at particular stage (-bc, -bi only) 這個選項可以為-bc, -bi
    階段的構建強制執行從那個階段開始;
 --test Create, save build scripts for review  --這一引數有利於我們對構建包過程中各個階段
  使用指令碼的情況具體的瞭解(但是我在我的系統上沒有找到這選項,難道這是騙人的!!!感覺這個選項是很有用的)
  
***--clean Clean up after build  構建完成之後移除構建時的目錄檔案。例如:
     rpmbuild -bp --clean xxx.spec  可以在直定階段使用這一引數;


*** --sign Add a digital signature to the package    此引數執行可以為構建的包新增一個數字簽名
                                                  簽名使用的PGP或者GPG,根據不同版本而定;
----buildroot <root> Execute %install using <root> as the root  指定安裝路徑,改變預設的安裝路徑
    這個引數在使用的過程中要注意兩個地:
1--在spec檔案中的指定BuildRoot:/tmp/foo ;
2--如果你的是用make來install,那麼make的指定安裝目錄在spec檔案中;
%install
make ROOT="$RPM_BUILD_ROOT" install


--buildarch <arch> Perform build for the <arch> architecture  這個引數也已經找不到了,但是他被‘--target’代替
--rcfile <rcfile> — Set alternate(替換) rpmrc file to <rcfile> 使用指定的檔案讀取巨集,不適用預設檔案(/usr/lib/rpm/rpmrc)
 
 -------------------------------------------------------------------------------------
 
-----------------rpmbuild ----做些什麼呢??
當你使用‘-b’選項時,一個包的構建就開始了。其餘的命令引數選項用來精確控制構建那個階段,下面我們來看:
一個完整的RPM build命令應該至少包含兩部分資訊:
1.spec檔案; 2.你希望構建到哪各階段;
在之前的討論中或者你已經從其他途徑瞭解到RPM的構建有好幾個階段部分,而且可以由命令引數來決定構建到那個階段;你可以輕鬆的檢視
構建的過程等;


*******選項:rpmbuild -bp — Execute %prep --只執行prep(準備階段)
---我們知道rpmbuild -bp 表示指定RPM構建的第一階段(stage),在spec檔案中由標籤巨集%prep來標記,在這一階段所做的事情在文章的前面已經討論;


下面來看這個簡單的例子中執行過程:
------------------------------------------------------------------------
# rpmbuild -bp cdplayer-1.0.spec
* Package: cdplayer
Executing(%prep):
+ umask 022
+ cd /usr/src/redhat/BUILD
+ cd /usr/src/redhat/BUILD
+ rm -rf cdplayer-1.0
+ gzip -dc /usr/src/redhat/SOURCES/cdplayer-1.0.tgz
+ tar -xvvf -
drwxrwxr-x root/users        0 Aug  4 22:30 1996 cdplayer-1.0/
-rw-r--r-- root/users    17982 Nov 10 01:10 1995 cdplayer-1.0/COPYING
-rw-r--r-- root/users      627 Nov 10 01:10 1995 cdplayer-1.0/ChangeLog

-rw-r--r-- root/users     2806 Nov 10 01:10 1995 cdplayer-1.0/volume.c
-rw-r--r-- root/users     1515 Nov 10 01:10 1995 cdplayer-1.0/volume.h
+ [ 0 -ne 0 ]
+ cd cdplayer-1.0
+ cd /usr/src/redhat/BUILD/cdplayer-1.0
+ chown -R root.root .
+ chmod -R a+rX,g-w,o-w .
+ exit 0

-----------------------------------------------------------------------------        
--在%prep部分包含一個%setup巨集,首先RPM確定cdplayer使我們要構建的目標,然後他設定umask並啟動%prep部分,
在這裡,%setup主要切換目錄和移除之前的構建遺留檔案。
---接下來%setup 來釋放已歸檔的原始檔並用tar來建立構建目錄樹。移除已經完成的檔案。
---最後,%setup切換到cdplayer的構建目錄樹並改變檔案屬主和適當的檔案許可權。exit 0 表示到了%prep的最後階段;
   所以當我們使用‘-bp’引數時,RPM就在這裡終止構建,我們可以看一下再BUILD中留下來的構建目錄檔案。
-----------------------------------------------------------------


# cd /usr/src/redhat/BUILD   值得注意的是,在新版的rpmbuild已經改換這一目錄到使用者家目錄下
# ls -l
total 1
drwxr-xr-x   2 root     root         1024 Aug  4 22:30 cdplayer-1.0
------------------------------------------------------------------
比如我的機子上:/home/zhongtian/rpmbuild/BUILD/
[
[email protected]
BUILD]$ ls
kernel-3.10.0-123.ns6
----這就是我們構建的頂層目錄,切換到cdplayer-1.0為原始碼所在;
--------------------------------------------------------------------
# cd cdplayer-1.0
# ls -lF
total 216
-rw-r--r--   1 root     root        17982 Nov 10  1995 COPYING
-rw-r--r--   1 root     root          627 Nov 10  1995 ChangeLog

-rw-r--r--   1 root     root         2806 Nov 10  1995 volume.c
-rw-r--r--   1 root     root         1515 Nov 10  1995 volume.h

-------------------------------------------------------------------
我們可以清楚的看到在%setup中chown和chmod命令所做的改動---所述使用者和組都為root,
 將相關的組的寫許可權禁用等;(一個恰到好處的許可權改動是非常必要的);
 
================================================= 
****選項:rpmbuild -bc — Execute %prep, %build


----我們如果不在構建中使用'-bp'命令選項,RPM會在軟體包構建完成之後停止。在
spec檔案中的所有%build部分命令都將被執行,下面的例子中我們先將%prep部分的輸出去掉來看%build部分,
需要明白的是,儘管如此他還是執行了(%prep);
------------------------------------------------------------------------------------
# rpmbuild -bc cdplayer-1.0.spec
* Package: cdplayer
Executing(%prep):

+ exit 0
Executing(%build):
+ cd /usr/src/redhat/BUILD
+ cd cdplayer-1.0
+ make
gcc -Wall -O2  -c -I/usr/include/ncurses  cdp.c 
gcc -Wall -O2  -c -I/usr/include/ncurses  color.c 
gcc -Wall -O2  -c -I/usr/include/ncurses  display.c 
gcc -Wall -O2  -c -I/usr/include/ncurses  misc.c 
gcc -Wall -O2  -c -I/usr/include/ncurses  volume.c 
volume.c: In function `mix_set_volume':
volume.c:67: warning: implicit declaration of function `ioctl'
gcc -Wall -O2  -c -I/usr/include/ncurses  hardware.c 
gcc -Wall -O2  -c -I/usr/include/ncurses  database.c 
gcc -Wall -O2  -c -I/usr/include/ncurses  getline.c 
gcc -o cdp cdp.o color.o display.o misc.o volume.o hardware.o database.o
getline.o  -I/usr/include/ncurses  -L/usr/lib -lncurses
groff -Tascii -man cdp.1 | compress >cdp.1.Z
+ exit 0



-------------------------------------------------------------------------------------
當執行上面的命令後,我們看到RPM首先執行%prep階段部分(因為篇幅關係省略);接下來
RPM開始執行%build階段部分並在groff命令之後結束,完成了%build部分的全部構建;
--我們spec檔案中的%build部分如下:
----------------------------------------------------
%build
 make
----------------------------------------------------
但是在輸出資訊中我們看到在make命令之前,RPM首先切換目錄進入BUILD,然後RPM開始執行make並在
grooff命令之後完成%build部分。因為我們使用'-bc'引數選項,RPM在這裡停止(這可以追蹤到RPM的實現的原始碼中)


---下一個構建階段是install新構建的軟體,這一部分工作由spec檔案中%install(和%check)階段部分來完成,
RPM可以使用命令引數選項‘-bi’來停止在install完成之後。
==============================


*********選項:rpmbuild -bi — Execute %prep, %build, %install, %check
---使用選項‘-bi’之後,RPM將在軟體完全完成構建、安裝、以及測試之後停下來。看一下下面的輸出:


----------------------------------------------------------
# rpmbuild -bi cdplayer-1.0.spec
* Package: cdplayer
Executing(%prep):

+ exit 0
Executing(%build):

+ exit 0
Executing(%install):
+ cd /usr/src/redhat/BUILD
+ cd cdplayer-1.0
+ make install
chmod 755 cdp
chmod 644 cdp.1.Z
cp cdp /usr/local/bin
ln -s /usr/local/bin/cdp /usr/local/bin/cdplay
cp cdp.1 /usr/local/man/man1
+ exit 0
Executing(%check):
+ umask 022
+ cd /usr/src/redhat/BUILD
+ cd cdplayer-1.0
+ make test
All tests run successfully.
+ exit 0
Executing(%doc):
+ cd /usr/src/redhat/BUILD
+ cd cdplayer-1.0
+ DOCDIR=//usr/doc/cdplayer-1.0-1
+ rm -rf //usr/doc/cdplayer-1.0-1
+ mkdir -p //usr/doc/cdplayer-1.0-1
+ cp -ar README //usr/doc/cdplayer-1.0-1
+ exit 0

----------------------------------------------------------
在下面單獨列出我們的例子中的%install部分:
----------------------
%install
 make install
-------------------------
--我們已經知道在完成了%prep和%build部分的構建之後%install部分開始執行。來看一下輸出資訊,
我們看到RPM切換目錄到BUILD然後執行make install命令(這是唯一在%install部分的命令)。
輸出資訊從make install 開始到最近的exit 0完成是make install的輸出。
--下一階段部分%check的只有唯一的命令make test 。在剩餘的命令就是spec檔案中的%files部分內容。
來看一下:
---------------------------
%files
%doc README
/usr/local/bin/cdp
/usr/local/bin/cdplay
/usr/local/man/man1/cdp.1
---------------------------
%doc README這一行就是文字相關。%doc這個標記可以識別檔案是文件。RPM處理文件檔案的方式是,建立一個doc
目錄來放置文件。做完這些事情就到了最後的的‘exit 0’了(表示%install部分的終結)。原因為‘-bi’選項的返回值所致;


--下面的部分構建執行的過程知道二進位制軟體包被創建出來之後RPM才會停止;這是由命令選項‘-bb’所為;


*****選項:rpmbuild -bb — Execute %prep, %build, %install, %check, package (bin)--(二進位制軟體)
------------------------------------------------------------------------------------
# rpmbuild -bb cdplayer-1.0.spec
* Package: cdplayer
Executing(%prep):

+ exit 0
Executing(%build):

+ exit 0
Executing(%install):

+ exit 0
Executing(%check):

+ exit 0
Executing(%doc):

+ 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
Executing(%clean):
+ umask 022
+ cd /usr/src/redhat/BUILD
+ cd cdplayer-1.0
+ exit 0

------------------------------------------------------------------------------------
---來看,當執行完成 %prep, %build, %install, and %check 部分和處理一些特定的文件之後,RPM建立了一個
二進位制包。在上面的輸出資訊中我們發現RPM首先執行自動依賴檢查。做檢查是為了那些確定動態庫被可執行程式需要。
接下來,RPM將檔案打包並輸出最終的‘產品’軟體包。最後在做一些移除臨時檔案的工作。


******選項:rpmbuild -ba — Execute %prep, %build, %install, %check, package (bin, src)
---這一選項驅使RPM執行所有的構建的階段;在這一個命令後面,RPM做了如下事情:
   <1> 解原始碼包;<2>打patch(如果需要的話);<3>編譯軟體 <4>安裝軟體 <5>執行test檢查軟體;
   <6>建立二進位制軟體包<7>建立原始碼包<cdplayer.src.rpm>;
---上面這一過程只需要一個命令就解決了!!!下面是執行之後的動作:
-----------------------------------------------------------------------------------------------


# rpmbuild -ba cdplayer-1.0.spec
* Package: cdplayer
Executing(%prep):

+ exit 0
Executing(%build):

+ exit 0
Executing(%install):

+ exit 0
Executing(%check):

+ exit 0
Executing(%doc):

+ exit 0
Binary Packaging: cdplayer-1.0-1

Executing(%clean):

+ exit 0
Source Packaging: cdplayer-1.0-1
cdplayer-1.0.spec
cdplayer-1.0.tgz
80 blocks
Generating signature: 0
Wrote: /usr/src/redhat/SRPMS/cdplayer-1.0-1.src.rpm
#
-----------------------------------------------------------------------------------------------
--在前面的例子中RPM執行一系列的各個階段以及處理文件資訊建立二進位制包並且清除動作;
--在最後一步建立原始碼包。由輸出資訊可以看到它包含了spec檔案和原始檔(也可能包含一個或者多個patch檔案,例子中沒有使用patch)。
--在‘-ba’引數的命令執行完成後構建和打包(二進位制和原始碼包)成功。然而這裡還有一些構建過程中可以使用的命令
引數選項。比如'-bl'引數:


*******選項:rpmbuild -bl — Check %files list
前面的描述中選項的命令的選項的最後一個字母指定rpm的動作通知在那個階段,但是不同的是,如果加入‘l’引數,下面餓檢查都要被執行:
   <1>擴充套件spec檔案中的%files 列表這個巨集,檢查每個檔案是否真實存在;
   <2>確定軟體需要的動態庫檢查每一個可執行檔案列表;
   <3>確定那個動態庫應該有包來提供;
----為什麼必須要做這些檢測?什麼情況會用到?需要牢記的是%files 列表必須是手工建立的。使用'-bl'選項時夏敏的步驟
  是必須的:
  **寫檔案列表的%fiels; 
  **使用‘-bl’選項檢測;
  **作必要的改動對%files 列表;
這個過程可能會發生多次迭代,但是最終會通過檢查。所以說使用‘-bl’選項來檢測檔案列表肯定比你花了兩個小時去構建最後發現寫錯了檔名要值得!!
看這個使用‘-bl’例子:
-----------------------------------------------------------
# rpmbuild -bl cdplayer-1.0.spec
* Package: cdplayer
File List Check: cdplayer-1.0-1
Finding dependencies...
Requires (2): libc.so.5 libncurses.so.2.0
#
-------------------------------------------------------------




****選項:--quiet — Produce as Little Output as Possible 讓輸出資訊儘量少;


****選項:--rcfile <rcfile> — Set alternate rpmrc file to <rcfile> 使用指定檔案中的巨集;


--除了上面介紹的還有另外你哥常用的與build相關的命令選項;




在開啟新的篇章:這一片參考charter 13,主要描述spec檔案中的一些細節;


****************************Inside the Spec File 漫遊spec*********************
在這一章的介紹中,我們將帶你詳細的瀏覽spec檔案。spec檔案是由不同型別的條目構成,我們來看看:
** Comments — Human-readable notes ignored by RPM. 這裡指給人看的註釋資訊
** Tags — Define data   定義資料--???
** Scripts  -- Contain commands to be executed at specific times --包含在制定的時間(階段)執行的命令;
** Macros — A method of executing multiple commands easily.   --執行多個命令的一種方法(make life easy!!)
** The %files list — A list of files to be included in the package.---包中包含的檔案列表
** Directives — Used in the %files list to direct RPM to handle certain files in a specific way. --在files中處理檔案的一種方式
** Conditionals — Permit operating system- or architecture-specific preprocessing of the spec file.--允許作業系統和指定架構的預處理spec檔案


--Comments 就是由‘#’號起始的行(與shell類似),可以放置在任何位置;註釋spec的巨集是要在使用‘#%%’:
  #%%vendorname


-- Tags ---這裡說是資料的定義:
格式為:<something>:<something-else>  這裡的前半部分是指Tag,被用來命名或者標記;後半部分用分號‘:’來隔開表示要表達的意思;
Tag一般出現在spec檔案的頂部的序言部分(preamble),比如:
Vendor:vendorname, Inc.
--在上面的例子中Tag就是“Vendor”。Tag沒有大小寫之分,既可以全是大寫;或者全是小寫;或者大小寫都有
“Vendor”在這裡表示公司名稱,所指定的資料就是“vendorname, Inc.”
---------------------------------------------------------
VeNdOr : White Socks Software, Inc.
vendor:White Socks Software, Inc.
VENDOR    :    White Socks Software, Inc.
---------------------------------------------------------
上面的寫法似乎很是沒有底線,但是我覺得還是有點底線的好哈哈!!但是不管你將Tag搞的看起來多麼整潔或者醜陋---RPM才懶得管這麼多。
但是,著說但是了,注意你必須將Tag後面的資料以特定格式組織起來(你總不希望別人看到你寫的東西那麼刺眼吧)。


******包名的Tags
<name>-<version>-<release>  --最後用來命名你的軟體包;格式就是如此;
--自然的這三個標籤(tags)就是名稱、版本、釋出次數;
--我們分解這三部分來看看:
--name--定義被名稱,多數情況下使用的name和打包的軟體的名稱應該在拼寫上是相同的;
name 中不能有空格,否則空格前面的部分被認為是name;例如:Name: cdplayer


--版本的Tags
定義包的版本資訊,version的命名儘量能和源版本的格式相近;這個命名一般不會出現問題,因為修改這一部分的
分一般都是原版本的開發者,他們熟悉這過程;但是有一個規定就是這裡不能使用破折號“-”,如果你誤用,RPM會提醒你:
---------------------------------------------------
# rpmbuild -ba cdplayer-1.0.spec
* Package: cdplayer
Illegal '-' char in version: 1.0-a
#
----------------------------------------------------
但是在我的試驗中沒有報錯!!!!!(這篇文章是有點過時,但還好只是少部分!!),還有空格等等不要用!!


--The release Tag 釋出次數,如果這個軟體包是第一次打包釋出,那麼realse:1,否則在前面的基礎上加一增長;


******描述 Tags 
這個tag主要提供一些打包者的資訊和包的資訊;
The %description Tag 用來更加深入的描述軟體包的資訊。大概幾句話的描述內容,告訴使用者軟體的作用功能等;
描述tag的格式比較簡單,在%description下面具體的描述就ok!
------------------------------------------------------------------------
%description
It slices!  It dices!  It's a CD player app that can't be beat.  By using
the resonant frequency of the CD itself, it is able to simulate 20X
oversampling.  This leads to sound quality that cannot be equaled with
more mundane software...
-------------------------------------------------------------------------
注意:和其他tag不同的是,描述tags由一個'%'起始,而且可以是多行;如果一行是空的話,那麼空白行上下的文字
段將被RPM格式化為兩個段落;多行中的每一行的開頭如果是空格的話,那麼RPM會認為這幾行都是一個段落的;比如:
------------------------------------------------------------
%description
 It slices!
 It dices!
 It's a CD player app that can't be beat.
By using the resonant frequency of the CD itself, it is able to simulate
20X oversampling.  This leads to sound quality that cannot be equaled with
more mundane software...
-------------------------------------------------------------
上面的例子中開始的三行家會被RPM逐字的顯示(因為這三行都是以空格開頭),剩餘的文字會被RPM處理,
最終他們都被認為是一個段落而處理;(RPM這一點體現了什麼呢???呵呵)


哈哈!!再來看下面的例子,其中有一行是空白行,那麼他最終會被認為是兩個段落,由空白行來separate;
---------------------------------------------------------------------------------------------------
%description
 It slices!
 It dices!
 It's a CD player app that can't be beat.


By using the resonant frequency of the CD itself, it is able to simulate
20X oversampling.  This leads to sound quality that cannot be equaled with
more mundane software...         
---------------------------------------------------------------------------------------------------


--The summary Tag 總結tag,總的來描述一下軟體包,只能是一行;
   ------------------------------------
   Summary: A CD player app that rocks!
   -----------------------------------
--The license Tag 所遵循的協議 --License: GPL


--The distribution Tag  ---用來定義一組包


--The icon Tag   --圖示 Icon: foo.xpm


--The url Tag  ---站點資訊
URL: http://www.gnomovision.com/cdplayer.html


--The group Tag  
用於將型別或者功能相近的包組織在一起,有點像目錄的感覺,將一些功能或者型別相似的檔案組織起來,比如文件類的、系統類的、除錯類的、應用類等:
Group: Documentation
Group: Development/System
Group: Development/Debug
Group: Applications/Editors
Group: Applications/Spreadsheets
後面兩個表示在Applications下面會有連個編輯軟體,或者其他編輯軟體;


--The packager Tag 定義一些開發者的名字或者聯絡資訊,可以使人名、公司名、Email或者電話,maybe 客戶會給你
送錢來或者打騷擾電話亦或是恐嚇信(⊙o⊙)哦!!!開個玩耍!!
Packager: zhongtian <
[email protected]
>   ---我也許會回覆你哦!!




*****Dependency Tags 依賴tag*****************


--RPM的一個特性就是確保一個包如果安裝那麼系統環境中需要提供這個報所需要的所有東西!!同樣,如果一個包被解除安裝必須確保沒有其他包依賴
要解除安裝的包。這種依賴功能非常有用對於終端使用者來安裝或者解除安裝;
--然而,為了RPM能夠得到更多的依賴資訊,打包者必須對包新增合適的依賴資訊。需要注意的是,新增一來資訊
要’深謀遠慮‘;下面我麼來看看依賴相關的tags。更加具體的討論將在後面《Adding Dependency Information to a Package》中列出;


來看看第一個依賴tag:
--The provides Tag  
這個tag用於指定一個虛擬包(一個打包的軟體)安裝時提供。一般來說,這個tag用來為不同的提供相同的服務。
比如說,一個包為允許使用者閱讀郵件提供了mail-reader虛擬包。另外一個包也依賴閱讀郵件這個虛擬包。這樣的情況下
安裝不會出現問題,如果一個郵件閱讀的程式被安裝。一睹為快:
Provides: mail-reader


--The requires Tag 
這個requires標記tag被用來提醒RPM,軟體包正常執行所需要的其它必要的功能。這個功能也就是指另一個包的名字,或者是
之前提起的虛擬包來提供一個或者多個包所要使用的Provides 標籤。當requries 標籤引用一個包名時,版本的比較也應該被包含
在包名中使用一些範圍符號,比如:<, >, =, >=, or <=, 這些符號。例如:
--------------------------------------------------------------
Requires: playmidi = 2.3
--------------------------------------------------------------
如果requires 標籤需要與下面定義的epoch 標籤最比對,應該寫成下面格式:
--------------------------------------------------------------
Requires: playmidi >= 4:2.3
Epoch: 4
--------------------------------------------------------------


--The conflicts Tag  
  這個標籤字面意思是衝突相關的標籤,他其實是對requires標籤的一個補充。我們通過上面的學習知道,requires標籤被用於指定什麼包必須準備好
以保證當前安裝的包能順利安裝。而conflicts標籤則是指為了當前包的正常執行,那些包不能被安裝,和requires標籤互補。
  conflicts標籤的格式和requires相同,標籤後面更隨一個真實的或者虛擬的包名稱。
----------------------------------
Conflicts: playmidi = 2.3-1          
----------------------------------
也可以和requires標籤類似在和epoch標籤作比較:
Conflicts: playmidi = 4:


--The epoch Tag   #這個用的不太多???先繞過不解釋!!!




----The autoreqprov, autoreq, and autoprov Tags 
這幾個標籤用來控制軟體包構建過程中的自動依賴過程。一般來說,在包構建過程中有下面幾個過程被執行:
<1>所有可執行程式和共享庫被打包分析以決定他們所需要的共享庫可解析器。
<2>每個共享庫的soname被自動加進包列表的“provides”資訊中。
<3>所需的Perl指令碼模組和被打包的模組都被自動新增到包的需求。
通過此操作,RPM幫助包的構建者節約了手工新增依賴的資訊量。然而(好多的然而,有人的地方就由然而!!)
有些時候自動以來過程並不如你所願(這就是悲劇哈)。在這種情況下 autoreqprov, autoreq, and autoprov tags 標籤可以用來
disable自動依賴處理。autoreqprov--指完全禁用, autoreq --指僅提供需求, autoprov ---指僅支援“provides”
--來看看怎麼寫:
<1>需要和提供都禁用使用:AutoReqProv: no 
<2>只禁用需要使用:AutoReq: no
<3>只禁用"provides" 使用:AutoPro: no
--也可以使用數字0來代替字元‘no’ ;儘管RPM預設處理自動依賴的過程,但是受到autoreqprov, autoreq, and autoprov tags標籤的影響
(把‘no’變為‘yes’或者把數字‘0’替換為數字‘1’)


******Architecture- and Operating System-Specific Tags  與作業系統有關的特定的標籤
--伴隨著RPM的受到廣大使用者的歡迎,有人希望在不同的計算機系統上使用它。當然這不會有什麼問題,但是當下面兩種情況發生時
事情開始變的有點棘手。
<1>一個特定的作業系統被移植到不同的硬體平臺或者架構上;
<2>一個特定的體系結構上跑了不同的作業系統;
--真正的打擊是當RPM被用來在不同的系統環境下打包軟體時。沒有方法控制構建的過程基於不同的架構和系統,打包者就必須為不同的
架構和作業系統開發軟體包確實是很難。而唯一令人感覺快要奔潰的做法就是維護一個並行的RPM構建環境並接受所有的協調。但是,哈!!
--但是,看好了,幸運的是,RPM讓這一切變得非常簡單。使用下面的這些標籤可以支援在多個環境下構建軟體包,而所有的這一切
只是用了一個原始碼、patches和一個spec檔案。(又來了,你是不是很受不了,但是沒辦法,為了行文簡介)在多平臺多架構上構建
RPM包的更加完善的討論,將在後面的章節給出,請看《Chapter 19. Building Packages for Multiple Architectures and Operating Systems》


--The excludearch Tag  
標籤 excludearch 保證讓RPM不去嘗試被排除的平臺架構上打包;為什麼要阻止包構建的原因是:
<1>軟體還沒有移植到被排除的架構上;
<2>軟體在被排除的架構上沒有意義;
--舉個例子,軟體本來是基於32位的,很顯然,在64位機器上該被排除。
--第二個例子,軟體是包含一個底層特性的架構專用,所以在不同的架構上應該被排除;比如說彙編程式;
--排除一個或者多個架構在 excludearch 標籤後面,多個架構用空格或者逗號隔開表示;
例如: 
---------------------------------------
ExcludeArch: sparc alpha mips
---------------------------------------
在這個例子中RPM將不會嘗試在SUN 的SPARC 、alpha 或者mips平臺架構上執行;如果你在這其中的某一個架構上
執行構建命令,則將失敗:
-------------------------------------------------------------------
# rpmbuild -ba cdplayer-1.0.spec
Arch mismatch!
cdplayer-1.0.spec doesn't build on this architecture
#
------------------------------------------------------------------
注意,如果你的意圖是隻在某一個指定平臺架構上構建,可以使用 exclusivearch 標籤;


--The exclusivearch Tag  --獨有的,排外的架構的標籤(其實顧名思義很好理解)
這個標籤告知RPM只能在指定的架構上構建軟體包。為什麼這麼做?這個標籤會確保沒有其他平臺架構將錯誤的構建。
----------------------------------
ExclusiveArch: sparc alpha           
-----------------------------------
在這例子中的包只能在指定的架構上那個構建;如果你還是想不在某個平臺平臺架構上構建,可以使用 excludearch 標籤;


--The excludeos Tag --排除os的標籤
用來排除指定的作業系統。ExcludeOS: linux irix


--The exclusiveos Tag  --指定os的標籤
和上面 excludeos的意思相反;只在指定的os上構建;


*******Directory-related Tags 目錄有關的tags
--The prefix Tag
這個標籤可以指定安裝時的路徑,而這個指定需要在files標籤中也做對應的改動:
Prefix: /opt
在files中的改動:
/opt/blather/foonly


---The buildroot Tag 構建根目錄
顧名思義用於制定一個構建根目錄。這名字可能會誤導你,實際是作為軟體包在構建過程的install使用。
這裡只是簡單的說明,詳細的描述會在後面說明。
比如說:
----------------------------
BuildRoot: /tmp/cdplayer
-------------------------------
buildroot 標籤可以在構建過程中被命令選項"--buildroot" 指定的路徑覆蓋。


****Source and Patch Tags 原始碼餓補丁有關的標籤
要構建並打包軟體,RPM必須知道原始碼是誰。如何實現這一目的呢!使用一系列sources 標籤來通知RPM原始碼
的資訊和補丁的資訊。


--The source Tag 源標籤
源標籤是一個spec檔案的核心。雖然你只看到了一個描述的資料,但實際上他執行了兩個功能:
<1>顯示軟體開發者可用的原始檔;
<2>告訴RPM原始碼的名稱;
--雖然沒有硬性規定對於第一個功能,但是一般認為是"URL";URL指向原始檔。原始檔必須是路徑的最後一個元素;
看一個例子:
Source: ftp://ftp.gnomovision.com/pub/cdplayer-1.0.tgz  
有了這一行,RPM將會在原始檔(SOURCES目錄)中尋找cdplayer-1.0.tgz 這個檔案。
--一個spec檔案可能會包含不止一個源標籤。這就需要源標籤必須具備唯一性以便於識別,我們在原標籤的尾部加上數字
來表示不同的多個原始檔。要注意的一點是Source在spec檔案表示Source0,看下面:
Source: blather-4.5.tar.gz   #不加數字結尾預設會為0
Source1: bother-1.2.tar.gz
--------------------------------
Source0: blather-4.5.tar.gz
Source1: bother-1.2.tar.gz
套用老外的一句話:Either approach may be used. The choice is yours. ---條條大路通羅馬,看你的選擇!!


--The nosource Tag 
這個標籤可以用在省略一個或者多個原始碼包的時候。為什麼要省略,神吶!!為甚有人會去找原始檔的麻煩,只有排除它嗎?
答案是:也許吧!這樣,我們來看一個例子:相信你聽說過一個PGP這個軟體吧!PGP包含加密程式,美國政府限制出口。
而剛好建立一個PGP包檔案,由此產生的包不能合法的美國和其他國家之間的傳播,反之亦然。
--然而所有除了原始碼的其他檔案都是用RPM打包嗎?這樣理解,一個二進位制檔案有沒有PGP作用不大,但是對於一個原始碼包而言呢?
它將包含規範檔案,也許一些補丁,甚至一個圖示檔案。因為有爭議的PGP軟體不是一個原始碼包的一部分,這個淨化源包可以在任何國家合法下載
下載一個副本的人可以合法獲得PGP來源本身,將它們在RPM的源目錄,並建立一個二進位制包。他們甚至不需要改變nosource標記。
一個rpmbuild -ba 命令後,使用者會完全使用PGP二進位制包檔案。
這個東西是美國人搞得一個安全的東西,但是對誰來說是安全的我們不得而知????建議可以使用開源的GPG(Gnu Privacy Guard)
--說了這麼多,看看怎麼使用:
--------------------------------------------------
nosource: <src-num>, <src-num>…<src-num>
source: blather-4.5.tar.gz
Source1: bother-1.2.tar.gz
source2: blather-lib-4.5.tar.gz
source3: bother-lib-1.2.tar.gz
----------------------------------------------------
如果blather bother-lib不要被打包,下面的寫法就ok!!
------------------------------------------------
NoSource: 0, 3
--------------------------------------------------
這裡的數字0指的是什麼還記得吧,spec檔案中第一個未編號的源會被RPM自動編號為0;


---The patch Tag  補丁標籤
補丁標籤用於識別哪一個補丁將被打包進軟體包。補丁檔案也存在於SOURCES目錄下.
Patch: cdp-0.33-fsstnd.patch
補丁檔案的命名沒有什麼硬性的要求,但是依照慣例名字應該是以軟體名和版本開始並用破折號‘-’隔開,
補丁檔名稱的下一部分通常包括一個或多個詞表明補丁的原因。


--一個spec檔案可能包含不止一個補丁檔案,補丁標籤的命名和Source標籤類似;
-----------------------------------------------------------------------
Patch: blather-4.5-bugfix.patch
Patch1: blather-4.5-config.patch
Patch2: blather-4.5-somethingelse.patch
或者, 少了多了一個0編號!!
Patch0: blather-4.5-bugfix.patch
Patch1: blather-4.5-config.patch
Patch2: blather-4.5-somethingelse.patch
------------------------------------------------------------------------


The nopatch Tag
--和nosource 類似
------------------------------
NoPatch: 2 3
-----------------------------


*****************Scripts: RPM's Workhorse 做苦力的指令碼:*****************
RPM 用指令碼來控制構建的過程是spec檔案中變幻多樣並精彩的的一部分。大多數spec檔案也使用指令碼來來實行各種
任務,包的安裝和解除安裝;
--每一個指令碼的開始用一個關鍵字。比如,關鍵字%build 標誌著RPM開始執行軟體包打包過程中的編譯階段。
值得注意的是,嚴格的來說這些是spec檔案的一部分而不是指令碼。比如說,他們不是以呼叫shell開始執行。而是將指令碼各部分
放在一個檔案中由RPM來作為一個完整的指令碼來執行。這就是RPM 強大的一種體現:任何指令碼都可以由RPM來執行。
--我們一起來看看在build過程中指令碼的使用;
---Build-time Scripts 編譯時指令碼
每個軟體開發人員都知曉RPM在打包的build階段執行指令碼的步驟:
解壓原始檔---編譯軟體----安裝軟體(install階段呢)---clean一些臨時檔案。
儘管每個指令碼執行特定的功能,但是它們在一個共同的環境中。rpmbuild的一個引數--test已經在新版本中找不到了,否則我們可以一睹
RPM根據spec檔案建立的每個階段的指令碼。????????
所以這裡我就不分析了》??????????我覺得這個引數選項很有用但不知道為什麼取消???
--好了先不管這麼多,反正這些build時的指令碼時會建立的,而且確實從在,我們可以通過其他方式獲得這些指令碼!!!自己想想》》


當你執行了rpmbuild -b{a/p/i/c}  cdplayer-1.0-1.spec 命令中任意個引數選項時,我們可以看到:
--------------------------------------------------------------
構建目標平臺:mips64el
3252 為目標mips64el構建
3253 執行(%prep): /bin/sh -e /var/tmp/rpm-tmp.zXjuSe
3254 + umask 022
3255 + cd /home/zhongtian/rpmbuild/BUILD
3256 + patch_command='patch -p1 -F1 -s'
3257 + cd /home/zhongtian/rpmbuild/BUILD
--------------------------------------------------------------
你不用管我使用的平臺,關鍵看‘/var/tmp/rpm-tmp.zXjuSe’ --這個指令碼就是RPM為prep階段生成的指令碼,而且是以臨時指令碼的
形式存在。構造完整之後會被清除。在這一過過程中會這隻一些列的環境變數。簡要來說如下所示:
-------------------------------------------
RPM_SOURCE_DIR 
RPM_BUILD_DIR
RPM_DOC_DIR 
RPM_OPT_FLAGS 
RPM_ARCH
RPM_OS
RPM_BUILD_ROOT
RPM_PACKAGE_NAME
RPM_PACKAGE_VERSION 
RPM_PACKAGE_RELEASE 
-----------------------------------------------
上面所列舉的這些變數是由RPM的全域性巨集配置檔案中定義的,舊版本上在/etc/rpm/macros這個檔案中,使用者配置檔案可以在
家目錄下配置“per-user configuration should be added to ~/.rpmmacros” ,這句話解釋的很清楚了。在新版本的RPM中
預設的全域性巨集配置檔案路徑改變到/usr/lib/rpm/macros中。
來看看:
------------------------------------------------------------------
%___build_pre   \
  RPM_SOURCE_DIR=\"%{u2p:%{_sourcedir}}\"\
  RPM_BUILD_DIR=\"%{u2p:%{_builddir}}\"\
  RPM_OPT_FLAGS=\"%{optflags}\"\
  RPM_LD_FLAGS=\"%{?__global_ldflags}\"\
  RPM_ARCH=\"%{_arch}\"\
  RPM_OS=\"%{_os}\"\
  export RPM_SOURCE_DIR RPM_BUILD_DIR RPM_OPT_FLAGS RPM_LD_FLAGS RPM_ARCH RPM_OS\
  RPM_DOC_DIR=\"%{_docdir}\"\
  export RPM_DOC_DIR\
  RPM_PACKAGE_NAME=\"%{name}\"\
  RPM_PACKAGE_VERSION=\"%{version}\"\
  RPM_PACKAGE_RELEASE=\"%{release}\"\
  export RPM_PACKAGE_NAME RPM_PACKAGE_VERSION RPM_PACKAGE_RELEASE\
  LANG=C\
  export LANG\
  unset CDPATH DISPLAY ||:\
  %{?buildroot:RPM_BUILD_ROOT=\"%{u2p:%{buildroot}}\"
------------------------------------------------------------------
在全域性巨集配置檔案中定義了這些巨集的屬性,以及巨集擴充套件之後的具體資訊,來看:
----------------------------------------------------------------------------
#       The directory where sources/patches from a source package will be
#       installed. This is also where sources/patches are found when building.
#       原始碼檔案和補丁檔案等打包所需的原始檔在目錄路徑
%_sourcedir             %{_topdir}/SOURCES


#       The directory where the spec file from a source package will be
#       installed.
%_specdir               %{_topdir}/SPECS


#       The directory where newly built source packages will be written.
%_srcrpmdir             %{_topdir}/SRPMS


#       The directory where buildroots will be created.
%_buildrootdir          %{_topdir}/BUILDROOT


#       Build root path, where %install installs the package during build.
%buildroot              %{_buildrootdir}/%{name}-%{version}-%{release}.%{_arch}


#       Directory where temporaray files can be created.
%_tmppath               %{_var}/tmp


#       Path to top of build area.
%_topdir                %{getenv:HOME}/rpmbuild


#       The path to the unzip executable (legacy, use %{__unzip} instead).
%_unzipbin              %{__unzip}
----------------------------------------------------------------------------
上面這些巨集的擴充套件後的原型在全域性巨集的配置檔案中有詳細的定義,我這裡列出了常見的幾個,具體可以在這檔案中檢視;


--指令碼還設定一個選項,讓shell列印每個命令,完成巨集引數的擴充套件。最後,設定預設的許可權。經過這個節點之後,指令碼開始發生變化。
讓我們一起看看RPM執行的指令碼的順序。


----The %prep Script 
The %prep Script 這個指令碼是RPM在包的構建過程中首先執行的指令碼。
在%prep指令碼之前,RPM已經初步的進行了一致性檢查,如規範檔案的源標籤指向檔案是否實際存在。首先%prep指令碼的內容控制RPM切換目錄
到構建域(這裡的域是指工作所在的目錄),預設這個路徑在家目錄下的rpmbuild/BUILD/ 目錄中(老版本在 /usr/src/redhat/BUILD)。
--在這一點,%prep 指令碼負責下面幾件事情:
**建立構建過程所需的頂層目錄。
**把原始碼解包到構建時目錄BUILD中。
**如果有patch的話打上補丁。
**執行其他必要的動作讓源來處於準備構建的狀態,為下一步構建過程做準備。
--上面列出的前三條動作在大多數軟體包的打包過程中比較常見。正因為如此,RPM提供了兩個巨集使這一過程大為簡化。這兩個巨集的具體描述
在下面的《Helpful Shorthand for Package Builders》部分具體講述。
--上面的最後一條包括建立一些目錄或者其他必要的讓源處於準備構建的狀態。總之,%prep指令碼可以是一行只包含
%setup巨集的形式,亦或是多行詭異的shell程式!(翻譯成“詭異”好嗎?)


----The %build Script
--其實這系列的操作你可以理解為“接力賽模式”,%build 指令碼撿起%prep的遺志繼續拼搏,來完成下一階段的構建任務。那麼,%build 是否
可以一統江湖嗎?我們再往下走!!一旦%prep指令碼為構建的過程做好準備,但是%build指令碼給人感覺有一點虎頭蛇尾,正常情況下
呼叫make,後者一個配置指令碼或什麼都沒有。


--和前面的%prep指令碼類似,%build指令碼有同樣的環境變數來使用。如%prep, %build也會切換目錄到軟體的包頂層構建目錄中去,
具體目錄巨集是RPM_BUILD_DIR(通常被命名為 <name>-<version> 前面這種格式),下面我把這巨集觀的具體擴充套件列了出來:
------------------------------------------------------------------------------------------------------------------
RPM_BUILD_DIR=\"%{u2p:%{_builddir}}\"\


#       The directory where sources/patches will be unpacked and built.  原始碼和補丁會在這個目錄中解包並編譯。
%_builddir              %{_topdir}/BUILD
-------------------------------------------------------------------------------------------------------------------


--和%prep不同的是,%build階段的指令碼沒有那麼多可用的巨集來被指令碼使用。原因當然很簡單:因為我們都知道有個make命令來幫忙,
或者這麼理解,這一階段主要編譯原始碼,而在稍大一點的工程的構建過程還沒有那個巨集能勝任。


----The %install Script   
--install指令碼的執行環境和其他指令碼一樣,還是切換工作目錄到構建的頂層目錄中去。
--顧名思義,%install 階段的指令碼負責新build的軟體的install(這裡會解釋一下什麼叫安裝,雖然比較基礎。)。多數情況下,
這裡就是一個make install命令,或者是拷貝檔案以及建立目錄。
####安裝實際的過程就是將編譯好的二進位制型別的軟體包放在指定的目錄下,我們平時安裝軟體就是這樣的過程。
--需要區分的是這裡的install是‘虛安裝’,我們這裡的目的是打包軟體,打包好的軟體裡包含了已經編譯好的二進位制程式,當用戶
安裝的我們打好的包的時候,這些二進位制軟體包會被拷貝到安裝程式中指定的目錄下
來看:(我們構建過程中的安裝目錄是:{_topdir}/BUILDROOT/%{name}-%{version}-%{release} 前面我們討論過,還記得嗎)。


---The %check Script  檢查指令碼,
檢查%check本身是包構建的一個階段的,只不過這階段不太長用。這個指令碼和其他指令碼類似,他的要務是對編譯的軟體進行測試。典型
的例子是make test 或者make check。
##注意:RPM在4.2以後的版本支援這個功能。


---The %clean Script
還是,顧名思義,%clean指令碼用來清理軟體的構建目錄樹。RPM預設會幫你做清理工作,
但是在某些情況下(當你使用--buildroot引數指定安裝的目錄的時)你需要包含你的%clean指令碼。
--大多數情況下你只需要一句簡單的命令:
----------------------------------------------------
rm -rf $RPM_BUILD_ROOT
----------------------------------------------------
哈哈!!所以前面說"--buildroot" 引數可能會咬你一口!!


****Install/Erase-time Scripts  安裝或者解除安裝時的指令碼(真實安裝)
下面這幾類的指令碼在spec檔案中主要被用於軟體的安裝或者解除安裝。在整個軟體包的生存週期裡
有四個指令碼在不同的時期被執行。如下:
**安裝之前
**安裝之後
**解除安裝之前
**解除安裝之後
--與前面討論的構建時的指令碼不同的是,在這種情況下沒有對這些指令碼的環境變數。
唯一可用的環境變數就是RPM_INSTALL_PREFIX ,而這還只是對安裝只使用唯一的安裝字首的情況。
--和構建時指令碼不同的是,這會定義一個引數。這個唯一的引數是一個數字,這數字代表當前系統安裝的這個軟體包的數量。聽起來
有點抽象,我們下面看一個例子:
--假設一個包名為blather-1.0的軟體被安裝了且沒有舊版本的blather被安裝。因為在軟體安裝的過程中有兩個
指令碼%pre和%post被執行,在此期間引數1被傳遞給這個指令碼,因為軟體blather安裝的數量是1.
--繼續深入這個例子。當一個新版本的blather軟體包,版本是1.3的已經可用了。那麼顯然已經是升級的時間了。那麼在
升級的過程中會是怎樣的一個指令碼的值呢?一旦新版本blather-1.3被安裝,指令碼%pre和%post的引數值會在之前的版本的
基礎上加1變為2 。在升級的最後階段會將blather-1.0解除安裝。而在包的解除安裝過程中,指令碼 %preun and %postun 會被執行
來解除安裝舊版的軟體。至此,系統上將只有一個新版本的blather-1.3被安裝。
--在這例子的最後,我們決定也解除安裝掉新版本(version 1.3)。我們不需要其他什麼東西,只要這個包被解除安裝,那麼
指令碼 %preun and %postun 依舊會被執行。一旦軟體blather完全被解除安裝,那麼傳給指令碼的引數就是0。


--綜上所述,可能使用的引數是什麼?嗯,它有兩個非常有趣的特點:
<1>當軟體包的第一個版本被安裝,傳給 %pre and %post指令碼的引數是1;
<2>當軟體包的最後一個版本被解除安裝,傳給 %preun and %postun指令碼的引數是0;
基於這些特性,很容易編寫一個指令碼安裝時,在特定的情況下可以採取某些行動。
通常,引數被用於%preun或%postun指令碼執行指定的任務當最後後一個包被解除安裝時。要注意的就是軟體包的名字在不同系統
環境上差異的問題。除非你能確保不同系統使用的指令碼的一致性。


----The %pre Script
這個指令碼在軟體包安裝之前被執行。這種安裝前需要執行某些指令碼的軟體包比較少見。350個包組成的Red Hat Linux Linux 4.0利用它。
???????????


----The %post Script
這個指令碼在已經安裝過的軟體包安裝時使用。主要的原因是在新版本的包被安裝後用ldconfig來更新可用的共享庫!當然,還有其他的
功能可以被%post指令碼執行。比如:使用%post指令碼新增shell的名稱為/etc/shells在安裝一個shell包的時候。
--如果一個包使用%post指令碼來執行某個功能,常常還會包含一個%postun 指令碼來執行相反的功能在包被解除安裝時。


---The %preun Script  
在使用者解除安裝你的包之前檢視它時,你可以在%preun指令碼中做這些事情。也就是說,在立即解除安裝軟體包之前所要
做的動作都可以在這裡來處理。


---The %postun Script
這個指令碼在包被解除安裝後執行(你可能會問都解除安裝了,怎麼還需要處理啊??)這就是最後一步的清理工作。通常,
這個指令碼用來執行ldconfig來從/etc/ld.so.cache 中移除相關的'.so' 庫檔案。


----Verification-Time Script — The %verifyscript Script
 %verifyscript腳本當RPM執行檢查命令的時候被執行。




 
========
說明
Notes
==============
[1]
Described in the Section called --test — Create, Save Build Scripts For Review in