パッケージ
Cargoを前提とした、いくつかのクレートの集まりを指します。
筆者の理解だと、一つのパッケージにつきCargo.toml
が一つあるイメージです。
クレート
ある程度の大きさの機能の集合体です。クレートには大きく
- バイナリクレート
- ライブラリクレート
の2種類があります。
一つのパッケージは少なくとも1つはクレートを持っていなければなりません。また、ライブラリクレートは2つ以上存在してはいけません(バイナリクレートに上限はありません)。
ビルドの結果、バイナリクレートとライブラリクレートのそれぞれからファイルが得られますが、それらの用途は異なります。
バイナリクレート
バイナリクレートからは実行可能なバイナリが生成されます。バイナリクレートはそれぞれmain
関数が定義されていなければならず、バイナリクレートの数だけバイナリが生成されます。cargo new
した段階では一つのsrc/main.rs
が存在しますが、このファイルはデフォルトでバイナリクレート(のクレートルート)として扱われます。他にバイナリクレートを増やしたい場合は、
- ファイルを作成して
Cargo.toml
に追記する -
src/bin
ディレクトリにファイルを作成する
のどちらかで増やせます。ここで追加する、main
関数が定義されているファイルをバイナリクレートのクレートルートと呼びます。
バイナリクレートは実行可能なエントリポイントであるため、他のクレートから参照されることは想定されていません。
厳密には「バイナリクレートに含まれるコードはモジュールとしてライブラリクレートから再利用可能」にすることは可能です。ただし、通常の使い方では、バイナリクレートは実行エントリポイントであり、他から参照される設計にはしないのが慣例です。
ライブラリクレート
ライブラリクレートからは他のクレートから参照かのうなバイナリが生成されます。ライブラリクレートにはCargo.toml
で定義された名前が付けられます。この名前は一つしか定義できないので、一つのパッケージには二つ以上のライブラリクレートが存在できないのです。
ライブラリクレートはsrc/lib.rs
がクレートルートであると決まっています。
クレートルート
クレートルートとは、あるクレートのトップレベルのファイルを指します。あるクレートに属するモジュールは、クレートルートからのパスを使って、他のモジュールから参照できます。
my_project/
├── Cargo.toml
├── src/
│ ├── main.rs // デフォルトのバイナリクレートのクレートルート
│ ├── lib.rs // デフォルトのライブラリクレートのクレートルート
│ └── bin/
│ ├── additional_binary.rs // 追加のバイナリクレート
│ └── another_binary.rs // さらに追加のバイナリクレート
バイナリクレート
fn main() {
println!("Hello, world!");
}
fn main() {
println!("This is another binary crate!");
}
fn main() {
println!("Yet another binary crate here!");
}
ライブラリクレート
pub fn greet(name: &str) {
println!("Hello, {}!", name);
}
Cargo.toml
で定義されている名前がmy_project
だった場合、他のクレートからはmy_projet::
で参照できます。
use my_project::greet;
fn main() {
greet("Alice");
}
ライブラリクレートがモジュールファイルを参照している場合は、my_project::モジュール名
でそのモジュールを参照できます。
pub mod utilities;
pub fn use_utility_function() {
utilities::helper_function();
}
pub fn helper_function() {
println!("This is a helper function!");
}
use my_project::use_utility_function;
fn main() {
use_utility_function();
}
クレートは、TypeScriptでいうnpmパッケージに近いかもしれません。
バイナリクレートはそれ自身が動作するロジックを持ち、それは一つのパッケージ(Cargoプロジェクトのこと)に複数存在します。
一方、ライブラリクレートはそのパッケージ名を冠した他のクレートに使ってもらうためのクレートです。こちらの方がTypeScriptでいうnpmパッケージの存在に近いでしょうか。