本文 AI 產出,尚未審核

Rust 入門與環境設置 ── 編譯與執行流程

簡介

在學習任何程式語言時,編譯與執行的流程是最先必須掌握的基礎概念。對於 Rust 這樣的系統程式語言,了解編譯器(rustc)與建置工具(cargo)如何協同工作,不僅能幫助你快速寫出可執行的程式,還能在日後的效能優化與錯誤除錯上奠定堅實的基礎。
本篇文章將從最簡單的單檔編譯說起,逐步延伸到使用 Cargo 進行專案管理、DebugRelease 兩種建置模式,以及常見的環境變數設定,讓讀者在實作時能夠 得心應手


核心概念

1. rustc:單檔編譯器

rustc 是 Rust 官方提供的底層編譯器,直接將 .rs 檔案編譯成可執行檔或函式庫。它接受多種指令列參數,讓開發者可以自行控制最佳化等級、目標平台等。

1.1 基本編譯指令

// hello.rs
fn main() {
    println!("Hello, Rust!");
}
$ rustc hello.rs               # 產生同目錄下的 `hello` 可執行檔
$ ./hello
Hello, Rust!
  • rustc hello.rs 會使用預設的 debug 設定(opt-level = 0),編譯速度快、除錯資訊完整。
  • 若想啟用最佳化,只需要加上 -C opt-level=3
$ rustc -C opt-level=3 hello.rs -o hello_opt
$ ./hello_opt
Hello, Rust!

1.2 指定目標平台

$ rustc --target=x86_64-unknown-linux-gnu hello.rs

這在交叉編譯(cross‑compilation)時非常有用,例如在 Windows 上產生 Linux 可執行檔。

2. cargo:專案建置與套件管理

雖然 rustc 能直接編譯單檔程式,但實際開發往往牽涉多個模組、相依套件與測試。Cargo 為 Rust 官方的建置系統與套件管理工具,提供以下核心功能:

功能 常用指令 說明
建立新專案 cargo new my_proj 產生包含 Cargo.tomlsrc/main.rs 的範本
編譯 (Debug) cargo build 產生 target/debug 目錄,含除錯資訊
編譯 (Release) cargo build --release 產生 target/release,啟用最高等級最佳化
執行程式 cargo run 先編譯再執行,等同 cargo build && ./target/debug/...
測試 cargo test 執行內建測試框架
套件相依 cargo add serde 自動把依賴寫入 Cargo.toml 並下載

2.1 Cargo.toml 基本結構

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

[dependencies]
serde = { version = "1.0", features = ["derive"] }
  • [package] 區塊描述專案本身的資訊。
  • [dependencies] 列出所有相依套件,Cargo 會自動解析版本衝突。

2.2 多檔案模組化

// src/main.rs
mod greeter;               // 引入 greeter.rs

fn main() {
    greeter::hello();
}
// src/greeter.rs
pub fn hello() {
    println!("Hello from greeter module!");
}

使用 mod 關鍵字即可把程式碼拆分成多個檔案,Cargo 會在編譯時自動把它們串接起來。

3. Debug vs. Release:何時使用哪個

項目 Debug (cargo build) Release (cargo build --release)
最佳化等級 opt-level = 0(無最佳化) opt-level = 3(最高最佳化)
編譯速度 較慢
可執行檔大小 較大 較小
執行效能 較差 最佳
除錯資訊 完整(包含符號表) 只保留必要資訊

實務建議:開發階段使用 Debug,提交測試或正式部署前切換到 Release,以確保效能與二進位大小皆符合需求。

4. 環境變數與自訂建置腳本

Cargo 允許透過環境變數調整編譯行為,例如:

$ export RUSTFLAGS="-C target-cpu=native"
$ cargo build --release
  • RUSTFLAGS 會在每次呼叫 rustc 時自動帶入,常用於 針對特定 CPU 做最佳化
  • 若需要更複雜的前置或後置處理,可在專案根目錄加入 build.rs,Cargo 會在編譯前執行它。
// build.rs
fn main() {
    println!("cargo:rerun-if-changed=src/config.toml");
    // 例如根據 config.toml 產生 Rust 常數
}

程式碼範例

範例 1:使用 cargo run 快速測試

// src/main.rs
fn main() {
    // 📌 這裡使用了 *format!* 宏,編譯時會自動展開成字串
    let greeting = format!("Hello, {}!", "Rust");
    println!("{}", greeting);
}
$ cargo run
   Compiling my_proj v0.1.0 (/path/to/my_proj)
    Finished dev [unoptimized + debuginfo] target(s) in 0.45s
     Running `target/debug/my_proj`
Hello, Rust!

範例 2:切換 Debug / Release 並測量執行時間

// src/main.rs
use std::time::Instant;

fn fib(n: u64) -> u64 {
    match n {
        0 => 0,
        1 => 1,
        _ => fib(n - 1) + fib(n - 2),
    }
}

fn main() {
    let start = Instant::now();
    let result = fib(40);               // 計算較大的費波那契數
    let duration = start.elapsed();
    println!("fib(40) = {}", result);
    println!("執行時間: {:.2?}", duration);
}
# Debug 版
$ cargo run
# Release 版
$ cargo run --release

