Hello, Cargo!

Cargoは、Rustのビルドシステム兼、パッケージマネージャです。ほとんどのRustaceanはこのツールを使用して、 Rustプロジェクトの管理をしています。Cargoは、コードのビルドやコードが依存しているライブラリのダウンロード、 それらのライブラリのビルド(コードが必要とするライブラリを我々は、依存と呼んでいます)などの多くの仕事を扱ってくれるからです。

今までに書いたような最も単純なRustプログラムは、依存がありません。従って、Hello, world!プロジェクトをCargoを使ってビルドしても、 Cargoのコードをビルドする部分しか使用しないでしょう。より複雑なRustプログラムを書くにつれて、 依存を追加し、Cargoでプロジェクトを開始したら、依存の追加は、遥かに簡単になるのです。

Rustプロジェクトの大多数がCargoを使用しているので、これ以降この本では、あなたもCargoを使用していることを想定します。 Cargoは、「インストール」節で議論した公式のインストーラを使用していれば、勝手にインストールされます。 Rustを他の何らかの手段でインストールした場合、以下のコマンドを端末に入れてCargoがインストールされているか確かめてください:

$ cargo --version

バージョンナンバーが見えたら、インストールされています!command not foundなどのエラーが見えたら、 自分のインストール方法を求めてドキュメンテーションを見、Cargoを個別にインストールする方法を決定してください。

Cargoでプロジェクトを作成する

Cargoを使用して新しいプロジェクトを作成し、元のHello, world!プロジェクトとどう違うかを見ましょう。 projectsディレクトリ(あるいはコードを格納すると決めた場所)に戻ってください。それから、 OSに関わらず、以下を実行してください:

$ cargo new hello_cargo --bin
$ cd hello_cargo

最初のコマンドは、hello_cargoという新しいバイナリの実行可能ファイルを作成します。cargo newに渡した--bin引数が、 ライブラリとは対照的に実行可能なアプリケーション(よく単にバイナリと呼ばれる)を作成します。プロジェクトをhello_cargoと名付け、 Cargoは、そのファイルを同名のディレクトリに作成します。

hello_cargoディレクトリに行き、ファイルを列挙してください。Cargoが2つのファイルと1つのディレクトリを生成してくれたことがわかるでしょう: Cargo.tomlファイルと、中にmain.rsファイルがあるsrcディレクトリです。また、 .gitignoreファイルと共に、新しいGitリポジトリも初期化しています。

注釈: Gitは一般的なバージョンコントロールシステムです。cargo newを変更して、異なるバージョンコントロールシステムを使用したり、 --vcsフラグを使用して何もバージョンコントロールシステムを使用しないようにもできます。 cargo new --helpを走らせて、利用可能なオプションを確認してください。

お好きなテキストエディタでCargo.tomlを開いてください。リスト1-2のコードのような見た目のはずです。

ファイル名: Cargo.toml

[package]
name = "hello_cargo"
version = "0.1.0"
authors = ["Your Name <you@example.com>"]

[dependencies]

リスト1-2: cargo newで生成されるCargo.tomlの中身

