Cargoのワークスペース
RustのパッケージマネージャーであるCargoには、複数のパッケージの依存パッケージのバージョンや、出力ディレクトリ、プロファイルなどの設定を共有できるワークスペース機能がある。
ワークスペースのマニフェスト
ワークスペースは[workspace]
セクションのあるCargo.toml
によって定義され、そのマニフェストファイルのあるディレクトリはワークスペースのルートディレクトリと呼ばれる。
[workspace]
members = []
default-members = []
exclude = []
[workspace]
セクションは[package]
セクションを持つパッケージのマニフェストにも追加可能で、その場合そのパッケージはワークスペースのルートパッケージと呼ばれる。反対に[package]
セクションを持たないワークスペースのマニフェストは、バーチャルマニフェストと呼ばれる。
ワークスペースのメンバー
ワークスペース内のパッケージは、ワークスペースのメンバーと呼ばれる。
メンバーは[workspace]
セクションのmembers
キーで指定することができる(?
や*
などのグロブパターンが使用可能)。
[workspace]
members = ["path/to/member1", "../external/member2", "members/*"]
その他、ルートパッケージやメンバーのマニフェストに記載されている依存パッケージのうち、ワークスペースのルートディレクトリに含まれるpath
によって指定されているもの(path dependency)も、自動的にワークスペースのメンバーとなる。
そのため、ルートパッケージの[workspace]
セクションが空となることもありうる。
[package]
name = "my-root-package"
version = "0.1.0"
[dependencies]
member1 = { path = "./member1" }
[workspace]
path
による依存パッケージが自動でメンバーに追加されるのを防いだり、一部パッケージをグロブパターンから除外したりのするには、exclude
キーを使うことができる。なおexclude
ではグロブパターンは使えず、指定されたパス以下のすべてのパッケージがメンバーから除外される仕様になっている。
[workspace]
members = ["crates/*"]
exclude = ["crates/bar"]
ワークスペースの認識
ワークスペースのマニフェストはCargoによって、自動的に親ディレクトリへと遡って探索される。ワークスペースのメンバーがルートディレクトリ外にある場合などのようにこの動作の上書きがしたい場合は、パッケージのマニフェストでpackage.workspace
キーを用いることで、パッケージの属するワークスペースを指定することができる。
[package]
name = "member"
version = "0.1.0"
workspace = "../../path/to/workspace"
ワークスペースの機能
ワークスペースによってメンバーは以下を共有することになる。
- 依存パッケージの解決
Cargo.lock
ファイルはワークスペースのルートディレクトリにのみ置かれる
- 出力ディレクトリ
- デフォルトではワークスペースのルートディレクトリ直下の
target
- デフォルトではワークスペースのルートディレクトリ直下の
Cargo.toml
の[patch]
、[replace]
、[profile.*]
セクション- ワークスペースのマニフェストのもののみが認識され、メンバーのマニフェストのものは無視される
[workspace]
members = ["crates/*"]
[profile]
opt-level = s
また、cargo new
やcargo init
で行われるgit
リポジトリの初期化も、作成されるパッケージが属することになるワークスペースが既にバージョン管理されている場合は行われなくなる。
そのほかpackage.metadata
と同様にworkspace.metadata
テーブルも許容されており、Cargo以外のツールが自由に使うことが可能となっている。
[workspace]
members = ["crates/*"]
[workspace.metadata.site]
title = "Project Site"
icon = { path = "icon.png" }
CLIのオプション
Cargoのコマンドでは、-p
(--package
)オブションを使うことで、カレントディレクトリが属するワークスペース内にあるパッケージを指定することができる。
cargo run -p member1
また--workspace
オプションを使うと、カレントディレクトリが属するワークスペース内にあるすべてのパッケージを対象に、そのコマンドが実行される。
cargo test --workspace
何も指定しなかった場合は、カレントディレクトリが属するパッケージに対して、コマンドが実行される(メンバーのディレクトリ内ではない場合は、ルートパッケージ)。
cargo build
属するパッケージがなく、代わりにバーチャルマニフェストに属するディレクトリで実行した場合は、デフォルトでは--workspace
を指定した場合と同様に振る舞うが、default-members
キーを用いるとその際実行されるメンバーを指定しておくことができる。なおdefault-members
でもグロブパターンは使えるが、メンバーに含まれないパッケージが選択されることはない。
[workspace]
members = ["crates/*", "others/*"]
default-members = ["crates/*"]
exclude = ["crates/bar"]