hiro99ma blog

rust: クレート、パッケージ、モジュール

最終更新日: 2025/07/06

概要

プログラムを複数のファイルに分割したときの取り扱い方について。
Cargoを使う前提とする。

参考

クレート(crate)

コンパイルは「クレート」が最小単位となっている。

image

バイナリクレートライブラリクレートの種類が生まれるのはパッケージのようにも思うが、細かく区別する必要もないだろう。
バイナリクレートはcargo new --bin(--binはデフォルトなのでなくてもよい)で作られるタイプでsrc/main.rsがエントリーポイントと思っていて良いだろう。
ライブラリクレートはsrc/lib.rsを持つ。

cargo addはクレートを追加するManifestコマンドで、空のクレートを追加するのではなくCargo.tomlに依存関係を追加するコマンドである。 「Cargo.toml Manifestファイル」と書いてあるので、ManifestコマンドはCargo.tomlに関するコマンドだろう。

パッケージ(package)

「パッケージ」は1つ以上のクレートを持つ。
cargo newで作られるのはパッケージである。packageコマンドという分類になっている。

image

ライブラリクレートは最大でも1つなのでsrc/lib.rsがあるかどうかでわかる。
Cargo.tomlでは[lib]セクションでカスタマイズできる。

バイナリクレートもsrc/main.rsがあるかどうかでわかるのだが、こちらは複数持つことができる。その場合はsrc/bin/にディレクトリを作ってmain.rsを置く。
src/main.rsを持たずにsrc/bin/*に複数のディレクトリを作ってそれぞれにmain.rsを持っても良い。
Cargo.tomlでは[[bin]]セクションでカスタマイズできる。括弧が1つ多い。

モジュール(module)

クレートやパッケージがどちらかといえば物理的?なのに対して、モジュールはどちらかといえば論理的なものだという印象を持った。
たぶんmodで定義できるからそう感じるのだろう。

mod <mod名> {...}という書き方はmodの定義と宣言を兼ねている。
mod <mod名>;とすると、このファイルでmod名というモジュールを使用するという宣言になる。

modの定義

同じファイルの中にあるので定義と使用する宣言を兼ねている。
useはC++のusingusing namespaceを混ぜたような使い方になる。

mod world_mod1 {
    pub mod world_mod2 {
        pub fn world_func() {
            println!("abc world")
        }
    }
}

use world_mod1::world_mod2::world_func as w;
use world_mod1::world_mod2 as w2;
use world_mod1 as w3;

fn main() {
    world_mod1::world_mod2::world_func();
    w();
    w2::world_func();
    w3::world_mod2::world_func();
}

mod名のファイルを作る

例えばhello_mod.rsというファイルを作り、その中にhello_func()という関数を作ったとする。

pub fn hello_func() {
    println!("Hello, abc!");
}

それと同じディレクトリにあるmain.rsからhello_func()を呼び出したい場合はこうなる。

mod hello_mod;

fn main() {
  hello_mod::hello_func();
}

つまりmod <ファイル名> {}で定義したのと同じ意味を持つことになる。

ディレクトリを作ってその下にmod名のファイルを作る

同じディレクトリではなく別のディレクトリにしたい場合もある。

hello_func()を含んだファイルをhello_mod2.rsとする。
ディレクトリhello_mod1を作ってhello_mod2.rsを移動させる。

そうすると、なんとなくmain.rsからはmod hello_mod1::hello_mod2;と書けばよさそうな気がするが、そうは書けない。
modに書けるのは単独のモジュール名だけで::は使えないのだった。
その代わりに、hello_mod1.rsというファイルをmain.rsと同じディレクトリに作り、その中でpub mod hello_mod2;と書く。

以前はmod.rsというファイルに書く方式だったが今ではこうらしい。

モジュールツリー

モジュールは入れ子にできるので、モジュールツリーと呼ぶツリー構造として表すようになっている。
ツリーのルートはmain.rslib.rsである。
use world_mod1::world_mod2 as w2;のように書いたあれは相対パスのような表現で、 これを絶対パスのような表現にするとuse crate::world_mod1::world_mod2 as w2;とルートを表すcrate::が頭に付く。

そうなると、モジュールとして扱えるのは今のクレートの中だけということになるのでは?
もちろんそういうことはなく、外部で既に公開されている関数などを使うこともできる。

「パッケージ」なのだ。
とはいえ実行ファイルを取り込むこともできないだろうから、ライブラリクレートを含むパッケージのはずである。
パッケージには最大で 1つまでしかライブラリクレートを持つことができないので、ライブラリクレートを持つパッケージのみuseで使えるようにできるのだろう。

image

記載予定

writer: hiro99ma
tags: Rust language   

 < Top page

コメント(Google Formへ飛びます)

GitHub

X/Twitter

Homepage

About me