长期支持版本

    社区创新版本

      构建RPM包

      本章介绍通过本地或OBS构建RPM软件包的方法。详见打包规则

      打包说明

      原理介绍

      RPM打包的时候需要编译源码,需要把编译好的配置文件、二进制命令文件等放到合适的位置,还要根据需要对RPM的包进行测试,这些都需要先有一个“工作空间”。rpmbuild命令使用一套标准化的“工作空间”:

      $ rpmdev-setuptree
      

      rpmdev-setuptree这个命令就是安装 rpmdevtools 带来的。可以看到运行了这个命令之后,在"/root"目录(非root用户为"/home/用户名"目录)下多了一个 rpmbuild 的文件夹,目录结构如下:

      $ tree rpmbuild
      rpmbuild
      ├── BUILD
      ├── RPMS
      ├── SOURCES
      ├── SPECS
      └── SRPMS
      

      内容相关的说明如下:

      目录

      宏代码

      名称

      功能

      ~/rpmbuild/BUILD

      %_builddir

      构建目录

      源码包被解压至此,并在该目录的子目录完成编译

      ~/rpmbuild/RPMS

      %_rpmdir

      标准 RPM 包目录

      生成/保存二进制 RPM 包

      ~/rpmbuild/SOURCES

      %_sourcedir

      源代码目录

      保存源码包(如 .tar 包)和所有 patch 补丁

      ~/rpmbuild/SPECS

      %_specdir

      Spec 文件目录

      保存 RPM 包配置(.spec)文件

      ~/rpmbuild/SRPMS

      %_srcrpmdir

      源代码 RPM 包目录

      生成/保存源码 RPM 包(SRPM)

      SPECS 下是RPM包的配置文件,是RPM打包的“图纸”,这个文件会告诉rpmbuild命令如何去打包。“宏代码”这一列就可以在SPEC文件中用来代指所对应的目录,类似于编程语言中的宏或全局变量。

      打包流程

      打包的过程主要分为如下步骤:

      1. 把源代码放到%_sourcedir中。
      2. 进行编译,编译的过程是在%_builddir中完成的,一般情况下,源代码是压缩包格式,需要先进行解压。
      3. 进行“安装”,类似于预先组装软件包,把软件包应该包含的内容(比如二进制文件、配置文件、man文档等)复制到%_buildrootdir中,并按照实际安装后的目录结构组装,比如二进制命令可能会放在/usr/bin下,那么就在%_buildrootdir下也按照同样的目录结构放置。
      4. 做一些必要的配置,比如在实际安装前的准备,安装后的清理等等。这些都是通过配置在SPEC文件中来告诉rpmbuild命令。
      5. 检查软件是否正常运行。
      6. 生成的RPM包放置到%_rpmdir,源码包放置到%_srcrpmdir下。

      在SPEC文件中,各个阶段说明如下:

      阶段

      读取的目录

      写入的目录

      具体动作

      %prep

      %_sourcedir

      %_builddir

      读取位于 %_sourcedir 目录的源代码和 patch 。之后,解压源代码至 %_builddir 的子目录并应用所有 patch

      %build

      %_builddir

      %_builddir

      编译位于 %_builddir 构建目录下的文件。通过执行类似 ./configure && make 的命令实现。

      %install

      %_builddir

      %_buildrootdir

      读取位于 %_builddir 构建目录下的文件并将其安装至 %_buildrootdir 目录。这些文件就是用户安装 RPM 后,最终得到的文件。

      %check

      %_builddir

      %_builddir

      检查软件是否正常运行。通过执行类似 make test 的命令实现。

      bin

      %_buildrootdir

      %_rpmdir

      读取位于 %_buildrootdir 最终安装目录下的文件,以便最终在 %_rpmdir 目录下创建 RPM 包。在该目录下,不同架构的 RPM 包会分别保存至不同子目录, noarch 目录保存适用于所有架构的 RPM 包。这些 RPM 文件就是用户最终安装的 RPM 包。

      src

      %_sourcedir

      %_srcrpmdir

      创建源码 RPM 包(简称 SRPM,以.src.rpm 作为后缀名),并保存至 %_srcrpmdir 目录。SRPM 包通常用于审核和升级软件包。

      打包选项

      通过rpmbuild命令构建软件包。rpmbuild构建软件包一般可以通过构建SPEC文件、tar文件、source文件实现。

      rpmbuild命令格式为:rpmbuild [option...]

      常用的rpmbuild打包选项如表1所示。

      表 1 rpmbuild打包选项

      option取值

      说明

      -bp specfile

      只执行specfile的%prep段(解开源码包并打补丁)。

      -bc specfile

      执行specfile的%prep和%build段(准备并编译)。

      -bi specfile

      执行specfile的%prep,%build与%install段(准备,编译并安装)。

      -bl specfile

      检查specfile的%file段(检验文件是否齐全)。

      -ba specfile

      通过specfile文件构建源码包和二进制包。

      -bb specfile

      通过specfile文件构建二进制包

      -bs specfile

      通过specfile文件构建源码包。

      -rp sourcefile

      sourcefile文件的%prep段开始构建(解开源码包并打补丁)。

      -rc sourcefile

      sourcefile文件的%build段开始构建。

      -ri sourcefile

      sourcefile文件的%install段开始构建。

      -rl sourcefile

      sourcefile文件的%file段开始检查。

      -ra sourcefile

      通过sourcefile文件构建源码包和二进制包。

      -rb sourcefile

      通过sourcefile文件构建二进制包

      -rs sourcefile

      通过sourcefile文件构建源码包。

      -tp tarfile

      tarfile文件的%prep段开始构建(解开源码包并打补丁)。

      -tc tarfile

      tarfile文件的%build段开始构建。

      -ti tarfile

      tarfile文件的%install段开始构建。

      -ta tarfile

      通过tarfile文件构建源码包和二进制包。

      -tb tarfile

      通过tarfile文件构建二进制包

      -ts tarfile

      通过tarfile文件构建源码包。

      --buildroot=DIRECTORY

      在构建时,使用DIRECTORY目录覆盖默认的/root目录。

      --clean

      完成打包后清除BUILD目录下的文件。

      --nobuild

      不执行任何实际的构建步骤。可用于测试spec文件。

      --noclean

      不执行spec文件的"%clean"阶段(即使它确实存在)。

      --nocheck

      不执行spec文件的"%check"阶段(即使它确实存在)。

      --dbpath DIRECTORY

      使用DIRECTORY中的数据库,而不是默认的 /var/lib/rpm。

      --root DIRECTORY

      使DIRECTORY为最高级别的路径,默认“/”为最高路径。

      --rebuild sourcefile

      将安装指定的源代码包sourcefile,然后进行准备、编译、安装。

      --recompile sourcefile

      在--recompile 的基础上额外构建一个新的二进制包。在构建结束时,构建目录、源代码和 spec 文件都将被删除(就好像用了 --clean)。

      -?,--help

      打印详细的帮助信息。

      --version

      打印详细的版本信息。

      本地构建

      本章通过一个简单的示例介绍如何在本地构建RPM软件包的方法。

      搭建开发环境

      前提条件

      需要root权限,已设置openEuler的repo软件源。

      操作步骤

      用户可以直接使用DNF工具安装 rpmdevtools,其中包含 rpm-build 等命令以及相关依赖(例如make、gdb)。使用如下命令:

      # dnf install rpmdevtools*
      

      创建Hello World RPM包

      这里以GNU “Hello World” 项目的打包过程作为示例,包含了典型的FOSS(Free and Open Source Software) 软件项目相关的最常用的外围组件,其中包括配置/编译/安装环境、文档、国际化等等。

      下载源码

      我们直接下载官方例子的源码,使用如下命令:

      $ cd ~/rpmbuild/SOURCES
      $ wget http://ftp.gnu.org/gnu/hello/hello-2.10.tar.gz
      

      编辑SPEC文件

      在~/rpmbuild/SPECS目录下新建spec文件,参考命令如下:

      $ cd ~/rpmbuild/SPECS
      $ vi hello.spec 
      

      在文件中写入对应内容后保存文件。文件内容示例如下,请根据实际情况修改相应字段。

      Name:     hello
      Version:  2.10
      Release:  1%{?dist}
      Summary:  The "Hello World" program from GNU
      Summary(zh_CN):  GNU "Hello World" 程序
      License:  GPLv3+
      URL:      http://ftp.gnu.org/gnu/hello
      Source0:  http://ftp.gnu.org/gnu/hello/%{name}-%{version}.tar.gz
      
      BuildRequires:  gettext
      Requires(post): info
      Requires(preun): info
      
      %description
      The "Hello World" program, done with all bells and whistles of a proper FOSS
      project, including configuration, build, internationalization, help files, etc.
      
      %description -l zh_CN
      "Hello World" 程序, 包含 FOSS 项目所需的所有部分, 包括配置, 构建, 国际化, 帮助文件等.
      
      %prep
      %setup -q
      
      %build
      %configure
      make %{?_smp_mflags}
      
      %install
      make install DESTDIR=%{buildroot}
      %find_lang %{name}
      rm -f %{buildroot}/%{_infodir}/dir
      
      %post
      /sbin/install-info %{_infodir}/%{name}.info %{_infodir}/dir || :
      
      %preun
      if [ $1 = 0 ] ; then
      /sbin/install-info --delete %{_infodir}/%{name}.info %{_infodir}/dir || :
      fi
      
      %files -f %{name}.lang
      %doc AUTHORS ChangeLog NEWS README THANKS TODO
      %license COPYING
      %{_mandir}/man1/hello.1.*
      %{_infodir}/hello.info.*
      %{_bindir}/hello
      
      %changelog
      * Thu Dec 26 2019 Your Name <youremail@xxx.xxx> - 2.10-1
      - Update to 2.10
      * Sat Dec 3 2016 Your Name <youremail@xxx.xxx> - 2.9-1
      - Update to 2.9
      
      • Name 标签是软件名,Version 标签是版本号,而 Release 标签是发布编号。
      • Summary 标签是简要说明,英文的话第一个字母应大写,以避免 rpmlint 工具(打包检查工具)警告。
      • License 标签说明软件包的协议版本,审查软件的 License 状态是打包者的职责,这可以通过检查源码或 LICENSE 文件,或与作者沟通来完成。
      • Group 标签过去用于按照 /usr/share/doc/rpm-/GROUPS 分类软件包。目前该标记已丢弃,vim的模板还有这一条,删掉即可,不过添加该标记也不会有任何影响。%changelog 标签应包含每个 Release 所做的更改日志,尤其应包含上游的安全/漏洞补丁的说明。%changelog 条目应包含版本字符串,以避免 rpmlint 工具警告。
      • 多行的部分,如 %changelog 或 %description 由指令下一行开始,空行结束。
      • 一些不需要的行 (如 BuildRequires 和 Requires) 可在行首使用 ‘#’ 注释。
      • %prep、%build、%install、%file暂时用默认的,未做任何修改。

      构建RPM包

      构建源码、二进制和包含调试信息的软件包,在spec文件所在目录执行如下命令:

      $ rpmbuild -ba hello.spec 
      

      执行成功后,查看结果,使用如下命令:

      $ tree ~/rpmbuild/*RPMS
      
      /home/testUser/rpmbuild/RPMS
      └── aarch64
          ├── hello-2.10-1.aarch64.rpm
          ├── hello-debuginfo-2.10-1.aarch64.rpm
          └── hello-debugsource-2.10-1.aarch64.rpm
      /home/testUser/rpmbuild/SRPMS
      └── hello-2.10-1.src.rpm
      

      使用OBS构建

      本章介绍通过网页和osc构建RPM软件包的方法。主要包括如下两类:

      • 修改已有软件包:修改已有软件包源代码,然后将修改后的源代码构建成一个RPM软件包。
      • 新增软件包:从无到有全新开发一个新的软件源文件,并将新开发的源文件构建成一个RPM软件包。

      OBS简介

      OBS是基于openSUSE发行版的通用编译框架,用于将源码包构建为RPM软件包或Linux镜像。OBS采用自动化的分布式编译方式,支持多种Linux操作系统发行版(openEuler、SUSE、Debian等)镜像和安装包的编译,且支持在多种架构平台(x86、ARM64等)上编译。

      OBS由后端和前端组成,后端实现所有核心功能,前端提供了网页应用和API,用于与后端进行交互。此外,OBS还有一个API命令行客户端osc,osc是在一个单独的存储库中开发的。

      OBS使用工程组织软件包。基础的权限控制、相关的存仓库和构建目标(操作系统和架构)都可以在工程中定义。一个工程可以包含多个子工程,各个子工程可以独立配置,共同完成任务。

      在线构建软件包

      本章介绍通过OBS网页端在线构建RPM软件包的方法。

      构建已有软件包

      说明:

      • 若为首次使用,请首先在OBS网页注册个人账号。
      • 该方法需要拷贝修改后的代码,因此,请在执行下述操作前完成代码修改并提交到正确的代码路径。代码路径会在_service文件中指定。

      使用OBS网页端,修改已有软件的源代码,并将修改后的源文件构建为RPM软件包的操作方法如下:

      1. 登录OBS界面,地址为:https://build.openeuler.org/

      2. 单击“All Projects”进入所有工程页面。

      3. 单击需要修改的对应工程,进入该工程的详情页面,例如单击“openEuler:Mainline”。

      4. 在工程详情页面的搜索框查找需要修改的软件包,然后单击该软件包包名,进入该软件包详情页面。

      5. 单击“Branch package”,在弹出的确认页面单击“Accept”确认创建子工程,如图1所示。

        图 1 Branch Confirmation页面

      6. 单击“_service”文件进入编辑页面,修改_service内容后点击“Save”保存该文件。_service内容示例如下,其中 userCodeURLuserCommitID 分别为用户代码托管路径、用户代码提交版本号或分支。

        <services>
            <service name="tar_scm_kernel">
                <param name="scm">git</param>
                <param name="url">userCodeURL</param>
        	<param name="revision">userCommitID</param>
            </service>
            <service name="recompress">
        	<param name="compression">bz2</param>
        	<param name="file">*.tar</param>
             </service>
        </services>
        

        说明:
        单击“Save”保存_service文件后,OBS服务会根据_service文件描述,从指定的url下载源码到OBS对应工程的软件目录下并替换原有文件,例如上述例子中 “openEuler:Mainline”工程的kernel目录。

      7. 文件拷贝并替换完成后,OBS会自动开始构建RPM软件包。等待构建完成,并查看右侧状态栏的构建状态。

        • succeeded:构建成功。用户可以单击“succeeded”查看构建日志,如图2所示。

          图 2 succeeded的页面

        • failed:构建失败。请单击“failed”查看错误日志进行问题定位后重新构建。

        • unresolvable:未进行构建,可能由于缺失依赖。

        • disabled:构建被手动关闭或正在排队构建。

        • excluded:构建被禁止,可能由于缺少spec文件或者spec文件中禁止了目标架构的编译。

      新增软件包

      使用OBS网页端,新增一个全新软件包的操作方法如下:

      1. 登录OBS界面。

      2. 根据新增软件包的依赖情况,选择合适的工程,即单击“All Projects”选择对应工程,例如“openEuler:Mainline”。

      3. 单击工程下任一软件包,进入该软件包的详情页面。

      4. 单击“Branch package”,在弹出的确认页面单击“Accept”确认创建子工程。

      5. 单击“Delete package”,删除新创建子工程中的软件包,如图3所示。

        图 3 删除子工程中软件包

        说明:
        通过已有软件创建新工程是为了继承环境等依赖,而不需要实际的文件,所以这里需要把这些文件删除。

      6. 单击“Create Package”,在弹出的页面输入软件包名称、标题和软件包描述,然后单击“Create”创建软件包,分别如图4图5所示。

        图 4 Create Package页面

        图 5 创建软件包信息填写页面

      7. 在页面中单击“Add file”上传spec文件和需要编译的文件(在spec文件中指定),如图6所示。

        图 6 Add file页面

      8. 文件上传成功后,OBS会自动开始构建RPM软件包。等待构建完成,并查看右侧状态栏的构建状态。

        • succeeded:构建成功。用户可以单击“succeeded”查看构建日志。
        • failed:构建失败。请单击“failed”查看错误日志进行问题定位后重新构建。
        • unresolvable:未进行构建,可能由于缺失依赖。
        • disabled:构建被手动关闭或正在排队构建。
        • excluded:构建被禁止,可能由于缺少spec文件或者spec文件中禁止了目标架构的编译。

      获取软件包

      RPM软件包构建完成后,通过网页端获取对应RPM软件包的方法如下:

      1. 登录OBS界面。

      2. 单击“All Projects”找到所需软件包的对应工程,例如“openEuler:Mainline”。

      3. 在工程下单击所需软件包的包名,进入该软件包详情页面。例如上述例子中的kernel页面。

      4. 选择Repositories页签进入软件包的软件仓库管理页面,在Publish Flag中通过单击选择“Enable”开启(状态由变为)对应的RPM软件包下载功能,如图7所示。

        图 7 Repositories页面

      5. 单击Repository列的构建工程名称,进入RPM软件包下载页面,单击RPM软件包右侧的“Download”即可下载对应RPM软件包,如图8所示。

        图 8 RPM软件包下载页面

      使用osc构建软件包

      本章介绍使用OBS的命令行工具osc创建工程并构建RPM软件包的方法。

      安装并配置osc

      前提条件

      需要root权限,已设置openEuler的repo软件源。

      操作步骤
      1. 使用root用户安装osc命令行工具及依赖。

        # dnf install osc build
        

        说明:
        编译RPM软件包的过程中会依赖build。

      2. 配置osc。

        1. 打开~/.oscrc,命令如下:

          $ vi ~/.oscrc
          
        2. 在~/.oscrc中添加user和pass字段,如下所示,它们的取值 userNamepassWord 分别是用户在OBS网页(https://build.openeuler.org/)上已经注册的账号和密码。

          [general]
          apiurl = https://build.openeuler.openatom.cn/
          [https://build.openeuler.org/]
          user=userName
          pass=passWord
          

      构建已有软件包

      创建工程

      1. 通过拷贝已有工程,创建属于用户自己的子工程。例如将openEuler:Mainline工程下的zlib软件包到新分支,参考命令如下:

        $ osc branch openEuler:Mainline zlib
        

        回显如下所示,说明在用户testUser下创建了新的分支工程home:testUser:branches:openEuler:Mainline。

        A working copy of the branched package can be checked out with:
        osc co home:testUser:branches:openEuler:Mainline/zlib
        
      2. 将需要修改软件包的相关配置文件(例如_service)下载到本地当前路径。其中 testUser 为~/.oscrc配置文件中配置的账户名称,请根据实际情况修改。

        $ osc co home:testUser:branches:openEuler:Mainline/zlib
        

        回显如下所示:

        A    home:testUser:branches:openEuler:Mainline
        A    home:testUser:branches:openEuler:Mainline/zlib
        A    home:testUser:branches:openEuler:Mainline/zlib/_service
        
      3. 进入本地子工程目录,并将软件包远程代码同步到本地。

        $ cd home:testUser:branches:openEuler:Mainline/zlib
        $ osc up -S
        

        回显如下所示:

        A    _service:tar_scm_kernel_repo:0001-Neon-Optimized-hash-chain-rebase.patch
        A    _service:tar_scm_kernel_repo:0002-Porting-optimized-longest_match.patch
        A    _service:tar_scm_kernel_repo:0003-arm64-specific-build-patch.patch
        A    _service:tar_scm_kernel_repo:zlib-1.2.11-optimized-s390.patch
        A    _service:tar_scm_kernel_repo:zlib-1.2.11.tar.xz
        A    _service:tar_scm_kernel_repo:zlib-1.2.5-minizip-fixuncrypt.patch
        A    _service:tar_scm_kernel_repo:zlib.spec
        

      构建RPM包

      1. 重命名源文件,然后将重命名后的源文件添加到OBS暂存中。

        $ rm -f _service;for file in `ls | grep -v .osc`;do new_file=${file##*:};mv $file $new_file;done
        $ osc addremove *
        
      2. 修改源代码和spec文件,并执行如下命令更新文件。

        $ osc up
        
      3. 将对应软件包的所有修改同步到OBS服务器。参考命令如下,-m参数后的信息为提交记录。

        $ osc ci -m "commit log"
        
      4. 获取当前工程的仓库名称和架构,参考命令如下:

        $ osc repos home:testUser:branches:openEuler:Mainline
        
      5. 修改提交成功后,OBS会自动开始编译软件包。可以通过如下命令,查看对应仓库的编译日志,其中 standard_aarch64aarch64 分别为查询所得仓库名称和架构。

        $ osc buildlog standard_aarch64  aarch64
        

        说明:
        用户也可以通过网页端打开自己创建的对应工程,查看构建日志。

      新增软件包

      使用OBS的osc工具新增一个全新软件包的操作方法如下:

      创建工程

      1. 根据新增软件包的依赖情况,基于合适的工程,创建属于用户自己的个人工程。例如基于 openEuler:Mainline 工程的 zlib 创建工程的参考命令如下,zlib 为工程下的任一软件包。

        $ osc branch openEuler:Mainline zlib
        
      2. 删除创建工程时新增的无用软件包。例如删除zlib软件包的参考命令如下:

        $ cd home:testUser:branches:openEuler:Mainline
        $ osc rm zlib
        $ osc commit -m "commit log"
        
      3. 在个人工程下创建新增的软件包。例如新增软件包 my-first-obs-package命令如下:

        $ mkdir my-first-obs-package 
        $ cd my-first-obs-package
        

      构建RPM包

      1. 添加准备的源文件和spec文件到软件包目录。

      2. 修改源代码和spec文件,并将对应软件包的所有文件上传到OBS服务器。参考命令如下,-m 参数后的信息为提交记录。

        $ cd home:testUser:branches:openEuler:Mainline
        $ osc add my-first-obs-package
        $ osc ci -m "commit log"
        
      3. 获取当前工程的仓库名称和架构,参考命令如下:

        $ osc repos home:testUser:branches:openEuler:Mainline
        
      4. 修改提交成功后,OBS会自动开始编译软件包。可以通过如下命令,查看对应仓库的编译日志,其中 standard_aarch64aarch64 分别为查询所得仓库名称和架构。

        $ cd home:testUser:branches:openEuler:Mainline/my-first-obs-package
        $ osc buildlog standard_aarch64  aarch64
        

        说明:
        用户也可以通过网页端打开自己创建的对应工程,查看构建日志。

      获取软件包

      RPM软件包构建完成后,使用osc获取对应RPM软件包的命令如下:

      $ osc getbinaries home:testUser:branches:openEuler:Mainline my-first-obs-package standard_aarch64 aarch64
      

      命令中的各参数含义如下,请用户根据实际情况修改:

      • home:testUser:branches:openEuler:Mainline :软件包所在工程名称
      • my-first-obs-package :软件包名称
      • standard_aarch64 :仓库名称
      • aarch64 :仓库架构名称

      说明:
      使用osc构建的软件包也可以在网页端获取,获取方式请参见获取软件包

      文档捉虫

      “有虫”文档片段

      问题描述

      提交类型 issue

      有点复杂...

      找人问问吧。

      PR

      小问题,全程线上修改...

      一键搞定!

      问题类型
      规范和低错类

      ● 错别字或拼写错误;标点符号使用错误;

      ● 链接错误、空单元格、格式错误;

      ● 英文中包含中文字符;

      ● 界面和描述不一致,但不影响操作;

      ● 表述不通顺,但不影响理解;

      ● 版本号不匹配:如软件包名称、界面版本号;

      易用性

      ● 关键步骤错误或缺失,无法指导用户完成任务;

      ● 缺少必要的前提条件、注意事项等;

      ● 图形、表格、文字等晦涩难懂;

      ● 逻辑不清晰,该分类、分项、分步骤的没有给出;

      正确性

      ● 技术原理、功能、规格等描述和软件不一致,存在错误;

      ● 原理图、架构图等存在错误;

      ● 命令、命令参数等错误;

      ● 代码片段错误;

      ● 命令无法完成对应功能;

      ● 界面错误,无法指导操作;

      风险提示

      ● 对重要数据或系统存在风险的操作,缺少安全提示;

      内容合规

      ● 违反法律法规,涉及政治、领土主权等敏感词;

      ● 内容侵权;

      您对文档的总体满意度

      非常不满意
      非常满意
      提交
      根据您的反馈,会自动生成issue模板。您只需点击按钮,创建issue即可。
      文档捉虫
      编组 3备份