Cargo除了可以編譯、執行、測試程式專案之外,還可以針對程式專案進行程式建構(build)時的細節調整、將不同程式專案組合成相同的工作空間(Workspace),還能搭配crates.io來使用,利用程式專案的相依關係快速取得crates.io上的套件,或是反過來將我們開發完成的函式庫發佈到crates.io上。



修改程式建構的方式

Cargo有兩種主要的程式建構模式,分別是執行cargo build指令的開發(dev)模式,和執行cargo build --relese指令用來正式發佈程式時使用的釋出(release)模式。在先前的章節中,我們知道加上--relese參數之後輸出的程式就會透過編譯器進行一些優化,並且移除掉開發階段時用來偵錯(debug)的功能和訊息,確保正式版本的程式能在最佳狀態下運作(高效能、小體積)。

透過在Cargo.toml設定檔中定義[profile.dev][profile.release]區塊的方式,我們可以覆寫掉開發模式或是釋出模式預設的程式建構參數。

舉例來說,影響著編譯時程式優化程度的設定項目為opt-level,設定值數值範圍在0~3之間(包含0和3),數值0表示不作優化,數值愈高表示優化程度愈高。0和1適合用在開發模式,2和3適合用在釋出模式。開發模式的優化程度預設值為0,釋出模式的優化程度預設值為3,如果要將開發模式的優化程度改為1,釋出模式的優化程度改為2,可以在Cargo.toml設定檔中添加以下內容:

[profile.dev]
opt-level = 1

[profile.release]
opt-level = 2

opt-level另外還可以設定為szs可以讓編譯器以小體積為優先來編譯程式;z可以讓編譯器嘗試編譯出比s還要更小的程式。

發佈crate到crates.io

將自己寫的函式庫開放原始碼到crates.io,提供給其它Rust開發者使用前,應先替函式庫準備好API文件,不然沒有人會用。Rust程式語言有提供文件註解,單行的話,一般註解是以//開頭,而文件註解是以///開頭,支援Markdown語法。

舉例來說:

/// Adds two to the number given.
///
/// # Examples
///
/// ```
/// let five = 5;
///
/// assert_eq!(7, adder::add_two(five));
/// ```
pub fn add_two(a: i32) -> i32 {
    if a < 0 {
        panic!("`a` shoud not smaller than zero, but `a` = {a}");
    }

    a + 2
}

接著執行cargo doc指令,就可以替這個程式專案產生出網頁版文件了!網頁會儲存在target目錄的doc目錄下。

如果想要在網頁版文件產生出來之後直接用瀏覽器開啟,可以替cargo doc指令加上--open參數。產生出來的網頁如下:

rust-cargo

rust-cargo

Examples是我們透過Markdown語法的Heading 1所產生出來的區塊,區塊名稱可以自行隨便定義。而範例程式的部份使用Markdown的```語法,除了能在網頁中有程式碼高亮的效果之外,在使用cargo test指令測試程式專案的時候還可以測試文件註解內寫的範例程式。

rust-cargo

Doc-tests的部份就是寫在文件註解內的範例程式,如此一來就可以確認程式文件中的範例程式是否是正確的。

除了函數可以加上文件註解之外,整個crate也可以加上文件註解,但就不是使用///,而是//!。舉例來說:

//! # Adder
//!
//! `adder` is a project that we used for practicing Rust.

/// Adds two to the number given.
///
/// # Examples
///
/// ```
/// let five = 5;
///
/// assert_eq!(7, adder::add_two(five));
/// ```
pub fn add_two(a: i32) -> i32 {
    if a < 0 {
        panic!("`a` shoud not smaller than zero, but `a` = {a}");
    }

    a + 2
}

如此一來,在文件的網頁中就會多出crate的說明。

rust-cargo

如果要使用多行註解,///可以改成/**(開頭)和*/(結尾),//!可以改成/*!(開頭)和*/(結尾)。舉例來說:

/*!
# Adder

`adder` is a project that we used for practicing Rust.
*/

/**
Adds two to the number given.

# Examples

```
let five = 5;

assert_eq!(7, adder::add_two(five));
```
*/
pub fn add_two(a: i32) -> i32 {
    if a < 0 {
        panic!("`a` shoud not smaller than zero, but `a` = {a}");
    }

    a + 2
}

