Rust 软件包指南

来自 ArchWiki
Arch 软件包指南

32 位CLRCMake交叉编译DKMSEclipseElectron字体Free PascalGNOMEGoHaskellJavaKDE内核模块LispMesonMinGWNode.js非自由OCamlPerlPHPPythonRRubyRust - 安全ShellVCSWebWine

本文档涵盖了关于为使用 Rust 编写的软件编写 PKGBUILD 的标准和指南。

软件包命名

在打包 Rust 项目时,软件包名称应几乎总是与生成的二进制文件的名称相同。请注意,打包库 crate 没有任何意义,因此只会打包带有二进制文件的 crate。对于生成多个二进制文件的项目,通常上游 crate 名称是合适的。在任何情况下,软件包名称都应完全小写。

来源

大多数 Rust 项目可以从 tarball、源代码存档(例如 GitHub 发布版本上的源代码链接)或任何其他已发布的源代码构建。

当其他来源不可用时,大多数 Rust 项目都发布在 crates.io 上,它为 cargo 提供了稳定的下载 URL 方案。这种来源的缺点是它通常不包含所有测试文件、许可证文件或通常在其他来源中的其他资产。如果需要,PKGBUILD#source 可以使用以下模板

source=("$pkgname-$pkgver.tar.gz::https://static.crates.io/crates/$pkgname/$pkgname-$pkgver.crate")

依赖

虽然一些 Rust 项目有外部依赖项,但大多数项目仅使用静态嵌入到最终二进制文件中的 Rust 生态系统库。因此,大多数项目不需要指定很多 depends。常见的例外是大多数 Rust 二进制文件都链接到 glibc 库,因此 gcc-libsglibc 通常是大多数 Rust 软件包的依赖项。如果构建过程查找并链接到任何系统库,则可能会有更多依赖项。

对于 makedepends,绝大多数 Rust 项目都设计为使用 cargo 依赖管理器构建,该管理器既协调库的下载以满足构建时依赖项,又调用 rustc(实际的 Rust 编译器)所需的所有调用。目前 cargo 和 rustc 均由 rust 软件包提供,但也有其他方法可以一起或单独获取这两者,包括 rustup 软件包。因此,大多数 PKGBUILD 将调用的工具是 cargo,您应该直接依赖它。

makedepends=(cargo)

如果项目需要使用 Rust 工具链的 nightly 版本,请使用

makedepends=(cargo-nightly)

准备

Rust 依赖管理器 cargo 能够提前下载构建项目所需的所有库。在 prepare() 阶段运行此获取操作使以后的 build() 和其他阶段能够完全离线运行。

prepare() {
    export RUSTUP_TOOLCHAIN=stable
    cargo fetch --locked --target "$(rustc -vV | sed -n 's/host: //p')"
}

