1 spec文件

1.1 spec文件的语法

TagName: value

比如

Version: 2.1.0

tag名大小写不敏感。

1.2 宏

spec支持定义宏,要定义宏,使用:

%define testMacro 2

这里定义了一个宏,名称为testMacro,值为2,要使用这个宏,使用%{testMacro}
或者%testMacro。

1.3 注释

注释使用#开头,如果注释里面出现了%,这需要转义,使用%%就可以了

2 定义包的信息

包的信息中最重要的是NVR,也就是name、version、release,最后生成的rpm包的名称为:name-version-release-architecture.rpm

2.1 定义包的名称

使用:

name: tair

包的名称不能含有空白字符,比如空格、Tab和回车等。

2.2 版本号

版本号用于做版本的比较,rpm的版本比较算法很复杂,最好使用统一的一种版本命名方法,比如2.1.0,要定义包的版本号,使用:

version: 2.1.0

在包的版本号中不能使用’-‘,因为rpm使用它来分隔name、version、release。

2.3 release number

release number在特定版本的第一次build时应该以1开始,之后每次build加1,比如

release: 1

2.4 说明

包括摘要(summary)和描述(description)

2.4.1 摘要

摘要包含一行介绍包的文字,不要超过50个字符,例如:

summary: A distribution key/value storage system

2.4.2 描述

描述允许更详细的介绍,描述支持少量的格式化,空行用于分割段落,以空白开头(比如空格或者Tab)的行通常会以等宽字体显示。例如:

%description
Tair is a distribution, hign performance key/value storage system.
 TairManager tairManager = new TairManager(configServers, groupName);

2.5 平台

spec文件可以指定一个包可以运行在多个平台上,还是必须运行在一个特定的平台上。

2.5.1 排除平台

可以使用excludeArch来表示不构建这些平台的rpm包,比如

excludeArch: sparc

这表示不build在sparc平台下的包

2.5.2 exclusiveArch

可以使用exclusiveArch来指定只build这些平台的rpm包,比如:

exclusiveArch: i386 x86-64

这表示只build i386和x8664平台的包

2.5.3 excludeOs和exclusiveOs

这两个指令用于指定特定的操作系统,比如:

excludeOs: windows

表示不build windows的包

2.6 指定build的路径

和rpm build相关的有两个目录: build和buildroot
build是RPM构建包的地方,编译、配置等操作都在这个目录下执行
buildroot和安装的路径差不多,在安装的时候,包会被安装在相对buildroot的子目录下,要设置buildroot,使用:

buildroot: %{_tmppath}/%{name}-%{version}-root

这将buildroot设定太tmp下的一个子目录,这个子目录类似:tair-2.1.0-root
在设置了Buildroot后,在spec中可以通过RPMBUILDROOT变量来访问这个目录,也可以通过–;buildroot选项来覆盖这个变量

2.7 指定源代码

可以通过source来指定构建需要的源代码,比如:

source: tair-2.1.0-src.tar.gz

如果有多个源代码包,那么使用source和数字混合的tagName,比如:

source0: tbsys-src.tar.gz
source1: tbnet-src.tar.gz
source2: tair-2.1.0-src.tar.gz

source指定的路径可以是网络路径,比如http://192.168.208.97/packages/%{name}-%{version}-src.tar.gz

3 构建

在指定了包的信息后,spec文件还应该包含构建的命令,rpm将使用这些命令来构建。构建通常由其他工具来完成,比如make。RPM不负责构建包,而是只负责打包。

构建一个包可以分为4步:

  1. 构建前的准备,包括解压缩代码包等
  2. 构建
  3. 安装程序和库
  4. 清理

3.1 构建前的准备

%prep中定义了构建前要做的准备工作,通常是要包括%setup就可以了

%prep
%setup -q

它将切换到构建所在的目录,通常是/usr/src/redhat/BUILD,然后解压源文件,使用以包名命令的子目录。

如果源代码是tar包,那么目标路径下的子目录会自动创建,如果不是,那么可以通过-c选项指定创建。

3.2 构建

构建的步骤在%build中指定,比如

%build
./bootstrap.sh
./configurate
make -j 6

3.3 安装

安装由%install表示,如果你的Makefile包含安装命令,那么只要

%install
make install PREFIX=$RPM_BUILD_ROOT/usr/local

就可以了。
也可以用makeinstall宏来执行安装,和make install的效果是一样的。

3.4 清理

在安装完成后,可以指定清理工作,通常删除整个构建路径就可以了,比如

%clean
rm -rf $RPM_BUILD_ROOT

4 指定安装的文件列表

