iT邦幫忙

2024 iThome 鐵人賽

DAY 25
0
Modern Web

Rust 的戰國時代:探索網頁前端工具的前世今生系列 第 25

Day 25:Rust 學習筆記 (2) - 套件管理工具 Cargo、Crates、VS Code 擴充套件

  • 分享至 

  • xImage
  •  

前言

昨天安裝完 Rust 環境也完成了一個最基本的 Hello world 踏出第一步,下一步想來做個簡單的小專案學習,而在此之前就得先了解在 Rust 中如何管理專案。

在 JavaScript 中當我們想做的應用程式變複雜,我們會用 npm 來建立一個專案並引入第三方套件,而對應到 Rust 中也有一套管理專案的工具稱為 Cargo。

如果你拿 Cargo 這個字去 google 圖片,會看到一堆輪船貨櫃的圖,因為這個字指的是飛機、輪船裝載的貨物。

cargo

附上圖片來源,雖然上圖偷置入 LogRocket,但覺得這張圖很貼切看起來更直觀。

實作

用 Cargo 啟新專案

來動手實作體驗看看,如果昨天有透過 rustup 正確安裝好 Rust,這個 cargo 也會跟著一起被安裝。試著執行這個指令應該會顯示 Cargo 的版本:

$ cargo --version
cargo 1.81.0 (2dbb1af80 2024-08-20)

cargo 啟一個新專案:

$ cargo new hello_cargo
$ cd hello_cargo
$ code .

用 VS Code 開啟後,能看到其中的資料夾結構如下:

~/hello_cargo
├── Cargo.lock
├── Cargo.toml
├── src
|  └── main.rs
└── target

TOML 檔案與安裝套件

main.rs 中可以看到我們昨天寫的 hello world,而另外有兩個檔案 Cargo.tomlCargo.lock,這看起來像極了 package.jsonpackage-lock.json

其中的這個 .toml 副檔名有點陌生,但如果去看其中的內容能猜到這應該是另一種類似 JSON、YAML 這些設定檔常用的檔案格式。從 TOML 官網的資訊來做一下筆記:

  • 全名為 Tom's Obvious Minimal Language 的縮寫,湯姆發明的淺顯易懂的語言
  • 目標是能呈現一種語法讓人類更好讀懂,且又能顧及機器好 parse 的資料結構
  • 這個 Tom 來歷不小,同時也是 GitHub 共同創辦人、SemVer、Jekyll 等工具的作者

理解玩 TOML 檔案格式後,接下來試試安裝隨意一個套件 rand,顧名思義是一個拿來產生亂數的簡單套件:

$ cargo add rand

安裝後看到其中的 Cargo.toml,會發現讀起來像是更一目瞭然的 package.json,利用 [] 這些 sections 來區分設定的用途,可以很明顯知道 package 底下指的是這個專案的資訊,而 dependencies 底下指的是這些套件的安裝版本:

[package]
name = "hello_cargo"
version = "0.1.0"
edition = "2021"

[dependencies]
rand = "0.8.5"

另外值得一提的是這些套件不像 npm 一樣會被安裝到當前專案目錄底下的 node_modules,會被放到 ~/.cargo/registry 底下做快取。

用 Cargo 編譯與執行

再來試著直接用指令來編譯這個專案中的主程式:

$ cargo build

執行後會看到在專案目錄底下自動產出一個資料夾 target,裡面會含有編譯後的內容,那麼如果想像昨天一樣去執行編譯出來的執行檔的話要怎麼做呢:

$ ./target/debug/hello_cargo
Hello, world!

但如果在開發中想要更方便地測試,可以用另一個指令直接做完上面的兩個步驟,這個 cargo run 指的就是「編譯並且執行」:

$ cargo run
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.04s
     Running `target/debug/hello_cargo`
Hello, world!

