linux spec文档解析

一、spec文档的作用

       随着RedHat   Linux的发展,其对rpm包的管理及其格式的规划也得到了推广和统一。现在在工作中应用的最多的就是rpm包。无论是你自己撰写spec文档和一些代码生成rpm,还是根据之前的.src.rpm包  打个patch生成rpm包,看懂spec文档是必须的。

二、关键字

Name:软件包的名称,后面引用的时候%{name}

Version:软件包的版本号,后面引用时候 %{version}

Release:序列号,后面引用时用%{release}

Summary : 软件包的概述

Group:软件分组,一般使用标准分组

License:软件授权的方式,一般是GPL

Source:源代码包,(可以有多个,Source1、Source2....),后面引用时可以用%{source1}、%{source2}

BuildRoot:安装编译时使用的“虚拟目录”,后面可以使用$RPM_BUILD_ROOT

Patch:补丁源码(可以有多个补丁Patch1、Patch2....),后面引用时,可以用%patch1 或 %{patch1}

URL:软件的主页

Vendor:发行商或打包组织的信息

Disstribution:发行版标识

Prefix: %{_prefix} 这个主要是为了解决今后安装rpm包时,并不一定把软件安装到rpm中打包的目录的情况。这样,必须在这里定义该标识,并在编写%install脚本的时候引用,才能实现rpm安装时重新指定位置的功能

Prefix: %{_sysconfdir} 这个原因和上面的一样,但由于%{_prefix}指/usr,而对于其他的文件,例如/etc下的配置文件,则需要用%{_sysconfdir}标识

Build Arch: 指编译的目标处理器架构,noarch标识不指定,但通常都是以/usr/lib/rpm/marcros中的内容为默认值

Requires: 该rpm包所依赖的软件包名称,可以用>=或<=表示大于或小于某一特定版本,例如:
      libpng-devel >= 1.0.20 zlib
注意::“>=”号两边需用空格隔开,而不同软件名称也用空格分开
还有例如PreReq、Requires(pre)、Requires(post)、Requires(preun)、Requires(postun)、BuildRequires等都是针对不同阶段的依赖指定


Provides: 指明本软件一些特定的功能,以便其他rpm识别

Packager: 打包者的信息

%description 软件的详细说明


三、主体

%prep   预处理

%setup -n %{name} - %{version} 把源码包解压       // -n 用来指定解压到哪个文件,即将/SOURCE下的包解压到/BUILD/ %{name} - %{version

%patch    打补丁(补丁一般都会存放在tar.gz,或SOURCE目录下)

◎补充一下

引用
%setup 不加任何选项,仅将软件包打开。
%setup -n newdir 将软件包解压在newdir目录。
%setup -c 解压缩之前先产生目录。
%setup -b num 将第num个source文件解压缩。
%setup -T 不使用default的解压缩操作。
%setup -T -b 0 将第0个源代码文件解压缩。
%setup -c -n newdir 指定目录名称newdir,并在此目录产生rpm套件。
%patch 最简单的补丁方式,自动指定patch level。
%patch 0 使用第0个补丁文件,相当于%patch ?p 0。
%patch -s 不显示打补丁时的信息。
%patch -T 将所有打补丁时产生的输出文件删除。

%configure 这个不是关键字,而是rpm定义的标准宏命令。意思是执行源代码的configure配置
在/usr/src/asianux/BUILD/%{name}-%{version}目录中进行,使用标准写法,会引 用/usr/lib/rpm/marcros中定义的参数
另一种不标准的写法是,可参考源码中的参数自定义,例如:
引用
CFLAGS="$RPM_OPT_FLAGS" CXXFLAGS="$RPM_OPT_FLAGS" ./configure --prefix=%{_prefix}

%build 开始构建包
在/usr/src/asianux/BUILD/%{name}-%{version}目录中进行make的工作,常见写法:
引用
make %{?_smp_mflags} OPTIMIZE="%{optflags}"

都是一些优化参数,定义在/usr/lib/rpm/marcros中

%install 开始把软件安装到虚拟的根目录中
在/usr/src/asianux/BUILD/%{name}-%{version}目录中进行make install的操作。 这个很重要,因为如果这里的路径不对的话,则下面%file中寻找文件的时候就会失败。常见内容有:
%makeinstall 这不是关键字,而是rpm定义的标准宏命令。也可以使用非标准写法:
引用
make DESTDIR=$RPM_BUILD_ROOT install


引用
make prefix=$RPM_BUILD_ROOT install

需要说明的是,这里的%install主要就是为了后面的%file服务的。所以,还可以使用常规的系统命令:
引用
install -d $RPM_BUILD_ROOT/
cp -a * $RPM_BUILD_ROOT/

%clean 清理临时文件
通常内容为:
引用
[ "$RPM_BUILD_ROOT" != "/" ] && rm -rf "$RPM_BUILD_ROOT"
rm -rf $RPM_BUILD_DIR/%{name}-%{version}

※注意区分$RPM_BUILD_ROOT和$RPM_BUILD_DIR:
$RPM_BUILD_ROOT是指开头定义的BuildRoot,而$RPM_BUILD_DIR通常就是指/usr/src/asianux/BUILD,其中,前面的才是%file需要的。


%pre
rpm安装前执行的脚本

%post rpm安装后执行的脚本

%preun rpm卸载前执行的脚本

%postun rpm卸载后执行的脚本

%preun %postun 的区别是什么呢?
前者在升级的时候会执行,后者在升级rpm包的时候不会执行

%files 定义那些文件或目录会放入rpm中
这里会在虚拟根目录下进行,千万不要写绝对路径,而应用宏或变量表示相对路径。如果描述为目录,表示目录中除%exclude外的所有文件。
%defattr (-,root,root) 指定包装文件的属性,分别是(mode,owner,group),-表示默认值,对文本文件是0644,可执行文件是0755

%exclude 列出不想打包到rpm中的文件
※小心,如果%exclude指定的文件不存在,也会出错的。
%changelog 变更日志

四、范例

下面一制作memcached的源码包为例,介绍编写spec脚本

 

Summary:  Free & open source, high-performance,distributed memory object caching system

Name:     memcached     #软件包的名称

Version:    1.4.5         #软件的实际版本号

Release:    1.139          #发布序列号,后面的139是与系统包区分开

License:    GPL           #软件授权方式,通常就是GPL

Group:    Applications

Source:     memcached-1.4.5.tar.gz   #源代码包

BuildRoot:  %{_tmppath}/%{name}-%{version}-root #这个是安装或编译时使用的“虚拟目录”

BuildRequires: libevent,libevent-devel  #rpm包所依赖的软件包名称

Url:          http://memcached.org/

 

%description

Memcached is an in-memory key-value store for smallchunks of arbitrary data (strings, objects) from results of database calls, APIcalls, or page rendering.

 

%prep   #预处理脚本

%setup –q     #提取源码到BUILD目录; -q指不显示输出(quietly

 

%build   #开始构建包

./configure

make

 

%install

rm -rf %{buildroot}  

make DESTDIR=$RPM_BUILD_ROOT install     #将软件安装到虚拟目录中

 

%files    #定义哪些些文件或目录会放入rpm

%defattr(-, root, root, 0755)     #指定包装文件的属性

/usr/local/            #利用rpm安装以后,安装文件的路径

五、其他
1、扩展
虽然上面的范例很简陋,而且缺少%build部分,但实际上只要记住两点:
a)就是%build和%install的过程中,都必须把编译和安装的文件定义到“虚拟根目录”中。
引用
%build
make -f admin/Makefile.common cvs
./configure --prefix=%{_prefix} --enable-final --disable-debug \
--with-extra-includes=%{_includedir}/freetype2 --includedir=%{_includedir}
make
%install
rm -fr $RPM_BUILD_ROOT
make DESTDIR=$RPM_BUILD_ROOT install
cp -r $RPM_BUILD_ROOT%{_datadir}/apps/kolourpaint/icons/hicolor/* $RPM_BUILD_ROOT%{_datadir}/icons/crystalsvg/

b)就是%file中必须明白,用的是相对目录

引用
%files
%defattr(-,root,root)
%{_bindir}
%{_libdir}
%{_datadir}
%exclude %{_libdir}/debug

如果把

引用
%files
%defattr(-,root,root)
%{_bindir}

写成

引用
%files
%defattr(-,root,root)
/usr/bin

则打包的会是根目录下的/usr/bin中所有的文件。
2、一些rpm相关信息
rpm软件包系统的标准分组:/usr/share/doc/rpm-4.3.3/GROUPS
各种宏定义: /usr/lib/rpm/macros
已经安装的rpm包数据库: /var/lib/rpm
如果要避免生成debuginfo包:这个是默认会生成的rpm包。则可以使用下面的命令:

echo '%debug_package %{nil}' >> ~/.rpmmacros

如果rpm包已经做好,但在安装的时候想修改默认路径,则可以:

rpm -ivh --prefix=/opt/usr xxx.rpm

又或者同时修改多个路径:

rpm xxx.rpm --relocate=/usr=/opt/usr --relocate=/etc=/usr/etc

3、制作补丁
详细看参考:
[原]使用diff同patch工具
4、如何编写%file段
由于必须在%file中包括所有套件中的文件,所以,我们需要清楚编译完的套件到底包括那些文件?
常见的做法是,人工模拟一次编译的过程:

./configrue --prefix=/usr/local/xxx
make
make DESTDIR=/usr/local/xxx install

make prefix=/usr/local/xxx install

这样,整个套件的内容就会被放到/usr/local/xxx中,可根据情况编写%file和%exclude段。
※当然,这个只能对源码按GNU方式编写,并使用GNU autotool创建的包有效,若自定义Makefile则不能一概而论。
5、关于rpm中的执行脚本
如果正在制作的rpm包是准备作为放到系统安装光盘中的话,则需要考虑rpm中定义的脚本是否有问题。由于系统在安装的时候只是依赖于一个小环境进行,而该环境与实际安装完的环境有很大的区别,所以,大部分的脚本在该安装环境中都是无法生效,甚至会带来麻烦的。
所以,对于这样的,需要放到安装光盘中的套件,不加入执行脚本是较佳的方法。
另外,为提供操作中可参考的信息,rpm还提供了一种信号机制:不同的操作会返回不同的信息,并放到默认变量$1中。

引用
0代表卸载、1代表安装、2代表升级

可这样使用:

引用
%postun
if [ "$1" = "0" ]; then
/sbin/ldconfig
fi

………………………………………………………………转载1…………….....................………………………………………
1.The RPM system assumes five RPM directories
BUILD:rpmbuild编译软件的目录
RPMS:rpmbuild创建的binary RPM所存放的目录
SOURCES:存放源代码的目录
SPEC:存放spec文件的目录
SRPMS:rpmbuild创建的source RPM所存放的目录
2.rpm内建的宏在文件/usr/lib/rpm/redhat/macros文件中有定义,这些宏基本上定义了目录路径或体系结构等等,rpm也包含了一组用于调试有问题的spec文件的宏,如下:
%dump:打印宏的值
%{echo:message} :打印信息到标准错误
%{error:message} :打印信息到标准错误,然后返回BADSPEC
%{expand:expression} :like eval, expands expression
%{F:file_exp} :扩展file_exp到一个文件名
%global name value :定义一个全局宏
%{P:patch_exp} :扩展patch_exp到一个补丁文件名
%{S:source_exp} :扩展source_exp到一个源码文件名
%trace :跟踪调试信息
%{uncompress:filename}
Tests if file filename is compressed. If so, uncompresses and includes
in the given context. If not compressed, calls cat to include file in given context.
%undefine macro :取消给定的宏定义
%{warn:message} :打印信息到标准错误
3.宏
%define  macro_name  value
然后可以用%macro_name或者%{macro_name}来调用,也可以扩展到shell,如
%define today %(date)
也可以传递参数给宏
%define macro_name(option)  value
%foo 1 2 3 传递1,2,3三个参数给宏foo
在宏扩展的宏参数
%0:宏的名字
%*:传递给宏的所有参数
%#:传递给宏的参数个数
%1:第一个参数
%2:第二个参数,等等
%{-p}:Holds -p
%{-p*}:Holds the value passed with the -p parameter, if the -p parameter was passed to the macro;otherwise holds nothing
%{-p:text}:Holds text if the -p parameter was passed to the macr;otherwise holds nothing
%{?macro_to_text:expression}:如果macro_to_text存在,expand expression,如国不存在,则输出为空;也可以逆着用,:%{!?macro_to_text:expression}
%{?macro}:忽略表达式只测试该macro是否存在,如果存在就用该宏的值,如果不存在,就不用,如:./configure %{?_with_ldap}
%if %{old_5x}
%define b5x 1
%undefine b6x
%endif
or
%if %{old_5x}
%define b5x 1
%undefine b6x
%else
%define b6x 1
%undefine b5x
%endif
还可以用!,&&等符号,如:
%if %{old_5x} && %{old_6x}
%{error: you cannot build for .5x and .6x at the same time}
%quit
%endif
%ifarch sparc  alpha:判断处理器的结构
%ifnoarch i386 alpha:跟%ifarch相反
%ifos linux:测试操作系统
%ifnos linux:跟%ifos相反
4.# This is a comment.
以#开头的一行为注释,如果在注释里加%会产生错误,如%prep,应该加上两个%,即%%prep
5.spec文件的写法:
Name: myapp    #设置rpm包的名字
Version: 1.1.2    #设置rpm包的版本号
Release:1        #设置rpm包的修订号
Group: System Environment/Shells        #设置rpm包的分类,所有组列在文件/usr/share/doc/rpm-version/GROUP
Distribution: Red Hat Linux    #列出这个包属于那个发行版
Icon: file.xpm or file.gif        #存储在rpm包中的icon文件
Vendor: Company            #指定这个rpm包所属的公司或组织
URL: http://www.somesite.com    #公司或组织的主页
Packager: sam shen     #rpm包制作者的名字和email
License: LGPL            #包的许可证
Copyright: BSD            #包的版权
Summary: something descripe the package    #rpm包的简要信息
ExcludeArch: sparc s390        #rpm包不能在该系统结构下创建
ExclusiveArch: i386 ia64        #rpm包只能在给定的系统结构下创建
Excludeos:windows            #rpm包不能在该操作系统下创建
Exclusiveos: linux            #rpm包只能在给定的操作系统下创建
Buildroot: /tmp/%{name}-%{version}-root    #rpm包最终安装的目录
Source0: telnet-client.tar.gz
Source1: telnet-xinetd
Source2: telnet-wmconfig        #源代码文件,如果只有一个源码目录,可以只写Source: telnet-client.tar.gz
Source3: ftp://ftp.somesite.you/pub/name.tar.gz    #用ftp或http命名源码包
NoSource:0                #第一个源码不包含在包中
Patch1:telnet-client-cvs.patch
Patch2:telnetd-0.17.diff
Patch3:telnet-0.17-env.patch    #补丁文件
NoPatch:0                #第一个补丁文件不包含在包中
Requires:packagename        #该包需要给定的packagename包
Requires:bash>=2.0        #该包需要包bash,且版本至少为2.0,还有很多比较符号如<,>,<=,>=,=
Requires:perl(Carp)>=3.2        #requirement for the Carp add-on module for Perl
PreReq: capability >=version    #capability包必须先安装
Conflicts:bash>=2.0            #该包和所有不小于2.0的bash包有冲突
BuildRequires:
BuildPreReq:
BuildConflicts:          
#这三个选项和上述三个类似,只是他们的依赖性关系在构建包时就要满足,而前三者是在安装包时要满足
Autoreq: 0                 #禁用自动依赖
Prefix: /usr           
#定义一个relocatable的包,当安装或更新包时,所有在/usr目录下的包都可以映射到其他目录,当定义Prefix时,所有%files标志的文件都要在Prefix定义的目录下
%triggerin --package < version  
#当package包安装或更新时,或本包安装更新且package已经安装时,运行script    
...script...                    
%triggerun --package       
#当package包删除时,或本包删除且package已经安装时,运行script    
...script...                        
%triggerpostun --package       
#当package删除时运行script,本包删除时不运行
...script...
%triggerpostun -p /usr/bin/perl  --vixie-cron <3.0.1-56
               -p /usr/sh package < version
               -n subpackage_name –vixie-cron <3.0.1-56
...script...
in trigger script,$1:the number of instances of your package that will remain     after operation has completed, $2:the number of instances of the target package that will remain after the operation ,if $2 is 0, the target package will be removed
%description: something        #rpm包的描述
%prep                 #定义准备编译的命令
%setup  -c            #在解压之前创建子目录
        -q            #在安静模式下且最少输出
     -T            #禁用自动化解压包
      -n name      #设置子目录名字为name
        -D            #在解压之前禁止删除目录
        -a number        #在改变目录后,仅解压给定数字的源码,如-a 0 for source0
        -b number        #在改变目录前,仅解压给定数字的源码,如-b 0 for source0                            
%patch -p0                #remove no slashes
%patch -p1                 #remove one slashes
%patch                #打补丁0
%patch1                #打补丁1
%patch2                #打补丁2
%patch -P 2           #打补丁2
%build                #编译软件
./configure  --prefix=$RPM_BUILD_ROOT/usr
make    
or
%configure            #可以用rpm –eval '%configure'命令查看该宏
make
%install              #安装软件
make install PREFIX=$RPM_BUILD_ROOT/usr
install -m755 myapp $RPM_BUILD_ROOT/usr/bin/myapp
or
%makeinstall
%clean                #清除编译和安装时生成的临时文件
rm -rf $RPM_BUILD_ROOT
%post                 #定义安装之后执行的脚本
...script...         
#rpm命令传递一个参数给这些脚本,1是第一次安装,>=2是升级,0是删除最新版本,用到的变量为$1,$2,$0
%preun                #定义卸载软件之前执行的脚本
...script...
%postun               #定义卸载软件之后执行的脚本
...script...
%files                #rpm包中要安装的所有文件列表
file1                 #文件中也可以包含通配符,如*
file2
directory             #所有文件都放在directory目录下
and so on
%dir   /etc/xtoolwait    #包含一个空目录/etc/xtoolwait
%doc  /usr/X11R6/man/man1/xtoolwait.*    #安装该文档
%doc README NEWS            #安装这些文档到/usr/share/doc/ or /usr/doc
%docdir                    #定义存放文档的目录
%config /etc/yp.conf            #标志该文件是一个配置文件
%config(noreplace) /etc/yp.conf      
 #该配置文件不会覆盖已存在文件(被修改)覆盖已存在文件(没被修改),创建新的文件加上扩展后缀.rpmnew(被修改)
%config(missingok)    /etc/yp.conf    #该文件不是必须要的
%ghost  /etc/yp.conf            #该文件不应该包含在包中
%attr(mode, user, group)  filename    #控制文件的权限如%attr(0644,root,root) /etc/yp.conf,如果你不想指定值,可以用-
%config  %attr(-,root,root) filename    #设定文件类型和权限
%defattr(-,root,root)            #设置文件的默认权限
%lang(en) %{_datadir}/locale/en/LC_MESSAGES/tcsh*    #用特定的语言标志文件
%verify(owner group size) filename    #只测试owner,group,size,默认测试所有
%verify(not owner) filename        #不测试owner
                    #所有的认证如下:
                    #group:认证文件的组
                    #maj:认证文件的主设备号
                    #md5:认证文件的MD5
                    #min:认证文件的辅设备号
                    #mode:认证文件的权限
                    #mtime:认证文件最后修改时间
                    #owner:认证文件的所有者
                    #size:认证文件的大小
                    #symlink:认证符号连接
%verifyscript                #check for an entry in a system             
...script...                #configuration file    
%changelog
* Wen Sep 24 sam shen
- sam updated to 1.3
    
%package sub_package_name   #定义一个子包,名字为package-subpackage
       -n sub_package_name  #定义一个子包,名字为sub_package_name
当定义一个子包时,必须至少包含Summary:,Group:,%description选项,任何没有指定的选项将用父包的选项,如版本等,如:
%package server
Requires: xinetd
Group: System Environment/Daemons
Summary:The server program for the telnet remote login protocol
%description server
Telnet is a popular protocol for logging into remote systems
如果在%package时用-n选项,那么在%description时也要用,如:
%description -n my-telnet-server
%files server
%defattr(-,root,root)
%{_sbindir}/in.telnetd
如果在%package时用-n选项,那么在%files时也要用,如:


*****************************************************转载2*****************************************************************

rpm软件包系统的标准分组:/usr/share/doc/rpm-4.3.3/GROUPS

rpmrc配置文件:/usr/lib/rpm/rpmrc /etc/rpmrc   ~/.rpmrc
各种宏定义: /usr/lib/rpm/macros /etc/rpm/macros  ~/.rpmmacros
已经安装的rpm包数据库: /var/lib/rpm*

临时文件:/var/tmp/rpm*

可以通过命令rpm --showrc查看实现代码。另外直接通过rpm--eval "%{macro}"来查看具体对应路径。

比如我们要查看%{_bindir}的路径,就可以使用命令rpm --eval"%{_bindir}"来查看。

用以下命令将spec文件取出。
  $rpm -qlp *.src.rpm
  $rpm2cpio *.src.rpm|cpio -ivh *.spec
  首先执行rpm-qlp查询得知该套件中有几个.spec文件再执行rpm2cpio将rpm文件转换成cpio文件格式并将转换结果输出给cpio程序把sourcerpm套件中的sepc文件解压取出。

SPEC脚本引用定义部分

�fine userpath /var/www/html/demo

Name:

软件包的名称,后面可使用%{name}的方式引用
Summary:

软件包的内容概要
Version:

软件的实际版本号,例如:1.0.1等,后面可使用%{version}引用
Release:

发布序列号,例如:1linuxing等,标明第几次打包,后面可使用%{release}引用

Copyright:

软件包所采用的版权规则。具体有:GPL(自由软件),BSD,MIT,PublicDomain(公共域),Distributable(贡献),commercial(商业),Share(共享)等,一般的开发都写GPL。
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 (文档)
  System Environment/Base(系统环境/基础)
  System Environment/Daemons (系统环境/守护)
  System Environment/Kernel (系统环境/内核)
  System Environment/Libraries (系统环境/函数库)
  System Environment/Shells (系统环境/接口)
  User Interface/Desktops(用户界面/桌面)
  User Interface/X (用户界面/X窗口)
  User Interface/X Hardware Support (用户界面/X硬件支持)

License:

软件授权方式,通常就是GPL
Source:

源代码包,可以带多个用Source1、Source2等源,后面也可以用%{source1}、%{source2}引用。

NoSource:0 #第一个源码不包含在包中


Patch:

补丁源码,可使用Patch1、Patch2等标识多个补丁,使用%patch0或%{patch0}引用,

补丁 ID 规则
0-9 Makefile、configure 等的补丁
10-39 指定功能或包含他的文件的补丁
40-59 配置文件的补丁
60-79 字体或字符补丁
80-99 通过 xgettexize 得到的目录情况的补丁
100- 其他补丁
NoPatch:0 #第一个补丁文件不包含在包中
BuildRoot:

这个是安装或编译时使用的“虚拟目录”,考虑到多用户的环境,一般定义为:%{_tmppath}/%{name}-%{version}-root
%{_tmppath}/%{name}-%{version}-%{release}-root

%{_tmppath}/%{name}-%{version}-%{release}-buildroot-%(%{__id_u}-n}
该参数非常重要,后面可使用$RPM_BUILD_ROOT 方式引用。因为在生成rpm的过程中,执行makeinstall时就会把软件安装到上述的路径中,在打包的时候,同样依赖“虚拟目录”为“根目录”进行操作。

※注意区分$RPM_BUILD_ROOT和$RPM_BUILD_DIR:
$RPM_BUILD_ROOT是指定义的BuildRoot,而$RPM_BUILD_DIR通常就是指/usr/src/asianux/BUILD,其中,前面的才是%file需要的。

URL:

软件的主页
Vendor:

软件开发者名字,发行商或打包组织的信息,例如RedFlagCo,Ltd
Distribution:

发行版标识

例如Red Hat Linux

ExcludeArch: sparcs390  #rpm包不能在该系统结构下创建,如果是这个环境,将报错。

ExclusiveArch: i386 ia64#rpm包只能在给定的系统结构下创建

ExcludeOS:windows       #rpm包不能在该操作系统下创建

ExclusiveOS:linux      #rpm包只能在给定的操作系统下创建

(

%ifarch sparc s390 判断处理器的结构

%ifnoarch i386 alpha 与上边相反

%ifos linux       测试操作系统

%ifnos linux      与上边相反

)

Icon:

file.xpm or file.gif#存储在rpm包中的icon文件


Prefix:

%{_prefix}这个主要是为了解决今后安装rpm包时,并不一定把软件安装到rpm中打包的目录的情况。这样,必须在这里定义该标识,并在编写%install脚本的时候引用,才能实现rpm安装时重新指定位置的功能
%{_sysconfdir}这个原因和上面的一样,但由于%{_prefix}指/usr,而对于其他的文件,例如/etc下的配置文件,则需要用%{_sysconfdir}标识

Prefix: /usr#定义一个relocatable的包,当安装或更新包时,#所有在/usr目录下的包都可以映射到其他目录,当定义Prefix时,所有%files标志的文件都要在Prefix 定义的目录下


BuildArch:

指编译的目标处理器架构,noarch标识不指定,但通常都是以/usr/lib/rpm/marcros中的内容为默认值

Obsoletes:

过时的,废弃的。

Obsoletes:anaconda-images<= 10

Provides:

指明本软件提供一些特定的功能,以便其他rpm识别

例如:

Provides: mail-reader
Requires:

该rpm包所依赖的软件包名称,可以用>=或<=表示大于或小于某一特定版本,

※“>=”号两边需用空格隔开,而不同软件名称也用空格分开

例如:该包需要 libpng-devel版本至少为1.0.20,以及zlib
Requires: libpng-devel >= 1.0.20 zlib

Requires: bzip2 = %{version},bzip2-libs = %{version}

Requires:perl(Carp)>=3.2 需要perl模块Carp
PreReq、Requires(pre)、Requires(post)、Requires(preun)、Requires(postun)、BuildRequires等都是针对不同阶段的依赖指定
PreReq: capability>=version     #capability包必须先安装

Conflicts:bash>=2.0             #该包和所有不小于2.0的bash包有冲突

以上三者是在安装RPM包时要满足.

BuildRequires:

BuildRequires: zlib-devel

BuildPreReq:

 

BuildConflicts:

这三个选项的依赖性关系在构建RPM包时就要满足

Autoreq:

rpm_build时会为包里的二进制文件找出对应的共享库(.so)依赖,打成RPM包后可能在安装时提示缺少依赖并退出,要避免执行find-requires找共享库依赖,可以加上禁用自动依赖Autoreq:no  或者设为0

Autoprov:

rpm_build时会为包里的二进制文件找出对应的共享库(.so)依赖,打成RPM包后可能在安装时提示缺少依赖并退出,要避免执行find-provides找共享库依赖,可以加上禁用自动依赖Autoprov:no  或者设为0

AutoReqProv:no

rpm_build时会为包里的二进制文件找出对应的共享库(.so)依赖,打成RPM包后可能在安装时提示缺少依赖并退出,要避免执行find-provides与find-requires找共享库依赖,可以加上禁用自动依赖

Autoprov:no   或者设为0 或者为flase相当于同时设定上边两个的值Autoreq:和Autoprov:

上边3个会因为顺序的不同而导致结果会有所不同,一般以最后一个为准。

%triggerin -- package <version

执行脚本或者命令

#当package包安装或更新时,或本包安装更新且package已经安装时,运行script

当其所在软件包与指定软件包仅有一方安装时,安装另一方将触发此程序执行。

%triggerun -- package

执行脚本或者命令

#当package包删除时,或本包删除且package已经安装时,运行script

当其所在软件包与指定软件包都已安装时,卸载任一方将触发此程序执行。

例如:

%triggerun -- anaconda <8.0-1

./script

%triggerpostun -- package

#当package删除时运行script,本包删除时不运行

指定软件包卸载后才触发此程序执行。

%triggerpostun -p /usr/bin/perl --vixie-cron <3.0.1-56

-p /usr/sh package <version

-n subpackage_name –vixie-cron<3.0.1-56

...script...

-p  解释程序

--  触发条件

-n  子包的触发条件等

Packager:

打包者的信息,姓名以及邮箱等,处于同一行。
�scription

软件的详细说明

上边是关于RPM包信息的一些描述。

spec脚本主体

%package

#定义一个子包

%package -n sub_package_name#定义一个子包,名字为sub_package_name

当定义一个子包时,必须至少包含Summary:,Group:,�scription选项,任何没有指定的选项将用父包的选项,如版本等,如:

%package server

Requires: xinetd

Group: System Environment/Daemons

Summary:The server program for thetelnet remote login protocol

�scription server

Telnet is a popular protocol forlogging into remote systems

如果在%package时用-n选项,那么在�scription时也要用,如:

�scription -n my-telnet-server

 

如果在%package时用-n选项,那么在%files时也要用,如:

%files -nmy-telnet-server,也可以定义安装或卸载脚本,像定义%files和�scription 一样

%package devel

Summary: Header files and libraries fordeveloping apps which will use bzip2.

Group: Development/Libraries

Requires: bzip2 = %{version},bzip2-libs = %{version}

�scription devel

Header files and a static library ofbzip2 functions, for developing apps

which will use the library.

 

%package libs

Summary: Libraries for applicationsusing bzip2

Group: System Environment/Libraries

�scription libs

Libraries for applications using thebzip2 compression format.

 


%prep

预处理脚本,这个段是预处理段,通常用来执行一些解开源程序包的命令,为下一步的编译安装作准备。%prep和下面的%build,%install段一样,除了可以执行RPM所定义的宏命令(以%开头)以外,还可以执行SHELL命令,命令可以有很多行,如我们常写的tar解包命令。
%preun

rpm卸载前执行的脚本
%setup

把源码包解压并放好
通常是从/usr/src/asianux/SOURCES里的包解压到/usr/src/asianux/BUILD/%{name}-%{version}中。

%setup -q %{name}-%{version}
一般用%setup-q就可以了,但有两种情况:一就是同时编译多个源码包,二就是源码的tar包的名称与解压出来的目录不一致,此时,就需要使用-n参数指定一下了。

%setup 不加任何选项,仅将软件包打开。

%setup -q 在安静模式下且最少输出

%setup -D #在解压之前禁止删除目录

%setup -a number #在改变目录后,仅解压给定数字的源码,如-a0 for source0
%setup -n newdir 将软件包解压到newdir目录。
%setup -c 解压缩之前先产生目录。
%setup -b num 包含多个源文件时,将第num个source文件解压缩。
%setup -T 不使用default的解压缩操作。
%setup -T -b 0 将第0个源代码文件SOURCE0解压缩。
%setup -c -n newdir 指定目录名称newdir,并在此目录产生rpm套件。

%patch
通常补丁都会一起在源码tar.gz包中,或放到SOURCES目录下。

一般参数为:
%patch -p1 使用前面定义的Patch补丁进行,-p1是忽略patch的第一层目录
%Patch2 -p1 -b xxx.patch 打上指定的补丁,-b是指生成备份文件
%patch 最简单的补丁方式,自动指定patch level。
%patch 0 使用第0个补丁文件,相当于%patch ?p 0。
%patch -s 不显示打补丁时的信息。
%patch -T 将所有打补丁时产生的输出文件删除。

%patch #打补丁0

%patch1 #打补丁1

%patch2 #打补丁2

%patch -P 2 #打补丁2

在%build之前,%prep部分将准备好编译工作,解开源码包,并将相应的补丁打进去。
%build

开始编译源码构建包,相当于configure以及make部分

所要执行的命令为生成软件包服务,如

%configure这个不是关键字,而是rpm定义的标准宏命令。意思是执行源代码的configure配置,可以用rpm –eval'%configure'命令查看该宏
在/usr/src/asianux/BUILD/%{name}-%{version}目录中进行操作,使用标准写法,会引用/usr/lib/rpm/marcros中定义的参数。
另一种不标准的写法是,可参考源码中的参数自定义,例如:

引用

CFLAGS="$RPM_OPT_FLAGS"CXXFLAGS="$RPM_OPT_FLAGS" ./configure --prefix=%{_prefix}

make 命令
在/usr/src/asianux/BUILD/%{name}-%{version}目录中进行make的工作 ,常见写法:

make %{?_smp_mflags}OPTIMIZE="%{optflags}"
都是一些优化参数,定义在/usr/lib/rpm/marcros中

%check
%install

开始把软件安装到虚拟的根目录中,本段是安装段,其中的命令在安装软件包时将执行,如makeinstall命令、cp、mv、install、ln。
在/usr/src/asianux/BUILD/%{name}-%{version}目录中进行makeinstall的操作。这个很重要,因为如果这里的路径不对的话,则下面%file中寻找文件的时候就会失败。 常见内容有:
%makeinstall 这不是关键字,而是rpm定义的标准宏命令,相当于执行make install命令那一步。

也可以使用非标准写法:

make DESTDIR=$RPM_BUILD_ROOTinstall

make prefix=$RPM_BUILD_ROOT install

make INSTROOT=$RPM_BUILD_ROOTinstall
需要说明的是,这里的%install主要就是为了后面的%file服务的。所以,还可以使用常规的系统命令:

rm -rf ${RPM_BUILD_ROOT}

mkdir -p$RPM_BUILD_ROOT/{%{_bindir},%{_mandir}/man1,%{_libdir},%{_includedir}}

install -m 755 bzlib.h$RPM_BUILD_ROOT/%{_includedir}

install -m 644 bzip2.1 bzdiff.1bzgrep.1 bzmore.1 $RPM_BUILD_ROOT/%{_mandir}/man1/

install -d $RPM_BUILD_ROOT/
cp -a * $RPM_BUILD_ROOT/

ln -s file/magic ${RPM_BUILD_ROOT}%{_datadir}/magic

%find_lang %{name}

%files -f %{name}.lang

第一句生成一个名为%{name}.lang的文件,内容是所有的%{name}.mo,第二句意思是一个一个列举.mo文件很麻烦,-f参数是将其后边接的文件合并到%files的文件列表。

%clean

清除编译和安装时生成的临时文件
通常内容为:

[ "$RPM_BUILD_ROOT" != "/" ]&& rm -rf "$RPM_BUILD_ROOT"
rm -rf $RPM_BUILD_DIR/%{name}-%{version}
%post

rpm安装后执行的脚本
%post libs -p /sbin/ldconfig

libs包时执行这部分动作
%postun

rpm卸载后执行的脚本
%postun libs  -p /sbin/ldconfig

 

rpm还提供了一种信号机制:不同的操作会返回不同的信息,并放到默认变量$1中。

引用

0代表卸载、1代表安装、2代表升级


可这样使用:

引用

%postun
if [ "$1" = "0" ]; then
/sbin/ldconfig
fi

%verifyscript #软件包校验脚本程序开始执行

%files

�fattr (-,root,root)

本段是文件段,用于定义构成软件包的文件列表,那些文件或目录会放入rpm中,分为三类-说明文档(doc),配置文件(config)及执行程序,还可定义文件存取权限,拥有者及组别。

这里会在虚拟根目录下进行,千万不要写绝对路径,而应用宏或变量表示相对路径。

※特别需要注意的是:%install部分使用的是绝对路径,而%file部分使用则是相对路径,虽然其描述的是同一个地方。千万不要写错。
%files  -f %{name}.lang tui

file1 #文件中也可以包含通配符,如*

file2

directory #所有文件都放在directory目录下

%dir /etc/xtoolwait#仅是一个空目录/etc/xtoolwait打进包里

%doc 表示这是文档文件,因此如安装时使用--excludedocs将不安装该文件,

%doc /usr/X11R6/man/man1/xtoolwait.*#安装该文档

%doc README NEWS#安装这些文档到/usr/share/doc/%{name}-%{version} 或者 /usr/doc或者

%docdir#定义说明文档的目录,例如/root,在这一语句后,所有以/root开头的行都被定义为说明文件。

%config /etc/yp.conf#标志该文件是一个配置文件,升级过程中,RPM会有如下动作。

%config(missisgok) /etc/yp.conf此配置文件可以丢失,即使丢失了,RPM在卸载软件包时也不认为这是一个错误,并不报错。一般用于那些软件包安装后建立的符号链接文件,如

/etc/rc.d/rc5.d/S55named文件,此类文件在软件包卸载后可能需要删除,所以丢失了也不要紧。

%config(noreplace) /etc/yp.conf

#该配置文件不会覆盖已存在文件(RPM包中文件会以.rpmnew存在于系统,卸载时系统中的该配置文件会以.rpmsave保存下来,如果没有这个选项,安装时RPM包中文件会以.rpmorig存在于系统)

覆盖已存在文件(没被修改),创建新的文件加上扩展后缀.rpmnew(被修改)

%{_bindir}/*

%config /etc/aa.conf

%ghost /etc/yp.conf#该文件不应该包含在包中,一般是日志文件,其文件属性很重要,但是文件内容不重要,用了这个选项后,仅将其文件属性加入包中。

%attr(mode, user, group) filename#控制文件的权限如%attr(0644,root,root) /etc/yp.conf

如果你不想指定值,可以用-

%config %attr(-,root,root) filename#设定文件类型和权限

�fattr(-,root,root)#设置文件的默认权限,-表示默认值,对文本文件是0644,可执行文件是0755

%lang(en)%{_datadir}/locale/en/LC_MESSAGES/tcsh* #用特定的语言标志文件

%verify(owner group size) filename#只测试owner,group,size,默认测试所有

%verify(not owner) filename#不测试owner,测试其他的属性

所有的认证如下:

group:  认证文件的组

maj:   认证文件的主设备号

md5:   认证文件的MD5

min:   认证文件的辅设备号

mode:   认证文件的权限

mtime:  认证文件最后修改时间

owner:  认证文件的所有者

size:   认证文件的大小

symlink:认证符号连接

 

如果描述为目录,表示目录中出%exclude外的所有文件。

%files
�fattr(-,root,root)

%doc
%{_bindir}/*
%{_libdir}/liba*
%{_datadir}/file

%{_infodir}/*

%{_mandir}/man[15]/*

%{_includedir}
%exclude %{_libdir}/debug

(%exclude列出不想打包到rpm中的文件。※小心,如果%exclude指定的文件不存在,也会出错的。)
如果把

%files
�fattr(-,root,root)
%{_bindir}
写成

%files
�fattr(-,root,root)
/usr/bin
则打包的会是根目录下的/usr/bin中所有的文件。

%files libs

�fattr(-,root,root)

%{_libdir}/*so.*

%files devel

�fattr(-,root,root)

%{_includedir}/*

 

由于必须在%file中包括所有套件中的文件,所以,我们需要清楚编译完的套件到底包括那些文件,常见的做法是,人工模拟一次编译的过程:

./configrue--prefix=/usr/local/xxx
make
make DESTDIR=/usr/local/xxx install

make prefix=/usr/local/xxx install
这样,整个套件的内容就会被放到/usr/local/xxx中,可根据情况编写%file和%exclude段
※当然,这个只能对源码按GNU方式编写,并使用GNUautotool创建的包有效,若自定义Makefile则不能一概而论。
%changelog

变更日志,本段是修改日志段。你可以将软件的每次修改记录到这里,保存到发布的软件包中,以便查询之用。每一个修改日志都有这样一种格式:

第一行是:* 星期月日 年 修改人电子信箱。

其中:星期、月份均用英文形式的前3个字母,用中文会报错。接下来的行写的是修改了什么地方,可写多行。一般以减号开始,便于后续的查阅。

* Mon Mar 31 1997 Erik Troan<[email protected]>

 

- Fixed problems caused by 64 bittime_t.



你可能感兴趣的:(linux,spec)