免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12345下一页
最近访问板块 发新帖
查看: 116228 | 回复: 41
打印 上一主题 下一主题

Linux平台软件管理系统设计与规划-进阶篇(2)-rpm生成:rpmbuild 和 spec文件剖析 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2012-12-16 18:19 |只看该作者 |倒序浏览
本帖最后由 duanjigang 于 2012-12-22 22:47 编辑

转载请保留作者信息和来自CU的原站
在第一篇文章中,我们介绍了 rpm 文件的基本概念,协议格式等基础知识。最近几周一直在断断续续的谋划第二篇的内容,终于定下来:以 RPM 文件的制作为使用情景,
主要介绍 rpm 生成工具 rpmbuild 和 rpm 定义文件 spec 文件。

其中 rpmbuild 部分针对rpmbuild 的使用方法,如何使用该命令来制作rpm文件,step by step.
另外,大多数内容以 spec 文件的语法为主,只有彻底掌握spec 中的各种玄机,才能对 rpm 的生成掌握牢固。
废话不多,让我们开始!

论坛徽章:
0
2 [报告]
发表于 2012-12-16 18:22 |只看该作者
本帖最后由 duanjigang 于 2012-12-16 18:31 编辑

在演讲PPT<<2012系统架构师大会-Linux平台软件管理系统设计与规划.pptx>>有这样一幅图,是说明 rpm 是如何产生的。:wink:


从图中我们可以看到,rpm 的制作过程跟美食的制作工艺很相仿,我们的源代码其实就是要熬粥的大米,豆子等原料。另外,食谱会告诉你,大米放多少,水放多少,豆子放多少,rpm制作中的 spec 文件也是类似功能,记录了如何制作rpm,用什么制作rpm等,然后,原料和食谱准备好了,还需要工具,熬粥的砂锅~~~,要烹制 rpm 这道菜,也需要工具,那就是rpmbuild工具(当然其它生成rpm文件的命令也可以)。

砂锅按照食谱上的规范把大米和豆子加工成美味的粥。
rpmbuild按照spec文件中的规范把源码加工成功能强大的rpm包。

论坛徽章:
0
3 [报告]
发表于 2012-12-16 18:37 |只看该作者
本帖最后由 duanjigang 于 2012-12-17 09:37 编辑

从 wget 的 rpm 制作开始

借鉴了 IBM 开发社区的文章,我们的话题也从一个例子 rpm 的制作展开。这个例子软件是wget,版本时1.14。
对于大多数从事开发的同学来说,安装 wget 的方法很可能是直接下载源码,解压缩,configure,make,make install 就OK了。
我们在这里会介绍如果用源码包制作标准的二进制 rpm 和 源码 rpm.

首先,看看系统提供的rpm制作环境是什么样的,大多数从事系统管理的同学都知道,linux 系统自带的rpm 生成环境在 /usr/src/redhat 目录下,
包含的目录以及作用是:

  1. BUILD:  rpmbuild 命令在这个目录进行代码编译
  2. RPMS: rpmbuild 命令会把最终生成的 rpm 文件存储在这个目录。
  3. SOURCES: 制作 rpm 的源码都应该放在这个目录中。
  4. SPECS:制作rpm时用到的spec 文件应该放在这个目录。
  5. SRPMS: rpmbuild 生成的 源码rpm包会存储在这个目录下。
复制代码
几个月前用openssl的srpm做的rpm就是这样流程,先 rpm 安装 openssl 的源码包,openssl 和众多patch文件都被安装到

  1. /usr/src/redhat/SOURCES/
复制代码
目录下了,对应的spec文件也被安装到

  1. /usr/src/redhat/SPECS
复制代码
目录下了。
我们要做的就是一条命令

  1. rpmbuild -ba /usr/src/redhat/SPECS/openssl.spec
复制代码
即可完成 rpm 的制作,生成的 rpm 存储路径是:

  1. /usr/src/redhat/RPMS/i386/openssl-0.9.8b-8.3.i386.rpm
