rpm包如何构建

1. RPM(RedHat Packager Manager) Basics

1.1 rpm和srpm

rpm即软件包的一种管理方式,类似于安装包,使用它可以将相应的软件安装到系统上,包含的软件必须是经过编译的。

格式为:unzip-6.0-20.el7.centos.es.x86_64.rpm(n: unzip, v:6.0, r: 20.el7.centos.es,a:x86_64)

安装时会将软件信息写入到RPM数据库(/var/lib/rpm),便于查询。

rpm -ivh /tmp/unzip-6.0-41.el8.es.src.rpm   // 安装并可查看安装信息及进度
rpm -qa   // 查看安装的所有软件
rpm -qi unzip // 查看某个安装的软件详细信息

优点编译打包完成,无需自己手动编译,安装方便

缺点1安装的环境需要与打包时的环境需求一直或相当

srpm的存在可以使得包重新编译,srpm即为Source RPM,内容没有经过编译,提供原始代码,格式为: unzip-6.0-20.el7.src.rpm,因为我们安装需要环境一致等条件,我们不得不重新编译我们的rpm包

1.2 srpm解压后的文件内容

查看下文件解压后的内容:

# 使用此命令解压到指定文件夹
rpm -i --define '_topdir /root/build/unzip'  \
  /opt/unzip-6.0-20.el7.src.rpm  
[root@localhost ~]# tree build/
build/
└── unzip
    ├── SOURCES
    │   ├── unzip-6.0-alt-iconv-utf8.patch
    │   ├── unzip-6.0-alt-iconv-utf8-print.patch
    │   ├── unzip-6.0-attribs-overflow.patch
    │   ├── unzip-6.0-bzip2-configure.patch
    │   ├── unzip-6.0-caseinsensitive.patch
    │   ├── unzip-6.0-close.patch
    │   ├── unzip-6.0-configure.patch
    │   ├── unzip-6.0-cve-2014-8139.patch
    │   ├── unzip-6.0-cve-2014-8140.patch
    │   ├── unzip-6.0-cve-2014-8141.patch
    │   ├── unzip-6.0-cve-2014-9636.patch
    │   ├── unzip-6.0-cve-2018-18384.patchldd
    │   ├── unzip-6.0-exec-shield.patch
    │   ├── unzip-6.0-fix-recmatch.patch
    │   ├── unzip-6.0-format-secure.patch
    │   ├── unzip-6.0-manpageandusage.patch
    │   ├── unzip-6.0-manpage-fix.patch      # 补丁
    │   ├── unzip-6.0-symlink.patch
    │   └── unzip60.tar.gz                   # 源代码
    └── SPECS
        └── unzip.spec                       # 配置文件

大概看下spec文件:

# 软件的基本信息
Summary: A utility for unpacking zip files
Name: unzip
Version: 6.0
Release: 20%{?dist}
License: BSD
Group: Applications/Archiving
Source: http://downloads.sourceforge.net/infozip/unzip60.tar.gz
# Not sent to upstream.
Patch1: unzip-6.0-bzip2-configure.patch
# Upstream plans to do this in zip (hopefully also in unzip).
Patch2: unzip-6.0-exec-shield.patchl

URL: http://www.info-zip.org/UnZip.html
# 制作成rpm包安装时,系统检查依赖的软件包
Requires: python-argparse, python-importlib
# 构建该软件包的依赖
BuildRequires:  bzip2-devel

# build
%build
make -f unix/Makefile CF_NOOPT="-I. -DUNIX $RPM_OPT_FLAGS -DNOMEMCPY -DNO_LCHMOD" LFLAGS2="%{?__global_ldflags}" generic_gcc %{?_smp_mflags}

# install
%install
rm -rf $RPM_BUILD_ROOT
make -f unix/Makefile prefix=$RPM_BUILD_ROOT%{_prefix} MANDIR=$RPM_BUILD_ROOT/%{_mandir}/man1 INSTALL="cp -p" install

# 编译出来的binary rpm包名称及各个binary rpm包含的文件
%files
...
  
# changelog
%changelog
* Mon Feb 25 2019 Jakub Martisko <jamartis@redhat.com> - 6.0-20
- Fix CVE-2018-18384
  Resolves: CVE-2018-18384

* Tue Jan 09 2018 Jakub Martisko <jamartis@redhat.com> - 6.0-19
- rename patch unzip-6.0-nostrip.patch to unzip-6.0-configure.patch
- make linking flags configurable from the specc file
- set linking flags to use relro hardening
  Related: #1531116

