忘记密码   免费注册 查看新帖 | 论坛精华区

ChinaUnix.net

  平台 论坛 博客 认证专区 大话IT 视频 徽章 文库 沙龙 自测 下载 频道自动化运维 虚拟化 储存备份 C/C++ PHP MySQL 嵌入式 Linux系统
12345下一页
最近访问板块 发新帖
查看: 19893 | 回复: 41

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

论坛徽章:
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
发表于 2012-12-16 18:22 |显示全部楼层
本帖最后由 duanjigang 于 2012-12-16 18:31 编辑

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

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

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

论坛徽章:
0
发表于 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
发表于 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:43ChinaUnix元老
日期:2015-01-30 15:14:07
发表于 2012-12-17 09:23 |显示全部楼层
非常不错,感谢原创!

论坛徽章:
0
发表于 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
发表于 2012-12-17 09:49 |显示全部楼层
@duanjigang
强力支持段总。

论坛徽章:
0
发表于 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
发表于 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
发表于 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 的自动添加,大家可以自己测试。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

【有奖调查】AI时代如何迎接未知挑战?

人工智能一直在医疗行业扮演着重要角色,最早的专家系统和后来的基因诊断都是人工智能技术在医疗的行业探索。近年来,随着深度学习等技术的进步,人工智能在医疗行业的应用领域不断扩展,医学影像智能诊断、语音电子病历、癌症智能诊断等均已逐渐成为热门发展方向。
而作为人工智能重要推动力的深度学习技术的快速发展却亟需认知系统的强力支撑。
----------------------------------------
活动时间:2017年5月15日-6月5日

调查入口>>
  

北京皓辰网域网络信息技术有限公司. 版权所有 京ICP证:060528号 北京市公安局海淀分局网监中心备案编号:1101082001
广播电视节目制作经营许可证(京) 字第1234号 中国互联网协会会员  联系我们:
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP