このページの目次
ワークスペースとプロジェクト管理
プロジェクトに複数の相互依存するクレート(コアライブラリ+APIサーバー+CLIなど)が含まれている場合、ワークスペースはそれらに同じ Cargo.lock と target ディレクトリを共有させます。これにより、コンパイルキャッシュの再利用や依存バージョンの統一が可能になります。patch を使用すると、開発中に特定の依存のソースコードを一時的に置き換えることができ、build.rs はコンパイル前にコード生成を実行します。
ワークスペース: 1つのリポジトリで複数のクレート
プロジェクトに複数の相互依存するクレート(コアライブラリ+APIサーバー+CLIなど)が含まれている場合、1つのワークスペースに配置することには以下の3つの利点があります。
[workspace]
members = ["crates/core", "crates/api", "crates/cli"]
resolver = "2"
- ビルド成果物の共有: すべてのメンバーが
target/ディレクトリを共有するため、依存関係は1回だけコンパイルされ、ディスク容量とコンパイル時間が大幅に削減されます。 - バージョンの一貫性:
Cargo.lockはワークスペースレベルで共有されるため、すべてのメンバーが同じバージョンの依存関係を確認できます。 - 内部からの相互参照:
apiはpath = "../../crates/core"を使用してcoreを直接参照できます(crates.io への公開は不要です)。
[workspace.dependencies]: バージョン宣言の共有
1.64以降では、ルート Cargo.toml でバージョンを宣言し、メンバーがキーで参照できるようになりました。
[workspace.dependencies]
serde = "1"
tokio = { version = "1", features = ["full"] }
# 各メンバー: [dependencies] → serde = { workspace = true }
これにより、複数のクレートを含むプロジェクトにおける「依存バージョンが各所に散在しており、アップグレード時に特定の箇所を見逃してしまう」という古典的な問題を解決します。バージョンを1箇所変更するだけで、すべてのメンバーが更新されます。
[patch]: 依存の一時的な置き換え
アップストリームのクレートにバグがあり、アップストリームが修正するまでフォーク版を使用したい場合:
[patch.crates-io]
serde = { git = "https://github.com/myfork/serde", branch = "fix" }
注意:[patch] 内のバージョンはワークスペース全体で互換性がある必要があります。メンバーの1つが serde 1.0 を、もう1つが serde 1.3 を依存している場合、フォークは両方のAPIを満たす必要があります。そのため、フォークでは内部ロジックのみを変更し、公開APIを変更しないことが推奨されます。
build.rs の高度な活用
// build.rs — メインコードのコンパイル前に実行される
build.rs は主に、C/C++ の依存関係のコンパイル(cc クレート経由)、システムライブラリの存在確認、コード生成(protobuf, OpenAPI)、feature フラグの設定に使用されます。
参考
- Cargo Book: ワークスペース、ビルドスクリプト
- cc crate: docs.rs/cc
Keywords: ワークスペース, メンバー, patch, build.rs, 共有依存関係, マルチクレート, Cargo.lock