上一篇使用salt.src.rpm文件生成salt rpm包,src.rpm内实际上就是.tar.gz源码、patch文件、.spec文件组成。生成rpm包除了源码外,还要懂得编写spec文件,spec文件一般包括软件包基础信息、源码包解压、安装路径等。

[root@localhost rpmbuild]# vim SPECS/salt.spec  # 来看下salt spec文件
%if ! (0%{?rhel} >= 6 || 0%{?fedora} > 12)
%global with_python26 1  
%define pybasever 2.6
%define __python_ver 26
%define __python %{_bindir}/python%{?pybasever}
%endif
%global include_tests 0
%{!?python_sitelib: %global python_sitelib %(%{__python} -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())")}
%{!?python_sitearch: %global python_sitearch %(%{__python} -c "from distutils.sysconfig import get_python_lib; print(get_python_lib(1))")}
%{!?pythonpath: %global pythonpath %(%{__python} -c "import os, sys; print(os.pathsep.join(x for x in sys.path if x))")}

%define _salttesting SaltTesting
%define _salttesting_ver 2014.8.5

分析:

要看懂上面那些内容,我们需要先看几种结构。
1、%if 0%(?rhel)   

在spec文件中0为假,非0为真

如果%{rhel}被定义了,则 %{?rhel} 返回 %{rhel},不然%{?rhel}视为未定义。

所以,当%{rhel}被定义过的话, 0%{?rhel}就等于0%{rhel} ,执行这个if block;

反之,0%{?rhel}等于0,不执行这个if block。


2、?:结构

%{?变量:动作1}

此条件与前面的%if有点不同,其只判断变量是否定义,定义了就为真,否则就为假,即使变量定义为0,也为真,并运行后面的语句。


还需要了解一些系统内置的宏,如下:

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

至于%global和%define的区别,根据rpm.org的wiki上面是这样描述的:

%define ...     define a macro
%undefine ...   undefine a macro 
%global ...     define a macro whose body is available in global context # 看这意思,应该是global定义的宏全局都生效

更多的默认宏定义在/usr/lib/rpm/macros*文件,操作系统不同,可能位置有所不一致。


再来看下面这段描述信息

Name: salt                                # 软件包名称,可用%{name}引用
Version: 2014.7.1                         # 软件包版本号,可用%{version}引用
Release: 1%{?dist}                        # 发布序列号,表示第几次打包,可用%{release}引用
Summary: A parallel remote execution system    # 软件包的内容概要
Group:   System Environment/Daemons            # 软件分组
License: ASL 2.0                               # 软件授权方式
URL:                      # 软件主页 
Source0: http://pypi.python.org/packages/source/s/%{name}/%{name}-%{version}.tar.gz   # 源码包,可以有多个,如Source0、Source1等,可用%{source0}、%{source1}引用 
Source1: https://pypi.python.org/packages/source/S/%{_salttesting}/%{_salttesting}-%{_salttesting_ver}.tar.gz
Source2: %{name}-master
Source3: %{name}-syndic
Source4: %{name}-minion
Source5: %{name}-api
Source6: %{name}-master.service
Source7: %{name}-syndic.service
Source8: %{name}-minion.service
Source9: %{name}-api.service
Source10: README.fedora
Source11: logrotate.salt
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)  # 安装或编译时使用的"虚拟目录",可用%{buildroot}引用,%{_tmppath}根据/usr/lib/rpm/macros查阅结果默认是在/var/tmp
BuildArch: noarch                         #  编译的cpu架构

%ifarch %{ix86} x86_64                    # 如果cpu是x86_64架构,%{ix86}默认宏定义可查阅/usr/lib/rpm/macros       
Requires: dmidecode                       # 该rpm包依赖的软件包名称,可以使用>=、=、<=某一特定版本号,">="两边需空格隔开
%endif       

%if ((0%{?rhel} >= 6 || 0%{?fedora} > 12) && 0%{?include_tests})
BuildRequires: m2crypto                    # 编译时依赖的软件包名称
BuildRequires: python-crypto
BuildRequires: python-jinja2
BuildRequires: python-msgpack
BuildRequires: python-pip
BuildRequires: python-zmq
BuildRequires: PyYAML
BuildRequires: python-requests
BuildRequires: python-unittest2
# this BR causes windows tests to happen
# clearly, that's not desired
# https://github.com/saltstack/salt/issues/3749
BuildRequires: python-mock
BuildRequires: git
BuildRequires: python-libcloud
%endif