复制代码
本文要说的,是在自定义目录下通过非root用户来制作rpm,而不是使用root帐号,在系统默认工作目录下制作rpm,为什么建议不要用root用户来编译生成rpm,在后面的内容中会涉及到,在此先不说了。

论坛徽章:
0
4 [报告]
发表于 2012-12-16 19:04 |只看该作者
本帖最后由 duanjigang 于 2012-12-17 10:26 编辑

wget 源码包制作rpm

首先下载wget 的源码包wget-1.14.tar.gz,然后在个人目录下建立 RPM 的工作目录:

  1. /home/jigang.djg/lessons/rpmbuild_dir
复制代码
然后建立对应的几个目录:

  1. $mkdir BUILD  RPMS  SOURCES  SPECS  SRPMS
  2. $ls /home/jigang.djg/lessons/rpmbuild_dir
  3. BUILD  RPMS  SOURCES  SPECS  SRPMS
复制代码
把源码挪到 SOURCES目录下.
然后编写 wget.spec 文件。

参考
http://www.ibm.com/developerworks/library/l-rpm1/
这里的例子,编写的 spec 文件内容如下:

SPECS/wget.spec

  1. # This is a sample spec file for wget
  2. %define _topdir   /home/jigang.djg/lessons/rpmbuild_dir
  3. %define name  wget
  4. %define release  1
  5. %define version  1.14
  6. %define buildroot %{_topdir}/%{name}-%{version}-root

  7. BuildRoot:  %{buildroot}
  8. Summary:   GNU wget
  9. License:   GPL
  10. Name:    %{name}
  11. Version:   %{version}
  12. Release:   %{release}
  13. Source:   %{name}-%{version}.tar.gz
  14. Prefix:   /usr
  15. Group:    Development/Tools

  16. %description
  17. The GNU wget program downloads files from the Internet using the command-line.

  18. %prep
  19. %setup -q

  20. %build
  21. ./configure
  22. make

  23. %install
  24. make install prefix=$RPM_BUILD_ROOT/usr

  25. %files
  26. %defattr(-,root,root)
  27. #这也是wget默认的安装目录
  28. /usr/bin/wget
  29. #文档的安装路径也要根据wget的默认路径写,否则可能出错,如果你不自己写 --prefix=xx的话
  30. #如果有报错的话,就根据wget-1.14-root里面的列表进行spec文件校准

  31. %doc %attr(0444,root,root) /usr/share/man/man1/wget.1.gz
复制代码
然后进行rpm的编译:

  1. rpmbuild -v -bb SPECS/wget.spec
复制代码
并没有完美的生成rpm,而是报了一堆错误。

部分信息如下:

  1. error: Installed (but unpackaged) file(s) found:
  2.    /usr/etc/wgetrc
  3.    /usr/share/info/wget.info.gz
  4.    /usr/share/locale/be/LC_MESSAGES/wget.mo
  5.    /usr/share/locale/bg/LC_MESSAGES/wget.mo
复制代码
根据提示,分析下出错的原因。

因为在用 wget 的源码编译安装时 make install 会把很多文件(wget-1.14-root下面的所有文件)都安装到目标目录,而我们在 $install 段写的脚本也正好是是 make install(或者你可以逐行的写 install 安装单个文件)。但是在%file 段却没有把所有 make install 到 wget-1.14-root 下的文件都写出来,因此 rpmbuild 在封装包时会报错,他提示我们: “找到了install 却没有 packaged 的文件”,这个提示是正确的。

解决这个问题有以下三个方法:

其一:  也是最简单的做法,就是把 “installed but unpackaged” 的文件补充到spec 文件的 files 列表当中去。
其二: 从常理思考,虽然build出了一大堆文件,但是只把一部分封装到rpm文件中,这个做法应该是可以接受的,因为某些时候,我们就只需要一部分重要的文件,别的man文件或许暂时不需要。然后该怎么做呢?人性化的配置是好的软件不和缺少的,rpm 当然自带了这个参数的配置项。