%file用于指定安装时需要安装的文件列表,可以指定文件、目录,也可以使用通配符,比如

%file
/usr/local/sbin/tairserver # 一个可指定文件
/usr/local/sbin/taircfgsvr
/usr/local/etc/*.conf # 使用通配符
/usr/local/lib # 使用目录

4.1 文档和配置文件

rpm中会区分文档和配置文件,分别使用%doc和%config来表示,比如

%doc README # 文档
%config /usr/local/etc/*.conf # 配置文件

4.2 设置文件的属性

设置文件属性的格式是:

%attr(mode, user, group) filename

比如:

%config %attr(0644, admin, admin) /usr/local/etc/*.conf

这将etc目录下的配置文件的mode都设置为644,用户和组都设置为admin

5 添加changelog

changelog通常位于spec文件的末尾,使用%changelog开头

6 依赖关系

依赖关系定义了一个包正常工作需要依赖的其他包,RPM在升级、安装和删除的时候会确保依赖关系得到满足。rpm支持4种依赖:

  1. Requirements, 包依赖其他包所提供的功能
  2. Provides, 这个包能提供的功能
  3. Conflicts, 一个包和其他包冲突的功能
  4. Obsoletes, 其他包提供的功能已经不推荐使用了,这通常是其他包的功能修改了,老版本不推荐使用了,可以在以后的版本中会被废弃。

6.1 定义依赖关系

定义依赖关系的语法是:

Requires: capability
Provides: capability
Obsoletes: capability
Conflicts: capability

大部分时候,capability应该是所依赖的包的名称。一行中也可以定义多个依赖,比如:
Requires: tbsys tbnet

6.2 指定依赖的版本号

在指定依赖关系的时候还可以指定版本号,比如:

Requires: tbsys >= 2.0

rpm支持的比较如下:

比较符 含义
package < version 小于version的包
package > version 大于version的包
package >= version 大于等于version的包
package <= version 小于等于version的包
package = version 等于version的包
package 任意版本

6.3 先决依赖

先决(prerequisites)依赖和依赖类似,但是只有在该先决依赖安装的前提下,依赖它的包才会被安装。比如Tair依赖tbsys:

prereq: tbsys >= 2.0

6.4 构建依赖

有些依赖在构建的时候就需要满足,比如构建tbnet依赖tbsys,这可以使用buildRequires来指定,比如:

buildRequires: tbsys >= 2.0

和requires一样,还可以指定:

  1. buildConflicts
  2. buildPreReq

7 淘宝build定制化

ABS对rpmbuild进行了一些简单的封装,这里讲一下我在添加Tair的rpmbuild方式的时候遇到的一些问题。

7.1 需要的文件

由于是公司内部使用,所以做了一些约定,这些约定本身和rpm无关。

7.1.1 rpm目录

首先需要在源代码的目录下添加一个子目录,名称为rpm,比如在Tair中添加之后的目录结构为:

tair_src/
|-- AUTHORS
|-- ChangeLog
|-- Makefile.am
|-- NEWS
|-- README
|-- bootstrap.sh
|-- configure.ac
|-- doc
|-- etc
|-- rpm  ==================== 添加的rpm目录
`-- src

rpm目录通常包含以下文件:

tair_src/rpm/
|-- rpm_create
|-- t-csrd-tair-VER.txt
|-- t-csrd-tair-build.sh
`-- t-csrd-tair.spec
文件 含义
rpmcreate 其中rpm_create是一个shell脚本,在写好配置文件后,运行它就可以执行build过程
t-csrd-tair-VER.txt 版本写在这个目录中(不过我没有发现这个文件起作用)
t-csrd-tair-build.sh 可以将项目的build命令集中写在这里,但这个是可选的,如果不需要,不用管它
t-csrd-tair.spec 这个便是spec文件了,是最重要的文件

7.2 一些特殊的地方

rpm_create脚本本身很简单,只是定义了一些变量,这些变量可以在spec文件中引用。
执行过后,rpm_create脚本会在用户的根目录下生成一个.rpmmacros文件,里面保留着这些变量。但是再次执行的时候却不会读取这个文件,Orz。
rpm_调用rpmbuild -bb $target –buildroot $BUILD_ROOT $i来最终生成rpm包。然后将包移动到rpm目录下。

spec文件本身还是一个标准的spec文件,只是这里会使用rpm_create定义的一些变量。例如:
Version: %{version} #使用rpm_create中定义的version变量

%description
Tair is a high performance, distribution key/value storage system.
%{_svn_path}
%{_svn_revision}

这里的”svnpath”和”svnrevision”用于和hudson平台的配合。