其中

  • RUSTUP_TOOLCHAIN=stable 确保默认工具链设置为 stable,以防用户更改了他们的默认设置。当然,如果上游项目需要 nightly 版本,则应将其设置为 nightly。这避免了在非 chroot 环境中构建时用户偏好的常见副作用。另请注意,如果上游项目在其源代码中具有 rust-toolchain 文件或 rust-toolchain.toml 文件以达到此目的,则不需要这样做。
  • --locked 告诉 cargo 严格遵守 Cargo.lock 文件中指定的版本,并防止其更新依赖项。这对于可重现构建非常重要。
  • --target "$(rustc -vV | sed -n 's/host: //p')" 告诉 cargo 仅获取构建特定目标平台所需的依赖项,从而减少下载量(请参阅 PKGBUILD#archRust 平台支持)。
注意: 如果为上游源代码项目构建 VCS 软件包,该项目在发布周期之间未使其 Cargo.lock 文件与 Cargo.toml 同步,请在运行 cargo fetch 之前添加 cargo update。构建的所有其他方面应按此处记录的方式工作,尽管结果将不是完全可重现的构建,因为依赖项将在构建时解析。

构建

构建 Rust 软件包。

build() {
    export RUSTUP_TOOLCHAIN=stable
    export CARGO_TARGET_DIR=target
    cargo build --frozen --release --all-features
}

其中

  • --release 告诉 cargo 编译发布版本(默认是调试版本)
  • --frozen 告诉 cargo 保持离线状态,并且仅使用 Cargo.lock 文件中指定的版本以及在 prepare() 阶段运行的 fetch 操作缓存的版本。这在功能上等同于 --locked --offline,也可以使用。这对于可重现构建非常重要。
  • --all-features 告诉 cargo 编译时启用软件包的所有功能。或者,如果您只想启用选定的功能,请使用 --features FEATURE1,FEATURE2
  • CARGO_TARGET_DIR=target 告诉 cargo 将输出放置在相对于当前目录的 target 目录中。这避免了在非 chroot 环境中构建时用户偏好的常见副作用。
注意: 对于 Arch 仓库软件包,不需要这两个环境变量,因为它们始终在具有默认设置的 chroot 环境中构建。此处包含它们是为了方便 AUR 用户,这些用户可能没有意识到更改其用户默认设置以及在构建软件包时不使用 chroot 的后果。

检查

大多数 Rust 项目都提供了一种简单的方法来运行测试套件。

check() {
    export RUSTUP_TOOLCHAIN=stable
    cargo test --frozen --all-features
}

您还应该检查仓库是否是 cargo workspace。只需打开 /Cargo.toml 并查看它是否包含 [workspace] 部分。如果是,您应该将 --workspace 标志添加到 cargo test,以确保也运行 workspace 成员的所有测试。

注意: 运行测试时避免使用 --release 标志,因为它会启用编译器优化并禁用一些功能,例如整数溢出检查和 debug_assert!() 宏,因此理论上您最终可能会发现更少的问题。尽管优化标志的差异确实意味着测试必须重建更多 crate,但它仍然必须重建任何影响单元测试的内容才能在测试中构建,并且优化标志会比不通过匹配优化标志重建那么多 crate 减慢构建速度。由于被测试的最终二进制工件与我们打包的工件不同,而且我们没有测试构建工具链,因此对于大多数 Rust 项目来说,在发布模式下进行测试没有任何好处。

打包

Rust 在 target/release 中构建二进制文件,并且可以简单地安装到 /usr/bin

package() {
    install -Dm0755 -t "$pkgdir/usr/bin/" "target/release/$pkgname"
}

如果一个软件包在 /usr/bin 中有多个可执行文件,您可以使用 find 命令

package() {
    find target/release \
        -maxdepth 1 \
        -executable \
        -type f \
        -exec install -Dm0755 -t "$pkgdir/usr/bin/" {} +
}

关于使用 cargo install 的注意事项

一些软件包应安装更多文件,例如 man page 或其他资源。如果此类软件包没有其他安装这些文件的方法,则可以使用 cargo install。在这种情况下,build() 是不必要的,因为 cargo install 会强制重建,即使软件包已经通过使用 cargo build 构建。prepare() 阶段仍然可以用于提前获取源代码

package() {
    export RUSTUP_TOOLCHAIN=stable 
    cargo install --no-track --frozen --all-features --root "$pkgdir/usr/" --path .
}

应始终使用 --no-track 参数,否则 cargo install 将创建不需要的文件,例如 /usr/.crates.toml/usr/.crates2.json

完整的 PKGBUILD 模板

# Maintainer: Firstname Lastname <email@example.org>

pkgname=
pkgver=
pkgrel=1
pkgdesc=''
url=''
license=()
makedepends=('cargo')
depends=()
arch=('i686' 'x86_64' 'armv6h' 'armv7h')
source=()
b2sums=()

prepare() {
    export RUSTUP_TOOLCHAIN=stable
    cargo fetch --locked --target "$(rustc -vV | sed -n 's/host: //p')"
}

build() {
    export RUSTUP_TOOLCHAIN=stable
    export CARGO_TARGET_DIR=target
    cargo build --frozen --release --all-features
}

check() {
    export RUSTUP_TOOLCHAIN=stable
    cargo test --frozen --all-features
}

package() {
    install -Dm0755 -t "$pkgdir/usr/bin/" "target/release/$pkgname"
    # for custom license, e.g. MIT
    # install -Dm644 LICENSE "${pkgdir}/usr/share/licenses/${pkgname}/LICENSE"
}

示例软件包

单击软件包页面中的“软件包操作 > 源代码文件”以查看其示例 PKGBUILD。