1.3 dependencies

我们都知道安装某个软件时有很多依赖关系,我们以unzip为例:

[root@localhost ~]# rpm -qR unzip
/bin/sh
libbz2.so.1()(64bit)
libc.so.6()(64bit)
libc.so.6(GLIBC_2.14)(64bit)
libc.so.6(GLIBC_2.2.5)(64bit)
libc.so.6(GLIBC_2.3)(64bit)
libc.so.6(GLIBC_2.3.4)(64bit)
libc.so.6(GLIBC_2.4)(64bit)
rpmlib(CompressedFileNames) <= 3.0.4-1
rpmlib(FileDigests) <= 4.6.0-1
rpmlib(PartialHardlinkSets) <= 4.0.4-1
rpmlib(PayloadFilesHavePrefix) <= 4.0-1
rpmlib(PayloadIsXz) <= 5.2-1
rtld(GNU_HASH)

1.4 rpm build实例

我们通过指令将srpm包编译成rpm包

rpmbuild -ba unzip.spec   // 编译产生rpm和srpm文件
rpmbuild -bb unzip.spec   // 编译仅产生rpm文件
rpmbuild -bs unzip.spec   // 编译仅产生srpm文件

我们来执行ba操作

[root@localhost SPECS]# rpmbuild -ba --define '_topdir /root/build/unzip/' ./unzip.spec
错误:构建依赖失败:
	bzip2-devel 被 unzip-6.0-20.el8.x86_64 需要

这里我们需要首先安装bzip2-devel

yum install bzip2-devel -y   # 还要安装 make, gcc等

最后就会生成了一下文件:

[root@localhost unzip]# tree RPMS/ SRPMS/
RPMS/
└── x86_64
    ├── unzip-6.0-20.el8.x86_64.rpm
    ├── unzip-debuginfo-6.0-20.el8.x86_64.rpm
    └── unzip-debugsource-6.0-20.el8.x86_64.rpm
SRPMS/
└── unzip-6.0-20.el8.src.rpm

缺点2构建依赖需要先安装依赖的包

1.5 yum

这里我们指出来,构建rpm包需要安装依赖,安装软件包时也需要安装依赖,yum可以解决安装软件包时的依赖问题,那么构建rpm包需要安装依赖的依赖问题我们总不能人工去解决吧,这里我们就推出来mock

2. MOCK

主要用于实现chroot 环境下,编译RPM 的工作,编译过程中会自动在chroot环境去安装依赖的软件包

2.1 如何使用

需要使用srpm为前提:

mock -r ./centos-8-x86_64.cfg --rebuild ~/build/unzip/SRPMS/unzip-6.0-20.el8.src.rpm

或者

mock -r ./centos-8-x86_64.cfg --init
mock -r ./centos-8-x86_64.cfg --rebuild ~/build/unzip/SRPMS/unzip-6.0-20.el8.src.rpm
mock -r ./centos-8-x86_64.cfg --clean

看下cfg文件:

# meta包
onfig_opts['chroot_setup_cmd'] = 'install tar gcc-c++ redhat-rpm-config redhat-release which xz sed make bzip2 gzip gcc coreutils unzip shadow-utils diffutils cpio bash gawk rpm-build info patch util-linux findutils grep' 
...

config_opts['dist'] = 'el8'  # only useful for --resultdir variable subst
config_opts['releasever'] = '8'
config_opts['package_manager'] = 'dnf'
...

# repo
[baseos]
name=CentOS-$releasever - Base
mirrorlist=http://mirrorlist.centos.org/?release=8&arch=$basearch&repo=BaseOS&infra=$infra
failovermethod=priority
gpgkey=file:///usr/share/distribution-gpg-keys/centos/RPM-GPG-KEY-CentOS-Official
gpgcheck=1
skip_if_unavailable=False
[appstream] ...
[powertools] ...
[devel] ...

2.2 mock构建步骤

  • 初始化chroot环境,创建文件夹(/var/lib/mock/centos-8-x86_64/root)
  • 该环境中填充一些文件夹(/etc/, /bin/, /dev/null/)
  • 拷贝srpm到chroot
  • 安装meta包
  • 安装要依赖的包
  • 创建用户
  • build (rpmbuild --rebuild)

2.3 mock caching

  • local repo // cfg文件修改源指向本地

3. KOJI

3.1 koji结构和功能

koji是rpm包的构建和管理系统,且可以制定多台builder构建,koji系统搭建参考:koji

