rpm介绍

rpm的全称是RedhatPackage Manager,常见的使用rpm软件包的系统主要有FedoraCentOSopenSUSESUSE企业版、PCLinuxOS等。使用deb软件包后缀的类Debian系统最常见的有DebianUbuntuFinnix等。

   从软件运行的结构来说,一个软件主要可以分为三个部分:可执行程序、配置文件和动态库。当然还有可能会有相关文档、手册、供二次开发用的头文件以及一些示例程序等等。可执行文件是必须的,其他部分都是可选的。

   制作rpm软件包的方法,使用最多的是rpmbuild这个命令行工具。如果你的rpm的版本<=4.4.x,那么rpmbuid工具其默认的工作路径是/usr/src/redhat,由于权限使得普通用户不能制作rpm包,在制作rpm软件包时必须切换到root身份才可以。所以,rpm4.5.x版本开始,将rpmbuid的默认工作路径移动到用户家目录下的rpmbuild目录里,即$HOME/rpmbuild。安全起见,建议用户在制作rpm软件包时尽量不要以root身份进行操作。

   关于rpmbuild默认工作路径由%_topdir的宏变量来定义,这个变量在/usr/lib/rpm/macros里的定义。也可使用rpmbuild命令查看。

$ rpmbuild --showrc |grep _topdir
……
-14: _topdir    %{getenv:HOME}/rpmbuild


如果用户想更改这个目录,官方不推荐直接更改这个文件,而是在用户家目录下建立一个名为.rpmmacros的隐藏文件,然后在里面重新定义%_topdir,指向一个新的目录名。

 

定制rpm包工作目录结构

定制rpm包需要在%_topdir下建立以下5个目录

目录名     说明                    macros中的宏名

BUILD     编译rpm包的临时目录           %_builddir

RPMS       最终生成的rpm包的所在目录      %_rpmdir

SOURCES    所有源代码和补丁文件的存放目录   %_sourcedir

SPECS     存放SPEC文件的目录(重要)        %_specdir

SRPMS     源码格式rpm包存放路径          %_srcrpmdir


以上目录无需手动创建,执行rpmdev-setuptree命令即可在用户家目录下自动创建目录树

$ yum install rpmdevtools   #安装rpmdevtools这个工具,该工具包含rpmbuild,rpmdev-newspec,rpmdev-setuptree等工具
$rpmdev -setuptree
$ tree
.
└── rpmbuild
    ├── BUILD
    ├── RPMS
    ├── SOURCES
    ├── SPECS
    └── SRPMS

 

rpmbuild命令常用选项

基本格式:rpmbuild  [options]  [spec文档|tarball包|源码包]
1、从spec文档建立rpm包有以下选项:
-bp        #只执行spec的%pre 段(解开源码包并打补丁,属于准备阶段)
-bc        #执行spec的%pre和%build 段(完成准备阶段并编译)
-bi        #执行spec中%pre,%build与%install(准备,编译并安装)
-bl        #检查spec中的%file段(查看文件是否包含完全)
-ba        #二进制的rpm包和源码的rpm包都建立(常用)
-bb        #只建立二进制的rpm包(常用)
-bs        #只建立源码的rpm包

2.  从tarball包建立rpm包有以下选项:
-tp         #对应sepc方式的-bp
-tc         #对应sepc方式的-bc
-ti         #对应sepc方式的-bi
-ta         #对应sepc方式的-ba
-tb         #对应sepc方式的-bb
-ts         #对应sepc方式的-bs

3.  从源码包建立rpm包有以下选项:
--rebuild    #建立二进制包,同sepc方式的-bb
--recompile   #同sepc方式的-bi

4.  其他选项:
--buildroot=DIRECTORY  #确定以root目录建立包
--clean         #完成打包后清除BUILD下的文件目录
--nobuild        #不进行%build的阶段
--nodeps         #不检查建立包时的关联文件
--nodirtokens          #generate packageheader(s) compatible with (legacy) rpm[23] packaging
--rmsource       #完成打包后清除SOURCES
--rmspec        #完成打包后清除SPEC
--short-cricuit     #skip straight tospecified stage (only for c,i)
--target=CPU-VENDOR-OS #确定包的最终使用平台


 

制作rpm包的几个关键阶段

%prep阶段

    这个阶段主要完成对源代码包的解压和打补丁,系统把源码包从SOURCES解压缩到BUILD目录,并切换到BUILD下的压缩包解压生成的目录(可能是%{name}-%{version} )里,完成打补丁等准备工作,最后退回到BUILD 目录下。常用指令如下:

