32 位 – CLR – CMake – Cross – DKMS – Eclipse – Electron – Font – Free Pascal – GNOME – Go – Haskell – Java – KDE – Kernel – Lisp – Meson – MinGW – Node.js – Nonfree – OCaml – Perl – PHP – Python – R – Ruby – Rust – VCS – Web – Wine
本文档涵盖了为 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
进行编译。目前 cargo 和 rustc 都由 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#arch 和 Rust 平台支持)。
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 环境构建时受用户配置影响。
检查
大多数 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。