Rust 軟件打包準則

出自 Arch Linux 中文维基


Arch 打包準則

32 位CLRCMakeCrossDKMSEclipseElectronFontFree PascalGNOMEGoHaskellJavaKDE內核模塊LispMesonMinGWNode.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