Rust 軟件打包準則
32 位 – CLR – CMake – Cross – DKMS – Eclipse – Electron – Font – Free Pascal – GNOME – Go – Haskell – Java – KDE – 內核模塊 – 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。