Public Theta Blog

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 newcargo 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"]

参考