觀察兩次執行時間差異,可明顯感受到 Release 的效能提升。

範例 3:使用 build.rs 產生編譯時常數

# Cargo.toml
[package]
name = "build_example"
version = "0.1.0"
edition = "2021"
build = "build.rs"
// build.rs
use std::env;
use std::fs;
use std::path::Path;

fn main() {
    // 讀取專案根目錄下的 VERSION 檔案
    let version = fs::read_to_string("VERSION")
        .expect("無法讀取 VERSION 檔案")
        .trim()
        .to_string();

    // 把版本資訊寫入環境變數,供程式碼使用
    println!("cargo:rustc-env=PROJECT_VERSION={}", version);
}
// src/main.rs
fn main() {
    // 透過 env! 巨集在編譯期取得環境變數
    let version = env!("PROJECT_VERSION");
    println!("此程式的版本是 {}", version);
}
$ echo "1.2.3" > VERSION
$ cargo run
此程式的版本是 1.2.3

範例 4:交叉編譯產生 Windows 可執行檔(在 Linux 主機上)

# 安裝目標平台的工具鏈
$ rustup target add x86_64-pc-windows-gnu

# 使用 cargo 交叉編譯
$ cargo build --target x86_64-pc-windows-gnu --release

產生的檔案位於 target/x86_64-pc-windows-gnu/release/your_proj.exe,可直接在 Windows 上執行。

範例 5:自訂 RUSTFLAGS 以啟用 LTO(Link Time Optimization)

$ export RUSTFLAGS="-C lto=yes"
$ cargo build --release
  • LTO 能在連結階段進一步優化程式碼,通常會讓 Release 版的執行效能提升 5%~15%

常見陷阱與最佳實踐

陷阱 說明 解決方式
忘記切換至 Release 在效能測試時仍使用 cargo run(Debug) 明確使用 cargo run --releasecargo build --release
相依套件版本衝突 多個套件要求不同的 serde 版本 使用 cargo tree 檢查依賴樹,必要時手動指定相容版本
環境變數未傳遞 在 IDE 中執行時 RUSTFLAGS 不生效 在 IDE 的執行設定中加入環境變數,或在 .cargo/config.toml 中設定
交叉編譯缺少 linker 目標平台的 linker 未安裝導致編譯失敗 安裝對應的交叉 linker(如 mingw-w64)或使用 rustup target add 後的預設工具鏈
過度使用 unsafe 在不必要的地方加入 unsafe 會失去 Rust 的安全保證 僅在確定需要且已做好安全審查時 使用 unsafe,並加上詳細註解說明原因

最佳實踐

  1. 保持 Cargo.toml 整潔:只列出實際使用的依賴,避免「過度依賴」造成編譯時間膨脹。
  2. 使用工作區(workspace):當專案規模變大時,將多個相關 crate 放入同一個 workspace,能共享 target 目錄、減少重複建置。
  3. 啟用 cargo fmtcargo clippy:自動格式化與靜態分析可以在編譯前捕捉潛在錯誤。
    $ cargo fmt        # 格式化程式碼
    $ cargo clippy     # 靜態分析,建議加上 `-- -D warnings` 把警告視為錯誤
    
  4. 持續集成(CI):在 GitHub Actions、GitLab CI 等平台上加入 cargo testcargo build --release,確保每次提交都能順利編譯與通過測試。

實際應用場景

場景 為何需要了解編譯與執行流程 典型做法
嵌入式開發(如 ARM Cortex-M) 必須交叉編譯至目標 MCU,且往往需要 no‑std 環境 rustup target add thumbv7em-none-eabihfcargo build --release --target thumbv7em-none-eabihf
WebAssembly (Wasm) 前端 Rust 程式碼要編譯成 .wasm,再由 JavaScript 呼叫 cargo install wasm-packwasm-pack build --target web
高頻交易或遊戲引擎 需要極致效能,必須使用 Release + LTO + target‑cpu=native export RUSTFLAGS="-C opt-level=3 -C target-cpu=native -C lto=yes"cargo build --release
CLI 工具 發布到 crates.io 前,需要同時提供 Linux、macOS、Windows 三平台的二進位 使用 cross(Docker + Cargo)或 GitHub Actions 產生多平台的 Release 檔案
大型服務端微服務 每個微服務都是獨立的 Cargo crate,使用 workspace 共享依賴與建置快取 cargo workspace + docker buildcargo run --release 於容器內執行

總結

  • 編譯與執行流程 是 Rust 開發的根基:從單檔 rustc 到全功能的 cargo,每一步都提供了不同層次的抽象與便利。
  • 了解 Debug vs. Release環境變數交叉編譯 以及 自訂建置腳本,能讓你在不同的專案需求下快速切換、優化與部署。
  • 避免常見的陷阱、遵循最佳實踐,並把 測試、格式化、靜態分析 融入日常開發流程,才能真正發揮 Rust 所提供的安全與效能保證。

掌握了本文的概念與範例,你就能在 本機、容器、甚至嵌入式設備 上自如地編譯、執行與部署 Rust 程式,為後續深入學習所有權、借用與異步編程奠定堅實的基礎。祝你在 Rust 的旅程中玩得開心、寫得順手! 🚀