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

柔光的暖阳◎ 2022-05-16 11:07 537阅读 0赞

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

rpm本地打包的回顾

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

spec文件

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

文件头:

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

Name:

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

Name(example):

  1. Name: python-django-horizon

Epoch:

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

Epoch(example):

  1. Epoch: 1

Version:

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

Version(example):

  1. Version: 4.0.2

Release:

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

Relase(example):

  1. Release: 4.0.2

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

Summary:

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

Summary(example):

  1. Summary: Django application for talking to Openstack

Group:

  • 软件包所属类别,具体类别有:
  1. * `Amusements/Games` (娱乐/游戏)
  2. * `Amusements/Graphics`(娱乐/图形)
  3. * `Applications/Archiving` (应用/文档)
  4. * `Applications/Communications`(应用/通讯)
  5. * `Applications/Databases` (应用/数据库)
  6. * `Applications/Editors` (应用/编辑器)
  7. * `Applications/Emulators` (应用/仿真器)
  8. * `Applications/Engineering` (应用/工程)
  9. * `Applications/File` (应用/文件)
  10. * `Applications/Internet` (应用/因特网)
  11. * `Applications/Multimedia`(应用/多媒体)
  12. * `Applications/Productivity` (应用/产品)
  13. * `Applications/Publishing`(应用/印刷)
  14. * `Applications/System`(应用/系统)
  15. * `Applications/Text` (应用/文本)
  16. * `Development/Debuggers` (开发/调试器)
  17. * `Development/Languages` (开发/语言)
  18. * `Development/Libraries` (开发/函数库)
  19. * `Development/System` (开发/系统)
  20. * `Development/Tools` (开发/工具)
  21. * `Documentation` (文档)
  22. * `System Environment/Base`(系统环境/基础)
  23. * `System Environment/Daemons` (系统环境/守护)
  24. * `System Environment/Kernel` (系统环境/内核)
  25. * `System Environment/Libraries` (系统环境/函数库)
  26. * `System Environment/Shells` (系统环境/接口)
  27. * `User Interface/Desktops`(用户界面/桌面)
  28. * `User Interface/X` (用户界面/X窗口)
  29. * `User Interface/X Hardware Support` (用户界面/X硬件支持)

Group(example):

  1. Group: Development/Libraries

License:

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

License(example)

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

URL:

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

URL(example):

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

Source:

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

Source(example):

  1. Source0: https://tarballs.openstack.org/horizon/horizon-%{upstream_version}.tar.gz
  2. Source2: openstack-dashboard-httpd-2.4.conf
  3. Source3: python-django-horizon-systemd.conf
  4. # demo config for separate logging
  5. Source4: openstack-dashboard-httpd-logging.conf
  6. # logrotate config
  7. Source5: python-django-horizon-logrotate.conf

BuildArch:

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

BuildArch(example):

  1. BuildArch: noarch

BuildRequires:

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

BuildRequires(example):

  1. BuildRequires: python-setuptools
  2. BuildRequires: python-pbr >= 2.0.0
  3. BuildRequires: git
  4. BuildRequires: python-six >= 1.10.0
  5. BuildRequires: gettext

Requires:

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

Requires(example):

  1. Requires: python-django
  2. Requires: pytz
  3. Requires: python-six >= 1.10.0
  4. Requires: python-pbr

Provides:

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

Provides(example):

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

Obsoletes:

  • 过时的,废弃的软件包

Obsoletes(example):

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

%description:

  • rpm软件包的详细说明。

%description(example):

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

%package:

  • 定义一个子包

%package(example):

  1. %package -n openstack-dashboard
  2. Summary: Openstack web user interface reference implementation
  3. Group: Applications/System
  4. Requires: httpd
  5. %description doc
  6. Documentation for the Django Horizon application for talking with Openstack

%files段:

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

%files段(example):

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

注意: 当需要去定义一个子包时,必须至少包含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):

  1. %prep
  2. %autosetup -n horizon-%{upstream_version} -S git
  3. # drop config snippet
  4. cp -p %{SOURCE4} .
  5. # customize default settings
  6. # WAS [PATCH] disable debug, move web root
  7. sed -i "/^DEBUG =.*/c\DEBUG = False" openstack_dashboard/local/local_settings.py.example
  8. sed -i "/^WEBROOT =.*/c\WEBROOT = '/dashboard/'" openstack_dashboard/local/local_settings.py.example
  9. sed -i "/^.*ALLOWED_HOSTS =.*/c\ALLOWED_HOSTS = ['horizon.example.com', 'localhost']" openstack_dashboard/local/local_settings.py.example
  10. sed -i "/^.*LOCAL_PATH =.*/c\LOCAL_PATH = '/tmp'" openstack_dashboard/local/local_settings.py.example
  11. sed -i "/^.*POLICY_FILES_PATH =.*/c\POLICY_FILES_PATH = '/etc/openstack-dashboard'" openstack_dashboard/local/local_settings.py.example
  12. sed -i "/^BIN_DIR = .*/c\BIN_DIR = '/usr/bin'" openstack_dashboard/settings.py
  13. sed -i "/^COMPRESS_PARSER = .*/a COMPRESS_OFFLINE = True" openstack_dashboard/settings.py
  14. # set COMPRESS_OFFLINE=True
  15. sed -i 's:COMPRESS_OFFLINE.=.False:COMPRESS_OFFLINE = True:' openstack_dashboard/settings.py

%build段:

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

%build段(example):

  1. %build
  2. # compile message strings
  3. cd horizon && django-admin compilemessages && cd ..
  4. cd openstack_dashboard && django-admin compilemessages && cd ..
  5. # Dist tarball is missing .mo files so they're not listed in distributed egg metadata.
  6. # Removing egg-info and letting PBR regenerate it was working around that issue
  7. # but PBR cannot regenerate complete SOURCES.txt so some other files wont't get installed.
  8. # Further reading why not remove upstream egg metadata:
  9. # https://github.com/emonty/python-oslo-messaging/commit/f632684eb2d582253601e8da7ffdb8e55396e924
  10. # https://fedorahosted.org/fpc/ticket/488
  11. echo >> horizon.egg-info/SOURCES.txt
  12. ls */locale/*/LC_MESSAGES/django*mo >> horizon.egg-info/SOURCES.txt
  13. %{__python} setup.py build
  14. # compress css, js etc.
  15. cp openstack_dashboard/local/local_settings.py.example openstack_dashboard/local/local_settings.py
  16. # get it ready for compressing later in puppet-horizon
  17. %{__python} manage.py collectstatic --noinput --clear
  18. %{__python} manage.py compress --force
  19. # build docs
  20. export PYTHONPATH=.
  21. sphinx-build -b html doc/source html
  22. # undo hack
  23. cp openstack_dashboard/local/local_settings.py.example openstack_dashboard/local/local_settings.py
  24. # Fix hidden-file-or-dir warnings
  25. rm -fr html/.doctrees html/.buildinfo

%install段:

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

%install段(example):

  1. %install
  2. %{__python} setup.py install -O1 --skip-build --root %{buildroot}
  3. # drop httpd-conf snippet
  4. install -m 0644 -D -p %{SOURCE2} %{buildroot}%{_sysconfdir}/httpd/conf.d/openstack-dashboard.conf
  5. install -d -m 755 %{buildroot}%{_datadir}/openstack-dashboard
  6. install -d -m 755 %{buildroot}%{_sharedstatedir}/openstack-dashboard
  7. install -d -m 755 %{buildroot}%{_sysconfdir}/openstack-dashboard
  8. # create directory for systemd snippet
  9. mkdir -p %{buildroot}%{_unitdir}/httpd.service.d/
  10. cp %{SOURCE3} %{buildroot}%{_unitdir}/httpd.service.d/openstack-dashboard.conf
  11. # Copy everything to /usr/share
  12. mv %{buildroot}%{python_sitelib}/openstack_dashboard \
  13. %{buildroot}%{_datadir}/openstack-dashboard
  14. cp manage.py %{buildroot}%{_datadir}/openstack-dashboard
  15. rm -rf %{buildroot}%{python_sitelib}/openstack_dashboard
  16. # remove unnecessary .po files
  17. find %{buildroot} -name django.po -exec rm '{}' \;
  18. find %{buildroot} -name djangojs.po -exec rm '{}' \;
  19. # Move config to /etc, symlink it back to /usr/share
  20. mv %{buildroot}%{_datadir}/openstack-dashboard/openstack_dashboard/local/local_settings.py.example %{buildroot}%{_sysconfdir}/openstack-dashboard/local_settings
  21. ln -s ../../../../..%{_sysconfdir}/openstack-dashboard/local_settings %{buildroot}%{_datadir}/openstack-dashboard/openstack_dashboard/local/local_settings.py
  22. mv %{buildroot}%{_datadir}/openstack-dashboard/openstack_dashboard/conf/*.json %{buildroot}%{_sysconfdir}/openstack-dashboard
  23. mv %{buildroot}%{_datadir}/openstack-dashboard/openstack_dashboard/conf/cinder_policy.d %{buildroot}%{_sysconfdir}/openstack-dashboard
  24. mv %{buildroot}%{_datadir}/openstack-dashboard/openstack_dashboard/conf/nova_policy.d %{buildroot}%{_sysconfdir}/openstack-dashboard
  25. %find_lang django --all-name
  26. grep "\/usr\/share\/openstack-dashboard" django.lang > dashboard.lang
  27. grep "\/site-packages\/horizon" django.lang > horizon.lang
  28. # copy static files to %{_datadir}/openstack-dashboard/static
  29. mkdir -p %{buildroot}%{_datadir}/openstack-dashboard/static
  30. cp -a openstack_dashboard/static/* %{buildroot}%{_datadir}/openstack-dashboard/static
  31. cp -a horizon/static/* %{buildroot}%{_datadir}/openstack-dashboard/static
  32. cp -a static/* %{buildroot}%{_datadir}/openstack-dashboard/static
  33. # create /var/run/openstack-dashboard/ and own it
  34. mkdir -p %{buildroot}%{_sharedstatedir}/openstack-dashboard
  35. # create /var/log/horizon and own it
  36. mkdir -p %{buildroot}%{_var}/log/horizon
  37. # place logrotate config:
  38. mkdir -p %{buildroot}%{_sysconfdir}/logrotate.d
  39. 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):

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

%post段:

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

%post段(example):

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

%postun段:

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

%postun段(example):

  1. %postun
  2. # update systemd unit files
  3. %{systemd_postun}

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

%doc段:

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

%doc段(example):

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

%dir段:

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

%dir段(example):

  1. %dir %{_datadir}/openstack-dashboard/

%config(noreplace):

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

%config(noreplace):

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

%attr(mode, user, group) filename

  • 控制文件权限

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

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

%changelog段:

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

%changelog段(example):

  1. %changelog

宏定义字段

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

JackDan Thinking

发表评论

表情:
评论列表 (有 0 条评论,537人围观)

还没有评论,来说两句吧...

相关阅读