在文件:
/usr/lib/rpm/macros
中有一个配置项:

  1. # Should unpackaged files in a build root terminate a build?
  2. #
  3. # Note: The default value should be 0 for legacy compatibility.
  4. %_unpackaged_files_terminate_build 1
复制代码
从字面意思应该能看懂,“是否应该在build root 目录发现未封装进包的文件时终止编译?”
系统默认这个值为 1,因此我们的编译会被终止。

然后将它改为0,再次 build,发现还是报错?
原因又何在呢?

查看帮助手册

  1. man rpmbuild
复制代码
能够看到 rpmbuild 使用的宏定义文件的路径:

  1. /usr/lib/rpm/macros
  2.        /usr/lib/rpm/redhat/macros
  3.        /etc/rpm/macros
  4.        ~/.rpmmacros
复制代码
而且生效顺序是从上往下的,这时可以理解,我们在  /usr/lib/rpm/macros 文件中把
%_unpackaged_files_terminate_build 1
改为 %_unpackaged_files_terminate_build 0
后,在 /usr/lib/rpm/redhat/macros 文件中它还是 1,因为这个值被覆盖了。
为了能够生效,可以把这个配置写到

  1. ~/.rpmmacros
复制代码
或者

  1. /etc/rpm/macros
复制代码
文件中,在此,我们写进 /etc/rpm/macros 文件中。

  1. echo "%_unpackaged_files_terminate_build 0" >> /etc/rpm/macros
复制代码
再次编译,果然通过,输出了 rpm 文件

  1. Wrote: /home/jigang.djg/lessons/rpmbuild_dir/RPMS/i386/wget-1.14-1.i386.rpm
  2. Wrote: /home/jigang.djg/lessons/rpmbuild_dir/RPMS/i386/wget-debuginfo-1.14-1.i386.rpm
复制代码
然后我们看下rpm的信息:

  1. rpm -qpl RPMS/i386/wget-1.14-1.i386.rpm
  2. /usr/bin/wget
  3. /usr/share/man/man1/wget.1.gz
复制代码
能够看到,不纳入到 %files 中的文件确实是 installed but unpackaged 了,呵呵.

其三:就是把不想封装进包的文件从build输出的目录删掉。
http://blog.163.com/hui_san/blog/static/5710286720125272350508/

这里有个例子,如是说:

  1. make install后删除这些文件:

  2. rm -rf %{buildroot}
  3. make INSTALL_ROOT=%{buildroot} install

  4. rm -rf %{buildroot}/.channels/.alias/pear.txt %{buildroot}/.channels/.alias/pecl.txt %{buildroot}/.channels/__uri.reg %{buildroot}/.channels/pear.php.net.reg %{buildroot}/.channels/pecl.php.net.reg %{buildroot}/.depdb %{buildroot}/.depdblock %{buildroot}/.filemap %{buildroot}/.lock
复制代码
可以借鉴上面的做法。

不过个人还是不建议这样做,最合适的做法就是把缺少的文件补充进去。
把 installed but unpackaged 的文件添加进spec 后,spec 文件如下:

  1. # This is a sample spec file for wget

  2. %define _topdir   /home/jigang.djg/lessons/rpmbuild_dir
  3. %define name  wget
  4. %define release  1
  5. %define version  1.14
  6. %define buildroot %{_topdir}/%{name}-%{version}-root

  7. BuildRoot:  %{buildroot}
  8. Summary:   GNU wget
  9. License:   GPL
  10. Name:    %{name}
  11. Version:   %{version}
  12. Release:   %{release}
  13. Source:   %{name}-%{version}.tar.gz
  14. Prefix:   /usr
  15. Group:    Development/Tools

  16. %description
  17. The GNU wget program downloads files from the Internet using the command-line.

  18. %prep
  19. %setup -q

  20. %build
  21. ./configure  --with-ssl=openssl
  22. make

  23. %install
  24. make install prefix=$RPM_BUILD_ROOT/usr

  25. %files
  26. %defattr(-,root,root)
  27. /usr/bin/wget
  28. /usr/etc/wgetrc
  29. /usr/share/info/wget.info.gz
  30. /usr/share/locale/be/LC_MESSAGES/wget.mo
  31. /usr/share/locale/bg/LC_MESSAGES/wget.mo
  32. /usr/share/locale/ca/LC_MESSAGES/wget.mo
  33. /usr/share/locale/cs/LC_MESSAGES/wget.mo
  34. /usr/share/locale/da/LC_MESSAGES/wget.mo
  35. /usr/share/locale/de/LC_MESSAGES/wget.mo
  36. /usr/share/locale/el/LC_MESSAGES/wget.mo
  37. /usr/share/locale/en_GB/LC_MESSAGES/wget.mo
  38. /usr/share/locale/eo/LC_MESSAGES/wget.mo
  39. /usr/share/locale/es/LC_MESSAGES/wget.mo
  40. /usr/share/locale/et/LC_MESSAGES/wget.mo
  41. /usr/share/locale/eu/LC_MESSAGES/wget.mo
  42. /usr/share/locale/fi/LC_MESSAGES/wget.mo
  43. /usr/share/locale/fr/LC_MESSAGES/wget.mo
  44. /usr/share/locale/ga/LC_MESSAGES/wget.mo
  45. /usr/share/locale/gl/LC_MESSAGES/wget.mo
  46. /usr/share/locale/he/LC_MESSAGES/wget.mo
  47. /usr/share/locale/hr/LC_MESSAGES/wget.mo
  48. /usr/share/locale/hu/LC_MESSAGES/wget.mo
  49. /usr/share/locale/id/LC_MESSAGES/wget.mo
  50. /usr/share/locale/it/LC_MESSAGES/wget.mo
  51. /usr/share/locale/ja/LC_MESSAGES/wget.mo
  52. /usr/share/locale/lt/LC_MESSAGES/wget.mo
  53. /usr/share/locale/nb/LC_MESSAGES/wget.mo
  54. /usr/share/locale/nl/LC_MESSAGES/wget.mo
  55. /usr/share/locale/pl/LC_MESSAGES/wget.mo
  56. /usr/share/locale/pt/LC_MESSAGES/wget.mo
  57. /usr/share/locale/pt_BR/LC_MESSAGES/wget.mo
  58. /usr/share/locale/ro/LC_MESSAGES/wget.mo
  59. /usr/share/locale/ru/LC_MESSAGES/wget.mo
  60. /usr/share/locale/sk/LC_MESSAGES/wget.mo
  61. /usr/share/locale/sl/LC_MESSAGES/wget.mo
  62. /usr/share/locale/sr/LC_MESSAGES/wget.mo
  63. /usr/share/locale/sv/LC_MESSAGES/wget.mo
  64. /usr/share/locale/tr/LC_MESSAGES/wget.mo
  65. /usr/share/locale/uk/LC_MESSAGES/wget.mo
  66. /usr/share/locale/vi/LC_MESSAGES/wget.mo
  67. /usr/share/locale/zh_CN/LC_MESSAGES/wget.mo
  68. /usr/share/locale/zh_TW/LC_MESSAGES/wget.mo

  69. %doc %attr(0444,root,root) /usr/share/man/man1/wget.1.gz

复制代码
然后我们还是把%_unpackaged_files_terminate_build 改为1

重新rpmbuild,这次终于成功了。

  1. rpm -qpl RPMS/i386/wget-1.14-1.i386.rpm
复制代码
也能看到新添加进去的filelist.

至此,简单的RPM总算制作成功了,看下包的信息:

  1. rpm -qpi RPMS/i386/wget-1.14-1.i386.rpm
  2. Name        : wget                         Relocations: /usr
  3. Version     : 1.14                              Vendor: (none)
  4. Release     : 1                             Build Date: 2012年12月15日 星期六 14时32分31秒
  5. Install Date: (not installed)               Build Host: localhost.localdomain
  6. Group       : Development/Tools             Source RPM: wget-1.14-1.src.rpm
  7. Size        : 2032997                          License: GPL
  8. Signature   : (none)
  9. Summary     : 一个使用 HTTP 或 FTP 协议来检索文件的工具。
  10. Description :
  11. GNU Wget 是一个文件检索工具,它既可以使用在
  12. HTTP 协议上,也可以使用在 FTP 协议上。Wget
  13. 的功能包括:当您注消后在背景内运行的能力,
  14. 递归地目录检索,文件名通配符匹配,远程文件
  15. 时间戳贮存和比较,与 FTP 服务器一起使用 Rest
  16. 和与 HTTP 服务器一起使用 Range 来在缓慢和不
  17. 可靠的连接上检索文件,对代理服务器的支持,以及可配置性
复制代码

论坛徽章:
49
15-16赛季CBA联赛之福建
日期:2016-06-22 16:22:002015年亚洲杯之中国
日期:2015-01-23 16:25:12丑牛
日期:2015-01-20 09:39:23未羊
日期:2015-01-14 23:55:57巳蛇
日期:2015-01-06 18:21:36双鱼座
日期:2015-01-02 22:04:33午马
日期:2014-11-25 09:58:35辰龙
日期:2014-11-18 10:40:07寅虎
日期:2014-11-13 22:47:15申猴
日期:2014-10-22 15:29:50摩羯座
日期:2014-08-27 10:49:43辰龙
日期:2014-08-21 10:47:58
5 [报告]
发表于 2012-12-17 09:23 |只看该作者
非常不错,感谢原创!

论坛徽章:
0
6 [报告]
发表于 2012-12-17 09:24 |只看该作者
本帖最后由 duanjigang 于 2012-12-17 09:57 编辑

问题讨论:

lofeng410   2012-12-16 22:55
    关于你在“Linux平台软件管理系统设计与规划-进阶篇(2)-rpm生成:rpmbuild 和 spec文件剖析”的帖子
    请教个spec文件中语句的问题哈:
    我使用的kernel.spec中有这么一句:
    %if  0%{?__debug_package:1},这个语句是什么意思呢?其中的0,?,:1分别起什么作用呢?
    google也没有找到相关说明,还请兄弟指点下哈


@lofeng410
能否把那段对应的spec 文件贴出来?

论坛徽章:
8
CU大牛徽章
日期:2013-09-18 15:20:48CU大牛徽章
日期:2013-09-18 15:20:58CU大牛徽章
日期:2013-09-18 15:21:06CU大牛徽章
日期:2013-09-18 15:21:12CU大牛徽章
日期:2013-09-18 15:21:17天秤座
日期:2013-10-30 14:01:03摩羯座
日期:2013-11-29 18:02:31luobin
日期:2016-06-17 17:46:36
7 [报告]
发表于 2012-12-17 09:49 |只看该作者
@duanjigang
强力支持段总。

论坛徽章:
0
8 [报告]
发表于 2012-12-17 11:56 |只看该作者
本帖最后由 duanjigang 于 2012-12-17 12:19 编辑

关于 rpmbuild 的用法可以参考 man 手册,在这里,我们着重对spec文件的语法细节进行说明。
SPEC 文件语法解析

一个spec 文件其实就是一个普通人类可读的文本文件,只不过这个文件由众多个 entry (entries)组成,每个不同的 entry 有不同的用法。构成spec 文件的entry 大致可以分为一下几类:

  1.     Comments — 人类可读的字符串,会被RPM忽略,就是为了注释,备注而生,方便人们理解spec文件。
  2.     Tags — 在spec 中定义数据

  3.     Scripts — 脚本,在rpm生成,安装,升级,卸载等过程的一些时间点执行。

  4.     Macros — 宏定义,主要是控制rpm的执行流程,为了执行不同的命令。

  5.     %files  — 定义 RPM 中将要包含的文件列表。

  6.     Directives — (指令),在%files 中,使得rpm能够针对不同的file进行不同的处理。

  7.     Conditionals — 条件,根据不同的操作系统,处理器架构,进行不同的配置,处理。
