spec文件是整个RPM包建立过程的中心,它的作用就如同编译程序时的Makefile文件。spec文件包含建立一个RPM包必需的信息,包括哪些文件是包的一部分以及它们安装在哪个目录下。这个文件一般分为如下的几节:
1,Preamle(序言)
序 言包含用户请求包的信息时所显示的内容。它可以包含包的功能描述、包的软件版本、版权信息和所属的包组等。Summary 是一行关于该软件包的描述,Name 是该软件包的基名,Version 是该软件的版本号,Release 是 RPM 本身的版本号,如果修复了 spec 文件中的一个错误并发布了该软件同一版本的新 RPM,就应该增加发行版号。License 应该给出一些许可术语(如:”GPL”、”Commercial”、”Shareware”),Group 标识软件类型。那些试图帮助人们管理 RPM 的程序通常按照组列出 RPM。您可以在usr/share/doc/rpm-4.0.4/GROUPS 文件看到一个 Red Hat 使用的组列表(假设您安装的 RPM 版本是 4.0.4)。但是您还可以使用那些组名以外的名称。Source0、Source1等等给这些源文件命名(通常为 tar.gz 文件)。%{name} 和 %{version} 是 RPM 宏,它们扩展成为头中定义的 rpm 名称和版本。
要注意的是,不要在 Source 语句中包含任何路径。缺省情况下,RPM 会在 /usr/src/redhat/SOURCES 中(对于Redhat6 系统,则是在 /root/rpmbuild/SOURCES 目录中)寻找文件,请将您的源文件复制或链接到那里。(要使 spec 文件尽量可移植的话,应当尽量避免嵌入自己开发机器上的假想路径。其他开发人员就可以指示 RPM 在别的目录下查找源文件,而不用修改您的 spec 文件。)
接下来的部分从 %description 行开始。您应该在这里提供该软件更多的描述,这样任何人使用 rpm -qi 查询您的软件包时都可以看到它。您可以解释这个软件包做什么,描述任何警告或附加的配置指令,等等。
一个序言的简单例子:
Summary: Utilities for managing accounts and shadow password files.
Name: shadow-utils
Version: 4.0.17
Release: 14%{?dist}
Source0: %{name}-%{version}.tar.bz2
Source1: shadow-4.0.17-login.defs
Source2: shadow-970616.useradd
Patch0: shadow-4.0.17-redhat.patch
Patch1: shadow-4.0.3-noinst.patch
Patch2: shadow-4.0.11.1-vipw.patch
Packager:amoblin
Group: Application
URL: http://www.ossxp.com
License: GPL
BuildRequires: autoconf, automake, libtool, gettext-devel
BuildRequires: libselinux-devel >= 1.25.2-1
BuildRequires: audit-libs-devel >= 1.0.10
Requires: libselinux >= 1.25.2-1
%description
This package includes the necessary programs for XXX.
2,Prep部分
Prep 节进行实际的打包准备工作,它是使用节前缀%prep表示的。主要功能有:
将文件 (SOURCES/) 解压到构建目录 (BUILD/)
应用Patch(打补丁) (SOURCES/ => BUILD/)
描述 “rm -rf $RPM_BUILD_ROOT”
描述或编辑本部分用到的命令到 PreReq:
通过 “-b .XXX” 描述补丁备份
%setup
-n newdir #将压缩的软件源程序在newdir目录下解开。
-c #在解开源程序之前先创建目录。
-b num #在包含多个源程序时,将第num个源程序解压缩。
-T #不使用缺省的解压缩操作。
通常patch补丁都会一起放到SOURCES目录下。一般参数为
%patchN -p1 #应用前面定义的第N个patch,-p1是忽略patch的第一层目录
例如:
%setup -q #最常用
%setup -q -n newdir #将source解压至newdir
%setup -T -b 0 #解开第一个源程序文件
%setup -c -n newdir #创建目录newdir,并在此目录之下解开源程序
%patch1 -p1 #应用第1个补丁
一个Prep部分的小例子:
%prep
%setup -q
%patch0 -p1
%patch1 -p1
%patch2 -p1
%patch3 -p1
cp %{SOURCE3} lib/nscd.c
rm po/*.gmo
rm po/stamp-po
3,Build部分
这一节主要用于编译源码,它是使用节前缀%build表示的。一般用于configure及make的过程。
一个build部分的例子:
%build
%configure --with-selinux --without-libpam --disable-shared --with-libaudit
make
4,Install部分
这一节主要用于完成实际安装软件必须执行的命令,它是使用节前缀%install表示的。这一节一般是由make install指令构成,但是有时也会包含cp、mv、install等指令。
这一节还能指定在用户安装的系统上,包安装时运行的脚本。这样的脚本称为安装(卸载)脚本。它可以指定包安装前、包安装后、包除去前、包除去后的系统必须运行的外壳程序段。在用户安装的系统上,为了验证一个包是否已经成功安装的验证脚本也可由这一节指定。
一个install节的例子:
%install
rm -rf $RPM_BUILD_ROOT
make install DESTDIR=$RPM_BUILD_ROOT gnulocaledir=$RPM_BUILD_ROOT/%{_datadir}/locale MKINSTALLDIRS=`pwd`/mkinstalldirs
install -d -m 755 $RPM_BUILD_ROOT/etc/default
install -c -m 0644 %{SOURCE1} $RPM_BUILD_ROOT/etc/login.defs
install -c -m 0600 %{SOURCE2} $RPM_BUILD_ROOT/etc/default/useradd
ln -s useradd $RPM_BUILD_ROOT%{_sbindir}/adduser
ln -s %{_mandir}/man8/useradd.8 $RPM_BUILD_ROOT/%{_mandir}/man8/adduser.8
for subdir in $RPM_BUILD_ROOT/%{_mandir}/{??,??_??,??_??.*}/man* ; do
test -d $subdir && test -e $subdir/useradd.8 && echo ".so man8/useradd.8" > $subdir/adduser.8
done
# Remove binaries we don't use.
rm $RPM_BUILD_ROOT/%{_bindir}/chfn
rm $RPM_BUILD_ROOT/%{_bindir}/chsh
5,Clean部分
这一节所描述的内容表示在完成包建立的工作之后,自动执行此节下的脚本进行附加的清除工作,它是使用节前缀%clean表示的。一般而言,这一节的内容是简单地使用rm -rf $RPM_BUILD_ROOT命令,不需要指定此节的其它内容。
一个clean部分的例子:
%clean
rm -rf $RPM_BUILD_ROOT
6,文件列表
这一节指定构成包的文件的列表,它是使用节前缀%files表示的。此外,它还包含一系列宏控制安装后的文件属性和配置信息。
%files 列出应该捆绑到 RPM 中的文件,并能够可选地设置许可权和其它信息。在 %files 中,您可以使用 %defattr 来定义缺省的许可权、所有者和组;%defattr(-,root,root) 会安装 root 用户拥有的所有文件,使用当 RPM 从构建系统捆绑它们时它们所具有的任何许可权。
可以用 %attr(permissions,user,group) 覆盖个别文件的所有者和许可权。可以在 %files 中用一行包括多个文件。可以通过在行中添加 %doc 或 %config 来标记文件。%doc 告诉 RPM 这是一个文档文件,因此如果用户安装软件包时使用 –excludedocs,将不安装该文件。您也可以在 %doc 下不带路径列出文件名,RPM 会在构建目录下查找这些文件并在 RPM 文件中包括它们,并把它们安装到 /usr/share/doc/%{name}-%{version}。以 %doc 的形式包括 README 和 ChangeLog 这样的文件是个好主意。
%config 告诉 RPM 这是一个配置文件。在升级时,RPM 将会试图避免用 RPM 打包的缺省配置文件覆盖用户仔细修改过的配置。
注意:如果在 %files 下列出一个目录名,RPM 会包括该目录下的所有文件。通常这不是您想要的,特别对于 /bin 这样的目录。
一个file部分的例子:
%files
%defattr(-,root,root) #指定默认权限
%doc NEWS doc/HOWTO README
%dir /etc/default
%attr(0644,root,root) %config(noreplace) /etc/login.defs
%attr(0600,root,root) %config /etc/default/useradd
%{_bindir}/sg
%{_bindir}/chage
%{_bindir}/faillog
%{_bindir}/gpasswd
%{_bindir}/lastlog
%{_bindir}/newgrp
%{_sbindir}/adduser
%attr(0750,root,root) %{_sbindir}/user*
%attr(0750,root,root) %{_sbindir}/group*
%{_sbindir}/grpck
%{_sbindir}/pwck
%{_sbindir}/*conv
%{_sbindir}/chpasswd
%{_sbindir}/newusers
7,改动日志
这一节主要描述软件的开发记录,它是使用节前缀%changlog表示的。这个段的内容是为了开发人员能详细的了解该软件的开发过程,对于包的维护极有好处。
所有宏都可以在/usr/lib/rpm/macros找到,附录一些常见的宏:
%{_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
%{_topdir} %{getenv:HOME}/rpmbuild
%{_builddir} %{_topdir}/BUILD
%{_rpmdir} %{_topdir}/RPMS
%{_sourcedir} %{_topdir}/SOURCES
%{_specdir} %{_topdir}/SPECS
%{_srcrpmdir} %{_topdir}/SRPMS
%{_buildrootdir} %{_topdir}/BUILDROOT
%{_var} /var
%{_tmppath} %{_var}/tmp
%{_usr} /usr
%{_usrsrc} %{_usr}/src
%{_docdir} %{_datadir}/doc
==================================================
一个简单的spce文件示例:
Summary: hello world rpm package
Name: hello
Version: 0.1
Release: 1
License: GPL
Source: %{name}-%{version}.tar.gz
Packager: amoblin
Group: Application
URL: http://www.ossxp.com
%description
%prep
%setup -q
%build
%install
mkdir -p $RPM_BUILD_ROOT/%{_bindir}
gcc -o hello hello.c
install -c -m 755 hello $RPM_BUILD_ROOT/%{_bindir}
%files
%{_bindir}/hello
%clean
rm -rf $RPM_BUILD_ROOT
Leave a Reply