openSUSE:Rust 软件打包

(重定向自 )
跳转到:导航搜索


如何为 openSUSE 构建服务打包用 Rust 编写的软件。

维护/创建使用 Rust 代码的软件包

依赖关系

您应该安装以下软件包来帮助构建 openSUSE 的 rust 软件包。

zypper install obs-service-cargo osc obs-service-tar obs-service-obs_scm \
    obs-service-recompress obs-service-set_version obs-service-format_spec_file \
    cargo cargo-packaging sudo

可选地,您可以安装 cargo lock2rpmprovides 来帮助生成许可证字符串。

cargo install cargo-lock2rpmprovides

如果您想缓存构建工件,从 osc-0.173.0 开始,您可以使用 sccache 来帮助减少重复构建时间。

# ~/.config/osc/oscrc
sccache = 1
sccache_uri = file:///var/cache/obs_sccache.tar

或者,您可以使用网络 sccache

# ~/.config/osc/oscrc
sccache = 1
sccache_uri = redis://127.0.0.1:6379

设置 redis 缓存超出了本页的范围。

创建软件包

您应该使用以下命令签出您的空白软件包

osc co home:<username>/package
cd home:<username>/package

一个 rust 软件包的骨架 RPM 规范文件是

Name:           hellorust
#               This will be set by osc services, that will run after this.
Version:        0.0.0
Release:        0
Summary:        A hello world with a number of the day printer
#               If you know the license, put it's SPDX string here.
#               Alternately, you can use cargo lock2rpmprovides to help generate this.
License:        Unknown
Url:            https://github.com/Firstyear/hellorust
Source0:        %{name}-%{version}.tar.zst
Source1:        registry.tar.zst
# Pull in the latest rust/cargo toolchain
BuildRequires:  cargo
# This contains rpm macros to assist with building
BuildRequires:  cargo-packaging
# Disable this line if you wish to support all platforms.
# In most situations, you will likely only target tier1 arches for user facing components.
ExclusiveArch:  %{rust_tier1_arches}

%description
A hello world with a number of the day printer.

%prep
# The number passed to -a (a stands for "after") should be equivalent to the Source tag number
# of the vendor tarball, 1 in this case (from Source1).
%autosetup -p1 -a1
# Remove exec bits to prevent an issue in fedora shebang checking. Uncomment only if required.
# find vendor -type f -name \*.rs -exec chmod -x '{}' \;

%build
export CARGO_HOME=$PWD/.cargo
%{cargo_build}

%install
# using cargo_install (only supports bindir)
export CARGO_HOME=$PWD/.cargo
%{cargo_install}
# manual process, this can place binaries in other directories like sbindin
# install -D -d -m 0755 %{buildroot}%{_bindir}
# install -m 0755 %{_builddir}/%{name}-%{version}/target/release/%{name} %{buildroot}%{_bindir}/%{name}

%check
export CARGO_HOME=$PWD/.cargo
%{cargo_test}

%files
%license LICENSE-FILE
%{_bindir}/%{name}

%changelog

有一些注释区域您需要填写和检查。请注意,如果您使用 %{cargo_install},%{cargo_build} 是多余的,因为 %{cargo_install} 将同时重建和安装。

一些项目可能需要自定义 rust 标志作为构建参数,可以使用以下变量在规范文件的开头设置。

%define __rustflags --cfg tokio_unstable

但是接下来我们将创建一个服务文件,允许 OBS 帮助我们获取源代码并将它们打包给我们。这应该放在一个名为 _service 的文件中

<services>
  <service mode="manual" name="tar_scm">
    <param name="url">https://github.com/Firstyear/hellorust.git</param>
    <param name="versionformat">@PARENT_TAG@~@TAG_OFFSET@</param>
    <param name="scm">git</param>
    <param name="revision">v0.1.1</param>
    <param name="match-tag">*</param>
    <param name="versionrewrite-pattern">v(\d+\.\d+\.\d+)</param>
    <param name="versionrewrite-replacement">\1</param>
    <param name="changesgenerate">enable</param>
    <param name="changesauthor"> YOUR EMAIL HERE </param>
  </service>
  <service mode="manual" name="recompress">
    <param name="file">*.tar</param>
    <param name="compression">zst</param>
  </service>
  <service mode="manual" name="set_version"/>
  <service name="cargo_vendor" mode="manual">
     <param name="src">hellorust</param>
     <param name="compression">zst</param>
     <param name="update">true</param>
     <param name="method">registry</param>
  </service>
</services>

此服务文件为我们做了很多工作

  • 它将根据我们设置的版本从 git 获取源代码。
  • 它会将它们转换为 tar.zst 供我们使用。
  • 它将更新 rpm 的 changelog,并设置规范文件中的正确版本。
  • 它将下载我们的 rust 依赖项,然后将它们打包到 vendor.tar.zst 中。
  • 它会扫描我们的项目是否存在已知的漏洞。这些来自 RustSec advisory 数据库

您可以使用以下命令运行它

osc service ra

可选地,您现在可以运行 lock2rpmprovides

cd hellorust
cargo lock2rpmprovides

这将生成一个您可以复制到规范文件中的许可证字符串。

然后您可以添加所需的源代码并提交到 OBS

osc add _service _servicedata cargo_config hellorust-0.1.1~git0.db340ad.tar.zst hellorust.spec vendor.tar.zst
osc ci