koji的结构图:

  • koji-hub: 这个其实是整个koji架构的中心,负责着整个系统的维护和各个组件之间的数据交换。是一个xml-rpc的server,通过mod_wsgi模块挂载在apache上提供服务。接受client和web到来的请求,然后驱使其他组件完成构建工作,同时将数据存放到数据库中。

    访问 /kojihub会定位到/koji-hub/kojixmlrpc.py文件来解析,只接收POST 请求

  • kojid:部署在要完成构建工作的相应机器上,可以部署到多个机器。主要负责从Koji-hub请求到任务进行处理,一般来讲就是构建任务

  • koji-web:主要提供给使用浏览器的一些接口,然后从上游(hub)获取数据传给浏览器,浏览器访问http://mirror.easystack.cn/koji/xxx,根据apache的kojiweb.conf配置,就会访问到web组件的代码文件wsgi_publisher.py

  • koji(client):命令行的客户端,输入指令与hub交互,执行一些指令(添加用户,提交build请求等等)

  • kojira: 主要负责和仓库建立,仓库更新等相关事宜。这里仓库不是指数据库,是指rpm repo。应该是只有一个实例在运行。

  • Postgresql DB: 数据库,只有hub和他建立连接,并存取一些关系的数据,比如说账号信息,构建信息,repo的信息等等

3.2 koji的一些概念

  • package:包,单纯是指nvr中的n,比如说unzip-6.0-20.el7.centos.es.x86_64.rpm中package是指unzip
  • build:我们所说的koji build是指构建这个动作,同时我们也会说产生nvr包也称为build,产生nvr的后果就是这个build包名字在koji系统中只能存在一个,不能重名
  • tag:build-tag和destination-tag,tag可以继承。build-tag
  • target:(build target),关联一个build-tag及destination-tag,当我们build的时候只需要制定target就可以以build-tag来打包,用destination-tag来管理包

3.3 koji build

3.3.1 build的流程

前置条件

  • 创建tag

    $ koji add-tag dist-foo
    $ koji add-tag --parent dist-foo --arches \
        "x86_64" dist-foo-build
    
  • 添加构建仓库

    $ koji add-external-repo -t \ 
         dist-foo-build base-external-repo \ 
         https://mirrors.aliyun.com/centos/8/BaseOS/\$arch/os/
    $ koji add-external-repo -t \ 
         dist-foo-build appstream-external-repo \
         https://mirrors.aliyun.com/centos/8/AppStream/\$arch/os/
    $ koji add-external-repo -t \
         dist-foo-build epel-external-repo \
         https://mirrors.aliyun.com/epel/8/Everything/\$arch/
    
  • 加入构建组

    $ koji add-group dist-foo-build build
    $ koji add-group dist-foo-build srpm-build
    
  • 添加meta包,我这里是从mock配置文件拷贝,最终这些包会从刚刚添加的仓库安装到chroot环境中

    $ koji add-group-pkg dist-foo-build build \
         tar gcc-c++ redhat-rpm-config redhat-release \
         which xz sed make bzip2 gzip gcc coreutils unzip \
         shadow-utils diffutils cpio bash gawk rpm-build \
         info patch util-linux findutils grep
    
    $ koji add-group-pkg dist-foo-build srpm-build \
         tar gcc-c++ redhat-rpm-config redhat-release \
         which xz sed make bzip2 gzip gcc coreutils unzip \
         shadow-utils diffutils cpio bash gawk rpm-build \
         info patch util-linux findutils grep
    
  • 添加build target

    # koji add-target <name> <build tag> <dest tag>
    koji add-target dist-foo dist-foo-build  dist-foo
    
  • 添加相应的pkg到指定tag,表示可以在该tag下编译这个pkg

    $ koji add-pkg --owner kojiadmin dist-foo unzip
    

build

  • build包,前边属于搭建仓库及构建等条件,每次编译包时只需要执行build指令即可

    # 这里的dist-foo是build target, 使用build-tag的编译条件(包含仓库等),输出的包被打上destination-tag来管理
    koji build dist-foo /opt/unzip-6.0-20.el7.src.rpm
    
3.3.2 build选项

build可以添加选项:

–skip-tag: 编译过程不加destination-tag,产生NVR,可做临时检查使用,之后决定发布时再tag build(一旦生成NVR,不可以重新编译)

–scratch: 只是编译包,不产生NVR,不会打tag

3.3.3 跟踪一下

以 “koji build dist-foo /opt/unzip-6.0-20.el7.src.rpm” 为开始,详细列出来koji系统的代码及相关结构讲述

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 22
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 22
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值