解压常用指令:

%setup              #不加任何选项,仅将软件包打开。
%setup -q            #quiet,静默方式解压,输出少量信息。
%setup -n destdir  #destdir为软件包解压后生成的目录名称,一般用在tar包名称和展开后生成的目录名不一致的情况下。
%setup -c           #解压缩之前先创建目录,目录名称一般为%{name}-%{version}。
%setup -a num        #a表示after,在切换到BUILD目录之后再解压第num个文件,如果有多个文件,会产生多个目录。
%setup -b num    #b表示before,在切换到BUILD目录之前再解压第num个文件。一般同-c一起使用,如果有多个文件,这样可以控制多个文件解压到一个目录下。
%setup -D          #在解压之前不删除原有目录
%setup -T           #不解压,直接把文件复制到BUILD目录即可。
%setup -T -b 0     #将第0个源代码文件解压缩。
%setup -c -n destdir   #指定目录名称destdir,并在此目录产生rpm套件。
打补丁常用指令:
%patch            #最简单的补丁方式,自动指定patch level。
%patch 0           #使用第0个补丁文件,相当于%patch?p 0。
%patch -s          #不显示打补丁时的信息。
%patch -T          #将所有打补丁时产生的输出文件删除。


 

%build阶段

这个阶段开始构建包,就是执行常见的configuremake操作。

%configure是个宏常量,会自动将prefix设置成/usr。另外,这个宏还可以接受额外的参数,如果某些软件有某些高级特性需要开启,可以通过给%configure宏传参数来开启。如果不用 %configure这个宏的话,就需要完全手动指定configure时的配置参数了。如果不指定,它自动将软件安装时的路径自动设置成如下默认目录:

可执行程序/usr/bin

依赖的动态库/usr/lib或者/usr/lib64视操作系统版本而定。

二次开发的头文件/usr/include

文档及手册/usr/share/man

 

configure执行完成之后系统重新进入BUILD下的压缩包解压出来的目录下执行 make命令,如make %{?_smp_mflags}OPTIMIZE="%{optflags}"       

以上这条命令的两个参数的含意为:

%{?_smp_mflags}如果系统里定义了make的并行编译参数,则使用这个参数。例如: -j2 表示 make并行执行两个文件的编译操作。如果你使用多个 CPU 或者非单核 CPU,这个参数可以明显提高编译速度,但是这里指定的数字不宜超过你的 CPU 内核数量+1

OPTIMIZE="%{optflags}" 表示如果系统里定义了 gcc的优化参数,则在软件默认优化参数的基础上追加使用这里指定的优化参数。例如: -O2 -g -pipe 表示使用 gcc 第二优化级、为调试工具GDB 提供额外的支持信息、使用管道而不是临时文件以便加快编译速度。

这两个参数在/usr/lib/rpm/mBuild/macros文件中定义。

 

%install阶段

   这个阶段就是执行make install操作。这个阶段会在BUILDROOT目录里建好目录结构,然后将需要打包到rpm软件包里的文件从BUILD里拷贝到BUILDROOT里对应的目录里。这个阶段最常见的两条指令是:

rm -rf $RPM_BUILD_ROOT
make install DESTDIR=$RPM_BUILD_ROOT

 

   其中$RPM_BUILD_ROOT也可以换成我们前面定义的BuildRoot变量,不过要写成%{buildroot}才可以,必须全部用小写,不然要报错。

   如果软件有配置文件或者脚本之类,需要使用用copy命令或者install命令拷贝到%{buildroot}相应的目录里,推荐用install命令。

install命令相关选项如下:
-b:类似 --backup,但不接受任何参数。 
-d,--directory:所有参数都作为目录处理,而且会创建指定目录的所有主目录。
-D:创建<目的地>前的所有主目录,然后将<来源>复制至 <目的地>;在第一种使用格式中有用。 
-g,--group=组:自行设定所属组,而不是进程目前的所属组。
-m,--mode=模式:自行设定权限模式 (像chmod),而不是rwxr-xr-x。 
-o,--owner=所有者:自行设定所有者 (只适用于超级用户)。 
-p,--preserve-timestamps:保留文件原有时间戳。 
-S,--suffix=后缀:自行指定备份文件的<后缀>。


 

%clean阶段

   执行编译完成后一些清理工作,主要包括对%{buildroot}目录的清空(不是必须),通常执行诸如make clean之类的命令。 通常执行以下命令:

