rpm本地打包之spec文件(linux)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/XXJ19950917/article/details/81868456

rpm本地打包之spec文件(linux)

rpm本地打包的回顾

  • Linux之rpm本地打包中分析了rpm的常用指令、rpmbuild的常用命令以及参数的配置说明,详细情况请进入链接详细查看。接下来重点是分析spec文件。

spec文件

  • 能够熟悉在以上链接中的操作命令以及配置参数的含义,管理日常的rpm软件包也就不成问题了。
  • 然而,随着linux操作系统越来越流行于世界各地,越来越多的开发者更喜欢采用RPM格式来发布自己的软件包。那么RPM软件包是怎么样制作的了?对于大多数的开发者来说还是比较陌生的。
  • 其实,制作RPM软件包并不是一件复杂的工作,其中最为关键在于编写SPEC软件包描述文件。要想制作一个rpm软件包就必须写一个软件包描述文件(SPEC)。这个文件中包含了软件包的诸多信息,如软件包的名字、版本、类别、说明摘要、创建时要执行什么指令、安装时要执行什么操作、以及软件包所要包含的文件列表等等。

  • 描述文件如下:

文件头:

  • 一般的spec文件头包含以下几个域:

Name:

  • 软件包的名字,最终RPM软件包是用该名字与版本号,释出号及体系号来命名软件包的。

Name(example):

Name:   python-django-horizon

Epoch:

  • 软件包的系列,也就是软件包的体系号,表示软件包的系列

Epoch(example):

Epoch:  1

Version:

  • 软件包的版本号。仅当软件包比以前有较大改变时才增加版本号。

Version(example):

Version:    4.0.2

Release:

  • 软件包释出号。一般我们对该软件包做一些小的补丁的时候就应该释出号出1。

Relase(example):

Release:    4.0.2

注意: 其中Epoch:Version:Release表示了rpm包的新旧,优先级依次降低,打出的rpm包也是以${package}-${Version}-${Release}命名

Summary:

  • 一句话概括该软件包尽量多的信息。

Summary(example):

Summary:    Django application for talking to Openstack

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硬件支持)

Group(example):

Group:      Development/Libraries

License:

  • 软件包的发行许可证,也就是软件的授权方式,通常是GPL。

License(example)

# Code in horizon/horizon/utils taken from django which is BSD
License:    ASL 2.0 and BSD

URL:

  • rpm软件包的主页链接地址。

URL(example):

URL:        http://horizon.openstack.org/

Source:

  • 源程序软件包的名称。例如:horizon-9.0.1.tar.gz
    注意: Source[0-n]是rpm软件包打包时的源代码

Source(example):

Source0:    https://tarballs.openstack.org/horizon/horizon-%{upstream_version}.tar.gz
Source2:    openstack-dashboard-httpd-2.4.conf
Source3:    python-django-horizon-systemd.conf

# demo config for separate logging
Source4:    openstack-dashboard-httpd-logging.conf

# logrotate config
Source5:    python-django-horizon-logrotate.conf

BuildArch:

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

BuildArch(example):

BuildArch:  noarch

BuildRequires:

  • rpm软件包构建过程中所依赖的软件包名称,可以使用>=或者<=表示大于或者小于某一特定版本。

BuildRequires(example):

BuildRequires: python-setuptools
BuildRequires: python-pbr >= 2.0.0
BuildRequires: git
BuildRequires: python-six >= 1.10.0
BuildRequires: gettext

Requires:

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

Requires(example):

Requires:   python-django
Requires:   pytz
Requires:   python-six >= 1.10.0
Requires:   python-pbr

Provides:

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

Provides(example):

# additional provides to be consistent with other django packages
Provides: django-horizon = %{epoch}:%{version}-%{release}

Obsoletes:

  • 过时的,废弃的软件包

Obsoletes(example):

Obsoletes: python-django-openstack-auth < 4.0.0-1
Obsoletes: python2-django-openstack-auth < 4.0.0-1

%description:

  • rpm软件包的详细说明。

%description(example):

%description
Horizon is a Django application for providing Openstack UI components.
It allows performing site administrator (viewing account resource usage,
configuring users, accounts, quotas, flavors, etc.) and end user
operations (start/stop/delete instances, create/restore snapshots, view
instance VNC console, etc.)

%package:

  • 定义一个子包

%package(example):

%package -n openstack-dashboard
Summary:    Openstack web user interface reference implementation
Group:      Applications/System

Requires:   httpd

%description doc
Documentation for the Django Horizon application for talking with Openstack

%files段:

  • 本段是文件段,用于定义软件包所包含的文件,分为三类–说明文档(doc),配置文件(config)及执行程序,还可定义文件存取权限,拥有者及组别。

%files段(example):

%files -n openstack-dashboard -f dashboard.lang
...

注意: 当需要去定义一个子包时,必须至少包含Summary;Group;%description选项,任何没有指定的选项将使用父包的选项,如版本等。
%package -n openstack-dashboard表示定义一个子包,子包的名称是openstack-dashboard
如果在%package中使用了-n选项,那么在使用%description时也要加上,如: %package -n openstack-dashboard以及它的%description -n openstack-dashboard
如果在%package中使用了-n选项,那么在使用%files时也要加上,如:%package -n openstack-dashboard以及它的%files -n openstack-dashboard -f dashboard.lang