想要將自己製作的函式庫放到crates.io上,必須先登入crates.io,並且利用以下網址來產生API Token:

假設產生出來的API Token為txDj58akNnoIoJXqzzbW4VYOoh3vgrow,執行以下指令,Cargo就可以藉由這組API Token來登入我們的crates.io帳號。

cargo login txDj58akNnoIoJXqzzbW4VYOoh3vgrow

在函式庫發佈前,可以替其選擇一個適當的開放原始碼License來套用。可以參考這個網站:

每個開放原始碼License都有其專屬的「辨識名稱」,選定好要用的License之後,在我們程式專案Cargo.toml設定檔中的[package]區塊,可以加上license設定項目,來指定這個專案要套用的License。舉例來說:

[package]
name = "adder"
license = "MIT"

此外也必須加上description設定項目,來描述一下這個函式庫的作用。

確認目前的程式專案設定無誤,且可以通過測試之後,就可以使用以下指令來將我們的函式庫發佈或是更新到crates.io上了!

cargo publish

工作空間

如果我們要開發的套件很龐大,可以將其分割成多個子套件,利用工作空間組合起來使用。工作空間由多個程式專案來組成,可以使這些程式專案共享同一個Cargo.lock檔案和輸出目錄。

建立一個工作空間的方式很簡單,只要建立出一個空目錄,並在這個空目錄中新增一個Cargo.toml設定檔,接著在設定檔內添加[workspace]區塊,將這個工作空間所包含的其它程式專案名稱設定至members項目中。

舉例來說,若我們的工作空間底下有lib1lib2這兩個程式專案,則Cargo.toml設定檔的內容如下:

[workspace]
members = [
    "lib1",
    "lib2"
]

接著將程式專案加入至工作空間中,或是直接在工作空間中建立出新的程式專案。舉例來說,若我們的工作空間底下有lib1lib2這兩個程式專案,則工作空間的檔案目錄結構如下:

├── Cargo.toml
├── lib1
│   ├── Cargo.toml
│   └── src
│       └── lib.rs
├── lib2
│   ├── Cargo.toml
│   └── src
│       └── lib.rs
├── (target)
└── (Cargo.lock)

工作空間目錄中的target目錄和Cargo.lock會在編譯整個工作空間時自動產生出來。

安裝crates.io上的可執行程式

除了函式庫可以被發佈到crates.io上之外,可執行的應用程式專案也是可以的。如果要直接將crates.io上的應用程式專案安裝(下載然後編譯)到自己電腦上執行,可以使用cargo install指令。

舉例來說,如果要安裝ripgrep這個工具型的應用程式的話,指令如下:

cargo install ripgrep

rust-cargo

安裝的執行檔會放置在家目錄中的.cargo/bin目錄下,如果PATH環境變數有包含家目錄中的.cargo/bin目錄,就可以直接在終端機輸入執行檔名稱來執行程式。

rust-cargo

擴充Cargo的功能

使用以下指令,可以看到目前Cargo所支援的命令:

cargo --list

rust-cargo

如果要擴充Cargo能夠使用的命令,我們可以將執行檔命名成cargo-something,放置在家目錄中的.cargo/bin目錄下,something即為我們想要使用的命令名稱。

舉例來說,我們將Hello World的執行檔命名為cargo-hello,並存放到家目錄中的.cargo/bin目錄下。之後只要輸入cargo hello指令就可以執行到cargo-hello這個檔案。

rust-cargo

由於cargo install指令會將crates.io上的可執行程式專案所編譯出來的執行檔也安裝至家目錄中的.cargo/bin目錄下,所以在crates.io上以cargo-前綴來命名的可執行程式專案都可以直接透過cargo install指令,在安裝之後擴充Cargo的功能。

總結

Cargo是個很方便的Rust程式專案管理工具,除了可以用來產生、編譯、執行、測試、管理程式專案,還可以幫助我們下載crates.io上的套件到我們的程式專案中,或是直接安裝至作業系統環境。如果我們想要分享自己的程式專案至crates.io,也可以使用Cargo來快速發佈。

下一章節,我們將會學習指標的進階用法。

下一章:智慧型指標