%if 0%{?systemd_preun:1}                            
Requires(post): systemd-units                 # PreReq、Requires(pre)、Requires(post)、Requires(preun)、Requires(postun)、BuildRequires等都是针对不同阶段的依赖指定
Requires(preun): systemd-units
Requires(postun): systemd-units
%endif

%description                                  # 软件包的详细说明
Salt is a distributed remote execution system used to execute commands and
query data. It was developed in order to bring the best solutions found in
the world of remote execution together and make them better, faster and more
malleable. Salt accomplishes this via its ability to handle larger loads of
information, and not just dozens, but hundreds or even thousands of individual
servers, handle them quickly and through a simple and manageable interface.


%package master                               # 对subpackage的描述
Summary: Management component for salt, a parallel remote execution system
Group:   System Environment/Daemons
Requires: %{name} = %{version}-%{release}
%if (0%{?rhel} >= 7 || 0%{?fedora} >= 15)
Requires: systemd-python
%endif

%description master
The Salt master is the central server to which all minions connect
关于子包的包名,来看一个例子:
Name: salt
%package master
这个子包的包名就是salt-master

%prep                                       # 预处理脚本
%setup -c                                   # 源码包解压
%setup -T -D -a 1  
%setup 常用参数选项参考这里:
-c: Create Directory (and change to it) Before Unpacking
-D: Do Not Delete Directory Before Unpacking Sources
-T: Do Not Perform Default Archive Unpacking
-b <n>: Unpack The nth Sources Before Changing Directory
-a <n>: Unpack The nth Sources After Changing Directory

%build                                      # 开始构建rpm包

%install                                    # 软件安装到对应的目录下,主要为了后面的%file做铺垫的
rm -rf %{buildroot}
cd $RPM_BUILD_DIR/%{name}-%{version}/%{name}-%{version}
%{__python} setup.py install -O1 --root %{buildroot}

install -d -m 0755 %{buildroot}%{_var}/cache/salt            # 可以使用系统命令install安装,
install -d -m 0755 %{buildroot}%{_sysconfdir}/salt
install -d -m 0755 %{buildroot}%{_sysconfdir}/salt/cloud.conf.d
install -d -m 0755 %{buildroot}%{_sysconfdir}/salt/cloud.deploy.d
install -d -m 0755 %{buildroot}%{_sysconfdir}/salt/cloud.maps.d
install -d -m 0755 %{buildroot}%{_sysconfdir}/salt/cloud.profiles.d
install -d -m 0755 %{buildroot}%{_sysconfdir}/salt/cloud.providers.d

%clean                                    # 清理临时文件
rm -rf %{buildroot}

%check                                    # 检查包是否工作正常,很多packages不执行这个阶段
%files                                    # 定义rpm package包含哪些文件或目录
%defattr(-,root,root,-)                   # 指定包装文件的属性,分别是(mode,owner,group),-表示默认值,对文本文件是0644,可执行文件是0755
%doc $RPM_BUILD_DIR/%{name}-%{version}/%{name}-%{version}/LICENSE
%{python_sitelib}/%{name}/*            
#%{python_sitelib}/%{name}-%{version}-py?.?.egg-info
%{python_sitelib}/%{name}-*-py?.?.egg-info
%{_sysconfdir}/logrotate.d/salt
%{_var}/cache/salt
%doc $RPM_BUILD_DIR/%{name}-%{version}/%{name}-%{version}/README.fedora

%exclude                                  # 列出不想打包到rpm中的文件


%preun master                             
  if [ $1 -eq 0 ] ; then
      /sbin/service salt-master stop >/dev/null 2>&1
      /sbin/chkconfig --del salt-master
  fi

%pre                                # rpm安装前执行的脚本
%post                               # rpm安装后执行的脚本
%preun                              # rpm卸载前执行的脚本
%postun                             # rpm卸载后执行的脚本

%changelog                                # 记录变更日志


参考链接

http://hlee.iteye.com/blog/343499

http://www.rpm.org/wiki/PackagerDocs/Macros