一堂C++课玩转rpm包的制作
常見的Linux發行版主要可以分為兩類,類ReadHat系列和類Debian系列,這里我們是以其軟件包的格式來劃分的,這兩類系統分別提供了自己的軟件包管理系統和相應的工具。類RedHat系統中軟件包的后綴是rpm;類Debian系統中軟件包的后綴是deb。另一方面,類RedHat系統提供了同名的rpm命令來安裝、卸載、升級rpm軟件包;類Debian系統同樣提供了dpkg命令來對后綴是deb的軟件包進行安裝、卸載和升級等操作。
? ?rpm的全稱是Redhat Package Manager,常見的使用rpm軟件包的系統主要有Fedora、CentOS、openSUSE、SUSE企業版、PCLinuxOS以及Mandriva Linux、Mageia等。使用deb軟件包后綴的類Debian系統最常見的有Debian、Ubuntu、Finnix等。
?
? ??無論是rpm命令還是dpkg命令在安裝軟件包時都存在一個讓人非常頭疼的問題,那就是軟件包的依賴關系。這一點很多人應該深有體會,這也使初學者在接觸Linux系統時覺得很不方便的地方。慶幸的是,很多發行版都考慮到了這問題,于是Fedora和CentOS提供了yum來自動解決軟件包的安裝依賴,同樣的openSUSE提供了zypper,類Debian系統提供了apt-*命令。也就是說這些工具本質上最終還是調用了rpm(或者dpkg)是不過安裝前自動幫用戶解決了軟件包的安裝依賴。如下表所示:
| 分類 | 發行版 | 手動安裝命令 | 自動安裝命令 | 軟件包后綴 |
| 類RedHat | Fedora/CentOS | rpm | yum | *.rpm |
| openSUSE/SUSE | zypper | |||
| Mandriva Linux/Mageia | urpmi | |||
| 類Debian | Debian/Ubuntu | dpkg | apt-get | *.deb |
?
?
? ??簡單點了說,如果你會在Fedora或者CentOS上用yum來自動安裝軟件包,那么在Debian或者Ubuntu上你就會用apt-get自動安裝軟件,同理,在openSUSE上你就會用zypper自動安裝軟件包。
?
??本文檔主要描述如何通過軟件包的源代碼構建自己的rpm軟件安裝包。
? ?從軟件運行的結構來說,一個軟件主要可以分為三個部分:可執行程序、配置文件和動態庫。當然還有可能會有相關文檔、手冊、供二次開發用的頭文件以及一些示例程序等等。其他部分都是可選的,只有可執行文件是必須的。
? ?關于如何制作rpm軟件包的方法,網上教程也一大堆,談及最多的當屬rpmbuild這個命令行工具。這也是本文要介紹的“配角”,而主角是它的輸入對象,也就是所謂的SPEC文件的格式,寫法和說明。
? ?rpm的打包流程相比deb的要稍微麻煩一些,因為它對打包目錄有一些嚴格的層次上的要求。如果你的rpm的版本<=4.4.x,那么rpmbuid工具其默認的工作路徑是/usr/src/redhat,這就使得普通用戶不能制作rpm包,因為權限的問題,在制作rpm軟件包時必須切換到root身份才可以。所以,rpm從4.5.x版本開始,將rpmbuid的默認工作路徑移動到用戶家目錄下的rpmbuild目錄里,即$HOME/rpmbuild,并且推薦用戶在制作rpm軟件包時盡量不要以root身份進行操作。
? ?關于rpmbuild默認工作路徑的確定,通常由在/usr/lib/rpm/macros這個文件里的一個叫做%_topdir的宏變量來定義。如果用戶想更改這個目錄名,rpm官方并不推薦直接更改這個目錄,而是在用戶家目錄下建立一個名為.rpmmacros的隱藏文件(注意前面的點不能少,這是Linux下隱藏文件的常識),然后在里面重新定義%_topdir,指向一個新的目錄名。這樣就可以滿足某些“高級”用戶的差異化需求了。通常情況下.rpmmacros文件里一般只有一行內容,比如:
?
點擊(此處)折疊或打開
?
? ??
? ?在%_topdir目錄下一般需要建立6個目錄:?
?
| 目錄名 | 說明 | macros中的宏名 |
| BUILD | 編譯rpm包的臨時目錄 | %_builddir |
| BUILDROOT | 編譯后生成的軟件臨時安裝目錄 | %_buildrootdir |
| RPMS | 最終生成的可安裝rpm包的所在目錄 | %_rpmdir |
| SOURCES | 所有源代碼和補丁文件的存放目錄 | %_sourcedir |
| SPECS | 存放SPEC文件的目錄(重要) | %_specdir |
| SRPMS | 軟件最終的rpm源碼格式存放路徑(暫時忽略掉,別掛在心上) | %_srcrpmdir |
? ?小技巧:執行rpmdev-setuptree會在當前用戶家目錄下的rpmbuild目錄(如果該目錄不存在也會被自動創建)里自動建立上述目錄。
? ?當上述目錄建立好之后,將所有用于生成rpm包的源代碼、shell腳本、配置文件都拷貝到SOURCES目錄里,注意通常情況下源碼的壓縮格式都為*.tar.gz格式(當然還可以為其他格式,但那就是另外一種方式,這里先不介紹)。然后,將最最最重要的SPEC文件,命名格式一般是“軟件名-版本.spec”的形式,將其拷貝到SPECS目錄下,切換到該目錄下執行:
?
?
點擊(此處)折疊或打開
?
? ?最終我們想要的rpm軟件包就安安穩穩地躺在RPMS目錄下了。對,就這么簡單。
? ?這里的關鍵就是上面的SPEC文件的寫法,我們可以用rpmdev-newspec?-o?Name-version.spec命令來生成SPEC文件的模板,然后在上面修改就可。例如:
點擊(此處)折疊或打開
?
? ??其實SPEC文件的核心是它定義了一些“階段”(%prep、%build、%install和%clean),當rpmbuild執行時它首先會去解析SPEC文件,然后依次執行每個“階段”里的指令。
? ?接下來,我們來簡單了解一下SPEC文件的頭部。假如,我們的源碼包名字是myapp-0.1.0.tar.gz,那么myapp-0.1.0.spec的頭部一般如下的樣子:
?
點擊(此處)折疊或打開
?
? ??下面我們來看一下制作rpm包的幾個關鍵階段,以及所發生的事情:??
?
| 階段 | 動作 |
| %prep | 將%_sourcedir目錄下的源代碼解壓到%_builddir目錄下。如果有補丁的需要在這個階段進行打補丁的操作 |
| %build | 在%_builddir目錄下執行源碼包的編譯。一般是執行./configure和make指令 |
| %install | 將需要打包到rpm軟件包里的文件從%_builddir下拷貝%_buildrootdir目錄下。當用戶最終用rpm -ivh name-version.rpm安裝軟件包時,這些文件會安裝到用戶系統中相應的目錄里 |
| 制作rpm包 | 這個階段是自動完成的,所以在SPEC文件里面是看不到的,這個階段會將%_buildroot目錄的相關文件制作成rpm軟件包最終放到%_rpmdir目錄里 |
| %clean | 編譯后的清理工作,這里可以執行make clean以及清空%_buildroot目錄等 |
?
?
?
?
?
? ??每個階段的詳細說明如下:
?
- %prep階段
? ??這個階段里通常情況,主要完成對源代碼包的解壓和打補丁(如果有的話),而解壓時最常見到的就是一句指令:
點擊(此處)折疊或打開
?
? ?當然,這句指令可以成功執行的前提是你位于SOURCES目錄下的源碼包必須是name-version.tar.gz的格式才行,它還會完成后續階段目錄的切換和設置。如果在這個階段你不用這條指令,那么后面每個階段都要自己手動去改變相應的目錄。解壓完成之后如果有補丁文件,也在這里做。想了解的童鞋可以自己去查查如何實現,也不難,這里我就不展開了。
?
- %build階段
? ? ?這個階段就是執行常見的configure和make操作,如果有些軟件需要最先執行bootstrap之類的,可以放在configure之前來做。這個階段我們最常見只有兩條指令:
點擊(此處)折疊或打開
?
? ??它就自動將軟件安裝時的路徑自動設置成如下約定:
?
?
? ?
? ? 注意,這里的%configure是個宏常量,會自動將prefix設置成/usr。另外,這個宏還可以接受額外的參數,如果某些軟件有某些高級特性需要開啟,可以通過給%configure宏傳參數來開啟。如果不用?%configure這個宏的話,就需要完全手動指定configure時的配置參數了。同樣地,我們也可以給make傳遞額外的參數,例如:
?
點擊(此處)折疊或打開
?
?
?
- %install階段
?
? ??這個階段就是執行make install操作。這個階段會在%_buildrootdir目錄里建好目錄結構,然后將需要打包到rpm軟件包里的文件從%_builddir里拷貝到%_buildrootdir里對應的目錄里。這個階段最常見的兩條指令是:
?
點擊(此處)折疊或打開
?
? ?其中$RPM_BUILD_ROOT也可以換成我們前面定義的BuildRoot變量,不過要寫成%{buildroot}才可以,必須全部用小寫,不然要報錯。
? ?如果軟件有配置文件或者額外的啟動腳本之類,就要手動用copy命令或者install命令你給將它也拷貝到%{buildroot}相應的目錄里。用copy命令時如果目錄不存在要手動建立,不然也會報錯,所以推薦用install命令。?
?
?
?
- %clean階段
?
? ??編譯完成后一些清理工作,主要包括對%{buildroot}目錄的清空(當然這不是必須的),通常執行諸如make clean之類的命令。?
?
?
?
- 制作rpm軟件包的階段
? ??這個階段必須引出下面一個叫做%files的階段。它主要用來說明會將%{buildroot}目錄下的哪些文件和目錄最終打包到rpm包里。
點擊(此處)折疊或打開
?
? ??
? ?在%files階段的第一條命令的語法是:
?
點擊(此處)折疊或打開
?
? ?如果不牽扯到文件、目錄權限的改變則一般用%defattr(-,root,root,-)這條指令來為其設置缺省權限。所有需要打包到rpm包的文件和目錄都在這個地方列出,例如:
?
點擊(此處)折疊或打開
?
? ?在安裝rpm時,會將可執行的二進制文件放在/usr/bin目錄下,動態庫放在/usr/lib或者/usr/lib64目錄下,配置文件放在/etc目錄下,并且多次安裝時新的配置文件不會覆蓋以前已經存在的同名配置文件。
? ?這里在寫要打包的文件列表時,既可以以宏常量開頭,也可以為“/”開頭,沒任何本質的區別,都表示從%{buildroot}中拷貝文件到最終的rpm包里;如果是相對路徑,則表示要拷貝的文件位于%{_builddir}目錄,這主要適用于那些在%install階段沒有被拷貝到%{buildroot}目錄里的文件,最常見的就是諸如README、LICENSE之類的文件。如果不想將%{buildroot}里的某些文件或目錄打包到rpm里,則用:
?
點擊(此處)折疊或打開
?
? ??
? ?但是關于%files階段有兩個特性要牢記:
?
?
? ??關于%doc宏,所有跟在這個宏后面的文件都來自%{_builddir}目錄,當用戶安裝rpm時,由這個宏所指定的文件都會安裝到/usr/share/doc/name-version/目錄里。
?
?
- %changelog階段
? ??這是最后一個階段,主要記錄的每次打包時的修改變更日志。標準格式是:
點擊(此處)折疊或打開
?
? ??
? ?說了這么多,我們實戰一下。網上很多教程都是拿Tomcat或者Nigix開頭,這里我就先從簡單的mp3解碼庫libmad入手,將它打成一個rpm包,具體步驟如下:
?
? ??(如果自己系統上沒有rpmbuild命令就安裝之:yum install rpm* rpm-build rpmdev*)
? ??1、構建rpm的編譯目錄結構:
2、下載libmad源碼到rpmbuild/SOURCES目錄下,可以從?http://downloads.sourceforge.net/mad/libmad-0.15.1b.tar.gz這里下載。
?
? ??3、在rpmbuild/SPECS目錄下執行rpmdev-newspec -o?libmad-0.15.1b.spec,會在當前目錄下生成名為libmad-0.15.1b.spec的模板文件。
? ??4、將libmad-0.15.1b.spec修改成如下的樣子:
?
? ??5、在rpmbuild/SPECS目錄下執行打包編譯:
?
點擊(此處)折疊或打開
?
?
? ??最終生成的rpm包如下:
?
? ??因為我是64位系統,所以編譯出的libmad適用于CentOS6.0-64。
? ??如果我們將libmad的源碼和spec文件拷貝32位系統上,再執行rpm打包,看看結果:
? ??結果如下:
后記:
? ?關于SPEC文件,還有一些其他特性,諸如安裝軟件包之前、之后要做的事情,以及卸載軟件包之前之后要做的事情,包括給源碼打補丁,關于這些特性感興趣的童鞋自己去摸索吧。最后給出一個完整的,包含了打補丁、安裝、卸載特性的SPEC文件模板:
點擊(此處)折疊或打開
?
轉載于:https://www.cnblogs.com/xujie2013/p/3413909.html
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的一堂C++课玩转rpm包的制作的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Struts2学习8--文件上传(单个文
- 下一篇: 学习Qt的资源-网站、论坛、博客等