RPM 系列文章:
打包目錄
rpm 打包目錄有一些嚴格的層次上的要求。
rpm 的版本 <=4.4.x
,rpmbuid
工具其默認的工作路徑是 /usr/src/redhat
。因為權限的問題,普通用戶不能制作 rpm 包,制作 rpm 軟件包時必須切換到 root 身份才可以。
rpm 從 4.5.x
版本開始,將 rpmbuid
的默認工作路徑移動到用戶家目錄下的 rpmbuild
目錄里,即 $HOME/rpmbuild
,並且推薦用戶在制作 rpm 軟件包時盡量不要以 root 身份進行操作。
本文所在環境:
- RPM 版本:
rpm-4.11.3-32.el7.x86_64
版本。 - CentOS 7
如果想發布 rpm 格式的源碼包或者是二進制包,就要使用 rpmbuild
工具( rpm 最新打包工具)。如果我們已經根據本地源碼包的成功編譯安裝而寫了 spec
文件(該文件要以 .spec
結束),那我們就可以建立一個打包環境,也就是目錄樹的建立,一般是在 ~/rpmbuild
目錄下建立 5 個目錄。它門分別是:
BUILD
:目錄用來存放打包過程中的源文件,就是來源於SOURCE
SOURCE
:用來存放打包是要用到的源文件和 patch,主要是一些tar
包SPEC
:用來存放 spec 文件SRPM
:存放打包生成的 rpm 格式的源文件RPM
:二進制文件
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 包通常用於審核和升級軟件包。 |
安裝工具
RPM打包使用的是 rpmbuild
命令,來自 rpm-build
包:
yum install -y rpm-build
也可以安裝 rpmdevtools
,這個工具部包含一些其他工具,依賴 rpm-build
,所以直接安裝會將 rpm-build
裝上:
yum install -y rpmdevtools
Python 的編譯打包工具是 setuptools
。
工具使用
rpmbuild
命令使用一套標准化的「工作空間」 ,生成 %_topdir
工作目錄 ~/rpmbuild
,以及配置文件 ~/.rpmmacros
:
rpmdev-setuptree
rpmdev-setuptree
這個命令就是安裝 rpmdevtools
帶來的。可以看到運行了這個命令之后,在 $HOME
家目錄下多了一個叫做 rpmbuild
的文件夾,里邊內容如下:
$ tree rpmbuild
rpmbuild
├── BUILD
├── RPMS
├── SOURCES
├── SPECS
└── SRPMS
rpmdev-setuptree
命令在當前用戶 home/rpmbuild
目錄里自動建立上述目錄。
如果沒有安裝 rpmdevtools
的話,其實用 mkdir
命令創建這些文件夾也是可以的:mkdir -p ~/rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS}
。
默認位置 | 宏代碼 | 名稱 | 用途 |
---|---|---|---|
~/rpmbuild/SPECS | %_specdir | Spec 文件目錄 | 保存 RPM 包配置(.spec)文件 |
~/rpmbuild/SOURCES | %_sourcedir | 源代碼目錄 | 保存源碼包(如 .tar 包)和所有 patch 補丁 |
~/rpmbuild/BUILD | %_builddir | 構建目錄 | 源碼包被解壓至此,並在該目錄的子目錄完成編譯 |
~/rpmbuild/RPMS | %_rpmdir | 標准 RPM 包目錄 | 生成/保存二進制 RPM 包 |
~/rpmbuild/SRPMS | %_srcrpmdir | 源代碼 RPM 包目錄 | 生成/保存源碼 RPM 包(SRPM) |
~/rpmbuild/BUILDROOT | %_buildrootdir | 最終安裝目錄 | 保存 %install 階段安裝的文件 |
rpmbuild
默認工作路徑的確定,通常由在 /usr/lib/rpm/macros
這個文件里的一個叫做 %_topdir
的宏變量來定義。如果用戶想更改這個目錄名,rpm 官方並不推薦直接更改這個目錄,而是在用戶家目錄下建立一個名為 .rpmmacros
的隱藏文件(Linux下隱藏文件,前面的點不能少),然后在里面重新定義 %_topdir
,指向一個新的目錄名。這樣就可以滿足某些用戶的差異化需求了。.rpmmacros
文件里內容,比如:
michael@localhost ~ cat .rpmmacros
%_topdir %(echo $HOME)/rpmbuild
%_smp_mflags %( \
[ -z "$RPM_BUILD_NCPUS" ] \\\
&& RPM_BUILD_NCPUS="`/usr/bin/nproc 2>/dev/null || \\\
/usr/bin/getconf _NPROCESSORS_ONLN`"; \\\
if [ "$RPM_BUILD_NCPUS" -gt 16 ]; then \\\
echo "-j16"; \\\
elif [ "$RPM_BUILD_NCPUS" -gt 3 ]; then \\\
echo "-j$RPM_BUILD_NCPUS"; \\\
else \\\
echo "-j3"; \\\
fi )
%__arch_install_post \
[ "%{buildarch}" = "noarch" ] || QA_CHECK_RPATHS=1 ; \
case "${QA_CHECK_RPATHS:-}" in [1yY]*) /usr/lib/rpm/check-rpaths ;; esac \
/usr/lib/rpm/check-buildroot
生成 SPEC 文件
最最最重要的 SPEC
文件,命名格式一般是“軟件名-版本.spec”的形式,將其拷貝到 SPECS
目錄下。
如果系統有 rpmdevtools
工具,可以用 rpmdev-newspec -o name.spec
命令來生成 SPEC
文件的模板,然后進行修改:
[root@localhost ~]# rpmdev-newspec -o myapp.spec
Skeleton specfile (minimal) has been created to "myapp.spec".
[root@localhost ~]# cat myapp-0.1.0.spec
Name: myapp
Version:
Release: 1%{?dist}
Summary:
License:
URL:
Source0:
BuildRequires:
Requires:
%description
%prep
%setup -q
%build
%configure
make %{?_smp_mflags}
%install
rm -rf $RPM_BUILD_ROOT
%make_install
%files
%doc
如果沒有安裝 rpmdevtools
,也可以自己手動創建一個 spec
文件。
打包命令
在 rpmbuild/SPECS
目錄下執行打包編譯,切換到該目錄下執行打包編譯命令。
rpmbuild 命令選項
rpmbuild
命令的選項 rpmbuild
命令有不少選項,用得比較多的有:
-bp 只解壓源碼及應用補丁
-bc 只進行編譯
-bi 只進行安裝到%{buildroot}
-bb 只生成二進制 rpm 包
-bs 只生成源碼 rpm 包
-ba 生成二進制 rpm 包和源碼 rpm 包
--target 指定生成 rpm 包的平台,默認會生成 i686 和 x86_64 的 rpm 包,但一般我只需要 x86_64 的 rpm 包
只生成二進制格式的 rpm 包
rpmbuild -bb 軟件名-版本.spec
用此命令生成軟件包,生成的文件會在剛才建立的RPM目錄下存在。
只生成 src 格式的 rpm 包
rpmbuild -bs 軟件名-版本.spec
生成的文件會在剛才建立的SRPM目錄下存在。
只需要生成完整的源文件
rpmbuild -bp 軟件名-版本.spec
源文件存在目錄 BUILD
下。可能對這個命令不太明白,這個命令的作用就是把 tar
包解開然后把所有的補丁文件合並而生成一個完整的具最新功能的源文件。
完全打包
rpmbuild -ba 軟件名-版本.spec
軟件包制作完成后可用 rpm 命令查詢,看看效果。如果不滿意的話可以再次修改軟件包描述文件,重新運行以上命令產生新的 RPM 軟件包。
實例
將所有用於生成 rpm 包的源代碼、 shell 腳本、配置文件都拷貝到 SOURCES
目錄里,注意通常情況下源碼的壓縮格式都為 *.tar.gz
格式。
下載源碼
cd ~/rpmbuild/SOURCES
wget wget http://ftp.gnu.org/gnu/hello/hello-2.10.tar.gz
編輯SPEC文件
cd ~/rpmbuild/SPECS
vim hello.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
Group
標簽過去用於按照 /usr/share/doc/rpm-/GROUPS
分類軟件包。目前該標記已丟棄,vim的模板還有這一條,刪掉即可,不過添加該標記也不會有任何影響。
構建RPM包
rpmbuild -ba hello.spec
OK,執行成功,看看結果:
michael@localhost ~/rpmbuild tree *RPMS
RPMS
└── x86_64
├── hello-2.10-1.el7.x86_64.rpm
└── hello-debuginfo-2.10-1.el7.x86_64.rpm
SRPMS
└── hello-2.10-1.el7.src.rpm
1 directory, 3 files
安裝 RPM 包
sudo rpm -ivh ~/rpmbuild/RPMS/x86_64/hello-2.10-1.el7.x86_64.rpm
運行:
$ hello
Hello, world!
$ which hello
/usr/bin/hello
$ rpm -qf `which hello`
hello-2.10-1.el7.centos.x86_64
$ man hello
附錄
rpmbuild 目錄結構
michael@localhost ~/rpmbuild tree . -L 3
.
├── BUILD
│ └── hello-2.10
│ ├── ABOUT-NLS
│ ├── aclocal.m4
│ ├── AUTHORS
│ ├── build-aux
│ ├── ChangeLog
│ ├── ChangeLog.O
│ ├── config.h
│ ├── config.in
│ ├── config.log
│ ├── config.status
│ ├── configure
│ ├── configure.ac
│ ├── contrib
│ ├── COPYING
│ ├── debugfiles.list
│ ├── debuglinks.list
│ ├── debugsources.list
│ ├── doc
│ ├── elfbins.list
│ ├── GNUmakefile
│ ├── hello
│ ├── hello.1
│ ├── hello.lang
│ ├── INSTALL
│ ├── lib
│ ├── m4
│ ├── maint.mk
│ ├── Makefile
│ ├── Makefile.am
│ ├── Makefile.in
│ ├── man
│ ├── NEWS
│ ├── po
│ ├── README
│ ├── README-dev
│ ├── README-release
│ ├── src
│ ├── stamp-h1
│ ├── tests
│ ├── THANKS
│ └── TODO
├── BUILDROOT
├── RPMS
│ └── x86_64
│ ├── hello-2.10-1.el7.x86_64.rpm
│ └── hello-debuginfo-2.10-1.el7.x86_64.rpm
├── SOURCES
│ └── hello-2.10.tar.gz
├── SPECS
│ └── hello.spec
└── SRPMS
└── hello-2.10-1.el7.src.rpm
17 directories, 37 files
configure、make、make install 命令的區別
configure
它是個shell
腳本,./configure
那么就是運行這個 shell 腳本啦!./configure
是用來檢測你的安裝平台的目標特征的。比如它會檢測你是不是有CC
或GCC
,
並不是需要CC
或GCC
。這一步一般用來生成Makefile
,為下一步的編譯做准備。 可以通過在configure
后加上參數來對安裝進行控制。例如,./configure --prefix=/usr
。意思是將該軟件安裝在/usr
下面,執行文件就會安裝在/usr/bin
(如果不指定,默認的路徑是/usr/local/bin
),
資源文件就會安裝在/usr/share
(而不是默認的/usr/local/share
)。可以通過./configure --help
察看詳細的說明幫助。之前就寫過一篇文章 CentOS 源碼編譯安裝 Python3make
是用來編譯的,它從Makefile
中讀取指令,然后編譯。如果 在 make 過程中出現 error ,你就要記下錯誤代碼(注意不僅僅是最后一行),然后你可以向開發者提交 bugreport(一般在 INSTALL 里有提交地址),或者你的系統少了一些依賴庫等,這些需要自己仔細研究錯誤代碼。make install
就是把編譯出來的二進制文件,庫,配置文件等等放到相應目錄下make uninstal
是卸載,不加參數就是默認的進行源代碼編譯。make clean
清除編譯結果
make
是 Linux 開發套件里面自動化編譯的一個控制程序,他通過借助 Makefile 里面編寫的編譯規范(語法很多,類似一個可以運行的腳本程序。反正我是看不懂,所以你也別問我怎么編寫)。進行自動化的調用 gcc 、ld 以及運行某些需要的程序進行編譯的程序。
一般情況下,他所使用的 Makefile 控制代碼,由 configure 這個設置腳本根據給定的參數和系統環境生成。
Makefile是什么東東?有什么用?怎么用?
makefile 是用於自動編譯和鏈接的,一個工程有很多文件組成,每一個文件的改變都會導致工程的重新鏈接--但是不是所有的文件都需要重新編譯,makefile 能夠紀錄文件的信息,決定在鏈接的時候需要重新編譯哪些文件。
cc 和 gcc 又是什么?
從名字上看,老的 Unix 系統的 CC 程序叫做 C Compiler
。但 GCC 這個名字按 GNU 的說法叫做 Gnu Compiler Collection
,注意這是一個編譯器集合,不僅僅是 c 或 c++。gcc 包含很多編譯器(C, C++, Objective-C, Ada, Fortran,and Java) 。所以它們是不一樣的,一個是一個古老的 C 編譯器,一個是編譯器的 Gnu 的編譯器的集合(Gcc里的 C 編譯器比 CC 強大太多了,所以你沒必要用 CC)。
cc 是 gcc 的連接。cc 來自於昂貴的 Unix 系統,cc 是商業軟件,gcc 是編譯器。
GCC 可以用來編譯 C/C++、FORTRAN、JAVA、OBJC、ADA等語言的程序,可根據需要選擇安裝支持的語言。
參考
- 開源中國-RPM包的制作 對構建目錄介紹的比較仔細
- RPM打包原理、示例、詳解及備查 很詳細,有示例
- 如何構建 RPM 包 Linux 中國的文章,贊
- Fedora-WIKI-How to create an RPM package/zh-cn 中文介紹
- JIN-YANG-RPM 包制作 總結很全,還介紹了簽名
- CSDN-RPM構建 - RPM構建 - 簡單實例 該博主,總共圍繞 RPM 構建寫了幾篇文章的
- 月與燈依舊-linux rpm包編譯過程(spec文件和spec宏 ) 這個博主的文章看到過不止一次,贊
兩份英文資料:
make gcc 命令了解的參考: