Public Theta Blog

Rustのtargetディレクトリをあるディレクトリ以下で共有する

Rustのビルドによるアーティファクトはビルドのキャッシュを含め、すべてtargetディレクトリに出力される。

デフォルトでは、targetディレクトリはプロジェクトのルートディレクトリ、すなわち(ワークスペースであればワークスペースの)Cargo.tomlがあるディレクトリに作成されるが、複数のプロジェクトで多くの同じパッケージを依存関係として持つ場合、同じものをプロジェクトごとにビルドすることになるため、ビルド時間的にもディスク容量的にもかなりの重複が生じることになる。

project-a/target/...
project-b/target/...
project-c/target/...

より高度な方法として、sccacheのようなツールを使うこともできるが、単純な方法として、Cargoの設定でtargetディレクトリに同じディレクトリを使うように指定することができる。

環境変数CARGO_TARGET_DIRを設定したり、

export CARGO_TARGET_DIR="/path/to/shared/target"

$CARGO_HOME/config.tomlbuild.target-dirを設定したり、

[build]
target-dir = "/path/to/shared/target"

といった方法があるが、実はこれらより先に、現在のディレクトリ以上にある.cargo/config.tomlを下から上へと再帰的に読んでくれるという仕組みがあるので、これを使うと、プロジェクトごとだったり、親ディレクトリごとだったりに、targetディレクトリを指定することもできる。

.cargo/config.tomlの相対パスは、.cargoのあるディレクトリを基準として解釈される。

なので、例えば次のような.cargo/config.tomlを作成することで、そのディレクトリ以下のすべてのプロジェクトで同じtargetディレクトリ(.cargo/target)を使うようにできる。

[build]
target-dir = ".cargo/target"
.cargo/config.toml
.cargo/target/...
project-a/
project-b/
project-c/

その際、あるプロジェクトだけ例外として扱いたい場合は、現在のディレクトリを含めてより近いディレクトリにある.cargo/config.tomlが優先されるので、そのプロジェクトのディレクトリに次のような.cargo/config.tomlを作成して、targetディレクトリを指定すれば良い。

[build]
target-dir = "target"

例えば、project-cにこのファイルを追加した場合、project-cのビルド結果はproject-c/targetに出力されるようになる。

.cargo/config.toml
.cargo/target/...
project-a/
project-b/
project-c/.cargo/config.toml
project-c/target/...

このような使い方をする場合、.gitignore_globalなどに.cargo/config.tomlを追加しておくと良いかもしれない。

.cargo/config.toml

ただし、その場合は逆にtargetディレクトリを.gitignoreに追加することを忘れないようにしなければならないだろう。

/target