1.RPM目錄結構
- rpmbuild
- SOURCES 源碼、圖標等文件
- SPECS 用于管理rpm制作進程的spec文件
- BUILD 解壓后的文件
- RPMS 由rpmbuild制作好的二進制包
- SRPMS 由rpmbuild制作好的源碼包
2.spec文件綜述
- spec文件有什么用?
- spec文件有兩個用途:構建和打包。構建即將源碼轉換為構建工件(java構建工具一般為Ant, Maven, Gradle; C語言構建工具為makefile)。打包即確定需要安裝在目標機器上的構建產物。
注意:#
字符表示注釋,但需要避免注釋宏(以 %
開頭),因為它們會首先被替換展開。使用 %%
注釋宏。另外,還要避免在腳本命令的相同行中使用行內注釋。
%{name}
,%{version}
和 %{release}
代表 Name, Version 和 Release 這三個標簽。只要更改標簽,宏就會使用新值。
spec文件主要標簽:
Name: 軟件包名,應與 SPEC 文件名一致。
Version: 版本號。
-
Release: 發行編號,初始值為 1%{?dist} ,每次制作新包時,遞增該數字。
- 什么是 1%{?dist} : 如果%{dist}未定義返回1,否則返回1%{dist},
- 用法:
- if判斷:
如果if 0%{?flag}; then foo fi
%{flag}
被定義了,條件語句為:0%{flag}
,執行if block; 反之,條件語句為:0, 不執行if block。
注意:%{?flag}
前必須加0,否則如果%{?flag}
未定義,if語句停止執行并退出。 -
%{?flag: ...}
:如果%{flag}
被定義,則展開"..."部分;
- if判斷:
Patch0: 用于源碼的補丁名稱。如果需要在源碼包解壓后對一些代碼做修改,應該修改代碼并使用
diff
命令生成 patch 文件,然后放在~/rpmbuild/SOURCES
目錄下。一個 Patch 應該只做一種修改,所以可能會包含多個 patch 文件。BuildRoot: 在
%install
階段(%build
階段后)文件需要安裝至此位置。默認情況下,根目錄為%{_topdir}/BUILDROOT/
。%description: 程序的詳細/多行描述。每行必須小于等于 80 個字符。
%prep: 打包準備階段執行一些命令(如,解壓源碼包,打補丁等),以便開始編譯。
%build: 包含構建階段執行的命令,構建完成后便開始后續安裝。
-
%install: 包含安裝階段執行的命令。命令將文件從
%{_builddir}
目錄安裝至%{buildroot}
目錄。可以使用$RPM_BUILD_ROOT
代替%{buildroot}
,兩者都可以使用。術語:
-
%{_builddir}
(即"build目錄"),與%{buildroot}
(即"build root目錄")是不同的目錄。在%{_builddir}
中進行編譯,并將需要打包的文件從%{_builddir}
中復制到%{buildroot}
中。 -
%install
階段的命令不會在用戶安裝RPM包時執行,此階段只在打包時執行。
一般在%install
階段執行make install
之類的命令。%make_install
命令等同于DESTDIR=%{buildroot}
,該命令會將文件安裝到%{buildroot}
目錄中。如果程序不支持DESTDIR
,可手動執行安裝:需要在%{buildroot}
下創建必要的目錄,并從%{_builddir
}復制文件至%{buildroot}
目錄。
-
%clean: 清理安裝目錄。一般只包含:
rm -rf %{buildroot}
-
%files:
%files
指令列出需要安裝的文件和目錄。-
%defattr
用于設置默認文件權限,一般在%files
開頭設置。格式為:%defattr(<文件權限>, <用戶>, <用戶組>, <目錄權限>)
常規用法為:
%defattr(-, user, group, -)
必須在
%files
部分列出該軟件所擁有的所有文件,注意不要使用如 /usr/bin/ 的硬編碼,盡量使用宏代替目錄名。如果路徑以"/"開頭(或從宏擴展),則認為文件在%{buildroot}目錄中。否則,默認文件在當前目錄中。
【問題:如果軟件包僅安裝一個文件,那么該文件會安裝在哪里?】
【答:必須有一個路徑】若要軟件包不受上游改動影響,可使用通配符匹配所有文件。
【問題:不受上游改動影響是什么意思?】
注意:%{somedir}/*
不會聲明軟件包擁有%{somedir}
目錄,而只包含其中的文件。如果列出一個目錄,則該軟件包擁有整個目錄,以及該目錄內所有的文件和子目錄,因此要小心處理可能和其他軟件共享的目錄。-
如果存在以下情況,可能引發錯誤:
- 通配符未匹配任何文件或目錄
- 文件或目錄被多次列出
- %{buildroot}中有文件未列出(空文件目錄不會報錯)
- 使用通配符來列出全部文件時,可使用 %exclude 來排除文件。注意如果未匹配到任何文件也會造成失敗。
-
3. %files指令
%files列表包括多種指令,主要用于:
- 識別文檔和配置文件
- 確定文件有正確的權限和擁有組
- 設置哪些文件需要在打包驗證時進行校驗
- 精簡語法
兩個%files指令可同時作用于同一個文件,例如:%foo %bar baz
I 文件相關指令
RPM需要根據文件類型分別處理不同類型的文件,然而,rpm并沒有自動識別文件類型的功能。因此,需要由打包者適當的對不同類型的文件進行標識。
注意:并非所有文件都需要被標識,在大多數包中,大多數文件都不需要被標識。
-
%doc
指令:
rpm會跟蹤其數據庫中的文檔文件,以便用戶查找已安裝包信息。
此外,rpm可在安裝期間創建包的文檔目錄,并將文檔復制其中。添加該步驟方法如下:
build期間,README 文件位于頂級目錄;軟件包install完成后,rpm將在軟件包同名的文檔目錄(即<software>-<version>-<release>)創建目錄,并將 README 文件拷貝其中。新創建的目錄和 README 文件將在rpm數據庫被作為文檔進行標識。默認的文檔目錄是%doc README %doc /usr/local/foo/README
/usr/doc
,可在rpmrc文件中更改。 -
%config
指令:用于標識文件作為配置文件。(只能一個配置文件) -
%attr
指令:用于設置文件權限。例:%attr(<file_mode>, <user>, <group>) filename
-
%defattr
指令: 用于設置文件默認權限,一般寫在%files
頭部。例:%defattr(<file_mode>, <user>, <group>, <dir_mode>)
-
%ghost
to be continue... -
%verify
to be continue...
II 目錄相關指令
-
%docdir
指令:向文檔目錄列表添加目錄。rpm的%docdir
列表默的認目錄有:/usr/doc
,/usr/info
,/usr/main
。例:%docfir /usr/test ,
任何
/usr/test
目錄下的文件都會自動被標識為文檔文件。 %dir
指令:之前提到,如果在%files
下列出文件夾,則該文件夾下的所有文件或子文件夾都會被打包到軟件包中。%dir
指令可設置rpm只打包自身,而忽略其中的文件或子文件夾。-f <file>
:從<file>中讀取%files
列表。
Tips
- shell腳本錯誤
Syntax error near unexpected token `fi`
:缺少then
- spec文件內的標簽必須有值,標簽前不能有空格;
- spec文件必須要有
%description
- spec文件的當前目錄為
/BUILD
-
%{buildroot}
是%install
階段,/BUILDROOT
下自動創建的子目錄/name-version-release
-
%{buildroot}
內的所有文件都必須在%files
中列出,空目錄可不必列出 -
/BUILDROOT
目錄會在%install
階段自動創建
代碼參考
package.sh:
CUR_DIR=$(cd `dirname $0`; pwd)
if [ -d ${CUR_DIR}/rpmbuild ]; then
rm -rf ${CUR_DIR}/rpmbuild
fi
mkdir -p ${CUR_DIR}/rpmbuild
mkdir -p ${CUR_DIR}/rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS}
cp ${CUR_DIR}/*.spec ${CUR_DIR}/rpmbuild/SPECS/
rpmbuild --define "_topdir ${CUR_DIR}/rpmbuild" -bb ${CUR_DIR}/rpmbuild/SPECS/web.spec
web.spec:
Name: web
Version: 1.0.0
Release: 1%{?dist}
Summary: test
License: GPL
URL: http://gitlabsec.huawei.com/h00416865/web
%description
%define PROJECT_ROOT %{_builddir}/../../..
%prep
%build
echo "begin to mvn install..."
cd %{PROJECT_ROOT}/web_console
mvn clean install
%install
rm -rf %{buildroot}
mkdir -p %{buildroot}/opt/weiee
mkdir -p %{_builddir}/webapp
cp -r %{PROJECT_ROOT}/web_console/target/*.war %{_builddir}
unzip -oq %{_builddir}/*.war -d %{_builddir}/webapp
cp -r %{_builddir}/webapp %{buildroot}/opt/weiee
%files
%defattr(-,root,root,-)
/opt/weiee/
%post
%clean
rm -rf %{buildroot}
%changelog
參考文章
http://ftp.rpm.org/max-rpm/index.html
How to create an RPM package/zh-cn