复制代码
comments

comments 也就是常说的注释,在 spec 文件中导出都可以写,就为了方便阅读理解。rpm 生成时会过滤注释。
比如我们在 openssl.spec 中看到的注释:

  1. # Install a makefile for generating keys and self-signed certs, and a script
  2. # for generating them on the fly.
  3. mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/pki/tls/certs
  4. install -m644 %{SOURCE2} $RPM_BUILD_ROOT%{_sysconfdir}/pki/tls/certs/Makefile
  5. install -m755 %{SOURCE6} $RPM_BUILD_ROOT%{_sysconfdir}/pki/tls/certs/make-dummy-cert
复制代码

论坛徽章:
0
9 [报告]
发表于 2012-12-17 12:19 |只看该作者
本帖最后由 duanjigang 于 2012-12-17 12:33 编辑

Tags

Tags 数据或者标签定义。

Tage 一般都被定义在spec 文件的顶端,通过


  1. Tag 名称: Tag取值
复制代码
的方式来定义。Tag 不是大小写敏感的,要注意这点。
我们在Spec中常见的Tag 有:

vendor: 产生软件的机构名称

比如:

  1. VeNdOr : White Socks Software, Inc.
  2. vendor:White Socks Software, Inc.
  3. VENDOR    :    White Socks Software, Inc.
复制代码
上面三行对spec 文件来说是一样的。

包命名Tag: Name,Version和Release

比如:

  1. Name: openssl
  2. Version: 0.9.8e
  3. Release: 22%{?dist}.4
复制代码
描述Tags:

%description: 对包进行详细的描述。比如:

  1. %description
  2. The OpenSSL toolkit provides support for secure communications between
  3. machines. OpenSSL includes a certificate management tool and shared
  4. libraries which provide various cryptographic algorithms and
  5. protocols.
复制代码
还有:
summary
copyright
distribution
icon
vendor
url
group
packager
这些tags,都是对包的描述信息,基本上可以通过 rpm 的 -i 参数看到这些信息,比如:

  1. rpm -qpi /usr/src/redhat/RPMS/x86_64/openssl-1.0.0i-1.x86_64.rpm
  2. Name        : openssl                      Relocations: (not relocatable)
  3. Version     : 1.0.0i                            Vendor: (none)
  4. Release     : 1                             Build Date: Sat 21 Apr 2012 01:32:28 PM CST
  5. Install Date: (not installed)               Build Host:test.localhost.mysite.com
  6. Group       : System Environment/Libraries   Source RPM: openssl-1.0.0i-1.src.rpm
  7. Size        : 3294837                          License: GPL
  8. Signature   : (none)
  9. Packager    : Damien Miller <djm@mindrot.org>
  10. URL         : http://www.openssl.org/
  11. Summary     : The OpenSSL toolkit
  12. Description :
  13. The OpenSSL toolkit provides support for secure communications between
  14. machines. OpenSSL includes a certificate management tool and shared
  15. libraries which provide various cryptographic algorithms and
  16. protocols.
复制代码

论坛徽章:
0
10 [报告]
发表于 2012-12-17 14:19 |只看该作者
本帖最后由 duanjigang 于 2012-12-17 20:20 编辑

Dependency (依赖性)TAGS:


我们都知道,一个软件不可能把所有功能都实现了,调用或者借助别的软件来实现自身功能是很常见的一种做法,比如,开发网络相关程序的同学会经常需要安装libpcap,做规则处理或者高速匹配应用的程序可能需要pcre库,做 mysql 数据库开发的需要libmysql或者 libmysql++,通讯程序的用libevent,ICE等等。

  总之,在不同的应用范畴内,我们几乎都需要借助别的软件来实现自己软件要达到的功能。

