cargo
rustc
的意思是 Rust 編譯器,實際的編譯工作由它完成。Rust 檔案是用 .rs
作結尾。但大多數人不會去寫類似 rustc main.rs
的東西來編譯。他們使用的是名為 cargo
的東西,它是 Rust 的主要套件管理器。
關於這個名字的說明:之所以叫 cargo
,是因為當你把板條箱 (crate) 放在一起時,你會得到貨物 (cargo)。Crate 就是你在貨船或卡車上見到的木箱,但你會記得,每個 Rust 專案也叫 Crate。那麼當你把它們放在一起時,你就會得到一整個 Cargo。
當你使用 Cargo 來執行專案時,你可以見到這一點。讓我們用 rand
來試試簡單的東西:我們只會隨機在八個字母之間選擇。
use rand::seq::SliceRandom; // 讓 .choose 能使用在 slices 上 fn main() { let my_letters = vec!['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']; let mut rng = rand::thread_rng(); for _ in 0..6 { print!("{} ", my_letters.choose(&mut rng).unwrap()); } }
會印出 b **c** g h e a
這樣的東西。但我們想先看看 cargo
的作用。要使用 cargo
來執行我們的程式,通常我們按鍵輸入 cargo run
。這樣就可以組建我們的程式,並為我們執行。當它開始編譯時,會做這樣的事情:
Compiling getrandom v0.1.14
Compiling cfg-if v0.1.10
Compiling ppv-lite86 v0.2.8
Compiling rand_core v0.5.1
Compiling rand_chacha v0.2.2
Compiling rand v0.7.3
Compiling rust_book v0.1.0 (C:\Users\mithr\OneDrive\Documents\Rust\rust_book)
Finished dev [unoptimized + debuginfo] target(s) in 13.13s
Running `C:\Users\mithr\OneDrive\Documents\Rust\rust_book\target\debug\rust_book.exe`
g f c f h b
所以看起來不只引進了 rand
,還有一些其它的也是。這是因為我們的 crate 需要 rand
,而 rand
也有一些程式碼也需要其它 crate。所以 cargo
會找到我們需要的所有 crate,並把它們放在一起。在我們的案例中,我們只有七個,但在非常大的專案中,你可能會有 200 個或更多的 crate 要引進。
這就是你可以看到 Rust 的權衡妥協的地方。Rust 的速度極快,因為它提前編譯。它透過檢視程式碼,看你寫的程式碼到底做了什麼。例如,你可能會寫這樣的泛型程式碼:
use std::fmt::Display; fn print_and_return_thing<T: Display>(input: T) -> T { println!("You gave me {} and now I will give it back.", input); input } fn main() { let my_name = print_and_return_thing("Windy"); let small_number = print_and_return_thing(9.0); }
這個函式可以接受實作 Display
的任何型別作為引數,所以我們給它 &str
,接下來給它 f64
,這對我們來說沒什麼問題。但是編譯器不看泛型,因為它不想在執行時期做任何事情。它想把能執行的程式儘可能快地組裝起來。所以當它看第一部分的 "Windy"
時,它不是看到 fn print_and_return_thing<T: Display>(input: T) -> T
,它看到的是 fn print_and_return_thing(input: &str) -> &str
這樣的東西。而接下來它看到的是 fn print_and_return_thing(input: f64) -> f64
。所有關於特徵的檢查等等都是在編譯時期完成的。這就是為什麼泛型需要更長的時間來編譯,因為它需要弄清楚它們,並使之具體化。
還有一件事:Rust 2020 正在努力處理編譯時間問題,因為這部分需要的時間最長。每個版本的 Rust 在編譯時都會快一點,而且還有一些其他的計劃來加快它的速度。但與此同時,這裡是你該知道的:
cargo build
會組建你的程式,這樣你就可以執行它了。cargo run
將組建你的程式並且執行。cargo build --release
和cargo run --release
有同樣的效果,不過是在釋出模式 (Release mode) 下。那是什麼?釋出模式是用在當你的程式碼終於完成的時候。然後 Rust 會花更多的時間來編譯,但它這樣做是因為它使用了它所知道的一切,來使編譯出的程式執行得更快。釋出模式實際上比被稱為除錯模式 (Debug mode) 的常規模式執行時還 快的多。那是因為常規模式的編譯速度更快,而且有更多的除錯資訊。常規的cargo build
叫做 "debug build",cargo build --release
叫做 "release build"。cargo check
是一種檢查程式碼的方式。它就像編譯一樣,除了它並不會真正地做出你的程式。這是經常檢查你的程式碼的好方式,因為它不像build
或run
那樣需要花很長時間。
對了,命令中的 --release
這部分叫做 flag
。這意味著命令裡帶有額外的資訊。
一些其他你需要知道的事情:
cargo new
這麼做是為了建立新的 Rust 專案。在new
之後寫上專案名稱,cargo
將會做出所有你需要的檔案和資料夾。cargo clean
當你把 crate 新增到Cargo.toml
時,電腦會下載所有需要的檔案,並且會佔用很多空間。如果你不想再讓它們留在你的電腦上,可以輸入cargo clean
。
關於編譯器還有一件事:只有當你第一次使用 cargo build
或 cargo run
時,它才會花費最多的時間。在那之後它就會記得一些資訊,又會快速的編譯了。但如果你使用 cargo clean
,然後執行 cargo build
,它將不得不再慢慢地編譯一次。