🎯

cargoにおけるターゲット

2022/12/10に公開

Rustのビルド兼パッケージ管理ツールであるcargoの設定ファイル(マニフェストと呼ばれる)Cargo.tomlはcrateと呼ばれるパッケージを定義していて、この中には[lib][[bin]]という項がありこれらはターゲットと呼ばれます。

https://doc.rust-lang.org/cargo/reference/cargo-targets.html

[[bin]]のように[]が2重になっているのはTOMLの仕様で、

Cargo.toml
[[bin]]
name = "a"

[[bin]]
name = "b"

と書くとJSONで言えば

{
  "bin": [{ "name": "a" }, { "name": "b" }]
}

の様にリストとみなされます。ターゲットには次の種類があります:

  • [lib]
  • [[bin]]
  • [[example]]
  • [[test]]
  • [[bench]]

[lib]だけはパッケージ(crate)に対して1つしか定義できず、他のものは上で述べたように複数定義できます。これらはプロジェクトのディレクトリ構成に応じて自動的に補完されます。例えばsrc/lib.rs[lib]のルートとみなされ、src/bin/xxx.rsというファイルがあれば対応する[[bin]]が補完されます。なのでこの記事で述べる説明は通常は必要なく、追加で特殊な設定を行いたいときに追加します。

これらのセクションでは共通のフィールドが使われます。以下はそれぞれのフィールドとターゲットの組み合わせに付いて、

  • デフォルト値がある場合はデフォルト値
  • ディレクトリ構成から自動的に補完される値の場合は *
  • 指定出来ない、指定しても効果が無い場合は -

を示した表です:

field [lib] [[bin]] [[example]] [[test]] [[bench]]
name crate name * * * *
path * * * * *
test true true false true false
bench true true false false true
doc true true false false false
doctest true - - - -
proc-macro false - - - -
harness true true true true true
crate-type ["lib"] - ["bin"] - -
required-features - [] [] [] []

加えてplugin, editionがありますが、これらはほぼ使うことは無いので省略します。

name, path fields

基本的に自動的に補完されます。特殊なディレクトリ構成をする場合、例えばsrc/bin/以外に実行ファイルとなるコードを置きたい時等に使います。

crate-type field

crateをビルドした出力を指定します。次の値のうち生成するものをリストで指定します。

  • bin
  • lib
  • rlib
  • dylib
  • cdylib
  • staticlib
  • proc-macro

proc-macro field

手続きマクロ(proc-macro)を提供するcrateで使います。

[lib]
proc-macro = true
# 他のフィールドは自動的に補完される値を使う

この場合crate-typeは強制的に["proc-macro"]になります。

doc field

cargo-docコマンドでドキュメントを生成するかどうかを変更できます。

[lib][[bin]]の場合にはデフォルトでtrueになり他ではfalseになりますが、特殊ルールとして[[bin]]の場合にターゲット名がcrate名と一致する場合はデフォルト値がfalseになります。

test, bench fields

それぞれcargo-test及びcargo-benchコマンドで実行するかどうかを変更できます。test = trueの場合、cargo-testを実行するとそのターゲットに含まれる#[test]で修飾された関数を探してそれを実行します。同じようにbench = trueだと#[bench]で修飾された関数を探してそのベンチマークをとりますが、この機能はnightlyの為stable toolchainでは使えません。この#[test]#[bench]を順番に実行して結果を表示するランタイムの事をharnessと呼んでいます。

独自のテストやベンチマークフレームワークを使う場合、実行ファイルに追加で引数を与えるケースがあります。例えば次に述べるcriterionではベンチマーク結果に名前をつけて保存する場合にその名前(例えばmain)を次の様に指定します:

cargo bench -- --save-baseline main

中間の--cargo-benchに与える引数と、cargo-benchが起動したプログラムに対する引数を区別する仕切りです。この時[lib]bench fieldはデフォルトでtrueなので、cargo benchによってたとえ#[bench]で修飾された関数が1つも無くても[lib]を対象としてベンチマークを実行されます。すると上の引数はサポートされていないので実行に失敗します。これを防ぐには次の様にします:

Cargo.toml
[lib]
bench = false

他のfieldは空のままにしておけばデフォルトの値が使われます。

harness field

Rust toolchainに含まれるlibtestによるテスト・ベンチマークのドライバを使用するかどうか変更できます。harness = falseにすると#[test]#[bench]を収集せずに、pathに指定されたファイルのmain関数を実行します。この機能により独自のテストやベンチマークスイートを言語ランタイムでなくサードパーティで実装できます。例えば代表的なベンチマークスイートであるcriterionはこの機能を使って実現されています。

GitHubで編集を提案

Discussion