如果您在构建软件包时遇到任何提及 crate 依赖项冲突的问题,您可以禁用自动更新依赖项,如下所示

<param name="update">false</param>

看看这是否可以解决问题。因为 git forge 上的 crates 通常只会对较旧的 Cargo.lock 文件运行 CI,而不是最新的 semver 兼容依赖项。

从这里,您可以按照 如何为 Factory 贡献 指南进行操作。

使用 Cargo 工作区的项目

工作区是 Cargo 的一项功能,可以从同一个 git 树构建多个项目。您可以对规范进行以下更改以在同一个项目中构建它们

BuildRequires:  cargo-packaging >= 1.2.0
[...]
%build
%{cargo_build} --all
[...]
%install
%{cargo_install -p project1}
%{cargo_install -p project2}

更新您的软件包

一旦您的软件包被接受,您可以使用以下步骤对其进行更新

osc bco devel:project/pkgname
cd home:username:branches:devel:project/pkgname
osc service ra
osc status

然后检查更改,并 osc rm 任何旧文件,并 osc add 任何更新的源文件。

从那里您可以执行构建和 ci/sr

osc build
osc ci
osc results
osc sr

修补已打包的 crates

有时有必要修补已打包的 crates,原因有很多,通常是因为尚未在上游版本中发布的 CVE。或者,如果您想修复 Leap 中较旧版本的 CVE。

虽然理论上您可以修改和重新打包您的 vendor-tarball,但我们尝试保持 vendor-tarball 不变,并使用补丁文件,以便清楚地了解我们修改了什么。

这有点棘手,但可以按以下方式进行

首先,手动或使用以下命令提取您的 sources- 和 vendor-tarballs

 quilt setup your.spec

或者,如果您正在使用服务文件,则使用

 osc service run obs_scm

但是请注意,您必须手动提取 vendor-tarball。

然后 cd 进入 source-dir。

现在您可以选择运行

 cargo tree | less

以识别您需要更改/升级的任何子(子子)软件包。

根据您需要执行的操作,继续执行下面的相应说明。

强制使用更高版本的直接依赖项

假设我们有一个如下所示的依赖树

 your_package v1.0
 ├── dep_lvl_1 v4.4
 ...

并且您想将 dep_lvl_1 升级到 v4.5

为此,您需要您的顶级 Cargo.toml 文件、如果存在 Cargo.lock 文件,以及 vendor/dep_lvl_1/ 放在某种版本控制下(quilt 可能不适合此用途,因为您可能事先不知道哪些文件会被更新 crate 修改)。

编辑您的 Cargo.toml 文件,以使 cargo 使用 v4.5 作为 dep_lvl_1

使用以下命令验证

 cargo tree | less

然后运行

 cargo vendor

以更新 crate dep_lvl_1

跳转到 所有步骤的最终步骤

强制使用更高版本的子依赖项

假设我们有一个如下所示的依赖树

 your_package v1.0
 ├── dep_lvl_1 v4.4
 │   ├── dep_lvl_2 v1.3  
 ...

并且您想将 dep_lvl_2 升级到 v1.4。

为此,您需要您的顶级 Cargo.toml 文件、如果存在 Cargo.lock 文件,以及 vendor/dep_lvl_1/Cargo.tomlvendor/dep_lvl_2/ 放在某种版本控制下(quilt 可能不适合此用途,因为您可能事先不知道哪些文件会被更新 crate 修改)。

编辑您要更改的 Cargo.toml 文件

 vi vendor/dep_lvl_1/Cargo.toml

并找到请求 dep_lvl_2 的位置。相应地将版本更改为 v1.4。

添加到顶级 Cargo.toml 文件

 [patch.crates-io]
 dep_lvl_1 = { path="vendor/dep_lvl_1" }

运行

 cargo vendor

以下载 dep_lvl_2 的新版本

跳转到 所有步骤的最终步骤

实际修改依赖项代码

假设我们有一个如下所示的依赖树

 your_package v1.0
 ├── dep_lvl_1 v4.4
 │   ├── dep_lvl_2 v1.3  
 ...

并且您想直接修改 dep_lvl_2 的代码。

为此,您需要您的顶级 Cargo.toml 文件、如果存在 Cargo.lock 文件,以及您需要编辑的文件,例如 vendor/dep_lvl_2/src/lib.rs 放在某种版本控制下。

编辑您要更改的源文件

 vi vendor/dep_lvl_2/src/lib.rs

添加到顶级 Cargo.toml 文件

 [patch.crates-io]
 dep_lvl_2 = { path="vendor/dep_lvl_2" }

跳转到 所有步骤的最终步骤

最终步骤

如果您在来这里之前运行了 cargo vendor,请检查您是否有一个 .cargo/config.toml 文件。如果没有,请创建该目录并将 cargo_config 文件从您的附加源复制到那里。

然后也将它置于版本控制之下,并将 cargo vendor 的输出写入 .cargo/config.toml(在大多数情况下,此文件不会被修改,但在极少数情况下可能会发生,当我们玩转依赖树时。因此,我们也希望将此修改包含在我们的补丁中)。

使用以下命令验证您拥有所有内容的正确版本

 cargo tree | less

创建您所做的修改的补丁(使用您的版本控制,例如 git diff > ../modifying_vendored_crate.patchquilt refresh),并将其添加到您的规范文件中。

参考资料