Rust 软件包指南
32 位 – CLR – CMake – 交叉编译 – DKMS – Eclipse – Electron – 字体 – Free Pascal – GNOME – Go – Haskell – Java – KDE – 内核模块 – Lisp – Meson – MinGW – Node.js – 非自由 – OCaml – Perl – PHP – Python – R – Ruby – Rust - 安全 – Shell – VCS – Web – Wine
本文档涵盖了关于为使用 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-libs
和 glibc
通常是大多数 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#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
告诉 cargo 编译发布版本(默认是调试版本)--frozen
告诉 cargo 保持离线状态,并且仅使用Cargo.lock
文件中指定的版本以及在prepare()
阶段运行的 fetch 操作缓存的版本。这在功能上等同于--locked --offline
,也可以使用。这对于可重现构建非常重要。--all-features
告诉 cargo 编译时启用软件包的所有功能。或者,如果您只想启用选定的功能,请使用--features FEATURE1,FEATURE2
。CARGO_TARGET_DIR=target
告诉 cargo 将输出放置在相对于当前目录的 target 目录中。这避免了在非 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。