パッケージとクレート
モジュールシステムで最初に取り上げる要素は、パッケージとクレートです。
クレート は、Rust コンパイラが一度に対象とするコードの最小単位です。
第1章の 「Rustプログラムの基本」 で行ったように、cargo ではなく rustc を実行して 1 つのソースコード
ファイルだけを渡した場合でも、コンパイラはそのファイルを 1 つのクレートと
見なします。クレートにはモジュールを含めることができ、そのモジュールは、
これからの節で見るように、クレートとともにコンパイルされる別のファイルで
定義されていることもあります。
クレートには 2 つの形式があります。バイナリクレートとライブラリクレートです。
バイナリクレート は、コンパイルして実行可能ファイルにできるプログラムです。
たとえば、コマンドラインプログラムやサーバーがこれに当たります。どの
バイナリクレートにも、実行可能ファイルが動いたときに何が起こるかを定義する
main という関数がなければなりません。これまで作成してきたクレートは、
すべてバイナリクレートでした。
ライブラリクレート には main 関数がなく、実行可能ファイルにも
コンパイルされません。その代わり、複数のプロジェクトで共有することを意図した
機能を定義します。たとえば、第2章で使った rand クレート
rand は、乱数を生成する機能を提供します。多くの場合、
Rustacean が「crate」と言うとき、それはライブラリクレートを意味しており、
「crate」を一般的なプログラミングの概念である「ライブラリ」とほぼ同じ意味で
使っています。
クレートルート は、Rust コンパイラが処理を開始するソースファイルであり、 クレートのルートモジュールを構成するものです(モジュールについては 「モジュールでスコープとプライバシーを制御する」 で詳しく説明します)。
パッケージ は、一連の機能を提供する 1 つ以上のクレートをまとめたものです。 パッケージには、それらのクレートをどのようにビルドするかを記述した Cargo.toml ファイルが含まれます。Cargo は実際には、これまでコードの ビルドに使ってきたコマンドラインツール用のバイナリクレートを含む パッケージです。Cargo パッケージには、バイナリクレートが依存する ライブラリクレートも含まれています。他のプロジェクトは Cargo の ライブラリクレートに依存することで、Cargo コマンドラインツールが使っている のと同じロジックを利用できます。
パッケージには、好きなだけ多くのバイナリクレートを含めることができますが、 ライブラリクレートは多くても 1 つだけです。パッケージには、ライブラリ クレートであれバイナリクレートであれ、少なくとも 1 つのクレートが 含まれていなければなりません。
では、パッケージを作成したときに何が起こるのかを見ていきましょう。まず、
cargo new my-project というコマンドを入力します。
$ cargo new my-project
Created binary (application) `my-project` package
$ ls my-project
Cargo.toml
src
$ ls my-project/src
main.rs
cargo new my-project を実行したあと、Cargo が何を作成したかを見るために
ls を使います。my-project ディレクトリには、パッケージを構成する
Cargo.toml ファイルがあります。また、main.rs を含む src
ディレクトリもあります。テキストエディタで Cargo.toml を開くと、
そこには src/main.rs への記述がないことがわかります。Cargo は、
src/main.rs がパッケージと同じ名前を持つバイナリクレートの
クレートルートであるという慣習に従います。同様に、パッケージディレクトリに
src/lib.rs が含まれていれば、そのパッケージにはパッケージと同じ名前の
ライブラリクレートが含まれており、src/lib.rs がそのクレートルートで
あることを Cargo は認識します。Cargo は、ライブラリまたはバイナリを
ビルドするために、クレートルートファイルを rustc に渡します。
ここでは、src/main.rs だけを含むパッケージがあり、つまり
my-project という名前のバイナリクレートだけを含んでいます。パッケージに
src/main.rs と src/lib.rs の両方が含まれている場合、そのパッケージには
2 つのクレート、すなわちバイナリクレートとライブラリクレートがあり、
どちらもパッケージと同じ名前を持ちます。src/bin ディレクトリに
ファイルを置くことで、パッケージは複数のバイナリクレートを持てます。
各ファイルは個別のバイナリクレートになります。