%prep段:

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

%prep段(example):

%prep
%autosetup -n horizon-%{upstream_version} -S git
# drop config snippet
cp -p %{SOURCE4} .

# customize default settings
# WAS [PATCH] disable debug, move web root
sed -i "/^DEBUG =.*/c\DEBUG = False" openstack_dashboard/local/local_settings.py.example
sed -i "/^WEBROOT =.*/c\WEBROOT = '/dashboard/'" openstack_dashboard/local/local_settings.py.example
sed -i "/^.*ALLOWED_HOSTS =.*/c\ALLOWED_HOSTS = ['horizon.example.com', 'localhost']" openstack_dashboard/local/local_settings.py.example
sed -i "/^.*LOCAL_PATH =.*/c\LOCAL_PATH = '/tmp'" openstack_dashboard/local/local_settings.py.example
sed -i "/^.*POLICY_FILES_PATH =.*/c\POLICY_FILES_PATH = '/etc/openstack-dashboard'" openstack_dashboard/local/local_settings.py.example

sed -i "/^BIN_DIR = .*/c\BIN_DIR = '/usr/bin'" openstack_dashboard/settings.py
sed -i "/^COMPRESS_PARSER = .*/a COMPRESS_OFFLINE = True" openstack_dashboard/settings.py

# set COMPRESS_OFFLINE=True
sed -i 's:COMPRESS_OFFLINE.=.False:COMPRESS_OFFLINE = True:' openstack_dashboard/settings.py

%build段:

  • 本段是建立段,所要执行的命令为生成软件包服务,如make 命令。

%build段(example):

