Cargo活用
Rustのビルドツール「Cargo」の高度な機能を学びます。
Cargo.tomlの詳細
基本構造
[package]
name = "my_app"
version = "0.1.0"
edition = "2021"
authors = ["Your Name <you@example.com>"]
description = "My awesome application"
license = "MIT"
[dependencies]
serde = "1.0"
[dev-dependencies]
criterion = "0.4"
[build-dependencies]
cc = "1.0"
バージョン指定
[dependencies]
# 完全一致
exact = "=1.0.0"
# キャレット(デフォルト): 互換性のある最新
caret = "1.0" # >=1.0.0, <2.0.0
caret2 = "1.0.0" # >=1.0.0, <2.0.0
# チルダ: マイナーバージョンまで固定
tilde = "~1.0" # >=1.0.0, <1.1.0
# ワイルドカード
wildcard = "1.*" # >=1.0.0, <2.0.0
# 範囲
range = ">=1.0, <2.0"
Features(機能フラグ)
依存クレートのfeatures
[dependencies]
serde = { version = "1.0", features = ["derive"] }
tokio = { version = "1", features = ["full"] }
# または一部のみ
tokio = { version = "1", features = ["rt", "net", "io-util"] }
自分のクレートにfeatures定義
[features]
default = ["json"]
json = ["dep:serde_json"]
yaml = ["dep:serde_yaml"]
full = ["json", "yaml"]
[dependencies]
serde_json = { version = "1.0", optional = true }
serde_yaml = { version = "0.9", optional = true }
#![allow(unused)]
fn main() {
#[cfg(feature = "json")]
pub fn parse_json(s: &str) -> Result<Value, Error> {
serde_json::from_str(s)
}
}
ビルドプロファイル
dev(開発用)
[profile.dev]
opt-level = 0 # 最適化なし
debug = true # デバッグ情報あり
release(本番用)
[profile.release]
opt-level = 3 # 最大最適化
debug = false # デバッグ情報なし
lto = true # リンク時最適化
カスタムプロファイル
[profile.bench]
opt-level = 3
debug = true
[profile.profiling]
inherits = "release"
debug = true
ワークスペース
複数のクレートをまとめて管理します。
my_workspace/
├── Cargo.toml # ワークスペースルート
├── app/
│ ├── Cargo.toml
│ └── src/
├── lib_core/
│ ├── Cargo.toml
│ └── src/
└── lib_utils/
├── Cargo.toml
└── src/
ルートCargo.toml
[workspace]
members = ["app", "lib_core", "lib_utils"]
app/Cargo.toml
[package]
name = "app"
version = "0.1.0"
[dependencies]
lib_core = { path = "../lib_core" }
lib_utils = { path = "../lib_utils" }
便利なCargoコマンド
| コマンド | 説明 |
|---|---|
cargo build | ビルド |
cargo build --release | リリースビルド |
cargo run | ビルド+実行 |
cargo check | 型チェックのみ(高速) |
cargo test | テスト実行 |
cargo doc --open | ドキュメント生成&表示 |
cargo fmt | コード整形 |
cargo clippy | 静的解析 |
cargo update | 依存関係更新 |
cargo tree | 依存関係ツリー表示 |
Cargo.lock
依存関係の正確なバージョンを記録します。
- ライブラリ: .gitignoreに入れる(利用者が決める)
- アプリケーション: コミットする(再現性のため)
環境変数
// ビルド時の情報
const VERSION: &str = env!("CARGO_PKG_VERSION");
const NAME: &str = env!("CARGO_PKG_NAME");
fn main() {
println!("{} v{}", NAME, VERSION);
}
まとめ
| 機能 | 用途 |
|---|---|
| features | オプション機能の切り替え |
| profiles | 最適化レベルの設定 |
| workspace | 複数クレートの管理 |
cargo check | 高速な型チェック |
cargo clippy | 静的解析 |
確認テスト
Q1. `cargo check`と`cargo build`の違いは?
正解: A) `cargo check`は実行ファイルを生成しないため高速です。開発中は`check`を使い、実行時のみ`build`を使うのが効率的です。
Q2. `[dependencies]`と`[dev-dependencies]`の違いは?
正解: A) `dev-dependencies`はテストやベンチマーク時のみ使われ、ライブラリとして公開した際には含まれません。
Q3. 以下のCargo.tomlで`serde`のどのfeaturesが有効になる?serde = { version = "1.0", features = ["derive", "rc"] }
正解: C) features配列に指定した`derive`と`rc`の2つが有効になります。deriveは`#[derive(Serialize, Deserialize)]`を使えるようにし、rcは`Rc`や`Arc`のシリアライズを可能にします。
Q4. 以下のCargo.tomlの問題は何?tokio = "1", features = ["full"]
正解: B) featuresを使う場合は`tokio = { version = "1", features = ["full"] }`のように中括弧で囲む必要があります。
Q5. ワークスペースのルートCargo.tomlで正しい記述は?
正解: D) ワークスペースのルートCargo.tomlでは`[workspace]`セクションに`members`配列でメンバークレートを指定します。
次のドキュメント: 02_crate_ecosystem.md