Cargoは、Rustのビルドシステム兼パッケージマネージャです。大抵のRustaceanはこのツールを使用して、自分のRustプロジェクトを管理をしています。というのも、Cargoは、あなたに代わって、コードのビルドやコードが依存しているライブラリのダウンロード、それらのライブラリのビルドなどの多くの仕事をこなしてくれるからです(ところで、Rustではあなたのプログラムが必要とするライブラリを「依存 dependencies」と呼んでいます)。
《訳注》 ビルド build: 〔建築する、の意〕 プログラムのソースコードを「実行可能なファイル」に変換すること。
先ほど書いたような最も単純なRustプログラムには、依存がありません。従って、「Hello, world!」プロジェクトでCargoを使っても、Cargoのコードをビルドする部分しか使用しないでしょう。より複雑なRustプログラムを書くようになるにつれて、依存を追加するようになりますが、Cargoを使ってプロジェクトを開始すれば、依存の追加は遥かに簡単になるのです。
Rustプロジェクトの大多数がCargoを使用しているので、これ以降この本では、あなたもCargoを使用していることを想定して話を進めます。Cargoは、「インストール」のところで説明した公式のインストーラーを使用していれば、勝手にインストールされています。Rustを何か他の手段でインストールした場合には、以下のコマンドを端末に入力してCargoがインストールされているか確かめてください:
cargo --version
バージョンナンバーが表示されれば、インストールされています! command not found
などのエラーが表示される場合は、自分がインストールした方法のドキュメンテーションで、Cargo を個別にインストールする方法を確認してください。
Cargoを使用して新しいプロジェクトを作成し、元の「Hello, world!」プロジェクトとどう違うかを見てみましょう。最初に作った「projects」ディレクトリ(あるいはコードを格納すると決めた場所)に戻ってください。それから、以下を実行してください(どのOSでも同じです):
cargo new hello_cargo
cd hello_cargo
最初のコマンド(cargo new
)で、「hello_cargo」という新しいディレクトリを作成します。私たちがプロジェクトに「hello_cargo」という名前を付けると、Cargoは同じ名前のディレクトリを作成して、その中に関連ファイルを作成します。
「hello_cargo」 ディレクトリに移動し、その中のファイルを見てください。Cargoが2つのファイルと1つのディレクトリを生成してくれたことがわかるでしょう: 作成されたのは Cargo.toml ファイルと、中に main.rs ファイルが入ったsrc(ソース source)ディレクトリです。
また、.gitignoreファイルと共に、新しい「Gitリポジトリ」も初期化されています。もしすでにGitリポジトリが存在し、その中でcargo new
を実行したのであれば、Git関連のファイルは生成されません。この挙動(振る舞い)はcargo new –vcs=git
を用いることで変更(オーバーライド)できます。
【原文注記】 Gitは一般的なバージョン管理システムです。`cargo new` に `--vcs` フラグを用いることで、別のバージョンコントロールシステムを使用したり、バージョンコントロールシステムを使用しないようにもできます。利用可能なオプションを確認するには`cargo new --help`を実行します。
ご自分のお気に入りのテキストエディタで Cargo.toml を開いてください。リスト1-2のようになっているはずです。
ファイル名: Cargo.toml
[package]
name = "hello_cargo"
version = "0.1.0"
edition = "2021"
[dependencies]
このファイルは TOML フォーマット(Tom’s Obvious, Minimal Language; 直訳 =トムの明瞭で最小限の言語)で、Cargo の設定フォーマットです。
最初の行の[package]
はセクションヘッダーで、それ以降の文がこの「パッケージ」の設定内容であることを示します。このファイルに情報を追加すると、他のセクションも追加されます。
ヘッダーに続く3行は、Cargoがプログラムをコンパイルするために必要な設定情報を指定します(プログラムの名前、バージョン、使用しているRustのエディション)。編集キー edition については付録 E の「エディション」(Appendix E)にて説明します。
最後の行[dependencies]
は、あなたのプロジェクトの依存関係を列挙するためのセクションの始まりです。Rustでは「コードのパッケージ」のことをクレートと呼びます。この「hello_cargo」プロジェクトではクレートは必要ありませんが、第2章のプロジェクトでは必要になるので、そのときにこの依存セクションを使用します。
《訳注》 クレート crates: 〔木箱・木枠、の意〕 Rustにおけるコンパイルの単位(もっとも基本的なソフトウェアの単位)。「クレート」関しては 第7.1章 パッケージとクレートに詳しい解説があります。
では、src/main.rsを開いて覗いてみてください:
ファイル名: src/main.rs
fn main() {
println!("Hello, world!");
}
Cargoが、私たちが第1.2章のリスト1-1で書いたような「Hello, world!」プログラムを生成してくれています。ここまでのところ、以前のプロジェクトとCargoが生成したこのプロジェクトとの違いは、Cargoがコードをsrcディレクトリに配置し、最上位のディレクトリに Cargo.toml 設定ファイルがあることです。
Cargoはソースファイルが「src」ディレクトリに保存されていることを想定しています。プロジェクトの最上位ディレクトリは、READMEファイル、ライセンス情報、設定ファイル、あるいは、コードに関連しないものだけを置きます。Cargoを使うとプロジェクトを整理することができます。すべてのものに決まった場所があり、すべてがそのあるべき場所にあるのです。
「Hello, world!」プロジェクトのように、Cargoを使用せずにプロジェクトを開始したときでも、Cargoを使用するプロジェクトに変換することができます。プロジェクトのコードをsrcディレクトリに移動し、適切なCargo.tomlファイルを作成すればよいのです。
では「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)に作成します。以下のコマンドで実行可能ファイルを実行できます。
$ ./target/debug/hello_cargo
Hello, world!
【原文注記】ウィンドウズの場合は「.\target\debug\hello_cargo.exe」と入力してください。
すべてがうまくいけば、端末に Hello, world!
が表示されるはずです。cargo build
の実行が初めての場合では、実行するとCargoが最上位ディレクトリにCargo.lockという新しいファイルを作成します。このファイルはプロジェクト内の依存関係の正確なバージョンを記録しています。今回のプロジェクトには依存がないので、ファイルの中は少しまばらです。このファイルは手動で修正する必要はありません; Cargoがあなたに代わって内容を管理してくれるのです。
先ほどはcargo build
を使ってプロジェクトをビルドし、./target/debug/hello_cargoで実行しました。しかし、cargo run
というコマンドを使うと、コードのコンパイルから作成された実行可能ファイルの実行までの流れを一つのコマンドで行なえます:
$ cargo run
Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs
Running `target/debug/hello_cargo`
Hello, world!
今回はCargoが「hello_cargo
をコンパイル中(Compiling ...)」というメッセージがないことに注目してください。これは、Cargoがファイル内容に変更がないことを把握したので、単にバイナリを実行したからです。もしソースコードを変更していたら、Cargoは実行前にプロジェクトを再ビルドし、以下のような出力を表示したことでしょう:
$ 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を使用するもう一つの利点は、どのOSで作業していてもコマンドが同じであることです。そのため、これ以降はLinuxやmacOS向けの手順と、Windows向けの手順を分けて説明することはありません。
プロジェクトが最終的にリリースできる状態になったら、cargo build --release
を使用してコンパイルすると、最適化した状態にビルドできます。このコマンドは、実行ファイルを「target/debug」ではなく、「target/release」に作成します。最適化によってRustコードの実行速度は上がりますが、最適化機能を有効にすることでプログラムのコンパイル時間が長くなります。このため二つの異なるビルド・プロファイルが用意されています: 一つは開発用(devモード)で、素早く頻繁に再ビルドしたいときのもの。もう一つはユーザーに渡す最終的なプログラムをビルドするためのもので、繰り返し再ビルドすることはなく、可能な限り高速に動作するようにします。コードの実行時間を評価基準にするであれば、cargo build --release
を確実に実行し、target/releaseの実行可能ファイルを使って評価してください。
単純なプロジェクトでは、Cargoは単にrustc
を使うだけで、あまり多くの価値を生みませんが、プログラムが複雑になるにつれて、その真価を証明するでしょう。複数のクレートからなる複雑なプロジェクトでは、Cargoにビルド時の調整をしてもらうほうが遥かに簡単です。
「hello_cargo」プロジェクトは単純ではありますが、Rustプログラマとしてキャリアを通じて使うことになる本物のツールを多く使用しています。実際、既存のどんなプロジェクトで作業するときも、Gitを使ってコードをチェックアウトし、そのプロジェクトのディレクトリに移動し、ビルドすることができます。:
$ git clone example.org/someproject
$ cd someproject
$ cargo build
Cargo についてより詳しく知るには、「ドキュメンテーション(The Cargo Book)」(英語版サイト)で確認してください。
あなたは既に、Rustの旅の素晴らしいスタートを切っています! 第1章では、以下の事柄を学びました:
rustup
で最新安定版のRustをインストールする方法- 新しいRustのバージョンに更新する方法
- ローカルにインストールされたドキュメンテーションを開く方法
- 直接
rustc
を使用して「Hello, world!」プログラムを書き、実行する方法 - Cargo の定石を使用して新しいプロジェクトを作成し、実行する方法
次に、より中身のあるプログラムをビルドし、Rustコードの読み書きに慣れるいいタイミングです。よって、第2章では「数当てゲーム」を構築します。もし一般的なプログラミングの概念がRustでどう動くのかを学ぶことから始めたいのであれば、第3章を見て、それから第2章に戻ってください。