openSUSE 软件包中的新闻
2020年11月23日 | Vítězslav Čížek 和 Kristýna Streitová | CC-BY-SA-3.0
如果您对 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 中用于
texinfo、glib schemas、mime、icons和desktop文件,因此您的软件包不再需要调用数据库/缓存更新宏。 - 目前(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 中拥有这些数据库/缓存更新宏现在不会造成任何危害。更改已在相应的软件包(texinfo、shared-mime-info、desktop-file-utils、glib2)中通过添加文件触发器完成,而所有这些旧宏现在都扩展为没有操作的命令。因此,您可以安全地从您的 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。支持的包括例如git、hg或quilt。默认值为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 除外。这包括 Requires、Recommends、Suggests、Supplements、Enhances 和 Conflicts。布尔表达式始终用括号括起来。依赖字符串可以包含软件包名称、比较和版本描述。
这有什么帮助?它大大简化了条件依赖关系。
实际示例:
您的软件包需要 pack1 或 pack2 中的两个软件包之一才能工作。最近,在 RPM 中没有一种优雅的方法来表达这种依赖关系。
惯用方法是引入一个新的功能,pack1 和 pack2 都将提供该功能,然后您的软件包可以从该功能中进行要求。
需要添加的 pack1 和 pack2
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-release、openSUSE-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)
- 与上面的
操作数可以嵌套。它们需要用括号括起来,除了 and 或 or 运算符的链条。
示例:
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。它为测试变体设置名称后缀,并为构建和安装部分定义一个构建条件,以便于进一步处理。
如果您需要为您的软件包寻找灵感,可以查看以下软件包
python39、libssh、python-pbr 或 glibc。
老旧的
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-cleaner 和 rpmlint 都会尽快实现新的打包更改和新规则。但维护人员可能会错过某些内容。在这种情况下,请随时在他们的 github 上将其报告为问题。
致谢
感谢 Simon Lees、Tomáš Chvátal 和 Dominique Leuenberger 提供的建议、更正和校对。这篇文章最初发表在 https://packageninjas.github.io/packaging/2020/10/13/news-in-packaging.html。