但眼尖的你可能會發現上面執行 cargo run 時沒有剛剛 cargo build 一連串的編譯訊息,這是因為在執行這些指令時會聰明地根據 target 中的快取資訊,去確認程式是否有更改,如果沒更動自然就不需要重新編譯。或針對這段想體驗看看的話可以這樣做,可以去快速清掉 target 資料夾並重新編譯並執行:

$ cargo clean
$ cargo run

另外一提還有一個 cargo check 的指令,差別在於只會拿來檢查編譯過程是否能正確通過,而不會產生執行檔,進而在開發測試時省下這段時間。

用 Cargo 構建正式版本

剛剛會看到在執行 cargo build 時其中的構建訊息有寫到 [unoptimized + debuginfo] 並且輸出檔被放在 target/debug 底下,這是因為在還沒有要發佈正式版本前,開發中的編譯可以省下最佳化的構建時間。

但當要發佈正式版時,可以用 cargo build --release 來執行,如果實際觀察一下構建時間會發現稍微久了些,且在打包後會將輸出檔放到 target/release 中:

$ cargo build --release
   Compiling proc-macro2 v1.0.87
   Compiling unicode-ident v1.0.13
   ...
    Finished `release` profile [optimized] target(s) in 4.45s

💡 補充:關於 VS Code 上的 Rust 擴充套件

後來在測試另一段基本四則運算的程式碼時:

fn add(a: i32, b: i32) -> i32 {
    a + b
}

fn sub(a: i32, b: i32) -> i32 {
    a - b
}

fn main() {
    let result_array = [add(55, 66), sub(55, 66)];
    println!("{:?}", result_array);
}

發現其實 VS Code 上如果有安裝 rust-analyzer 這個擴充套件的話,也可以直接點擊像圖上這個 run 就可以在同個 terminal 底下測試,不需要一直打 cargo run

VS Code run

關於擴充套件前面忘了提到,我在搜尋時看到有一個同捆包 Rust Extension Pack 可以直接一鍵安裝,裡面有必裝的 rust-analyzercrates。另外還包了一個 Even Better TOML,顧名思義是支援 TOML 語法的 highlighting 跟一些附加功能如檢查套件、折疊區塊等。

而上方有另一個 debug 按鈕如果按下去的話,會顯示一個錯誤提示說另外還需要安裝 CodeLLDB。當你裝完這個套件後,如果去點擊上圖中的 L11 下中斷點後,再次嘗試點擊 debug 按鈕,會發現這個套件能自動根據 Cargo.toml 產出一個 .vscode/launch.json 檔案來初始化 VS Code 的 debug 環境,並能正確在斷點上停下來並顯示當前資訊:

VS Code rust debug

Cargo 是什麼?Crates 是什麼?

實際操作完後,回過來做個重點整理。

前面說到 cargo 是 Rust 的套件管理工具,就像是 npm 一樣,可以透過 cargo 指令管理設定檔、安裝第三方套件。

但除了做為套件管理工具外,它同時也具備了類似構建工具的功能,除了可以像上面用 cargo runcargo build 等來編譯與執行外,在這份文件中也提到它還可以透過 cargo test 來執行單元測試與整合測試。

crate

圖片來源

另外在 Rust 生態系的這些套件被稱為 Crates,就像 npm 一樣可以在套件庫 (package registry) 上找到各種套件直接用 cargo add 來安裝使用。這個 Crate 在中文指的是木板條箱,雖然它的 logo 畫的是紙箱,但下面有一些木板條應該也算是有接近的概念。

crates logo

小結

今天實際操作了許多 cargo 的指令,也理解了何謂 crates,算是對 Rust 中的套件管理有了初步的概念,明天會來進階試試上面提到的 cargo test,順便研究一下在 Rust 中要怎麼寫單元測試,我們明天見!

延伸閱讀


上一篇
Day 24:Rust 學習筆記 (1) - 千里始於 Hello, world!
下一篇
Day 26:Rust 學習筆記 (3) - 用單元測試來學習 Rust 語法
系列文
Rust 的戰國時代:探索網頁前端工具的前世今生30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言