%build
# compile message strings
cd horizon && django-admin compilemessages && cd ..
cd openstack_dashboard && django-admin compilemessages && cd ..
# Dist tarball is missing .mo files so they're not listed in distributed egg metadata.
# Removing egg-info and letting PBR regenerate it was working around that issue
# but PBR cannot regenerate complete SOURCES.txt so some other files wont't get installed.
# Further reading why not remove upstream egg metadata:
# https://github.com/emonty/python-oslo-messaging/commit/f632684eb2d582253601e8da7ffdb8e55396e924
# https://fedorahosted.org/fpc/ticket/488
echo >> horizon.egg-info/SOURCES.txt
ls */locale/*/LC_MESSAGES/django*mo >> horizon.egg-info/SOURCES.txt
%{__python} setup.py build

# compress css, js etc.
cp openstack_dashboard/local/local_settings.py.example openstack_dashboard/local/local_settings.py
# get it ready for compressing later in puppet-horizon
%{__python} manage.py collectstatic --noinput --clear
%{__python} manage.py compress --force


# build docs
export PYTHONPATH=.
sphinx-build -b html doc/source html

# undo hack
cp openstack_dashboard/local/local_settings.py.example openstack_dashboard/local/local_settings.py

# Fix hidden-file-or-dir warnings
rm -fr html/.doctrees html/.buildinfo

%install段:

  • 本段是安装段,其中的命令在安装软件包时将执行,如make install命令。

%install段(example):

%install
%{__python} setup.py install -O1 --skip-build --root %{buildroot}

# drop httpd-conf snippet
install -m 0644 -D -p %{SOURCE2} %{buildroot}%{_sysconfdir}/httpd/conf.d/openstack-dashboard.conf
install -d -m 755 %{buildroot}%{_datadir}/openstack-dashboard
install -d -m 755 %{buildroot}%{_sharedstatedir}/openstack-dashboard
install -d -m 755 %{buildroot}%{_sysconfdir}/openstack-dashboard

# create directory for systemd snippet
mkdir -p %{buildroot}%{_unitdir}/httpd.service.d/
cp %{SOURCE3} %{buildroot}%{_unitdir}/httpd.service.d/openstack-dashboard.conf


# Copy everything to /usr/share
mv %{buildroot}%{python_sitelib}/openstack_dashboard \
   %{buildroot}%{_datadir}/openstack-dashboard
cp manage.py %{buildroot}%{_datadir}/openstack-dashboard
rm -rf %{buildroot}%{python_sitelib}/openstack_dashboard

# remove unnecessary .po files
find %{buildroot} -name django.po -exec rm '{}' \;
find %{buildroot} -name djangojs.po -exec rm '{}' \;

# Move config to /etc, symlink it back to /usr/share
mv %{buildroot}%{_datadir}/openstack-dashboard/openstack_dashboard/local/local_settings.py.example %{buildroot}%{_sysconfdir}/openstack-dashboard/local_settings
ln -s ../../../../..%{_sysconfdir}/openstack-dashboard/local_settings %{buildroot}%{_datadir}/openstack-dashboard/openstack_dashboard/local/local_settings.py

mv %{buildroot}%{_datadir}/openstack-dashboard/openstack_dashboard/conf/*.json %{buildroot}%{_sysconfdir}/openstack-dashboard
mv %{buildroot}%{_datadir}/openstack-dashboard/openstack_dashboard/conf/cinder_policy.d %{buildroot}%{_sysconfdir}/openstack-dashboard
mv %{buildroot}%{_datadir}/openstack-dashboard/openstack_dashboard/conf/nova_policy.d %{buildroot}%{_sysconfdir}/openstack-dashboard

%find_lang django --all-name

grep "\/usr\/share\/openstack-dashboard" django.lang > dashboard.lang
grep "\/site-packages\/horizon" django.lang > horizon.lang

# copy static files to %{_datadir}/openstack-dashboard/static
mkdir -p %{buildroot}%{_datadir}/openstack-dashboard/static
cp -a openstack_dashboard/static/* %{buildroot}%{_datadir}/openstack-dashboard/static
cp -a horizon/static/* %{buildroot}%{_datadir}/openstack-dashboard/static
cp -a static/* %{buildroot}%{_datadir}/openstack-dashboard/static

# create /var/run/openstack-dashboard/ and own it
mkdir -p %{buildroot}%{_sharedstatedir}/openstack-dashboard

# create /var/log/horizon and own it
mkdir -p %{buildroot}%{_var}/log/horizon

# place logrotate config:
mkdir -p %{buildroot}%{_sysconfdir}/logrotate.d
cp -a %{SOURCE5} %{buildroot}%{_sysconfdir}/logrotate.d/openstack-dashboard

需要特别注意的是:%install部分使用的是绝对路径,而%files使用的则是相对路径,虽然描述的是同一个地方,但是路径的书写格式千万不要出错
%files -n openstack-dashboard -f dashboard.lang中的-f dashboard.lang分析: 生成一个名为dashboard.lang的文件,内容是所有的dashboard.mo-f参数是将其后边接的文件合并到%files的文件列表。
开始把软件安装到虚拟的根目录中,本段是安装段,其中的命令在安装软件包时将执行,如: make install命令、cp、mv、install、ln。

%check段:

  • rpm软件包的测试。

%check段(example):

%check
%{__python2} manage.py test horizon --settings=horizon.test.settings

%post段:

  • rpm软件包安装之后执行的脚本。

%post段(example):

%post -n openstack-dashboard
# ugly hack to set a unique SECRET_KEY
sed -i "/^from horizon.utils import secret_key$/d" /etc/openstack-dashboard/local_settings
sed -i "/^SECRET_KEY.*$/{N;s/^.*$/SECRET_KEY='`openssl rand -hex 10`'/}" /etc/openstack-dashboard/local_settings
# reload systemd unit files
systemctl daemon-reload >/dev/null 2>&1 || :

%postun段:

  • rpm软件包卸载之后执行的脚本。

%postun段(example):

%postun
# update systemd unit files
%{systemd_postun}

课外知识: rpm还提供了一种信号机制:不同的操作会返回不同的信息,并放到默认变量$1中。
引用
0代表卸载,1代表安装,2代表升级

%doc段:

  • 表示这是文档文件,因此如果安装时使用--excludedocs将不会安装此类文件。

%doc段(example):

%doc README.rst openstack-dashboard-httpd-logging.conf

%dir段:

  • 表示将dir目录路径下的内容打进rpm软件包里。

%dir段(example):

%dir %{_datadir}/openstack-dashboard/

%config(noreplace):

  • 该配置文件不会覆盖已经存在文件(RPM包中文件会以.rpmnew存在于系统,卸载时系统中的该配置文件会以.rpmsave保存下来,如果没有这个选项,安装时RPM包中文件会以.rpmorig存在于系统)覆盖已经存在文件(没被修改),创建新的文件加上扩展后缀.rpmnew(被修改)。

%config(noreplace):

%config(noreplace) %{_sysconfdir}/httpd/conf.d/openstack-dashboard.conf
...

%attr(mode, user, group) filename

  • 控制文件权限

%attr(mode, user, group) filename(example):

%dir %attr(0750, root, apache) %{_sysconfdir}/openstack-dashboard
%dir %attr(0750, root, apache) %{_sysconfdir}/openstack-dashboard/cinder_policy.d/
%dir %attr(0750, apache, apache) %{_sharedstatedir}/openstack-dashboard
%dir %attr(0750, apache, apache) %{_var}/log/horizon

%changelog段:

  • 本段是修改日志段。你可以将软件的每次修改记录到这里,保存到发布的软件包中,以便查询之用。每一个修改日志都有这样一种格式:第一行是:* 星期 月 日 年 修改人 电子信箱。其中:星期、月份均用英文形式的前3个字母,用中文会报错。接下来的行写的是修改了什么地方,可写多行。一般以减号开始,便于后续的查阅。

%changelog段(example):

%changelog

宏定义字段

%{_sysconfdir} /etc
%{_prefix} /usr
...
  • 所有的宏定义都可以在/usr/lib/rpm/macros中进行查看。

JackDan Thinking

展开阅读全文

没有更多推荐了,返回首页