对于 rpm 也存在这样的情况:安装B软件,它需要A软件的功能支持,因此,在安装B之前,需要把A安装成功;卸载C软件时,D软件还用到C软件的功能,因此不能直接卸载C,或者需要卸载掉D之后,再卸载C,或者为了D的正常运转,C就不能卸载掉。这是最常见的依赖。

因此,RPM 的 SPEC 语法中提供了 Dependency(依赖性)  这个TAG,当然,SPEC 中的依赖性 TAG 设计的比较灵活,可以说是一个比较普适的Dependency 语法。这些会在介绍中看到。

为了详细说明 Dependency ,我们设计了两个例子包,一个叫 test-baby-1.1,另外一个叫 test-daday-1.1

首先看 provides:
provides: 主要是说明本包提供了什么,这里的provides 的取值可以是任何字符串,代表了一个虚拟的包,这个tag的最常用场景就是多个包提供了相同的功能,为了标识他们提供的相同功能可用,着多个包之间就可以provides 出来一个同名的虚拟 package,一旦任何一个包被安装了,只要虚拟的package可用,则依赖于这个功能的软件包就能够安装了。

看下三个包的spec 文件中的 Requires 和 Provides tag是怎么写的:

daddy.spec

  1. #daddy.spec
  2. Requires:                 baby-is-provided
复制代码
baby.spec

  1. Provides:                 baby-is-provided
复制代码
girl.spec

  1. Provides:                 baby-is-provided
复制代码
然后编译生成三个rpm包。

  1. RPMS/x86_64/test-baby-1.1-1.x86_64.rpm
  2. RPMS/x86_64/test-daddy-1.1-1.x86_64.rpm
  3. RPMS/x86_64/test-girl-1.1-1.x86_64.rpm
复制代码
看下 test-daddy 的Require 和 test-girl 和 test-baby 的 Provides

  1. rpm -qp RPMS/x86_64/test-daddy-1.1-1.x86_64.rpm --requires
  2. /bin/sh  
  3. baby-is-provided  
  4. libc.so.6()(64bit)  
  5. libc.so.6(GLIBC_2.2.5)(64bit)  
  6. rpmlib(CompressedFileNames) <= 3.0.4-1
  7. rpmlib(PayloadFilesHavePrefix) <= 4.0-1
  8. rtld(GNU_HASH)  

  9. rpm -qp RPMS/x86_64/test-baby-1.1-1.x86_64.rpm --provides
  10. baby-is-provided  
  11. test-baby = 1.1-1

  12. rpm -qp RPMS/x86_64/test-girl-1.1-1.x86_64.rpm --provides
  13. baby-is-provided  
  14. test-girl = 1.1-1
复制代码
能够看到,test-girl 和 test-baby 都提供了 test-daddy 需要的 requires.
直接安装 test-daddy 看下:

  1. rpm -ivh RPMS/x86_64/test-daddy-1.1-1.x86_64.rpm
  2. error: Failed dependencies:
  3.         baby-is-provided is needed by test-daddy-1.1-1.x86_64
复制代码
提示: "baby-is-provided" 未被提供。

我们尝试安装 test-girl 或者 test-baby,然后再安装test-daddy

  1. sudo rpm -i RPMS/x86_64/test-baby-1.1-1.x86_64.rpm
  2. $ sudo rpm -i RPMS/x86_64/test-daddy-1.1-1.x86_64.rpm
  3. rpm -qa test-daddy
  4. test-daddy-1.1-1
复制代码
这次确实能成功安装了。

  1. sudo rpm -e test-baby
  2. error: Failed dependencies:
  3.         baby-is-provided is needed by (installed) test-daddy-1.1-1.x86_64
复制代码
也能够看到 test-baby 通过的 “baby-is-provided” 被 test-daddy 使用着,不能卸载。
然后:

  1. sudo rpm -i RPMS/x86_64/test-girl-1.1-1.x86_64.rpm
  2. $ sudo rpm -e test-baby
