こんにちは、Cargo!
Cargo は Rust のビルドシステムであり、パッケージマネージャーです。ほとんどの Rust 開発者はこのツール を使って Rust プロジェクトを管理しています。これは、Cargo がコードのビルド、 コードが依存するライブラリのダウンロード、それらのライブラリのビルドなど、 多くの作業を代わりに処理してくれるからです。(コードが必要とするライブラリを 依存関係 と呼びます。)
これまでに書いてきたもののような単純な Rust プログラムには、依存関係が ありません。「Hello, world!」プロジェクトを Cargo でビルドしていたとしても、 使われるのはコードのビルドを担当する Cargo の部分だけです。より複雑な Rust プログラムを 書くようになると依存関係を追加することになりますが、Cargo を使ってプロジェクトを 始めていれば、依存関係の追加はずっと簡単になります。
Rust プロジェクトの大半は Cargo を使っているため、本書の残りの部分でも あなたも Cargo を使っていることを前提に進めます。Cargo は、 「インストール」 節で説明した公式インストーラーを 使って Rust をインストールしたなら一緒にインストールされています。別の方法で Rust を インストールした場合は、次のコマンドをターミナルで入力して、Cargo がインストール されているか確認してください:
$ cargo --version
バージョン番号が表示されれば、Cargo はインストールされています! command not found のようなエラーが表示された場合は、使ったインストール方法のドキュメントを
確認して、Cargo を個別にインストールする方法を調べてください。
Cargo でプロジェクトを作成する
Cargo を使って新しいプロジェクトを作成し、それが元の「Hello, world!」プロジェクトと どう違うのかを見てみましょう。projects ディレクトリ(あるいは、コードを保存する場所として 選んだディレクトリ)に戻ってください。そのうえで、どのオペレーティングシステムでも、 次を実行します:
$ cargo new hello_cargo
$ cd hello_cargo
最初のコマンドは、hello_cargo という名前の新しいディレクトリとプロジェクトを作成します。 ここではプロジェクト名を hello_cargo にしたので、Cargo はそのファイルを 同じ名前のディレクトリに作成します。
hello_cargo ディレクトリに移動して、ファイルを一覧表示してください。Cargo が 2 つのファイルと 1 つのディレクトリを生成してくれていることがわかります。つまり、 Cargo.toml ファイルと、その中に main.rs ファイルを含む src ディレクトリです。
さらに、.gitignore ファイルとともに新しい Git リポジトリも初期化されています。
既存の Git リポジトリ内で cargo new を実行した場合、Git 関連のファイルは生成されません。
この挙動は cargo new --vcs=git を使うことで上書きできます。
注: Git は一般的なバージョン管理システムです。
--vcsフラグを使うと、cargo newを 別のバージョン管理システムを使うようにしたり、バージョン管理を使わないようにしたり できます。利用可能なオプションを見るにはcargo new --helpを実行してください。
お好みのテキストエディターで Cargo.toml を開いてください。リスト 1-2 の コードのようになっているはずです。
[package]
name = "hello_cargo"
version = "0.1.0"
edition = "2024"
[dependencies]
このファイルは、Cargo の設定フォーマットである TOML (Tom’s Obvious, Minimal Language)形式です。
最初の行 [package] はセクション見出しで、続く記述がパッケージを設定するもので
あることを示しています。このファイルにさらに情報を追加していくと、ほかのセクションも追加していきます。
次の 3 行では、Cargo がプログラムをコンパイルするために必要な設定情報、
つまり名前、バージョン、そして使用する Rust のエディションを設定しています。
edition キーについては 付録 E で説明します。
最後の行 [dependencies] は、プロジェクトの依存関係を列挙するためのセクションの
始まりです。Rust では、コードのパッケージを クレート と呼びます。このプロジェクトでは
ほかのクレートは必要ありませんが、第 2 章の最初のプロジェクトでは必要になるので、
そのときにこの dependencies セクションを使います。
では、src/main.rs を開いて見てみましょう:
ファイル名: src/main.rs
fn main() {
println!("Hello, world!");
}
Cargo は、リスト 1-1 で書いたものと同じ「Hello, world!」プログラムを生成してくれています! ここまでのところ、私たちのプロジェクトと Cargo が生成したプロジェクトの違いは、 Cargo がコードを src ディレクトリに置き、 トップディレクトリに Cargo.toml 設定ファイルがあることです。
Cargo は、ソースファイルが src ディレクトリの中に置かれていることを前提としています。トップレベルの プロジェクトディレクトリは、README ファイル、ライセンス情報、 設定ファイル、そのほかコードに関係のないもののためだけにあります。Cargo を使うと、 プロジェクトを整理しやすくなります。すべてのものに置き場所があり、すべてがその場所に収まります。
「Hello, world!」プロジェクトで行ったように、Cargo を使わないプロジェクトから始めた場合でも、
Cargo を使うプロジェクトに変換できます。プロジェクトのコードを src ディレクトリに移し、適切な Cargo.toml
ファイルを作成してください。その Cargo.toml ファイルを用意する簡単な方法のひとつは
cargo init を実行することで、これにより自動的に作成されます。
Cargo プロジェクトのビルドと実行
では、「Hello, world!」プログラムを Cargo でビルドして実行すると何が違うのかを 見てみましょう! hello_cargo ディレクトリで、次のコマンドを入力して プロジェクトをビルドしてください:
$ cargo build
Compiling hello_cargo v0.1.0 (file:///projects/hello_cargo)
Finished dev [unoptimized + debuginfo] target(s) in 2.85 secs
このコマンドは、現在のディレクトリではなく target/debug/hello_cargo(Windows では target\debug\hello_cargo.exe)に実行可能ファイルを作成します。デフォルトのビルドは デバッグビルドなので、Cargo はバイナリを debug という名前のディレクトリに 配置します。次のコマンドでその実行可能ファイルを実行できます:
$ ./target/debug/hello_cargo # または Windows では .\target\debug\hello_cargo.exe
Hello, world!
すべてがうまくいけば、Hello, world! がターミナルに表示されるはずです。最初に cargo build を実行すると、Cargo はトップレベルに Cargo.lock という新しいファイルも
作成します。このファイルは、プロジェクトの依存関係の正確なバージョンを記録します。
このプロジェクトには依存関係がないので、ファイルの内容は少し簡素です。このファイルを
手動で変更する必要はありません。Cargo がその内容を管理してくれます。
私たちは今、cargo build でプロジェクトをビルドし、
./target/debug/hello_cargo で実行しましたが、cargo run を使えばコードを
コンパイルして、生成された実行可能ファイルを 1 つのコマンドですぐに実行することもできます:
$ cargo run
Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs
Running `target/debug/hello_cargo`
Hello, world!
cargo run を使うほうが、cargo build を実行してからバイナリへの完全なパスを
使うことを覚えておくよりも便利なので、ほとんどの開発者は cargo run を使います。
今回は、Cargo が hello_cargo をコンパイルしていることを示す出力が表示されなかったことに
注目してください。Cargo はファイルが変更されていないことを判断したので、再ビルドせずに
バイナリを実行しただけです。ソースコードを変更していたなら、Cargo は実行前にプロジェクトを
再ビルドし、次のような出力が表示されていたでしょう:
```console
$ cargo run
Compiling hello_cargo v0.1.0 (file:///projects/hello_cargo)
Finished dev [unoptimized + debuginfo] target(s) in 0.33 secs
Running `target/debug/hello_cargo`
Hello, world!
Cargo には cargo check というコマンドも用意されています。このコマンドは、
実行可能ファイルを生成せずに、コードがコンパイルできることをすばやく確認します。
$ cargo check
Checking hello_cargo v0.1.0 (file:///projects/hello_cargo)
Finished dev [unoptimized + debuginfo] target(s) in 0.32 secs
なぜ実行可能ファイルが不要なのでしょうか。多くの場合、cargo check は
cargo build よりもはるかに高速です。これは、実行可能ファイルを生成する
手順を省くためです。コードを書きながら継続的に作業内容を確認しているなら、
cargo check を使うことで、プロジェクトが引き続きコンパイルできるかどうかを
把握するまでの時間を短縮できます。したがって、多くの Rustacean はプログラムを
書いている間、コンパイルできることを確認するために定期的に cargo check を
実行します。そして、実行可能ファイルを使う準備ができたら cargo build を
実行します。
ここまでに Cargo について学んだことを振り返ってみましょう。
cargo newを使ってプロジェクトを作成できる。cargo buildを使ってプロジェクトをビルドできる。cargo runを使って、プロジェクトのビルドと実行を 1 ステップで行える。cargo checkを使って、バイナリを生成せずにエラーを確認するためのビルドができる。- Cargo は、ビルド結果をコードと同じディレクトリに保存するのではなく、 target/debug ディレクトリに保存する。
Cargo を使うもう 1 つの利点は、どのオペレーティングシステムで作業していても コマンドが同じであることです。したがって、この時点からは、Linux や macOS と Windows を分けた個別の説明はもう行いません。
リリース用にビルドする
プロジェクトがついにリリースの準備ができたら、cargo build --release を使って最適化付きでコンパイルできます。このコマンドは、
実行可能ファイルを target/debug ではなく target/release に作成します。
最適化によって Rust のコードはより高速に実行されますが、それを有効にすると
プログラムのコンパイルにかかる時間は長くなります。そのため、2 つの異なる
プロファイルがあります。1 つは、すばやく何度も再ビルドしたい開発用のもの、
もう 1 つは、繰り返し再ビルドされることはなく、できるだけ高速に動作してほしい、
ユーザーに渡す最終的なプログラムをビルドするためのものです。コードの実行時間を
ベンチマークする場合は、必ず cargo build --release を実行し、
target/release にある実行可能ファイルでベンチマークしてください。
Cargo の規約を活用する
単純なプロジェクトでは、Cargo は単に rustc を使う場合と比べてそれほど大きな
価値を提供しませんが、プログラムがより複雑になるにつれて、その真価を発揮します。
プログラムが複数のファイルにまたがったり依存関係を必要としたりするようになると、
ビルドの調整を Cargo に任せるほうがはるかに簡単です。
hello_cargo プロジェクトは単純ですが、それでも今後の Rust キャリアを通じて
使うことになる本格的なツール群の多くをすでに利用しています。実際、既存の
プロジェクトで作業するには、Git を使ってコードをチェックアウトし、その
プロジェクトのディレクトリに移動してビルドするために、次のコマンドを使えます。
$ git clone example.org/someproject
$ cd someproject
$ cargo build
Cargo の詳細については、ドキュメントを参照してください。
まとめ
Rust の学習は、すでにとても良いスタートを切っています! この章では、次のことを 学びました。
rustupを使って Rust の最新の安定版をインストールする。- より新しい Rust バージョンに更新する。
- ローカルにインストールされたドキュメントを開く。
rustcを直接使って “Hello, world!” プログラムを書いて実行する。- Cargo の規約に従って新しいプロジェクトを作成し、実行する。
ここは、Rust のコードを読んだり書いたりすることに慣れるため、もう少し本格的な プログラムを作ってみる絶好のタイミングです。そこで、第 2 章では数当てゲームの プログラムを作成します。Rust における一般的なプログラミングの概念がどのように 機能するかを先に学びたい場合は、第 3 章を見てから第 2 章に戻ってください。