rpm建包的原理其實並不複雜,可以理解為按照標準的格式整理一些資訊,包括:軟體基礎資訊,以及安裝、卸載前後執行的指令碼,對源碼包解壓、打補丁、編譯,安裝路徑和檔案等。
1.編寫spec檔案
1.1 spec指令碼關鍵字
Name: 軟體包的名稱,後面可使用%{name}的方式引用
Summary: 軟體包的內容概要
Version: 軟體的實際版本號碼,例如:1.0.1等,後面可使用%{version}引用
Release: 發布序號,例如:1linuxing等,標明第幾次打包,後面可使用%{release}引用
Group: 軟體分組,建議使用標準分組
License: 軟體授權方式,通常就是GPL
Source: 原始碼包,可以帶多個用Source1、Source2等源,後面也可以用%{source1}、%{source2}引用
BuildRoot: 這個是安裝或編譯時間使用的“虛擬目錄”,考慮到多使用者的環境,一般定義為:
%{_tmppath}/%{name}-%{version}-%{release}-root或%{_tmppath}/%{name}-%{version}-%{release}-buildroot-%(%{__id_u} -n}該參數非常重要,因為在產生rpm的過程中,執行make install時就會把軟體安裝到上述的路徑中,在打包的時候,同樣依賴“虛擬目錄”為“根目錄”進行操作。後面可使用$RPM_BUILD_ROOT 方式引用。
URL: 軟體的首頁
Vendor: 發行商或打包組織的資訊,例如RedFlag Co,Ltd
Disstribution: 發行版標識
Patch: 補丁源碼,可使用Patch1、Patch2等標識多個補丁,使用%patch0或%{patch0}引用
Prefix: %{_prefix} 這個主要是為瞭解決今後安裝rpm包時,並不一定把軟體安裝到rpm中打包的目錄的情況。這樣,必須在這裡定義該標識,並在編寫%install指令碼的時候引用,才能實現rpm安裝時重新指定位置的功能
Prefix: %{_sysconfdir} 這個原因和上面的一樣,但由於%{_prefix}指/usr,而對於其他的檔案,例如/etc下的設定檔,則需要用%{_sysconfdir}標識
Build Arch: 指編譯的目標處理器架構,noarch標識不指定,但通常都是以/usr/lib/rpm/marcros中的內容為預設值
Requires: 該rpm包所依賴的軟體包名稱,可以用>=或<=表示大於或小於某一特定版本,例如:
libpng-devel >= 1.0.20 zlib
※“>=”號兩邊需用空格隔開,而不同軟體名稱也用空格分開
還有例如PreReq、Requires(pre)、Requires(post)、Requires(preun)、Requires(postun)、BuildRequires等都是針對不同階段的依賴指定
Provides: 指明本軟體一些特定的功能,以便其他rpm識別
Packager: 打包者的資訊
%description 軟體的詳細說明
1.2 spec指令碼主體描述
%prep 預先處理指令碼
%setup -n %{name}-%{version} 把源碼包解壓並放好
通常是從/usr/src/asianux/SOURCES裡的包解壓到/usr/src/asianux/BUILD/%{name}-%{version}中。
一般用%setup -c就可以了,但有兩種情況:一就是同時編譯多個源碼包,二就是源碼的tar包的名稱與解壓出來的目錄不一致,此時,就需要使用-n參數指定一下了。
%patch 打補丁
通常補丁都會一起在源碼tar.gz包中,或放到SOURCES目錄下。一般參數為:
%patch -p1 使用前面定義的Patch補丁進行,-p1是忽略patch的第一層目錄
%Patch2 -p1 -b xxx.patch 打上指定的補丁,-b是指產生備份檔案
◎補充一下
引用
%setup 不加任何選項,僅將軟體包開啟。
%setup -n newdir 將軟體包解壓在newdir目錄。
%setup -c 解壓縮之前先產生目錄。
%setup -b num 將第num個source檔案解壓縮。
%setup -T 不使用default的解壓縮操作。
%setup -T -b 0 將第0個原始碼檔案解壓縮。
%setup -c -n newdir 指定目錄名稱newdir,並在此目錄產生rpm套件。
%patch 最簡單的補丁方式,自動指定patch level。
%patch 0 使用第0個補丁檔案,相當於%patch ?p 0。
%patch -s 不顯示打補丁時的資訊。
%patch -T 將所有打補丁時產生的輸出檔案刪除。
%configure 這個不是關鍵字,而是rpm定義的標準宏命令。意思是執行原始碼的configure配置
在/usr/src/asianux/BUILD/%{name}-%{version}目錄中進行 ,使用標準寫法,會引用/usr/lib/rpm/marcros中定義的參數。
另一種不標準的寫法是,可參考源碼中的參數自訂,例如:
引用CFLAGS="$RPM_OPT_FLAGS" CXXFLAGS="$RPM_OPT_FLAGS" ./configure --prefix=%{_prefix}
%build 開始構建包
在/usr/src/asianux/BUILD/%{name}-%{version}目錄中進行make的工作 ,常見寫法:
引用
make %{?_smp_mflags} OPTIMIZE="%{optflags}"
都是一些最佳化參數,定義在/usr/lib/rpm/marcros中
%install 開始把軟體安裝到虛擬根目錄中
在/usr/src/asianux/BUILD/%{name}-%{version}目錄中進行make install的操作。這個很重要,因為如果這裡的路徑不對的話,則下面%file中尋找檔案的時候就會失敗。 常見內容有:
%makeinstall 這不是關鍵字,而是rpm定義的標準宏命令。也可以使用非標準寫法:
引用
make DESTDIR=$RPM_BUILD_ROOT install
或
引用
make prefix=$RPM_BUILD_ROOT install
需要說明的是,這裡的%install主要就是為了後面的%file服務的。所以,還可以使用常規的系統命令:
引用
install -d $RPM_BUILD_ROOT/
cp -a * $RPM_BUILD_ROOT/
%clean 清理臨時檔案
通常內容為:
引用
[ "$RPM_BUILD_ROOT" != "/" ] && rm -rf "$RPM_BUILD_ROOT"
rm -rf $RPM_BUILD_DIR/%{name}-%{version}
※注意區分$RPM_BUILD_ROOT和$RPM_BUILD_DIR:
$RPM_BUILD_ROOT是指開頭定義的BuildRoot,而$RPM_BUILD_DIR通常就是指/usr/src/asianux/BUILD,其中,前面的才是%file需要的。
%pre rpm安裝前執行的指令碼
%post rpm安裝後執行的指令碼
%preun rpm卸載前執行的指令碼
%postun rpm卸載後執行的指令碼
%preun %postun 的區別是什麼呢?
前者在升級的時候會執行,後者在升級rpm包的時候不會執行
%files 定義那些檔案或目錄會放入rpm中
這裡會在虛擬根目錄下進行,千萬不要寫絕對路徑,而應用宏或變數表示相對路徑。 如果描述為目錄,表示目錄中除%exclude外的所有檔案。
%defattr (-,root,root) 指定封裝檔案的屬性,分別是(mode,owner,group),-表示預設值,對文字檔是0644,可執行檔是0755
%exclude 列出不想打包到rpm中的檔案
※小心,如果%exclude指定的檔案不存在,也會出錯的。
%changelog 變更日誌
1.3
2.運行rpmbuild進行打包
1) 只產生二進位格式的rpm包
rpmbuild -bb xxx.spec
用此命令產生軟體包,執行後螢幕將顯示如下資訊:(每行開頭為行號)
1 Executing: %prep 2 + umask 022 3
+ cd /usr/src/dist/BUILD 4
+ exit 0
5 Executing: %build 6
+ umask 022 7
+ cd /usr/src/dist/BUILD
產生的檔案會在剛才建立的RPM目錄下存在。
2)只產生src格式的rpm包
rpmbuild -bs xxx.spec
產生的檔案會在剛才建立的SRPM目錄下存在。
3) 只需要產生完整的源檔案
rpmbuild -bp xxx.spec
源檔案存在目錄BUILD下。
讀者朋友可能對這個命令不太明白,這個命令的作用就是把tar包解開然後把所有的補丁檔案合并而產生一個完整的具最新功能的源檔案。
4) 完全打包
rpmbuild -ba xxx.spec
產生以上3個過程分別產生的包。存放在相應的目錄下。
4.附錄:宏路徑
%{_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.
RPM directory macros
%{_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.
Build flags macros
%{_global_cflags} -O2 -g -pipe
%{_optflags} %{__global_cflags} -m32 -march=i386 -mtune=pentium4 # if redhat-rpm-config is installed
Other macros
%{_var} /var
%{_tmppath} %{_var}/tmp
%{_usr} /usr
%{_usrsrc} %{_usr}/src
%{_docdir} %{_datadir}/doc