openSUSE 软件包中的新闻

2020年11月23日 | Vítězslav Čížek 和 Kristýna Streitová | CC-BY-SA-3.0

News in openSUSE Packaging

如果您对 openSUSE 感兴趣,您迟早可能会学习到软件包和 spec 文件的工作原理。但打包不是静态知识,您学一次就万事大吉。规则会随着时间而变化,会创建新的宏,旧的宏会被历史淘汰,会使用新的文件路径,而旧的文件路径会被遗忘。那么,如何才能跟上这些变化呢?

在本文中,我们将用银盘子为您奉上 openSUSE 打包的最新消息和重要变化。无论您是专业的软件包维护者,还是只想了解最新情况的普通打包者,您一定会找到您不知道的东西。我们保证。

目录

openSUSE 宏

%_libexecdir


TL;DR

  • %_libexecdir 宏现在扩展到 /usr/libexec(而不是 /usr/lib

我们将从最近的变化开始,即 %_libexecdir 宏。过去,将不打算由用户或 shell 脚本直接执行的二进制文件存储在 /usr/lib 目录中是一种标准做法。随着 FHS 3.0 的发布,现在 定义 应用程序应将这些内部二进制文件存储在 /usr/libexec 目录中。

在 openSUSE 中,关于将 %_libexecdir 宏从 /usr/lib 更改为 /usr/libexec 的讨论始于 2019 年秋季,但所有受影响的软件包的修复和更改的采用花费了几个月的时间。它于 2020 年 8 月在 TW 0825 中完全 合并

请注意,openSUSE Leap 发行版,包括即将发布的 Leap 15.3,仍然将 %_libexecdir 扩展到旧的 /usr/lib

systemd 宏


TL;DR

  • 使用 %{?systemd_ordering} 代替 %{?systemd_requires}
  • 使用 pkgconfig(libsystemd) 代替 pkgconfig(systemd-devel)
  • BuildRequires: systemd-rpm-macros 不需要

过去,您被告知如果您的软件包使用 systemd,您应该只需将以下行添加到您的 spec 文件中,一切就绪。

BuildRequires: systemd-rpm-macros
%{?systemd_requires}

然而,时代在变化,现代需要采取稍微不同的方法,特别是如果您希望您的软件包包含在容器中。要解释它,我们需要知道 %{?systemd_requires} 宏是什么样子

$ rpm --eval %{?systemd_requires}

Requires(pre): systemd 
Requires(post): systemd 
Requires(preun): systemd 
Requires(postun): systemd 

这会创建对 systemd 的硬依赖。在容器的情况下,这可能适得其反,因为我们不想强制包含 systemd,除非它确实需要。这就是为什么 %{?systemd_ordering} 宏开始被使用的原因

$ rpm --eval %{?systemd_ordering}

OrderWithRequires(post): systemd 
OrderWithRequires(preun): systemd 
OrderWithRequires(postun): systemd 

OrderWithRequires 类似于 Requires 标签,但它不会生成实际的依赖关系。它只是为计算事务顺序提供排序提示,但仅当软件包存在于同一事务中时。对于 systemd 而言,这意味着如果您需要在事务早期安装 systemd(例如,创建安装),这将确保它被提前排序。

除非您需要在 spec 文件中显式调用 systemctl 命令(您可能不需要,因为 %service_* 宏可以处理它),否则您不应该再使用 %{?systemd_requires}

另外请注意,systemd-rpm-macros 已被 rpm 软件包要求一段时间,因此无需显式要求它。您可以安全地省略它,除非您担心 rpm 会在未来删除它,这不太可能。

最后是 BuildRequires,这在您的软件包需要链接到 systemd 库时需要。在这种情况下,您应该使用

BuildRequires: pkgconfig(libsystemd)

而不是旧的

BuildRequires: pkgconfig(systemd-devel)

因为新的变体可以帮助缩短 OBS 中的构建链。

跨发行版宏


TL;DR

  • %leap_version 宏已弃用
  • 请参阅此 表格,了解所有发行版宏及其特定发行版的数值

通常,您希望为多个目标发行版构建您的软件包。但是,如果您想同时支持最新的 Tumbleweed 和 Leap 或 SLE,则需要相应地调整您的 spec 文件。这就是您需要了解发行版版本宏的原因。

最佳信息来源是 openSUSE wiki 上的 表格,它将向您显示每个 SLE/openSUSE 版本的这些发行版宏的值。如果您想了解如何识别特定发行版的示例,请参阅此 表格

Leap 42(SLE-12)和 Leap 15(SLE-15)之间最大的变化是 %leap_version 宏已弃用。如果您想解决例如 openSUSE Leap 15.2,您应该使用

%if 0%{?sle_version} == 150200 && 0%{?is_opensuse}

如您所见,要区分特定的 Leap 次要版本,使用 %sle_version 宏。

如果您想识别 SLE-15-SP2,只需否定 %is_opensuse

%if 0%{?sle_version} == 150200 && !0%{?is_opensuse}

当前的 Tumbleweed 发行版(显然在不断变化)可以通过以下方式识别

%if 0%{?suse_version} > 1500

通常,如果您想显示系统上的这些宏的值,可以使用 rpm --eval

$ rpm --eval %suse_version 
1550

已弃用的宏


TL;DR

这些宏已弃用

  • %install_info / %install_info_delete
  • %desktop_database_post / %desktop_database_postun
  • %icon_theme_cache_post / %icon_theme_cache_postun
  • %glib2_gsettings_schema
  • %make_jobs(现在称为 %cmake_build%make_build

如果您对打包感兴趣一段时间,您可能已经学习了很多宏。坏消息是,其中一些不应该再使用了。在本节中,我们将介绍最常见的宏。

数据库/缓存更新宏

最大的弃用宏组可能是那些调用更新数据库和缓存的命令,当特定目录中出现新文件时

  • %install_info / %install_info_delete
    • 更新 info/dir 条目
  • %desktop_database_post / %desktop_database_postun
    • 当在 /usr/share/applications 中添加/删除 .desktop 文件时更新桌面数据库缓存
  • %icon_theme_cache_post / %icon_theme_cache_postun
    • 当将图标添加到 /usr/share/icons 时更新图标缓存
  • %glib2_gsettings_schema
    • 编译安装到 /usr/share/glib-2.0/schemas 的模式

例如,过去,每当您在软件包中安装新的 .desktop 文件时,您应该调用

%post
%desktop_database_post

%postun
%desktop_database_postun

自 2017 年以来,这些宏开始被 文件触发器 替代,这是 RPM 4.13 的一项新功能。有关更多信息,请参阅 文件触发器 部分。

%make_jobs

%make_jobs 宏最初用于 cmake 打包,但后来被许多其他软件包采用,令人困惑的是,有时定义略有不同。由于这个原因,以及为了使宏更符合其他宏,例如 meson,%make_jobs 已被 %cmake_build 替换为使用 cmake,并用 %make_build 替换为所有其他用法。

在过去,您调用:%cmake%make_jobs%cmake_install.

现在它更连贯,您调用:%cmake%cmake_build%cmake_install 使用 cmake,只需将 %make_jobs 替换为 %make_build 在其他情况下。

为了完整起见,我们补充说命名也与 meson 和 automake 宏相符,即

%meson%meson_build%meson_install

或者

%configure%make_build%make_install

%make_jobs 宏仍然由 KDE Framework kf5-filesystem 软件包提供,并且被大约 250 个 Factory 软件包使用,但其使用正在逐步淘汰。

路径和标签

/etc 和 /usr/etc 中的配置文件


TL;DR

  • /usr/etc 将成为提供发行版配置文件的新的目录
  • /etc 目录将包含由管理员更改的配置文件

从历史上看,配置文件始终安装在 /etc 目录中。然后,如果您编辑此配置文件并更新软件包,您最终会得到 .rpmsave.rpmnew 额外的文件,您必须手动解决。

由于这种次优情况,主要是因为需要满足 事务更新(原子更新)的新要求,配置文件处理方式必须更改。

新解决方案是将发行版提供的配置(/usr/etc),该配置不可修改,与管理员更改的特定于主机的配置(/etc)分开。

这项改动需要大量的工作。首先,应用程序本身需要调整,以便从多个位置读取配置,而不仅仅是传统的 /etc,当然,还需要进行大量的打包变更。在打包方面,有 3 种变体 的实现方式,您作为打包人员应该选择最适合您的软件包的一种。

此外,还有一个新的 RPM 宏,它引用了 /usr/etc 位置

%_distconfdir  /usr/etc

Group: tag


TL;DR

  • Group: 标签现在是可选的

也许您注意到了一场关于移除 Group: 标签的激烈讨论,这场讨论在 2019 年秋季冲击了 opensuse-factory 邮件列表。它激起了强烈的情绪,以至于 openSUSE 委员会不得不介入并帮助解决这场冲突。

他们决定将组包含在 spec 文件中应该由维护者自行决定,是可选的。

RPM 中的新闻

RPM 小版本更新大约每两年发布一次,并且总是会带来许多有趣的新闻,这将使打包更加容易。有时,将这些更改付诸实践会有点困难,因为这可能需要大量的工作或数百个软件包,或者处理向后兼容性问题。因此,在使用您的软件包中的新功能之前,您应该在 openSUSE 中找到更多关于它们当前采用状态的信息。

当前 SUSE 和 openSUSE 的 rpm 包的状态如下

发行版 RPM 版本
openSUSE:Factory 4.15.1
SLE-15 / openSUSE:Leap:15.* 4.14.1
SLE-12 4.11.2

以下段落介绍了一些最近的 RPM 版本中引入的最有趣的功能。

文件触发器


TL;DR

  • 文件触发器是一个脚本,每当软件包安装/卸载特定位置的文件时都会执行
  • 例如,在 Factory 中用于 texinfoglib schemasmimeiconsdesktop 文件,因此您的软件包不再需要调用数据库/缓存更新宏。
  • 目前(2020 年 11 月),zypper 无法正确处理 transfiletrigger

RPM 4.13 引入了文件触发器,即 RPM 脚本,每当软件包安装或卸载特定位置的文件时都会执行(如果安装/卸载带有触发器的软件包时也会执行)。

这个概念的主要优点是,单个软件包引入一个文件触发器,然后它会自动应用于所有新安装/重新安装的软件包。因此,与其每个软件包都携带用于某些后处理的宏,不如将代码放在实现文件触发器的软件包中,并在所有地方透明地运行。

触发器类型是

  • filetrigger{in, un, postun}
  • transfiletrigger{in, un, postun}

根据变体,*in/*un/*postun 脚本的执行方式与常规 rpm 脚本类似,在软件包安装/卸载/卸载后执行,具体取决于变体。

trans* 变体在每次事务后执行一次,在处理与触发器匹配的文件后,所有软件包都会执行一次。

示例 (Factory shared-mime-info)

%filetriggerin -- %{_datadir}/mime                                                                                                                                              
export PKGSYSTEM_ENABLE_FSYNC=0
%{_bindir}/update-mime-database "%{_datadir}/mime"

此文件触发器将在安装包含 /usr/share/mime 下文件的软件包后立即更新 mime 数据库。文件触发器将为每个软件包执行一次(无论软件包中匹配的文件数量多少)。

文件触发器可以轻松替换数据库/缓存更新宏(例如 %icon_theme_cache_post)。这种方法自 2017 年以来一直 在 Factory 中使用。文件触发器用于处理图标、mime 和桌面文件、glib 模式等。

您可能根本没有注意到这种变化,因为通常在您的 specfile 中拥有这些数据库/缓存更新宏现在不会造成任何危害。更改已在相应的软件包(texinfoshared-mime-infodesktop-file-utilsglib2)中通过添加文件触发器完成,而所有这些旧宏现在都扩展为没有操作的命令。因此,您可以安全地从您的 specfile 中删除它们。

! 重要提示 ! 目前(2020 年 11 月),zypper 无法正确处理 transfiletrigger。如果事务中存在 %transfiletrigger%post 脚本,那么 zypper 只会调用脚本,而不会调用您的 %transfiletrigger。有关更多信息,请参阅 Bug#1041742

%autopatch 和 %autosetup


TL;DR

  • 使用 %autopatch 自动应用 spec 文件中的所有补丁
  • 使用 %autosetup 自动运行 %setup%autopatch

应用补丁的旧方法和经典方法是

Patch1:     	openssl-1.1.0-no-html.patch
Patch2:     	openssl-truststore.patch
Patch3:     	openssl-pkgconfig.patch

%prep
%setup -q
%patch1 -p1
%patch2 -p1
%patch3 -p1

有了最近的 RPM,您可以使用 %autosetup%autopatch 宏来自动执行源解包和补丁应用。无需按名称指定每个补丁。

%autopatch 应用 spec 中的所有补丁。缺点是它不能本机用于条件补丁或具有不同模糊级别的补丁。

示例 (Factory openssl-1_1.spec)

Patch1:     	openssl-1.1.0-no-html.patch
Patch2:     	openssl-truststore.patch
Patch3:     	openssl-pkgconfig.patch

%prep
%setup -q
%autopatch -p1 

-p 选项控制传递给 patch 程序的补丁级别。

功能最强大的宏是 %autosetup 宏,它结合了 %setup%autopatch,以便它可以解包 tarball 并应用补丁集到一个命令中。

%autosetup 接受与 %setup 几乎相同的参数,但

  • -v 用于详细的源解包,默认是静默模式,因此 -q 不适用
  • -N 禁用自动补丁应用。补丁稍后可以使用 %patch 或使用 %autopatch 手动应用。在需要在上游源上进行某种预处理才能应用补丁的情况下,它会派上用场。
  • -S 指定在构建目录中使用的 VCS。支持的包括例如 githgquilt。默认值为 patch,其中补丁只是使用 patch 在目录中应用。设置 git 将在构建目录中创建一个 git 存储库,每个补丁都表示为一个 git 提交,这对于例如双向查找补丁很有用

因此,使用 %autosetup 应用补丁的最简单方法如下。

示例 (Factory openssl-1_1)

Patch1:     	openssl-1.1.0-no-html.patch
Patch2:     	openssl-truststore.patch
Patch3:     	openssl-pkgconfig.patch

%prep
%autosetup -p1

%patchlist 和 %sourcelist


TL;DR

  • 使用 %patchlist 部分指令标记一个纯补丁列表
  • 使用 %sourcelist 部分指令标记一个纯源列表
  • 然后使用 %autosetup 代替 %setup 和 %patch<number>

这些是用于声明补丁和源的新的 spec 文件部分,具有最少的样板代码。它们旨在与 %autopatch%autosetup 结合使用。

示例 - 正常方式 (Factory openssl-1_1)

Source:     	https://www.%{_rname}.org/source/%{_rname}-%{version}.tar.gz
Source2:    	baselibs.conf
Source3:    	https://www.%{_rname}.org/source/%{_rname}-%{version}.tar.gz.asc
Source4:    	%{_rname}.keyring
Source5:    	showciphers.c

Patch1:     	openssl-1.1.0-no-html.patch
Patch2:     	openssl-truststore.patch
Patch3:     	openssl-pkgconfig.patch

%prep
%autosetup -p1

文件需要用数字标记,因此在系列中间添加补丁需要重新编号所有连续的标签。

示例 - 使用 %sourcelist/%patchlist

%sourcelist
https://www.%{_rname}.org/source/%{_rname}-%{version}.tar.gz
baselibs.conf
https://www.%{_rname}.org/source/%{_rname}-%{version}.tar.gz.asc
%{_rname}.keyring
showciphers.c

%patchlist
openssl-1.1.0-no-html.patch
openssl-truststore.patch
openssl-pkgconfig.patch

%prep
%autosetup -p1

这里源文件不需要任何标记。然后,补丁按部分中列出的顺序由 %autopatch 应用。缺点是无法通过 %{SOURCE} 宏引用源,也无法有条件地应用补丁。

%elif


TL;DR

  • RPM 现在支持 %elif%elifos%elifarch

经过 22 年的开发,RPM 4.15 终于实现了 %elif。现在可以简化仅使用另一个 %if%else 对才能实现的条件。

示例 仅使用 %if%else (Java:packages/ant)

%if %{with junit}                                                                                                                                                               	 
%description 
This package contains optional JUnit tasks for Apache Ant.

%else
  %if %{with junit5}

%description
This package contains optional JUnit5 tasks for Apache Ant.

  %else

%description
Apache Ant is a Java-based build tool.

  %endif
%endif

示例 使用 %elif

%if %{with junit}                                                                                                                                                               	 
%description
This package contains optional JUnit tasks for Apache Ant.

%elif %{with junit5}

%description
This package contains optional JUnit5 tasks for Apache Ant.

%else

%description
Apache Ant is a Java-based build tool.

%endif

else if 版本也实现了 %ifos (%elifos) 和 %ifarch (%elifarch)。

布尔依赖项


TL;DR

  • Factory 现在支持布尔依赖运算符,允许丰富的依赖关系
  • 示例:Requires: (sles-release or openSUSE-release)

RPM 4.13 引入了对布尔依赖关系(也称为“丰富依赖关系”)的支持。这些表达式可用于所有依赖关系标签,但 Provides 除外。这包括 RequiresRecommendsSuggestsSupplementsEnhancesConflicts。布尔表达式始终用括号括起来。依赖字符串可以包含软件包名称、比较和版本描述。

这有什么帮助?它大大简化了条件依赖关系。

实际示例:

您的软件包需要 pack1pack2 中的两个软件包之一才能工作。最近,在 RPM 中没有一种优雅的方法来表达这种依赖关系。

惯用方法是引入一个新的功能,pack1pack2 都将提供该功能,然后您的软件包可以从该功能中进行要求。

需要添加的 pack1pack2

Provides:    pack-capability 	

您的软件包需要此功能

Requires:    pack-capability 	

因此,为了需要一组软件包中的一个,您必须修改每个软件包以引入新的功能。这需要付出很多额外的努力,并且并非总是可行的。

如今,使用布尔依赖关系,您可以简单地添加

Requires:    (pack1 or pack2)                                                                                                                                                        

到您的软件包中,一切都会按预期工作,无需触碰任何其他软件包。

以下布尔运算符是在 RPM 4.13 中引入的。任何可用的软件包都可以匹配要求。

  • and
    • 必须满足所有操作数
    • Conflicts: (pack1 >= 1.1 and pack2)
  • 或者
    • 必须满足其中一个操作数
    • Requires: (sles-release or openSUSE-release)
    • 软件包需要 (sles-releaseopenSUSE-release) 中的至少一个
  • if
    • 如果满足第二个条件,则必须满足第一个操作数
    • Requires: (grub2-snapper-plugin if snapper)
  • if-else
    • 与上面的 if 相同,另外需要满足第三个操作数,如果第二个条件未满足
    • Requires: (subpack1 if pack1 else pack2)

RPM 4.14 添加了对单个软件包起作用的运算符。与上述运算符不同,必须有一个软件包满足所有操作数

  • with
    • 类似于 and,需要满足两个条件
    • BuildRequires: (python3-prometheus_client >= 0.4.0 with python3-prometheus_client < 0.9.0)
    • python3-prometheus_client 必须在范围 <0.4.0, 0.9.0) 内
  • without
    • 必须满足第一个操作数,第二个操作数必须不满足
    • Conflicts: (python2 without python2_split_startup)
  • unless
    • 如果第二个条件不满足,则必须满足第一个操作数
    • Conflicts: (pack1 unless pack2)
  • unless-else
    • 与上面的 unless 相同,另外需要满足第三个操作数,如果第二个条件未满足
    • Conflicts: (pack1 unless pack2 else pack3)

操作数可以嵌套。它们需要用括号括起来,除了 andor 运算符的链条。

示例:

Recommends: (gdm or lightdm or sddm)
Requires: ((pack1) or (pack2 without func2))

直到最近,Factory 只允许在 Recommends/Suggests(也称为软依赖项)中使用布尔依赖项,否则在从旧发行版执行 zypper dup 时会导致问题。现在支持以上所有运算符。

%license


TL;DR

  • 通过 %license 指令打包许可证文件,而不是 %doc

A %license 指令在 RPM 中添加于 4.11.0 (2013),但 openSUSE 和其他发行版在 2016 年才采用它。主要原因是允许轻松将许可证与普通文档分离。在此指令之前,许可证文本通常使用 %doc 指令标记,该指令管理将许可证复制到 %_defaultdocdir (/usr/share/doc/packages)。使用 %license,它可以很好地分离,并被复制到 %_defaultlicensedir (/usr/share/licenses)。

这对于资源有限的系统(例如容器)也很有用,这些系统在构建时没有文档文件,但仍然需要出于法律原因运送软件包许可证。

示例:

%files
%license LICENSE COPYING
%doc NEWS README.SUSE

许可证文件在 rpm 中进行了注释,这允许搜索特定软件包的许可证文件

$ rpm -qL sudo
/usr/share/licenses/sudo/LICENSE

OBS

新的 osc 选项

osc 命令行工具也收到了一些新功能。让我们快速了解一下最有趣的变化。

osc maintained –version

新的 --version 选项打印每个代码流中维护的软件包的版本,这在您想确定哪些代码流受到特定问题影响时非常有用。唯一的问题是它目前还不是很可靠——有时它只打印“unknown”。

$ osc maintained --version sudo
openSUSE:Leap:15.1:Update/sudo (version: unknown)
openSUSE:Leap:15.2:Update/sudo (version: 1.8.22)

osc request –incoming

request 命令的新 --incoming 选项仅显示项目是目标的请求/评审。

示例 列出 Base:System 项目的新或评审状态下的所有传入请求

$ osc request list Base:System --incoming -s new,review

osc browse

有时,通过 osc 比在 OBS GUI 中查看构建状态或构建日志更容易。有了这个新选项,您可以轻松地在浏览器中打开特定软件包。只需运行

$ osc browse [PROJECT [PACKAGE]

如果不带任何参数运行它,它将打开当前工作目录中的软件包。

删除整个项目的请求

这不是您每天都想调用的操作。但是,如果您需要删除包含所有软件包的整个项目,则只需调用

$ osc deletereq PROJECT --all

变更日志中的真实姓名

这是一个您可能注意到的变化。如果您通过 osc vc 创建一个 changelog 条目,它不仅会将您的电子邮件添加到 changelog 条目标头中,还会将您的全名添加进去。

rdiff 和 diff 增强

此外,rdiff 子命令还带有新的选项。可能最有用的选项是 rdiff --issues-only,它不打印整个 diff,而只显示已修复(实际上提到)的问题(bug、CVE、Jira)列表。

示例 osc rdiff --issues-only

# osc rdiff -c 124 --issues-only openSUSE:Factory/gnutls      
CVE-2020-13777
boo#1171565
boo#1172461
boo#1172506
boo#1172663

osc diff 命令添加了更多新选项。第一个是 --unexpand,它执行本地 diff,忽略链接的软件包源。第二个是 diff --meta,它仅对元文件执行 diff。

osc blame

osc 终于带有一个 blame 命令,您可能从 git 中了解它。它显示最后修改跟踪文件的每一行的用户。

它使用与 osc cat 相同的调用方式

$ osc blame <file>
$ osc blame <project> <package> <file>

缺点是它显示的是签入修订的用户,例如接受提交的人,而不是实际的作者。但它还在第一列显示修订号,因此您可以轻松显示带有原始作者的特定修订版本。

示例:

# osc blame openssl-fips-DH_selftest_shared_secret_KAT.patch
[...]
   2 (jsikes       2020-09-17 10:51:27    62) +
   5 (jsikes       2020-09-22 19:07:01    63) +    if ((len = DH_compute_key(shared_secret, dh->pub_key, dh)) == -1)
   2 (jsikes       2020-09-17 10:51:27    64) +        goto err;
   2 (jsikes       2020-09-17 10:51:27    65) +
[...]

假设我们对第 63 行感兴趣,即调用 DH_compute_key() 的地方。它上次在修订版 5 中更改,因此我们将检查该修订版

> osc log -r 5
----------------------------------------------------------------------------
r5 | jsikes | 2020-09-22 17:07:01 | 16a582f1397aa14674261a54c74056ce | unknown | rq227064

Fix a porting bug in openssl-fips-DH_selftest_shared_secret_KAT.patch
----------------------------------------------------------------------------

该更改是由请求 227064 创建的,因此我们最终可以找到实际代码的作者

$ osc rq show -b 227064
227064  State:accepted   By:jsikes       When:2020-09-22T17:07:07
        submit:          
        From: Request created: vitezslav_cizek -> Request got accepted: jsikes
        Descr: Fix a porting bug in openssl-fips-
               DH_selftest_shared_secret_KAT.patch

您还可以 blame 元文件,并显示元文件的每一行的作者,其中显示作者,因为元数据是直接编辑的。

$ osc meta pkg <project> <package> --blame

请注意,它适用于项目和软件包元数据,但不适用于属性。

osc comment

osc 允许您从命令行处理项目、软件包和请求上的评论。这对于编写机器人和其他自动处理特别有用。

  • osc comment list
    • 打印项目、软件包或请求的评论。
  • osc comment create
    • 添加新的顶级评论,或使用 -p 选项,回复到现有评论。
  • osc comment delete
    • 删除具有给定 ID 的评论。

检查工作者和约束

osc checkconstraints

当您有一个具有特殊构建约束的软件包时,您可能想知道有多少 OBS worker 能够构建它。osc checkconstraints 正是这样做的。

它可以打印匹配的 worker 列表

$ osc checkconstraints LibreOffice:Factory libreoffice openSUSE_Tumbleweed x86_64
Worker     	 
------     	 
x86_64:cloud137:1
x86_64:cloud138:1
x86_64:goat01:1
x86_64:goat01:2
[...]

甚至可以从软件包检出时打印每个仓库的摘要。

$ osc checkconstraints
Repository            	Arch                  	Worker
----------            	----                  	------
openSUSE_Tumbleweed   	x86_64                	94
openSUSE_Factory_zSystems  s390x                   	18
[...]

osc workerinfo

此命令打印有关 worker 硬件的详细信息,这在搜索适当的构建约束时很有用。

示例:

$ osc workerinfo x86_64:goat01:1

它将打印 lamb51 的内核版本、CPU 标志、CPU 数量以及可用内存和磁盘空间。

多构建


TL;DR

  • Multibuild 是 OBS 的一项功能,允许您使用不同的变体(例如,一次使用 GUI,然后不使用 GUI)构建相同的 spec 文件

multibuild 是 OBS 在 OBS 2.8 (2017) 中引入的一项功能,它提供了在相同的仓库中使用不同的变体构建相同的源代码的能力。这样的 spec 文件比为每个变体维护单独的 spec 文件更容易。

变体在软件包源代码目录中的 _multibuild xml 文件中定义。除了正常的软件包之外,为每个仓库和架构构建指定变体的每一个变体。

示例 _multibuild 文件(来自 Factory python-pbr

<multibuild>
  <package>test</package>
</multibuild>

在这里,OBS 将构建常规的 python-pbr 软件包,并额外构建 test 调味的 RPM。用户可以在 spec 中使用和执行相应操作来区分不同的变体(调整 BuildRequires、软件包名称/描述、打开额外的构建开关等)。

这里我们可以看到,正在构建一个额外的变体

$ osc r -r standard -a x86_64
standard         	x86_64 	python-pbr                 	succeeded
standard         	x86_64 	python-pbr:test            	succeeded

示例 spec 文件用法(再次是 python-pbr

%global flavor @BUILD_FLAVOR@%{nil}
%if "%{flavor}" == "test"
%define psuffix -test
%bcond_without test
%else
%define psuffix %{nil}
%bcond_with test
%endif
Name:       	python-pbr%{psuffix}

首先,spec 将 flavor 宏定义为它从 OBS 获取的值。然后,它根据 flavor 值分支 spec。它为测试变体设置名称后缀,并为构建和安装部分定义一个构建条件,以便于进一步处理。

如果您需要为您的软件包寻找灵感,可以查看以下软件包

python39libsshpython-pbrglibc

老旧的


TL;DR

  • PreReq 现在是 Requires(pre)
  • 使用 /run,而不是 /var/run
  • /bin/sbin/lib/lib64 合并到 /usr 下的对应目录中
  • SysV 已死,使用 systemd

我们意识到下面描述的变化非常、非常、非常古老。但我们仍然将本节放在这里,因为我们有时仍然在一些 spec 文件中看到它。所以让我们快速看一下。

PreReq → Requires(pre)

PreReq 不再使用,它已被弃用并映射到 RPM 4.8.0 (2010) 中的 Requires(pre)

/var/run → /run

自 openSUSE 12.2 (2012) 以来,/run 目录已提升到顶层,因为各发行版已达成共识,它不属于 /var。它仍然是符号链接以实现向后兼容性,但您绝对应该使用 /run (%_rundir 宏)。

/usr 合并

/usr Merge 是所有 Linux 发行版历史上的一个重要步骤,有助于提高与其他 Unix/Linux、GNU 构建系统或通用上游开发的兼容性。

简而言之,它的目的是将 /bin/sbin/lib 和 /lib64 的内容合并并移动到 /usr 下的对应目录中(当然也创建向后兼容的符号链接)。在 openSUSE 中,这发生在 2012 年左右。

SysV 已死

错过 SysV 已死的唯一借口就是您已经进入了冬眠状态 10 年。如果是这样,那么现在是 2020 年,并且自 openSUSE 12.3 (2013) 以来,我们使用 systemd

自动清理工具


TL;DR

  • 调用 spec-cleaner -i mypackage.spec 以根据 openSUSE 风格指南清理您的 spec 文件。
  • 调用 rpmlint mypackage.rpm 或检查 OBS 构建后生成的 rpmlint 报告,以查找常见的打包错误/警告。

如果您读到这里,您可能对所有这些打包中的新事物感到不知所措。也许您会问自己如何记住所有这些,或者更重要的是,如何使您维护的所有软件包与所有这些更改保持一致。我们给您一个好消息。有自动化工具可以做到这一点。

spec-cleaner

spec-cleaner 是一种根据风格指南清理 RPM spec 文件的工具。它可以将行放在正确的顺序中,使用正确的宏转换硬编码路径,并且主要用新的宏替换所有旧的宏。而且它还可以做更多的事情。

它也使用起来非常简单,只需调用

$ spec-cleaner -i mypackage.spec

即可直接将所有更改应用到您的 spec 文件。

如果您只想查看 spec-cleaner 将进行的更改的 diff,请调用

$ spec-cleaner -d mypackage.spec 

rpmlint

另一个可以帮助您保持软件包良好状态的工具是 rpmlint。它检查 RPM 软件包和 spec 文件中的常见错误。它可以找到重复的文件,检查二进制文件是否位于正确的位置,关注正确的库、systemd、tmpfiles 打包等等。它从上到下检查您的软件包,并报告任何错误或警告。

rpmlint 在 OBS 构建期间自动运行,如果存在严重问题,它可以使整个构建失败。它充当强制执行 OBS 中构建的软件包中特定标准的一种工具。如果您想自行运行它,请调用

$ rpmlint mypackage.rpm

spec-cleanerrpmlint 都会尽快实现新的打包更改和新规则。但维护人员可能会错过某些内容。在这种情况下,请随时在他们的 github 上将其报告为问题。

致谢

感谢 Simon LeesTomáš ChvátalDominique Leuenberger 提供的建议、更正和校对。这篇文章最初发表在 https://packageninjas.github.io/packaging/2020/10/13/news-in-packaging.html

分享此帖子