このファイルはTOML(Tom's Obvious, Minimal Language; 直訳: トムの明確な最小限の言語)フォーマットで、 Cargoの設定フォーマットです。

最初の行の[package]は、後の文がパッケージを設定していることを示すセクションヘッダーです。もっと情報を追加するにつれて、 別のセクションも追加するでしょう。

その後の3行が、Cargoがプログラムをコンパイルするのに必要な設定情報をセットします: 名前、バージョン、誰が書いたかです。 Cargoは名前とEメールの情報を環境から取得するので、その情報が正しくなければ、 今修正してそれから保存してください。

最後の行の[dependencies]は、プロジェクトの依存を列挙するためのセクションの始まりです。 Rustでは、パッケージのコードはクレートとして参照されます。このプロジェクトでは何も他のクレートは必要ありませんが、 第2章の最初のプロジェクトでは必要なので、その時にはこの依存セクションを使用するでしょう。

では、src/main.rsを開いて覗いてみてください:

ファイル名: src/main.rs

fn main() {
    println!("Hello, world!");
}

ちょうどリスト1-1で書いたように、CargoはHello, world!プログラムを生成してくれています。ここまでで、 前のプロジェクトとCargoが生成したプロジェクトの違いは、Cargoがsrcディレクトリにコードを配置し、 最上位のディレクトリにCargo.toml設定ファイルがあることです。

Cargoは、ソースファイルがsrcディレクトリにあることを期待します。プロジェクトの最上位のディレクトリは、 READMEファイル、ライセンス情報、設定ファイル、あるいは、他のコードに関連しないもののためのものです。 Cargoを使用すると、プロジェクトを体系化する手助けをしてくれます。適材適所であり、 全てがその場所にあるのです。

Hello, world!プロジェクトのように、Cargoを使用しないプロジェクトを開始したら、 実際にCargoを使用するプロジェクトに変換することができます。プロジェクトのコードをsrcディレクトリに移動し、 適切なCargo.tomlファイルを作成してください。

Cargoプロジェクトをビルドし、実行する

さて、CargoでHello, world!プログラムをビルドし、実行する時の違いに目を向けましょう!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 # or .\target\debug\hello_cargo.exe on Windows
                             # あるいは、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がhello_cargoをコンパイルしていることを示唆する出力がないことに気付いてください。 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
   Compiling 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 buildcargo checkでプロジェクトをビルドできる。
  • プロジェクトのビルドと実行を1ステップ、cargo runでできる。
  • ビルドの結果をコードと同じディレクトリに保存するのではなく、Cargoはtarget/debugディレクトリに格納する。

Cargoを使用する追加の利点は、使用しているOSに関わらず、同じコマンドが使用できることです。 故にこの時点で、WindowsとLinux及びmacOSで特定の手順を提供することは最早なくなります。

リリースビルドを行う

プロジェクトを最終的にリリースする準備ができたら、cargo build --releaseを使用して、 最適化を行なってコンパイルすることができます。このコマンドは、target/debugではなく、 target/releaseに実行可能ファイルを作成します。最適化は、Rustコードの実行を速くしてくれますが、 オンにするとプログラムをコンパイルする時間が延びます。このため、2つの異なるプロファイルがあるのです: 頻繁に再ビルドをかけたい開発用と、繰り返し再ビルドすることはなく、できるだけ高速に動いてユーザにあげる最終的なプログラムをビルドする用です。 コードの実行時間をベンチマークするなら、cargo build --releaseを確実に実行し、target/releaseの実行可能ファイルでベンチマークしてください。

習慣としてのCargo

単純なプロジェクトでは、Cargoは単にrustcを使用する以上の価値を生みませんが、プログラムが複雑になるにつれて、 その価値を証明するでしょう。複数のクレートからなる複雑なプロジェクトでは、Cargoにビルドを調整してもらうのが遥かに簡単です。

hello_cargoプロジェクトは単純ではありますが、今では、Rustのキャリアを通じて使用するであろう本物のツールを多く使用するようになりました。 事実、既存のどんなプロジェクトに取り組むにも、以下のコマンドを使用して、Gitでコードをチェックアウトし、 そのプロジェクトのディレクトリに移動し、ビルドできます:

$ git clone someurl.com/someproject
$ cd someproject
$ cargo build

Cargoについてより詳しく知るには、ドキュメンテーションを確認してください。

まとめ

既にRustの旅の素晴らしいスタートを切っています!この章では、以下の方法を学びました:

  • rustupで最新の安定版のRustをインストールする方法
  • 新しいRustのバージョンに更新する方法
  • ローカルにインストールされたドキュメンテーションを開く方法
  • 直接rustcを使用してHello, world!プログラムを書き、実行する方法
  • Cargoの慣習を使用して新しいプロジェクトを作成し、実行する方法

より中身のあるプログラムをビルドし、Rustコードの読み書きに慣れるいいタイミングです。故に、第2章では、 数当てゲームを構築します。むしろ一般的なプログラミングの概念がRustでどう動くのか学ぶことから始めたいのであれば、 第3章を見て、それから第2章に戻ってください。