zoukankan      html  css  js  c++  java
  • spec 文件详解

     转自http://blog.sina.com.cn/s/blog_43b39e250100nnu4.html

    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程序�把source rpm套件中的sepc文件解压取出。

    SPEC脚本引用定义部分

    �fine userpath /var/www/html/demo

    Name:

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

    软件包的内容概要
    Version:

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

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

    Copyright:

    软件包所采用的版权规则。具体有:GPL(自由软件),BSD,MIT,Public Domain(公共域),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的过程中,执行make install时就会把软件安装到上述的路径中,在打包的时候,同样依赖“虚拟目录”为“根目录”进行操作。

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

    URL:

    软件的主页
    Vendor:

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

    发行版标识

    例如Red Hat Linux

    ExcludeArch: sparc s390  #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 the telnet remote login protocol

    �scription server

    Telnet is a popular protocol for logging into remote systems

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

    �scription -n my-telnet-server

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

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

    %package devel

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

    Group: Development/Libraries

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

    �scription devel

    Header files and a static library of bzip2 functions, for developing apps

    which will use the library.

    %package libs

    Summary: Libraries for applications using bzip2

    Group: System Environment/Libraries

    �scription libs

    Libraries for applications using the bzip2 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 #在改变目录后,仅解压给定数字的源码,如-a 0 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

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

    也可以使用非标准写法:

    make DESTDIR=$RPM_BUILD_ROOT install

    make prefix=$RPM_BUILD_ROOT install

    make INSTROOT=$RPM_BUILD_ROOT install
    需要说明的是,这里的%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.1 bzgrep.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方式编写,并使用GNU autotool创建的包有效,若自定义Makefile则不能一概而论。
    %changelog

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

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

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

    * Mon Mar 31 1997 Erik Troan <ewt@redhat.com>

    - Fixed problems caused by 64 bit time_t.



     

    技巧:

    如果要避免生成debuginfo包:这个是默认会生成的rpm包。则可以使用下面的命令:

    echo '�bug_package %{nil}' >> ~/.rpmmacros
    如果rpm包已经做好,但在安装的时候想修改默认路径,则可以:

    rpm -ivh --prefix=/opt/usr xxx.rpm
    又或者同时修改多个路径:

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

    所有的宏都可以在/usr/lib/rpm/macros里找到。

    下面是宏对应路径一览表:

    Macros mimicking autoconf variables

    %{_sysconfdir}        /etc

    %{_prefix}            /usr

    %{_exec_prefix}      %{_prefix}

    %{_bindir}           %{_exec_prefix}/bin

    %{_lib}               lib (lib64 on 64bit systems)

    %{_libdir}           %{_exec_prefix}/%{_lib}

    %{_libexecdir}       %{_exec_prefix}/libexec

    %{_sbindir}          %{_exec_prefix}/sbin

    %{_sharedstatedir}    /var/lib

    %{_datadir}          %{_prefix}/share

    %{_includedir}       %{_prefix}/include

    %{_oldincludedir}     /usr/include

    %{_infodir}           /usr/share/info

    %{_mandir}            /usr/share/man

    %{_localstatedir}     /var

    %{_initddir}         %{_sysconfdir}/rc.d/init.d

    Note: On releases older than Fedora 10 (and EPEL),%{_initddir}does not exist. Instead, you should use the deprecated%{_initrddir}macro.

    RPM directory macros

    %{_topdir}           %{getenv:HOME}/rpmbuild

    %{_builddir}         %{_topdir}/BUILD

    %{_rpmdir}           %{_topdir}/RPMS

    %{_sourcedir}        %{_topdir}/SOURCES

    %{_specdir}          %{_topdir}/SPECS

    %{_srcrpmdir}        %{_topdir}/SRPMS

    %{_buildrootdir}     %{_topdir}/BUILDROOT

    Note: On releases older than Fedora 10 (and EPEL),%{_buildrootdir}does not exist.

    Build flags macros

    %{_global_cflags}     -O2 -g -pipe

    %{_optflags}         %{__global_cflags} -m32 -march=i386 -mtune=pentium4 # if redhat-rpm-config is installed

    Other macros

    %{_var}               /var

    %{_tmppath}          %{_var}/tmp

    %{_usr}               /usr

    %{_usrsrc}           %{_usr}/src

    %{_docdir}           %{_datadir}/doc

  • 相关阅读:
    119. Pascal's Triangle II
    118. Pascal's Triangle
    112. Path Sum
    111. Minimum Depth of Binary Tree
    110. Balanced Binary Tree
    108. Convert Sorted Array to Binary Search Tree
    88. Merge Sorted Array
    83. Remove Duplicates from Sorted List
    70. Climbing Stairs
    陌陌面试经历
  • 原文地址:https://www.cnblogs.com/sunshine-long/p/9809042.html
Copyright © 2011-2022 走看看