%clean
rm -rf $RPM_BUILD_ROOT
rm -rf $RPM_BUILD_DIR/%{name}-%{version}

也可以写成

%clean
%{__rm}-rf %{buildroot}
%{__rm}-rf %{_builddir}/%{name}-%{version}


%files阶段

   这里是包含制作rpm包文件的阶段,它主要用来说明会将%{buildroot}目录下的哪些文件和目录最终打包到rpm包里。

   %files阶段的第一条命令的语法是:%defattr(文件权限,用户名,组名,目录权限)

   如果不需要改变文件、目录权限则一般用%defattr(-,root,root,-)这条指令来为其设置缺省权限。所有需要打包到rpm包的文件和目录都在这个地方列出。

 %files阶段有一个重要特性:

 %{buildroot}里的所有文件都需要明确指定是否要被打到rpm包里。如果不打也要用%exclude排除掉。当然,也不能声明%{buildroot}里不存在的文件或目录。

 

其他附加阶段

%pre        #在此编写rpm包安装前执行的脚本。

%post        #在此编写rpm包安装后执行的脚本。

%preun       #在此编写rpm包卸载前执行的脚本。

%postun      #在此编写rpm包卸载后执行的脚本。

 

例如:

%postun
if ["$1" = "0" ]; then
    rm -rf $RPM_BUILD_ROOT%{jdk_home}/jdk
fi

这里的$1可能会有012或以上,这几个值。

0表示卸载这个包的最新版本

1表示第一次安装这个包

2或以上表示升级这个软件包


%changelog阶段

这是最后一个阶段,记录每次打包时的变更日志,日期一定不能写错,只能使用英文格式,如:

* WedApr 11 2014 ju.com <ju@puhuifianance.com> - 1.8.0-1

- modifythe spec file and rebuild

 

rpm包标准分组

制作rpm包的spec文件里定义的Group,建议使用标准分组,软件包具体分组类别有:

Amusements/Games              娱乐/游戏
Amusements/Graphics           娱乐/图形
Applications/Archiving    应用/文档
Applications/Communications  应用/通讯
Applications/Databases     应用/数据库
Applications/Editors      应用/编辑器
Applications/Emulators    应用/仿真器
Applications/Engineering    应用/工程
Applications/File       应用/文件
Applications/Internet     应用/因特网
Applications/Multimedia    应用/多媒体
Applications/Productivity   应用/产品
Applications/Publishing    应用/印刷
Applications/System      应用/系统
Applications/Text       应用/文本
Development/Debuggers     开发/调试器
Development/Languages     开发/语言
Development/Libraries     开发/函数库
Development/System      开发/系统
Development/Tools       开发/工具
Documentation         文档
SystemEnvironment/Base    系统环境/基础
SystemEnvironment/Daemons     系统环境/守护
SystemEnvironment/Kernel      系统环境/内核
SystemEnvironment/Libraries  系统环境/函数库
SystemEnvironment/Shells   系统环境/接口
UserInterface/Desktops    用户界面/桌面
UserInterface/X        用户界面/X窗口
UserInterface/X Hardware Support   用户界面/X硬件支持


 

常见宏定义

在系统的/usr/lib/rpm/macros文件中定义了各种宏变量,这里列出常见的宏定义:

%_prefix     /usr            #展开后是/usr
%_exec_prefix   %{_prefix}         #展开后是/usr
%_bindir     %{_exec_prefix}/bin       #展开后是/usr/bin
%_sbindir     %{_exec_prefix}/sbin     #展开后是/usr/sbin
%_libexecdir   %{_exec_prefix}/libexec   #展开后是/usr/libexec
%_datadir      %{_prefix}/share      #展开后是/usr/share
%_sysconfdir   %{_prefix}/etc       #展开后是/usr/etc
%_sharedstatedir %{_prefix}/com        #展开后是/usr/com
%_localstatedir  %{_prefix}/var      #展开后是/usr/var
%_libdir     %{_exec_prefix}/lib    #展开后是/usr/lib
%_includedir   %{_prefix}/include      #展开后是/usr/include
%_infodir    %{_prefix}/info         #展开后是/usr/info
%_mandir     %{_prefix}/man       #展开后是/usr/man

 


上面说了一堆制作rpm包涉及的一些概念和既定的东西,然而要真正制作一个rpm包,这些并没有什么大的卵用,哈哈,关键还要会写最最重要的SPEC文件,请见下回分解àrpm包制作(二)》。