RPM打包原理、示例、详解及备查
原文地址:https://blog.csdn.net/qq_16542775/article/details/80961213
RPM(Redhat Package Manager)是用于Redhat、CentOS、Fedora等Linux 分發版(distribution)的常見的軟件包管理器。因為它允許分發已編譯的軟件,所以用戶只用一個命令就可以安裝軟件。看到這篇文章的朋友想必已經知道RPM是個啥,rpm/yum命令怎么用,廢話不多說,直接進入正題,來看看RPM包咋打。
1 準備
首先請準備一個Linux環境,比如CentOS。?
RPM打包使用的是rpmbuild命令,這個命令來自rpm-build包,這個是必裝的。
當然也可以直接安裝rpmdevtools,這個工具還包含一些其他的工具,同時它依賴rpm-build,所以直接安裝的話會同時把rpm-build裝上。
yum install rpmdevtools當然,根據不同的軟件構建過程,還需要其他的編譯打包工具,比如C語言的make、gcc,python的setuptools等,根據需要安裝即可。
2 原理
RPM打包的時候需要編譯源碼,還需要把編譯好的配置文件啊二進制命令文件啊之類的東西按照安裝好的樣子放到合適的位置,還要根據需要對RPM的包進行測試,這些都需要先有一個“工作空間”。rpmbuild命令使用一套標準化的“工作空間”:
rpmdev-setuptreerpmdev-setuptree這個命令就是安裝rpmdevtools帶來的。可以看到運行了這個命令之后,在$HOME家目錄下多了一個叫做rpmbuild的文件夾,里邊內容如下:
tree rpmbuild rpmbuild ├── BUILD ├── RPMS ├── SOURCES ├── SPECS └── SRPMS mkdir -p ~/rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS}從這些文件的名字大體也能看得出來都是干嘛用的。具體來說:
| ~/rpmbuild/SPECS | %_specdir | Spec 文件目錄 | 保存 RPM 包配置(.spec)文件 |
| ~/rpmbuild/SOURCES | %_sourcedir | 源代碼目錄 | 保存源碼包(如 .tar 包)和所有 patch 補丁 |
| ~/rpmbuild/BUILD | %_builddir | 構建目錄 | 源碼包被解壓至此,并在該目錄的子目錄完成編譯 |
| ~/rpmbuild/BUILDROOT | %_buildrootdir | 最終安裝目錄 | 保存 %install 階段安裝的文件 |
| ~/rpmbuild/RPMS | %_rpmdir | 標準 RPM 包目錄 | 生成/保存二進制 RPM 包 |
| ~/rpmbuild/SRPMS | %_srcrpmdir | 源代碼 RPM 包目錄 | 生成/保存源碼 RPM 包(SRPM) |
?
SPECS下是RPM包的配置文件,是RPM打包的“圖紙”,這個文件會告訴rpmbuild命令如何去打包。“宏代碼”這一列就可以在SPEC文件中用來代指所對應的目錄,類似于編程語言中的宏或全局變量。當然~/rpmbuild這個文件夾也是有宏代碼的,叫做%_topdir。
打包的過程有點像是流水線,分好幾個工序:?
1. 首先,需要把源代碼放到%_sourcedir中;?
2. 然后,進行編譯,編譯的過程是在%_builddir中完成的,所以需要先把源代碼復制到這個目錄下邊,一般情況下,源代碼是壓縮包格式,那么就解壓過來即可;?
3. 第三步,進行“安裝”,這里有點類似于預先組裝軟件包,把軟件包應該包含的內容(比如二進制文件、配置文件、man文檔等)復制到%_buildrootdir中,并按照實際安裝后的目錄結構組裝,比如二進制命令可能會放在/usr/bin下,那么就在%_buildrootdir下也按照同樣的目錄結構放置;?
4. 然后,需要配置一些必要的工作,比如在實際安裝前的準備啦,安裝后的清理啦,以及在卸載前后要做的工作啦等等,這樣也都是通過配置在SPEC文件中來告訴rpmbuild命令;?
5. 還有一步可選操作,那就是檢查軟件是否正常運行;?
5. 最后,生成的RPM包放置到%_rpmdir,源碼包放置到%_srpmdir下。
以上這些步驟都是配置在SPEC文件中的,具體來說各個階段:
| %prep | %_sourcedir | %_builddir | 讀取位于?%_sourcedir?目錄的源代碼和 patch 。之后,解壓源代碼至?%_builddir?的子目錄并應用所有 patch。 |
| %build | %_builddir | %_builddir | 編譯位于?%_builddir?構建目錄下的文件。通過執行類似?./configure && make?的命令實現。 |
| %install | %_builddir | %_buildrootdir | 讀取位于?%_builddir?構建目錄下的文件并將其安裝至?%_buildrootdir?目錄。這些文件就是用戶安裝 RPM 后,最終得到的文件。注意一個奇怪的地方: 最終安裝目錄 不是 構建目錄。通過執行類似?make install?的命令實現。 |
| %check | %_builddir | %_builddir | 檢查軟件是否正常運行。通過執行類似?make test?的命令實現。很多軟件包都不需要此步。 |
| bin | %_buildrootdir | %_rpmdir | 讀取位于?%_buildrootdir?最終安裝目錄下的文件,以便最終在?%_rpmdir?目錄下創建 RPM 包。在該目錄下,不同架構的 RPM 包會分別保存至不同子目錄,?noarch?目錄保存適用于所有架構的 RPM 包。這些 RPM 文件就是用戶最終安裝的 RPM 包。 |
| src | %_sourcedir | %_srcrpmdir | 創建源碼 RPM 包(簡稱 SRPM,以.src.rpm?作為后綴名),并保存至?%_srcrpmdir目錄。SRPM 包通常用于審核和升級軟件包。 |
3 示例
解釋再多不如一個例子來的明白,這里用官方文檔中的例子來操作一遍。?
下面演示 GNU“Hello World” 項目的打包過程。雖然用 C 語言程序打印 “Hello World” 到標準輸出是小菜一碟,但 GNU 版本包含了與一個典型的 FOSS 軟件項目相關的最常用的外圍組件,包括配置/編譯/安裝環境、文檔、國際化等等。GNU 版本包含了一個由源代碼和 configure/make 腳本組成的 tar 文件,但并不包含打包信息。因此,這是一個很好的 RPM 包打包示例。
3.1 下載源碼
還記得前面介紹到的幾個階段嗎,先準備源碼,這里我們直接下載官方例子的源碼,是個壓縮包:
cd ~/rpmbuild/SOURCES wget http://ftp.gnu.org/gnu/hello/hello-2.10.tar.gz不知道為啥有時候源碼包下起來特別慢甚至下不動,可以先用迅雷下載下來,然后傳到虛擬機里。
3.2 編輯SPEC文件
然后后續的步驟就交給SPEC文件來配置了,編輯SPEC文件(Emacs 和 vi 的最新版本有 .spec 文件編輯模式,它會在創建新文件時打開一個類似的模板。所以可使用以下命令來自動使用模板文件):
$ cd ~/rpmbuild/SPECS $ vim hello.spec既然有模板,那么后邊的工作就是填空題了:
Name: hello Version: 2.1 Release: 1%{?dist} Summary: The "Hello World" program from GNU Summary(zh_CN): GNU "Hello World" 程序 License: GPLv3+ URL: http://ftp.gnu.org/gnu/hello Source0: http://ftp.gnu.org/gnu/hello/%{name}-%{version}.tar.gz%description The "Hello World" program, done with all bells and whistles of a proper FOSS project, including configuration, build, internationalization, help files, etc. %description -l zh_CN "Hello World" 程序, 包含 FOSS 項目所需的所有部分, 包括配置, 構建, 國際化, 幫助文件等. %prep %setup -q%build %configure make %{?_smp_mflags}%install make install DESTDIR=%{buildroot}%files %doc %changelog * Sun Dec 4 2016 Your Name <youremail@xxx.xxx> - 2.10-1 - Update to 2.10 * Sat Dec 3 2016 Your Name <youremail@xxx.xxx> - 2.9-1 - Update to 2.9%changelog?標簽應包含每個 Release 所做的更改日志,尤其應包含上游的安全/漏洞補丁的說明。Changelog 日志可使用?rpm --changelog -q <packagename>?查詢,通過查詢可得知已安裝的軟件是否包含指定漏洞和安全補丁。%changelog?條目應包含版本字符串,以避免?rpmlint?工具警告。
3.3 構建RPM包
有點迫不及待了,嘗試執行以下命令,以構建源碼、二進制和包含調試信息的軟件包:
rpmbuild -ba hello.spec1)包含要安裝的文件?
不過上邊的命令執行失敗了0_0。?
命令執行后,提示并列出未打包的文件:
那些需要安裝在系統中的文件,我們需要在 %files 中聲明它們,這樣rpmbuild命令才知道哪些文件是要安裝的。?
注意不要使用形如?/usr/bin/?的硬編碼, 應使用類似?%{_bindir}/hello?這樣的宏來替代。手冊頁應在?%doc?中聲明 :?%doc %{_mandir}/man1/hello.1.*。?
由于示例的程序使用了翻譯和國際化,因此會看到很多未聲明的 i18 文件。 使用?推薦方法?來聲明它們:
- 包含程序安裝的相關文件
- 查找 %install 中的語言文件:?%find_lang %{name}
- 添加編譯依賴:?BuildRequires: gettext
- 聲明找到的文件:?%files -f %{name}.lang
這樣下來,%files部分的內容為:
%files -f %{name}.lang %doc AUTHORS ChangeLog NEWS README THANKS TODO %license COPYING %{_mandir}/man1/hello.1.* %{_infodir}/hello.info.* %{_bindir}/hello2)info文件的處理?
如果程序使用 GNU info 文件,你需要確保安裝和卸載軟件包,不影響系統中的其他軟件,按以下步驟操作:
- 在 %install 中添加刪除 ‘dir’ 文件的命令:?rm -f %{buildroot}/%{_infodir}/dir
- 在安裝后和卸載前添加依賴?Requires(post): info?和?Requires(preun): info
- 添加以下安裝腳本(在%install和%files中間即可,分別對應安裝后和卸載前的階段,詳見后邊內容):
3)看看各個目錄里邊的東西?
*?%_sourcedir下邊仍然是源碼的壓縮包;?
*?%_builddir下邊是源碼解壓出來的文件夾hello-2.10及其下邊的所有文件;?
*?%_buildrootdir下邊是一個名為“hello-2.10-1.el7.centos.x86_64”的文件夾(那么生成的RPM包的完整名稱也是{Name}-{Version}-{Release}.{Arch}.rpm),這個文件夾下邊有“usr”文件夾,其下還有“bin”、“lib”、“share”、“src”這幾個文件夾,可以看到這里的目錄結構和安裝之后各個文件和文件夾的位置已經是基本一致的了。這里要注意的是,“usr”所在的“根目錄”,也就是“hello-2.10-1.el7.centos.x86_64”這個文件夾,用宏表示就是%{buildroot},有的地方也用$RPM_BUILD_ROOT?代替?%{buildroot},不過跟%{_buildrootdir}不是一個概念,請注意。
為什么是“趁著失敗”呢,因為成功打包之后有些文件夾(比如%_builddir和%_buildrootdir)內的內容就會被清理掉了,不過也可以在%build和%install階段的時候把這倆文件夾內的東西tree一下或者干脆復制到其他地方再看也行。?
那么%build和%install以及其他幾個階段一般怎么配置呢?
4)本示例最終的完整SPEC
Name: hello Version: 2.10 Release: 1%{?dist} Summary: The "Hello World" program from GNU Summary(zh_CN): GNU "Hello World" 程序 License: GPLv3+ URL: http://ftp.gnu.org/gnu/hello Source0: http://ftp.gnu.org/gnu/hello/%{name}-%{version}.tar.gz BuildRequires: gettext Requires(post): info Requires(preun): info%description The "Hello World" program, done with all bells and whistles of a proper FOSS project, including configuration, build, internationalization, help files, etc. %description -l zh_CN "Hello World" 程序, 包含 FOSS 項目所需的所有部分, 包括配置, 構建, 國際化, 幫助文件等. %prep %setup -q %build %configure make %{?_smp_mflags} %install make install DESTDIR=%{buildroot} %find_lang %{name} rm -f %{buildroot}/%{_infodir}/dir %post /sbin/install-info %{_infodir}/%{name}.info %{_infodir}/dir || : %preun if [ $1 = 0 ] ; then /sbin/install-info --delete %{_infodir}/%{name}.info %{_infodir}/dir || : fi %files -f %{name}.lang %doc AUTHORS ChangeLog NEWS README THANKS TODO %license COPYING %{_mandir}/man1/hello.1.* %{_infodir}/hello.info.* %{_bindir}/hello %changelog * Sun Dec 4 2016 Your Name <youremail@xxx.xxx> - 2.10-1 - Update to 2.10 * Sat Dec 3 2016 Your Name <youremail@xxx.xxx> - 2.9-1 - Update to 2.9那么就開動起來,在執行一下rpmbuild命令瞅瞅吧:
rpmbuild -ba hello.specOK,執行成功了,看看成果吧:
$ tree ~/rpmbuild/*RPMS /root/rpmbuild/RPMS └── x86_64├── hello-2.10-1.el7.centos.x86_64.rpm└── hello-debuginfo-2.10-1.el7.centos.x86_64.rpm /root/rpmbuild/SRPMS └── hello-2.10-1.el7.centos.src.rpm在RPMS文件夾下生成了RPM包,在x86_64下,表示所應用的架構,由于沒有指定arch為noarch,所以默認用本機架構。在SRPMS文件夾下生產了源碼包,源碼包當然木有架構這一說了。?
所以有些人喜歡在裝軟件的時候從源碼開始安裝,因為更能貼合本機的物理情況,就像用光盤安裝windows和GHOST安裝windows,相對來說光盤一步一步安裝更好一點點,不過我比較懶,還是直接yum install。
5)運行一下下?
既然已經有RPM包了,那就安裝上吧:
運行一下:
$ hello Hello, world! $ which hello /usr/bin/hello $ rpm -qf `which hello` hello-2.10-1.el7.centos.x86_64可以看到編譯好的二進制文件hello已經裝到/usr/bin下了,其他位置的文件請自行查看吧^_^。因為這個示例程序五臟俱全,不妨man一下,看看使用文檔~
$ man hello4 詳解
SPEC文件是RPM打包的核心,下面就對SPEC文件中漏掉的而且比較重要的關于各個部分的配置方法進行詳細說明:
4.1 %prep階段
%prep?部分描述了解壓源碼包的方法。一般而言,其中包含?%autosetup?命令。另外,還可以使用?%setup?和?%patch?命令來指定操作?Source0、Patch0?等標簽的文件。
%autosetup?命令?
%autosetup?命令用于解壓源碼包。可用選項包括:
- -n name : 如果源碼包解壓后的目錄名稱與 RPM 名稱不同,此選項用于指定正確的目錄名稱。例如,如果 tarball 解壓目錄為 FOO,則使用 “%autosetup -n FOO”。
- -c name : 如果源碼包解壓后包含多個目錄,而不是單個目錄時,此選項可以創建名為 name 的目錄,并在其中解壓。
%setup?命令?
如果使用?%setup?命令,通常使用?-q?抑止不必要的輸出。?
如果需要解壓多個文件,有更多 %spec 選項可用,這對于創建子包很有用。常用選項如下:
- -a number:在切換目錄后,只解壓指定序號的 Source 文件(例如 “-a 0” 表示 Source0)。
- -b number :在切換目錄前, 只解壓指定序號的 Source 文件(例如 “-b 0” 表示 Source0)。
- -D:解壓前,不刪除目錄。
- -T:禁止自動解壓歸檔。
%patch?命令?
如果使用?%autosetup?命令,則不需要手動進行補丁管理。如果你的需求很復雜,或需要與 EPEL 兼容,需要用到此部分的內容。%patch0?命令用于應用 Patch0(%patch1?應用 Patch1,以此類推)。Patches 是修改源碼的最佳方式。常用的?-pNUMBER?選項,向 patch 程序傳遞參數,表示跳過 NUM 個路徑前綴。
補丁文件名通常像這樣?telnet-0.17-env.patch,命名格式為?%{name} - %{version} - REASON.patch(有時省略 version 版本)。補丁文件通常是?diff -u?命令的輸出;如果你在?~/rpmbuild/BUILD?子目錄執行此命令,則之后便不需要指定 -p 選項。
cp foo/bar foo/bar.orig vim foo/bar diff -u foo/bar.orig foo/bar > ~/rpmbuild/SOURCES/PKGNAME.REASON.patch如果需要修改多個文件,簡單方法是復制 BUILD 下的整個子目錄,然后在子目錄執行 diff。切換至?~rpmbuild/BUILD/NAME?目錄后,執行以下命令:
cp -pr ./ ../PACKAGENAME.orig/ ... 執行修改 ... diff -ur ../PACKAGENAME.orig . > ~/rpmbuild/SOURCES/NAME.REASON.patch如果你想在一個補丁中編輯多個文件,你可以在編輯之前,使用?.orig?擴展名復制原始文件。然后,使用?gendiff(在 rpm-build 包中)創建補丁文件。
4.2 %build階段
%build階段顧名思義就是對解壓到%_builddir下的源碼進行編譯的階段,整個過程在該目錄下完成。?
許多程序使用 GNU configure 進行配置。默認情況下,文件會安裝到前綴為 “/usr/local” 的路徑下,對于手動安裝很合理。然而,打包時需要修改前綴為 “/usr”。共享庫路徑視架構而定,安裝至 /usr/lib 或 /usr/lib64 目錄。?
由于 GNU configure 很常見,可使用?%configure?宏來自動設置正確選項(例如,設置前綴為?/usr)。一般用法如下:
?若需要覆蓋 makefile 變量,請將變量作為參數傳遞給 make:
make %{?_smp_mflags} CFLAGS="%{optflags}" BINDIR=%{_bindir}你會發現SPEC中會用到很多預定義好的宏,用來通過一個簡單的宏來完成一個或一系列常見的操作,比如:%prep階段用于解壓的%setup和%autosetup,%build階段的%configure等。
4.3 %install階段
此階段包含安裝階段需要執行的命令,即從?%{_builddir}?復制相關文件到?%{buildroot}?目錄(通常表示從?~/rpmbuild/BUILD?復制到?~/rpmbuild/BUILDROOT/XXX) 目錄,并根據需要在?%{buildroot}?中創建必要目錄。
容易混淆的術語: * “build 目錄”,也稱為 %{_builddir},實際上與 “build root”,又稱為 %{buildroot},是不同的目錄。在前者中進行編譯,并將需要打包的文件從前者復制到后者, %{buildroot}通常為 ~/rpmbuild/BUILD/%{name}-%{version}-%{release}.%{arch}。 * 在 %build 階段,當前目錄為 %{buildsubdir},是 %prep 階段中在 %{_builddir} 下創建的子目錄。這些目錄通常名為 ~/rpmbuild/BUILD/%{name}-%{version}。 * %install 階段的命令不會在用戶安裝 RPM 包時執行,此階段僅在打包時執行。 %install rm -rf %{buildroot} # 僅用于 RHEL 5 %makeinstall?
?
- 理想情況下,對于支持的程序,你應該使用?%makeinstall(這又是一個宏),它等同于?DESTDIR=%{buildroot},它會將文件安裝到?%{buildroot}?目錄中。
使用 “%makeinstall” 宏。此方法可能有效,但也可能失敗。該宏會展開為?make prefix=%{buildroot}%{_prefix} bindir=%{buildroot}%{_bindir} ... install,可能導致某些程序無法正常工作。請在?%{buildroot}?根據需要創建必要目錄。
-
使用?auto-destdir?軟件包的話,需要?BuildRequires: auto-destdir,并將?make install?修改為?make-redir DESTDIR=%{buildroot} install。這僅適用于使用常用命令安裝文件的情況,例如 cp 和 install。
- 手動執行安裝。這需要在?%{buildroot}?下創建必要目錄,并從?%{_builddir}?復制文件至?%{buildroot}?目錄。要特別注意更新,通常會包含新文件。示例如下:
4.4 %check 階段
如果需要執行測試,使用?%check?是個好主意。測試代碼應寫入?%check?部分(緊接在?%install?之后,因為需要測試?%{buildroot}?中的文件),而不是寫入?%{build}?部分,這樣才能在必要時忽略測試。通常,此部分包含:
make test有時候也可以用:
make check請熟悉 Makefile 的用法,并選擇適當的方式。
4.5 %files 部分
此部分列出了需要被打包的文件和目錄。
%files 基礎?
%defattr?用于設置默認文件權限,通常可以在 %files 的開頭看到它。注意,如果不需要修改權限,則不需要使用它。其格式為:
第 4 個參數通常會省略。常規用法為?%defattr(-,root,root,-),其中 “-” 表示默認權限。?
您應該列出該軟件包擁有的所有文件和目錄。盡量使用宏代替目錄名,具體的宏列表如下:
如果路徑以 “/” 開頭(或從宏擴展),則從?%{buildroot}?目錄取用。否則,假設文件在當前目錄中(例如:在?%{_builddir}?中,包含需要的文檔)。如果您的包僅安裝一個文件,如?/usr/sbin/mycommand,則 %files 部分如下所示:
%files %{_sbindir}/mycommand若要使軟件包不受上游改動的影響,可使用通配符匹配所有文件:
%{_bindir}/*包含一個目錄:
%{_datadir}/%{name}/注意,%{_bindir}/*?不會聲明此軟件包擁有 /usr/bin 目錄,而只包含其中的文件。如果您列出一個目錄,則該軟件包擁有這個目錄,及該目錄內的所有文件和子目錄。因此,不要列出 %{_bindir},并且要小心的處理那些可能和其他軟件包共享的目錄。
如果存在以下情況,可能引發錯誤:
- 通配符未匹配到任何文件或目錄
- 文件或目錄被多次列出
- 未列出 %{buildroot} 下的某個文件或目錄
您也可以使用 %exclude 來排除文件。這對于使用通配符來列出全部文件時會很有用,注意如果未匹配到任何文件也會造成失敗。
%files 前綴?
上邊的“hello”的示例中,%files部分還有用到%doc等宏,可能您看得一知半解,這里詳細介紹一下。?
如果需要在 %files 部分添加一個或多個前綴,用空格分隔。
%doc?用于列出?%{_builddir}?內,但不復制到?%{buildroot}?中的文檔。通常包括?README?和?INSTALL等。它們會保存至?/usr/share/doc?下適當的目錄中,不需要聲明?/usr/share/doc?的所有權。
注意: 如果指定?%doc?條目,rpmbuild < 4.9.1?在安裝前會將?%doc?目錄刪除。這表明已保存至其中的文檔,例如,在?%install?中安裝的文檔會被刪除,因此最終不會出現在軟件包中。如果您想要在?%install?中安裝一些文檔,請將它們臨時安裝到 build 目錄(不是 build root 目錄)中,例如?_docs_staging,接著在?%files?中列出,如?%doc _docs_staging/*?這樣。
配置文件保存在?/etc?中,一般會這樣指定(確保用戶的修改不會在更新時被覆蓋):
%config(noreplace) %{_sysconfdir}/foo.conf如果更新的配置文件無法與之前的配置兼容,則應這樣指定:
%config %{_sysconfdir}/foo.conf“%attr(mode, user, group)” 用于對文件進行更精細的權限控制,”-” 表示使用默認值:
%attr(0644, root, root) FOO.BAR“%caps(capabilities)” 用于為文件分配 POSIX capabilities。例如:
%caps(cap_net_admin=pe) FOO.BAR如果包含特定語言編寫的文件,請使用 %lang 來標注:
%lang(de) %{_datadir}/locale/de/LC_MESSAGES/tcsh*使用區域語言(Locale)文件的程序應遵循 處理 i18n 文件的建議方法:
- 在 %install 步驟中找出文件名: %find_lang ${name}
- 添加必要的編譯依賴: BuildRequires: gettext
- 使用找到的文件名: %files -f ${name}.lang
4.6 Scriptlets
當用戶安裝或卸載 RPM 時,您可能想要執行一些命令。這可以通過 scriptlets 完成。
腳本片段可以:
- 在軟體包安裝之前 (%pre) 或之后 (%post) 執行
- 在軟體包卸載之前 (%preun) 或之后 (%postun) 執行
- 在事務開始 (%pretrans) 或結束 (%posttrans) 時執行
例如,每個二進制 RPM 包都會在動態鏈接器的默認路徑中存儲共享庫文件,并在 %post 和 %postun 中調用 ldconfig 來更新庫緩存。如果軟件包有多個包含共享庫的子包,則每個軟體包也需要執行相同動作。
%post -p /sbin/ldconfig %postun -p /sbin/ldconfig 如果僅執行一個命令,則 “-p” 選項會直接執行,而不啟用 shell。然而,若有許多命令時,不要使用此選項,按正常編寫 shell 腳本即可。如果你在腳本片段中執行任何程序,就必須以?Requires(CONTEXT)(例:?Requires(post))的形式列出所有依賴。
%pre、%post、%preun?和?%postun?提供?$1?參數,表示動作完成后,系統中保留的此名稱的軟件包數量。因此可用于檢查軟件安裝情況,不過不要比較此參數值是否等于 2,而是比較是否大于等于 2。對于%pretrans?和?%posttrans,$1 的值恒為 0。
例如,如果軟件包安裝了一份 info 手冊,那么可以用 info 包提供的 install-info 來更新 info 手冊索引。首先,我們不保證系統已安裝 info 軟件包,除非明確聲明需要它;其次,我們不想在 install-info 執行失敗時,使軟件包安裝失敗:
Requires(post): info Requires(preun): info...%post /sbin/install-info %{_infodir}/%{name}.info %{_infodir}/dir || :%preun if [ $1 = 0 ] ; then /sbin/install-info --delete %{_infodir}/%{name}.info %{_infodir}/dir || : fi上邊的示例中還有一個安裝 info 手冊時的小問題需要解釋一下。install-info 命令會更新 info 目錄,所以我們應該在?%install?階段刪除?%{buildroot}?中無用的空目錄:
rm -f %{buildroot}%{_infodir}/dir5 命令及工具
5.1 rpmbuild打包
一旦 SPEC 編寫完畢,請執行以下命令來構建 SRPM 和 RPM 包:
$ rpmbuild -ba program.spec如果成功,RPM 會保存至?~/rpmbuild/RPMS,SRPM 會保存至?~/rpmbuild/SRPMS。
如果失敗,請查看 BUILD 目錄的相應編譯日志。為了幫助調試,可以用?--short-circuit?選項來忽略成功的階段。例如,若想要(略過更早的階段)重新從?%install?階段開始,請執行:
$ rpmbuild -bi --short-circuit program.spec如果只想創建 RPM,請執行:
rpmbuild -bb program.spec如果只想創建 SRPM(不需要執行 %prep 或 %build 或其他階段),請執行:
rpmbuild -bs program.spec5.2 rpmlint檢查
為避免常見錯誤,請先使用?rpmlint?查找 SPEC 文件的錯誤:
$ rpmlint program.spec5.2 rpmlint檢查
為避免常見錯誤,請先使用?rpmlint?查找 SPEC 文件的錯誤:
$ rpmlint program.spec如果返回錯誤/警告,使用 “-i” 選項查看更詳細的信息。
也可以使用?rpmlint?測試已構建的 RPM 包,檢查 SPEC/RPM/SRPM 是否存在錯誤。你需要在發布軟件包之前,解決這些警告。此頁面 提供一些常見問題的解釋。如果你位于 SPEC 目錄中,請執行:
$ rpmlint NAME.spec ../RPMS/*/NAME*.rpm ../SRPMS/NAME*.rpm進入?~/rpmbuild/RPMS?下的特定架構目錄中,您會發現有許多二進制 RPM 包。使用以下命令快速查看 RPM 包含的文件和權限
$ rpmls *.rpm5.3 rpm安裝
如果看上去正常,以 root 身份安裝它們:
$ rpm -ivp package1.rpm package2.rpm package3.rpm ...以不同方式來測試程序,看看是否全部都正常工作。如果是 GUI 工具,請確認其是否出現在桌面菜單中,否則表示 .desktop 條目可能有錯。?
最后卸載軟件包:
6 備查
6.1 rpmbuild目錄
| ~/rpmbuild/SPECS | %_specdir | Spec 文件目錄 | 保存 RPM 包配置(.spec)文件 |
| ~/rpmbuild/SOURCES | %_sourcedir | 源代碼目錄 | 保存源碼包(如 .tar 包)和所有 patch 補丁 |
| ~/rpmbuild/BUILD | %_builddir | 構建目錄 | 源碼包被解壓至此,并在該目錄的子目錄完成編譯 |
| ~/rpmbuild/BUILDROOT | %_buildrootdir | 最終安裝目錄 | 保存 %install 階段安裝的文件 |
| ~/rpmbuild/RPMS | %_rpmdir | 標準 RPM 包目錄 | 生成/保存二進制 RPM 包 |
| ~/rpmbuild/SRPMS | %_srcrpmdir | 源代碼 RPM 包目錄 | 生成/保存源碼 RPM 包(SRPM) |
?
6.2 spec文件階段
| %prep | %_sourcedir | %_builddir | 讀取位于?%_sourcedir?目錄的源代碼和 patch 。之后,解壓源代碼至?%_builddir?的子目錄并應用所有 patch。 |
| %build | %_builddir | %_builddir | 編譯位于?%_builddir?構建目錄下的文件。通過執行類似?./configure && make?的命令實現。 |
| %install | %_builddir | %_buildrootdir | 讀取位于?%_builddir?構建目錄下的文件并將其安裝至?%_buildrootdir?目錄。這些文件就是用戶安裝 RPM 后,最終得到的文件。注意一個奇怪的地方: 最終安裝目錄 不是 構建目錄。通過執行類似?make install?的命令實現。 |
| %check | %_builddir | %_builddir | 檢查軟件是否正常運行。通過執行類似?make test?的命令實現。很多軟件包都不需要此步。 |
| bin | %_buildrootdir | %_rpmdir | 讀取位于?%_buildrootdir?最終安裝目錄下的文件,以便最終在?%_rpmdir?目錄下創建 RPM 包。在該目錄下,不同架構的 RPM 包會分別保存至不同子目錄,?noarch?目錄保存適用于所有架構的 RPM 包。這些 RPM 文件就是用戶最終安裝的 RPM 包。 |
| src | %_sourcedir | %_srcrpmdir | 創建源碼 RPM 包(簡稱 SRPM,以.src.rpm?作為后綴名),并保存至?%_srcrpmdir?目錄。SRPM 包通常用于審核和升級軟件包。 |
6.3 代表路徑的宏列表
%{_sysconfdir} /etc %{_prefix} /usr %{_exec_prefix} %{_prefix} %{_bindir} %{_exec_prefix}/bin %{_libdir} %{_exec_prefix}/%{_lib} %{_libexecdir} %{_exec_prefix}/libexec %{_sbindir} %{_exec_prefix}/sbin %{_sharedstatedir} /var/lib %{_datarootdir} %{_prefix}/share %{_datadir} %{_datarootdir} %{_includedir} %{_prefix}/include %{_infodir} /usr/share/info %{_mandir} /usr/share/man %{_localstatedir} /var %{_initddir} %{_sysconfdir}/rc.d/init.d %{_var} /var %{_tmppath} %{_var}/tmp %{_usr} /usr %{_usrsrc} %{_usr}/src %{_lib} lib (lib64 on 64bit multilib systems) %{_docdir} %{_datadir}/doc %{buildroot} %{_buildrootdir}/%{name}-%{version}-%{release}.%{_arch} $RPM_BUILD_ROOT %{buildroot}6.4 參考文檔
- Fedora Packaging Guidelines
- How to create an RPM package
- How to create a GNU Hello RPM package
?
- Spec File Preamble
?
這篇博文講解關于RPM打包的過程和原理非常好,轉載學習一下。
附上作者原文地址:https://blog.csdn.net/get_set/article/details/53453320
?
轉載于:https://www.cnblogs.com/dyh004/p/10402393.html
總結
以上是生活随笔為你收集整理的RPM打包原理、示例、详解及备查的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2018年中国研究生数学建模竞赛C题 二
- 下一篇: web scraper 抓取网页数据的几