Rust 软件打包准则

来自 Arch Linux 中文维基


Arch 打包准则

32 位CLRCMakeCrossDKMSEclipseElectronFontFree PascalGNOMEGoHaskellJavaKDEKernelLispMesonMinGWNode.jsNonfreeOCamlPerlPHPPythonRRubyRustVCSWebWine

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

软件包命名[编辑 | 编辑源代码]

打包 Rust 项目时,软件包的名称应基本与生成的二进制文件名一致。请注意,打包库单元包 (library crate) 没有任何意义,只有带二进制文件的单元包 (crate) 才需要打包。对于生成多个二进制文件的包,通常使用上游单元包 (crate) 的名称较为合适。在任何情况下软件包的名称都应该小写。

源码[编辑 | 编辑源代码]

大多数 Rust 项目可以从 tarball、源归档文件(例如 GitHub Release 上的源链接)或其他已发布的源构建。另外,许多项目发布在 crates.io 上,该网站给 cargo 提供了稳定的 URL 下载方案。如果需要,PKGBUILD#source 可使用以下模板:

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

依赖关系[编辑 | 编辑源代码]

虽然有些 Rust 项目有外部依赖,但大多数项目只使用在最终二进制文件中静态链接的 Rust 生态系统库。因此,大多数项目不需要指定很多 depends (依赖),只需要 makedepends (构建依赖)。绝大多数 Rust 项目都使用 cargo 依赖管理器构建,它会协调下载库以满足编译时的依赖关系,并执行所有必要的调用,使用真正的 Rust 编译器 rustc 进行编译。目前 cargorustc 都由 rust 提供,但也有其他方法可同时获取或单独获取这两个包,包括 rustup。因此,大多数 PKGBUILD 都会调用 cargo 工具,应该直接依赖它。

makedepends=(cargo)

如果项目需要使用开发版 Rust 工具链,请使用:

makedepends=(cargo-nightly)

准备工作[编辑 | 编辑源代码]

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

prepare() {
    export RUSTUP_TOOLCHAIN=stable
    cargo fetch --locked --target "$CARCH-unknown-linux-gnu"
}

其中:

  • RUSTUP_TOOLCHAIN=stable 确保默认工具链被设置为稳定版,以防用户改变默认值。当然,如果在上游项目有特殊要求,则应被设置为开发版。此操作可避免在未使用 chroot 环境构建时受用户配置影响。另外,如果上游项目的源代码中有 rust-toolchain 文件或 rust-toolchain.toml 文件可实现此目的,则无需此步骤。
  • --locked 确保严格遵守 Cargo.lock 文件中指定的版本,防止其更新依赖关系。这对可重现构建很重要。
  • --target "$CARCH-unknown-linux-gnu" 确保只获取正在构建的特定目标平台所需的依赖项,从而减少下载量(参见 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 确保使用发布模式编译 (默认使用调试模式编译)
  • --frozen 确保 cargo 保持离线状态,只使用 Cargo.lock 文件中指定的版本和 prepare() 阶段缓存的版本。这在功能上与 --locked --offline 一致。这对可重现构建很重要。
  • --all-features 确保编译时启用软件包的所有特性。另外,如果只需启用指定特性,可使用 --features FEATURE1, FEATURE2
  • CARGO_TARGET_DIR=target 指定输出路径为当前目录下的 target 目录,以防未使用 chroot 环境构建时受用户配置影响。
注意: 对于 Arch 仓库的软件包来说不需要这两个环境变量,因为 Arch 仓库的软件包总是在 chroot 环境下使用默认设置下构建。但为了方便 AUR 用户,此处仍提到了上述环境变量,因为 AUR 用户可能没有意识到改变用户默认设置和在构建软件包时不使用 chroot 的后果。

检查[编辑 | 编辑源代码]

大多数 Rust 项目提供了运行测试的简单方法。

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

还应该检查仓库是否是 cargo 工作空间。只需打开 /Cargo.toml,检查是否包含 [workspace] 部分。如果包含 [workspace],则应当在 cargo test 后添加 --workspace,以确保所有工作区成员的测试都能运行。

运行测试时应避免使用 --release 标志,否则二进制文件将会使用 bench 参数重新编译,并覆盖 build() 生成的文件。或者也可以保留 --release 标志,但使用不同的 CARGO_TARGET_DIR。但需要注意的是,使用发布模式也会启用编译器优化,并禁用一些功能,如整数溢出检查和 debug_assert!() 宏,所以理论上可能最终问题会更少。这两种方法都会重新编译依赖项,从而使总编译时间略微增加。

打包[编辑 | 编辑源代码]

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 的注意事项[编辑 | 编辑源代码]

有些软件包需要安装更多的文件,如手册页面或其他必要的文件。如果没有其他方式来安装这些文件,可使用 cargo install。在这种情况下不必使用 build(),因为即使该软件包已通过 cargo build 构建,cargo install 仍会强制重新构建。但仍然可使用 prepare() 提前获取源代码:

package() {
    cd "$pkgname-$pkgver"
    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 样例请参阅软件包页面上的 Package Actions > Source Files