复制代码
这次,test-baby 能够卸载了,因为新安装的 test-girl 也提供了虚拟包 "baby-is-provided" 供 test-daddy 依赖。
到此,相信已经对 Provides 理解透彻了吧。


其次是 requires  tag:
provides 提供了虚拟包或者实体的包,requires 表明自己需要哪些包为前提,只有requires 的包安装了,才能安装当前包
使用 requires 注意版本的书写,如果你的应用明确需要某个版本的第三方包的话,可以写上版本,如果没有特殊版本需要,建议还是不要写,因为很可能当你的程序从rhel4升级到rhle5或者rhel6时,require 的包版本也升级了,如果写 :

  1. requires pkgname = 1.23
复制代码
这样的,很可能在5u 或者 6u的 机器上就需要重现改写spec文件生成rpm了。
requires 支持包的版本运算符有5个。

  1. requires: pkgname  = 1.2-2
  2. requires: pkgname  > 1.2
  3. requires: pkgname  >= 1.2
  4. requires: pkgname  < 1.2
  5. requires: pkgname  <= 1.2-5
复制代码
没有不等于运算符。


另外还有 conflicts

conflicts  与requires 相反, Requires 说明 “我必须与这个包一起安装在这台机器上”,而 conflicts  则表明:“我不能与这个(版本的)包共处一台机器上”。
我们稍微修改下 test-baby 的spec 文件:

  1. rpm -qp RPMS/x86_64/test-girl-1.1-1.x86_64.rpm --provides
  2. baby-is-provided  
  3. test-girl = 1.1-1
  4. $ rpm -qa test-girl
  5. test-girl-1.1-1
  6. $ rpm -ivh RPMS/x86_64/test-baby-1.1-1.x86_64.rpm
  7. error: Failed dependencies:
  8.         baby-is-provided conflicts with test-baby-1.1-1.x86_64
复制代码
能够看到, test-girl provides 了 “baby-is-provided”,而 test-baby conflicts with "baby-is-provided"
因此,当 test-girl 安装后, test-baby 的安装就会失败。


还有一个比较恶心的tag是 serial ,这个tag 专门是为了当版本比较不能够标明包的新旧时,用serial 的值来标识。
serial  大的rpm 就是新包,从根本上不建议使用这个tag。当你用到这个tag区分版本时,说明你的rpm 已经管理的比较乱了。呵呵。

最后一个是不太用却比较重要的 Tag:autoreqprov

autoreqprov  是用来自动产生 rpm 依赖的,它的取值为 yes 或者no, 1 或者 0,
当autoreqprov tag 打开时,在 rpm 包编译的时候,会执行以下操作:

  1. (1):所有打包进rpm 的二进制程序需要的共享库都会被分析出来,然后打包进rpm 的  requirements 中。
  2. (2):所有该rpm 提供的 so 文件的名字都会被自动添加到该RPM的 provides 中。
复制代码
以 test-baby 为例,没有配置 autoreqprov 时 autoreq 默认 为 1,看下它的Requires

  1. $ rpm -qp RPMS/x86_64/test-baby-1.1-1.x86_64.rpm --requires
  2. /bin/sh  
  3. libc.so.6()(64bit)  
  4. libc.so.6(GLIBC_2.2.5)(64bit)  
  5. rpmlib(CompressedFileNames) <= 3.0.4-1
  6. rpmlib(PayloadFilesHavePrefix) <= 4.0-1
  7. rtld(GNU_HASH)  
复制代码
加上: autoreq: 0
后,再看:

  1. rpm -qp RPMS/x86_64/test-baby-1.1-1.x86_64.rpm --requires
  2. /bin/sh  
  3. rpmlib(PayloadFilesHavePrefix) <= 4.0-1
  4. rpmlib(CompressedFileNames) <= 3.0.4-1
复制代码
很明显可以看到,对于 libc 的共享库的自动添加 requires 被取消了。provides 的自动添加,大家可以自己测试。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP