轉自http://blog.sina.com.cn/s/blog_43b39e250100nnu4.html
rpm軟件包系統的標准分組:/usr/share/doc/rpm-4.3.3/GROUPS
rpmrc配置文件:/usr/lib/rpm/rpmrc /etc/rpmrc ~/.rpmrc
各種宏定義: /usr/lib/rpm/macros /etc/rpm/macros ~/.rpmmacros
已經安裝的rpm包數據庫: /var/lib/rpm*
臨時文件:/var/tmp/rpm*
可以通過命令rpm --showrc查看實現代碼。另外直接通過rpm --eval "%{macro}"來查看具體對應路徑。
比如我們要查看%{_bindir}的路徑,就可以使用命令rpm --eval "%{_bindir}"來查看。
用以下命令將spec文件取出。
$rpm -qlp *.src.rpm
$rpm2cpio *.src.rpm|cpio -ivh *.spec
首先執行rpm -qlp查詢得知該套件中有幾個.spec文件再執行rpm2cpio將rpm文件轉換成cpio文件格式並將轉換結果輸出給cpio程序把source rpm套件中的sepc文件解壓取出。
SPEC腳本引用定義部分
�fine userpath /var/www/html/demo
Name:
軟件包的名稱,后面可使用%{name}的方式引用
Summary:
軟件包的內容概要
Version:
軟件的實際版本號,例如:1.0.1等,后面可使用%{version}引用
Release:
發布序列號,例如:1linuxing等,標明第幾次打包,后面可使用%{release}引用
Copyright:
軟件包所采用的版權規則。具體有:GPL(自由軟件),BSD,MIT,Public Domain(公共域),Distributable(貢獻),commercial(商業),Share(共享)等,一般的開發都寫GPL。
Group:
軟件分組,建議使用標准分組,軟件包所屬類別,具體類別有:
Amusements/Games (娛樂/游戲)
Amusements/Graphics(娛樂/圖形)
Applications/Archiving (應用/文檔)
Applications/Communications(應用/通訊)
Applications/Databases (應用/數據庫)
Applications/Editors (應用/編輯器)
Applications/Emulators (應用/仿真器)
Applications/Engineering (應用/工程)
Applications/File (應用/文件)
Applications/Internet (應用/因特網)
Applications/Multimedia(應用/多媒體)
Applications/Productivity (應用/產品)
Applications/Publishing(應用/印刷)
Applications/System(應用/系統)
Applications/Text (應用/文本)
Development/Debuggers (開發/調試器)
Development/Languages (開發/語言)
Development/Libraries (開發/函數庫)
Development/System (開發/系統)
Development/Tools (開發/工具)
Documentation (文檔)
System Environment/Base(系統環境/基礎)
System Environment/Daemons (系統環境/守護)
System Environment/Kernel (系統環境/內核)
System Environment/Libraries (系統環境/函數庫)
System Environment/Shells (系統環境/接口)
User Interface/Desktops(用戶界面/桌面)
User Interface/X (用戶界面/X窗口)
User Interface/X Hardware Support (用戶界面/X硬件支持)
License:
軟件授權方式,通常就是GPL
Source:
源代碼包,可以帶多個用Source1、Source2等源,后面也可以用%{source1}、%{source2}引用。
NoSource:0 #第一個源碼不包含在包中
Patch:
補丁源碼,可使用Patch1、Patch2等標識多個補丁,使用%patch0或%{patch0}引用,
補丁 ID 規則
0-9 Makefile、configure 等的補丁
10-39 指定功能或包含他的文件的補丁
40-59 配置文件的補丁
60-79 字體或字符補丁
80-99 通過 xgettexize 得到的目錄情況的補丁
100- 其他補丁
NoPatch:0 #第一個補丁文件不包含在包中
BuildRoot:
這個是安裝或編譯時使用的“虛擬目錄”,考慮到多用戶的環境,一般定義為:%{_tmppath}/%{name}-%{version}-root
%{_tmppath}/%{name}-%{version}-%{release}-root
或
%{_tmppath}/%{name}-%{version}-%{release}-buildroot-%(%{__id_u} -n}
該參數非常重要,后面可使用$RPM_BUILD_ROOT 方式引用。因為在生成rpm的過程中,執行make install時就會把軟件安裝到上述的路徑中,在打包的時候,同樣依賴“虛擬目錄”為“根目錄”進行操作。
※注意區分$RPM_BUILD_ROOT和$RPM_BUILD_DIR:
$RPM_BUILD_ROOT是指定義的BuildRoot,而$RPM_BUILD_DIR通常就是指/usr/src/asianux/BUILD,其中,前面的才是%file需要的。
URL:
軟件的主頁
Vendor:
軟件開發者名字,發行商或打包組織的信息,例如RedFlag Co,Ltd
Distribution:
發行版標識
例如Red Hat Linux
ExcludeArch: sparc s390 #rpm包不能在該系統結構下創建,如果是這個環境,將報錯。
ExclusiveArch: i386 ia64 #rpm包只能在給定的系統結構下創建
ExcludeOS:windows #rpm包不能在該操作系統下創建
ExclusiveOS: linux #rpm包只能在給定的操作系統下創建
(
%ifarch sparc s390 判斷處理器的結構
%ifnoarch i386 alpha 與上邊相反
%ifos linux 測試操作系統
%ifnos linux 與上邊相反
)
Icon:
file.xpm or file.gif #存儲在rpm包中的icon文件
Prefix:
%{_prefix} 這個主要是為了解決今后安裝rpm包時,並不一定把軟件安裝到rpm中打包的目錄的情況。這樣,必須在這里定義該標識,並在編寫%install腳本的時候引用,才能實現rpm安裝時重新指定位置的功能
%{_sysconfdir} 這個原因和上面的一樣,但由於%{_prefix}指/usr,而對於其他的文件,例如/etc下的配置文件,則需要用%{_sysconfdir}標識
Prefix: /usr #定義一個relocatable的包,當安裝或更新包時, #所有在/usr目錄下的包都可以映射到其他目錄,當定義Prefix時,所有%files標志的文件都要在Prefix 定 義的目錄下
BuildArch:
指編譯的目標處理器架構,noarch標識不指定,但通常都是以/usr/lib/rpm/marcros中的內容為默認值
Obsoletes:
過時的,廢棄的。
Obsoletes:anaconda-images <= 10
Provides:
指明本軟件提供一些特定的功能,以便其他rpm識別
例如:
Provides: mail-reader
Requires:
該rpm包所依賴的軟件包名稱,可以用>=或<=表示大於或小於某一特定版本,
※“>=”號兩邊需用空格隔開,而不同軟件名稱也用空格分開
例如:該包需要 libpng-devel版本至少為 1.0.20,以及zlib
Requires: libpng-devel >= 1.0.20 zlib
Requires: bzip2 = %{version}, bzip2-libs = %{version}
Requires: perl(Carp)>=3.2 需要perl模塊Carp
PreReq、Requires(pre)、Requires(post)、Requires(preun)、Requires(postun)、BuildRequires等都是針對不同階段的依賴指定
PreReq: capability >=version #capability包必須先安裝
Conflicts:bash>=2.0 #該包和所有不小於2.0的bash包有沖突
以上三者是在安裝RPM包時要滿足.
BuildRequires:
BuildRequires: zlib-devel
BuildPreReq:
BuildConflicts:
這三個選項的依賴性關系在構建RPM包時就要滿足
Autoreq:
rpm_build時會為包里的二進制文件找出對應的共享庫(.so)依賴,打成RPM包后可能在安裝時提示缺少依賴並退出,要避免執行find-requires找共享庫依賴,可以加上禁用自動依賴Autoreq:no 或者設為0
Autoprov:
rpm_build時會為包里的二進制文件找出對應的共享庫(.so)依賴,打成RPM包后可能在安裝時提示缺少依賴並退出,要避免執行find-provides找共享庫依賴,可以加上禁用自動依賴Autoprov:no 或者設為0
AutoReqProv:no
rpm_build時會為包里的二進制文件找出對應的共享庫(.so)依賴,打成RPM包后可能在安裝時提示缺少依賴並退出,要避免執行find-provides與find-requires找共享庫依賴,可以加上禁用自動依賴
Autoprov:no 或者設為0 或者為flase 相當於同時設定上邊兩個的值Autoreq:和Autoprov:
上邊3個會因為順序的不同而導致結果會有所不同,一般以最后一個為准。
%triggerin -- package < version
執行腳本或者命令
#當package包安裝或更新時,或本包安裝更新且 package已經安裝時,運行script
當其所在軟件包與指定軟件包僅有一方安裝時,安裝另一方將觸發此程序執行。
%triggerun -- package
執行腳本或者命令
#當package包刪除時,或本包刪除且package已經安裝時,運行script
當其所在軟件包與指定軟件包都已安裝時,卸載任一方將觸發此程序執行。
例如:
%triggerun -- anaconda < 8.0-1
./script
%triggerpostun -- package
#當package刪除時運行script,本包刪除時不運行
指定軟件包卸載后才觸發此程序執行。
%triggerpostun -p /usr/bin/perl -- vixie-cron <3.0.1-56
-p /usr/sh package < version
-n subpackage_name –vixie-cron <3.0.1-56
...script...
-p 解釋程序
-- 觸發條件
-n 子包的觸發條件等
Packager:
打包者的信息,姓名以及郵箱等,處於同一行。
�scription
軟件的詳細說明
上邊是關於RPM包信息的一些描述。
spec腳本主體
%package
#定義一個子包
%package -n sub_package_name #定義一個子包,名字為sub_package_name
當定義一個子包時,必須至少包含Summary:,Group:,�scription選項,任何沒有指定的選項將用父包的選項,如版本等,如:
%package server
Requires: xinetd
Group: System Environment/Daemons
Summary:The server program for the telnet remote login protocol
�scription server
Telnet is a popular protocol for logging into remote systems
如果在%package時用-n選項,那么在�scription時也要用,如:
�scription -n my-telnet-server
如果在%package時用-n選項,那么在%files時也要用,如:
%files -n my-telnet-server,也可以定義安裝或卸載腳本,像定義%files和�scription 一樣
%package devel
Summary: Header files and libraries for developing apps which will use bzip2.
Group: Development/Libraries
Requires: bzip2 = %{version}, bzip2-libs = %{version}
�scription devel
Header files and a static library of bzip2 functions, for developing apps
which will use the library.
%package libs
Summary: Libraries for applications using bzip2
Group: System Environment/Libraries
�scription libs
Libraries for applications using the bzip2 compression format.
%prep
預處理腳本,這個段是預處理段,通常用來執行一些解開源程序包的命令,為下一步的編譯安裝作准備。%prep和下面的%build,%install段一樣,除了可以執行RPM所定義的宏命令(以%開頭)以外,還可以執行SHELL命令,命令可以有很多行,如我們常寫的tar解包命令。
%preun
rpm卸載前執行的腳本
%setup
把源碼包解壓並放好
通常是從/usr/src/asianux/SOURCES里的包解壓到/usr/src/asianux/BUILD/%{name}-%{version}中。
%setup -q %{name}-%{version}
一般用%setup -q就可以了,但有兩種情況:一就是同時編譯多個源碼包,二就是源碼的tar包的名稱與解壓出來的目錄不一致,此時,就需要使用-n參數指定一下了。
%setup 不加任何選項,僅將軟件包打開。
%setup -q 在安靜模式下且最少輸出
%setup -D #在解壓之前禁止刪除目錄
%setup -a number #在改變目錄后,僅解壓給定數字的源碼,如-a 0 for source0
%setup -n newdir 將軟件包解壓到newdir目錄。
%setup -c 解壓縮之前先產生目錄。
%setup -b num 包含多個源文件時,將第num個source文件解壓縮。
%setup -T 不使用default的解壓縮操作。
%setup -T -b 0 將第0個源代碼文件SOURCE0解壓縮。
%setup -c -n newdir 指定目錄名稱newdir,並在此目錄產生rpm套件。
%patch
通常補丁都會一起在源碼tar.gz包中,或放到SOURCES目錄下。
一般參數為:
%patch -p1 使用前面定義的Patch補丁進行,-p1是忽略patch的第一層目錄
%Patch2 -p1 -b xxx.patch 打上指定的補丁,-b是指生成備份文件
%patch 最簡單的補丁方式,自動指定patch level。
%patch 0 使用第0個補丁文件,相當於%patch ?p 0。
%patch -s 不顯示打補丁時的信息。
%patch -T 將所有打補丁時產生的輸出文件刪除。
%patch #打補丁0
%patch1 #打補丁1
%patch2 #打補丁2
%patch -P 2 #打補丁2
在%build之前,%prep部分將准備好編譯工作,解開源碼包,並將相應的補丁打進去。
%build
開始編譯源碼構建包,相當於configure以及make部分
所要執行的命令為生成軟件包服務,如
%configure 這個不是關鍵字,而是rpm定義的標准宏命令。意思是執行源代碼的configure配置,可以用rpm –eval '%configure'命令查看該宏
在/usr/src/asianux/BUILD/%{name}-%{version}目錄中進行操作 ,使用標准寫法,會引用/usr/lib/rpm/marcros中定義的參數。
另一種不標准的寫法是,可參考源碼中的參數自定義,例如:
引用
CFLAGS="$RPM_OPT_FLAGS" CXXFLAGS="$RPM_OPT_FLAGS" ./configure --prefix=%{_prefix}
make 命令
在/usr/src/asianux/BUILD/%{name}-%{version}目錄中進行make的工作 ,常見寫法:
make %{?_smp_mflags} OPTIMIZE="%{optflags}"
都是一些優化參數,定義在/usr/lib/rpm/marcros中
%check
%install
開始把軟件安裝到虛擬的根目錄中,本段是安裝段,其中的命令在安裝軟件包時將執行,如make install命令、cp、mv、install、ln。
在/usr/src/asianux/BUILD/%{name}-%{version}目錄中進行make install的操作。這個很重要,因為如果這里的路徑不對的話,則下面%file中尋找文件的時候就會失敗。 常見內容有:
%makeinstall 這不是關鍵字,而是rpm定義的標准宏命令,相當於執行make install命令那一步。
也可以使用非標准寫法:
make DESTDIR=$RPM_BUILD_ROOT install
make prefix=$RPM_BUILD_ROOT install
make INSTROOT=$RPM_BUILD_ROOT install
需要說明的是,這里的%install主要就是為了后面的%file服務的。所以,還可以使用常規的系統命令:
rm -rf ${RPM_BUILD_ROOT}
mkdir -p $RPM_BUILD_ROOT/{%{_bindir},%{_mandir}/man1,%{_libdir},%{_includedir}}
install -m 755 bzlib.h $RPM_BUILD_ROOT/%{_includedir}
install -m 644 bzip2.1 bzdiff.1 bzgrep.1 bzmore.1 $RPM_BUILD_ROOT/%{_mandir}/man1/
install -d $RPM_BUILD_ROOT/
cp -a * $RPM_BUILD_ROOT/
ln -s file/magic ${RPM_BUILD_ROOT}%{_datadir}/magic
%find_lang %{name}
%files -f %{name}.lang
第一句生成一個名為%{name}.lang的文件,內容是所有的%{name}.mo,第二句意思是一個一個列舉.mo文件很麻煩,-f參數是將其后邊接的文件合並到%files的文件列表。
%clean
清除編譯和安裝時生成的臨時文件
通常內容為:
[ "$RPM_BUILD_ROOT" != "/" ] && rm -rf "$RPM_BUILD_ROOT"
rm -rf $RPM_BUILD_DIR/%{name}-%{version}
%post
rpm安裝后執行的腳本
%post libs -p /sbin/ldconfig
libs包時執行這部分動作
%postun
rpm卸載后執行的腳本
%postun libs -p /sbin/ldconfig
rpm還提供了一種信號機制:不同的操作會返回不同的信息,並放到默認變量$1中。
引用
0代表卸載、1代表安裝、2代表升級
可這樣使用:
引用
%postun
if [ "$1" = "0" ]; then
/sbin/ldconfig
fi
%verifyscript #軟件包校驗腳本程序開始執行
%files
�fattr (-,root,root)
本段是文件段,用於定義構成軟件包的文件列表,那些文件或目錄會放入rpm中,分為三類-說明文檔(doc),配置文件(config)及執行程序,還可定義文件存取權限,擁有者及組別。
這里會在虛擬根目錄下進行,千萬不要寫絕對路徑,而應用宏或變量表示相對路徑。
※特別需要注意的是:%install部分使用的是絕對路徑,而%file部分使用則是相對路徑,雖然其描述的是同一個地方。千萬不要寫錯。
%files -f %{name}.lang tui
file1 #文件中也可以包含通配符,如*
file2
directory #所有文件都放在directory目錄下
%dir /etc/xtoolwait #僅是一個空目錄/etc/xtoolwait打進包里
%doc 表示這是文檔文件,因此如安裝時使用--excludedocs將不安裝該文件,
%doc /usr/X11R6/man/man1/xtoolwait.* #安裝該文檔
%doc README NEWS #安裝這些文檔到/usr/share/doc/%{name}-%{version} 或者 /usr/doc或者
%docdir #定義說明文檔的目錄,例如/root,在這一語句后,所有以/root開頭的行都被定義為說明文件。
%config /etc/yp.conf #標志該文件是一個配置文件,升級過程中,RPM會有如下動作。
%config(missisgok) /etc/yp.conf 此配置文件可以丟失,即使丟失了,RPM在卸載軟件包時也不認為這是一個錯誤,並不報錯。一般用於那些軟件包安裝后建立的符號鏈接文件,如
/etc/rc.d/rc5.d/S55named文件,此類文件在軟件包卸載后可能需要刪除,所以丟失了也不要緊。
%config(noreplace) /etc/yp.conf
#該配置文件不會覆蓋已存在文件(RPM包中文件會以.rpmnew存在於系統,卸載時系統中的該配置文件會以.rpmsave保存下來,如果沒有這個選項,安裝時RPM包中文件會以.rpmorig存在於系統 )
覆蓋已存在文件(沒被修改),創建新的文件加上擴展后綴.rpmnew(被修改)
%{_bindir}/*
%config /etc/aa.conf
%ghost /etc/yp.conf #該文件不應該包含在包中,一般是日志文件,其文件屬性很重要,但是文件內容不重要,用了這個選項后,僅將其文件屬性加入包中。
%attr(mode, user, group) filename #控制文件的權限如%attr(0644,root,root) /etc/yp.conf
如果你不想指定值,可以用-
%config %attr(-,root,root) filename #設定文件類型和權限
�fattr(-,root,root) #設置文件的默認權限,-表示默認值,對文本文件是0644,可執行文件是0755
%lang(en) %{_datadir}/locale/en/LC_MESSAGES/tcsh* #用特定的語言標志文件
%verify(owner group size) filename #只測試owner,group,size,默認測試所有
%verify(not owner) filename #不測試owner,測試其他的屬性
所有的認證如下:
group: 認證文件的組
maj: 認證文件的主設備號
md5: 認證文件的MD5
min: 認證文件的輔設備號
mode: 認證文件的權限
mtime: 認證文件最后修改時間
owner: 認證文件的所有者
size: 認證文件的大小
symlink:認證符號連接
如果描述為目錄,表示目錄中出%exclude外的所有文件。
%files
�fattr(-,root,root)
%doc
%{_bindir}/*
%{_libdir}/liba*
%{_datadir}/file
%{_infodir}/*
%{_mandir}/man[15]/*
%{_includedir}
%exclude %{_libdir}/debug
(%exclude 列出不想打包到rpm中的文件。※小心,如果%exclude指定的文件不存在,也會出錯的。)
如果把
%files
�fattr(-,root,root)
%{_bindir}
寫成
%files
�fattr(-,root,root)
/usr/bin
則打包的會是根目錄下的/usr/bin中所有的文件。
%files libs
�fattr(-,root,root)
%{_libdir}/*so.*
%files devel
�fattr(-,root,root)
%{_includedir}/*
由於必須在%file中包括所有套件中的文件,所以,我們需要清楚編譯完的套件到底包括那些文件,常見的做法是,人工模擬一次編譯的過程:
./configrue --prefix=/usr/local/xxx
make
make DESTDIR=/usr/local/xxx install
或
make prefix=/usr/local/xxx install
這樣,整個套件的內容就會被放到/usr/local/xxx中,可根據情況編寫%file和%exclude段
※當然,這個只能對源碼按GNU方式編寫,並使用GNU autotool創建的包有效,若自定義Makefile則不能一概而論。
%changelog
變更日志,本段是修改日志段。你可以將軟件的每次修改記錄到這里,保存到發布的軟件包中,以便查詢之用。每一個修改日志都有這樣一種格式:
第一行是:* 星期月日 年 修改人電子信箱。
其中:星期、月份均用英文形式的前3個字母,用中文會報錯。接下來的行寫的是修改了什么地方,可寫多行。一般以減號開始,便於后續的查 閱。
* Mon Mar 31 1997 Erik Troan <ewt@redhat.com>
- Fixed problems caused by 64 bit time_t.
技巧:
如果要避免生成debuginfo包:這個是默認會生成的rpm包。則可以使用下面的命令:
echo '�bug_package %{nil}' >> ~/.rpmmacros
如果rpm包已經做好,但在安裝的時候想修改默認路徑,則可以:
rpm -ivh --prefix=/opt/usr xxx.rpm
又或者同時修改多個路徑:
rpm xxx.rpm --relocate=/usr=/opt/usr --relocate=/etc=/usr/etc
所有的宏都可以在/usr/lib/rpm/macros里找到。
下面是宏對應路徑一覽表:
Macros mimicking autoconf variables
%{_sysconfdir} /etc
%{_prefix} /usr
%{_exec_prefix} %{_prefix}
%{_bindir} %{_exec_prefix}/bin
%{_lib} lib (lib64 on 64bit systems)
%{_libdir} %{_exec_prefix}/%{_lib}
%{_libexecdir} %{_exec_prefix}/libexec
%{_sbindir} %{_exec_prefix}/sbin
%{_sharedstatedir} /var/lib
%{_datadir} %{_prefix}/share
%{_includedir} %{_prefix}/include
%{_oldincludedir} /usr/include
%{_infodir} /usr/share/info
%{_mandir} /usr/share/man
%{_localstatedir} /var
%{_initddir} %{_sysconfdir}/rc.d/init.d
Note: On releases older than Fedora 10 (and EPEL),%{_initddir}does not exist. Instead, you should use the deprecated%{_initrddir}macro.
%{_topdir} %{getenv:HOME}/rpmbuild
%{_builddir} %{_topdir}/BUILD
%{_rpmdir} %{_topdir}/RPMS
%{_sourcedir} %{_topdir}/SOURCES
%{_specdir} %{_topdir}/SPECS
%{_srcrpmdir} %{_topdir}/SRPMS
%{_buildrootdir} %{_topdir}/BUILDROOT
Note: On releases older than Fedora 10 (and EPEL),%{_buildrootdir}does not exist.
%{_global_cflags} -O2 -g -pipe
%{_optflags} %{__global_cflags} -m32 -march=i386 -mtune=pentium4 # if redhat-rpm-config is installed
%{_var} /var
%{_tmppath} %{_var}/tmp
%{_usr} /usr
%{_usrsrc} %{_usr}/src
%{_docdir} %{_datadir}/doc
