[Rust 入門] #01 Rust とは — 環境構築と Hello World、Cargo が作るファイルを読む

[Rust 入門] #01 Rust とは — 環境構築と Hello World、Cargo が作るファイルを読む

はじめに

Rust で、デスクトップアプリを、いくつも作ってきました(Tote、shotkey、HotRun、WiredFrame、DDlauncher)。ただ、Rust そのものを、順を追って学んだことはありません。ほかの言語で学んだ知識をもとに、コードを読んで、動かしながら、理解してきました。

そこで、基礎から順に、学び直す連載を始めます。第1回は、環境を作って、Hello World を動かして、Cargo が作るファイルを読むところまでです。

このシリーズについて

連載は、3つの編で進める予定です。回数は、書きながら増減します。

編内容回数(仮)
入門編所有権を越えるところまで。変数・型、所有権、借用、構造体と enum、エラー処理、トレイト、ライフタイム8
実践編Tauri で、自作アプリの中身を分解する8
応用編WASM と、エミュレーター8

各回に、動くサンプルを1つ残します。サンプルの出力は、実際に動かした結果を、そのまま載せます。

Rust とは

Rust は、コンパイルして、実行ファイルを作る言語です。ガベージコレクタ(GC)は持たず、所有権という決まりで、メモリの安全さを、コンパイルの時点で確かめます。

Java を使ってきた立場から、並べるとこうなります。

観点JavaRust
実行の形バイトコードを、JVM が実行する機械語の実行ファイルを作る
メモリの管理GC が、使われなくなった物を片付ける所有権の決まりで、コンパイル時に決める(GC なし)
値がないことnullOption(第6回)
エラー例外(throw / catch)Result(第6回)
型静的型付け静的型付け(型推論が強い)

表の「第6回」は、あとの回で扱います。今回は、「コンパイルして、実行ファイルができる」ことと、「GC がない」ことだけを、覚えておけば足ります。

歴史

Rust は、Mozilla の社員だった Graydon Hoare が、個人のプロジェクトとして、2006年に作り始めた言語です。名前は、さび菌(rust fungus)に由来すると、言われています。

年できごと
2006Graydon Hoare が、個人のプロジェクトとして、作り始める
2009Mozilla が、公式に支援を始める
2011コンパイラが、OCaml 製から、Rust 自身で書かれたもの(セルフホスト)に切り替わる。LLVM を使う
2012年1月最初の公開版 0.1 が出る
2013Hoare が、プロジェクトの中心から退く。GC が、言語から取り除かれ、所有権が中心になる
2014年3月言語の変更を、RFC(提案書)で決める仕組みが始まる
2015年5月15日Rust 1.0。最初の安定版
2016〜2017Firefox が、Rust のコードを取り込み始める(Firefox 45 以降。57 では、Servo の部品が入る)
2020年8月Mozilla の人員整理で、Rust チームの多くが、職を失う
2021年2月8日Rust Foundation 設立。創設メンバーは、AWS、Huawei、Google、Microsoft、Mozilla
2022年末〜Linux カーネルが、Rust の実験的な対応を始める(6.1 以降)

表の中で、この記事の内容に関わるのは、次の3つです。

  • 2013年に、GC が取り除かれたことで、「GC がなく、所有権で守る」という、いまの形になりました。第3回で扱う所有権は、この時期に、言語の中心になっています
  • 2015年の 1.0 で、互換性の約束が始まりました。以降は、安定版で書いたコードが、新しい版でも、動き続けることを目指しています
  • 2020〜2021年に、Mozilla から、Rust Foundation へ、運営が移りました。ひとつの会社の製品ではなく、複数の会社が支える形になっています

エディション

互換性を保ったまま、言語を変えていくための仕組みが、エディションです。数年に一度、新しいエディションが出ます。使うエディションは、クレートごとに、Cargo.toml で選びます。エディションの違うクレート同士でも、組み合わせて使えます。

エディション入った版日付
20151.02015年5月15日
20181.312018年12月6日
20211.562021年10月21日
20241.852025年2月20日

cargo new で作ったプロジェクトは、そのときの最新のエディションで始まります。後で見る Cargo.toml に、edition = "2024" と書かれているのは、そのためです。古いエディションのプロジェクトは、そのまま動かせます。

環境を作る

Rust の道具は、rustup が入れます。rustup は、Rust のバージョンを入れ替えたり、更新したりする、管理用のツールです。入ると、次の 3 つが使えるようになります。

  • rustc: コンパイラ
  • cargo: ビルドとパッケージの管理(普段は、こちらを使います)
  • rustup: バージョンの管理

Windows

  1. rustup.rs から、rustup-init.exe をダウンロードして、実行します
  2. C++ のビルドツール(Microsoft C++ Build Tools)が必要です。無ければ、画面の案内に沿って入れます
  3. 終わったら、ターミナルを開き直します

macOS / Linux

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

macOS では、先に、xcode-select --install で、コマンドラインツールを入れておきます。

入ったか確かめる

rustc --version
cargo --version
rustc 1.97.0 (2d8144b78 2026-07-07)
cargo 1.97.0 (c980f4866 2026-06-30)

バージョンの数字は、入れた時期によって変わります。更新するときは、rustup update です。

cargo で Hello World

cargo new hello
cd hello
    Creating binary (application) `hello` package
note: see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

hello というフォルダーができます。中は、これだけです。

hello/
├── .git/            ← git の入れ物(自動で作られます)
├── .gitignore       ← 中身は `/target` だけ
├── Cargo.toml       ← プロジェクトの設計図
└── src/
    └── main.rs      ← プログラム本体

Cargo.toml

[package]
name = "hello"
version = "0.1.0"
edition = "2024"

[dependencies]
行意味
nameパッケージの名前。実行ファイルの名前にもなります
versionバージョン
edition使うエディション
[dependencies]使うクレート(他の人が作った部品)を、ここに並べます。今は空です

Java で言えば、pom.xml や build.gradle にあたるものです。

src/main.rs

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

実行します。

cargo run
   Compiling hello v0.1.0 (/tmp/rs/hello)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 5.16s
     Running `target/debug/hello`
Hello, world!

cargo run は、ビルドして、そのまま実行する命令です。上の3行の意味は、次のとおりです。

  • Compiling: コンパイルしています
  • Finished: できました。dev は、開発用のビルド(最適化なし、デバッグ情報つき)です
  • Running: できた実行ファイルを、動かしています

もう一度、続けて実行すると、こうなります。

    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.00s
     Running `target/debug/hello`
Hello, world!

ソースが変わっていないと、コンパイルは、やり直されません。

main.rs を読む

fn main() {
    println!("Hello, world!");
}
部分意味
fn関数を作る、という宣言です
mainプログラムが、ここから始まります。引数も、戻り値も、書かなくてよい形です
{ }関数の中身
println!画面に、1 行出すマクロです。名前の最後の ! が、マクロの印です
"Hello, world!"文字列
;文の終わり。付け忘れると、コンパイルできません

Java の System.out.println("Hello, world!"); は、public static void main(String[] args) を、クラスの中に書く必要があります。Rust は、クラスも、public static も、書きません。

println! の書式

println! は、{} の場所に、値を入れて表示します。

fn main() {
    let name = "lain";
    let n = 3;
    println!("Hello, {}!", name);
    println!("{} と {} を足すと {}", n, 4, n + 4);
    println!("{name} は {n} 回呼ばれました");
    println!("[{:>6}] [{:<6}] [{:^6}]", "右", "左", "中");
    println!("{:?} / {:?}", name, (n, 4.5));
}
Hello, lain!
3 と 4 を足すと 7
lain は 3 回呼ばれました
[     右] [左     ] [  中   ]
"lain" / (3, 4.5)
書き方意味
{}順番に、値を入れます
{name}変数の名前を、そのまま書けます
{:>6} / {:<6} / {:^6}幅 6 で、右 / 左 / 中央に寄せます
{:?}デバッグ用の表示。文字列には、引用符がつきます。タプルも、そのまま出せます

let は、変数を作る宣言です。型は、書かなくても、決まります。変数と型は、第2回で詳しく扱います。

cargo の基本コマンド

コマンド内容
cargo new 名前新しいプロジェクトを作ります
cargo runビルドして、実行します
cargo buildビルドだけ行います(target/debug/ にできます)
cargo build --release最適化つきで、ビルドします(target/release/ にできます)
cargo checkコンパイルが通るかだけを、確かめます。実行ファイルは作りません。速いです
cargo fmtコードの書き方を、整えます
cargo clippy書き方の、よくない所を、指摘します

debug と release の大きさ

同じ Hello, world! を、2通りでビルドして、実行ファイルの大きさを測りました(Linux、Rust 1.97.0)。

ビルド大きさ
cargo build(debug)4,408,008 バイト(約 4.4 MB)
cargo build --release474,928 バイト(約 475 KB)

debug は、デバッグ用の情報が入るので、大きくなります。配るときは、--release を使います。これは、Hello World の大きさで、実際のアプリでは、変わります。

target/ の中身は、ビルドの作業場です。.gitignore に /target が入っているので、git には、含まれません。

rustc だけで動かす

cargo を使わず、コンパイラを直接呼ぶこともできます。

fn main() { println!("Hello, rustc!"); }
rustc main.rs
./main
Hello, rustc!

Windows では、main.exe ができます。1 ファイルの実験には、これで足ります。ファイルが増えたり、他のクレートを使ったりするときは、cargo を使います。

わざと間違える

Rust のコンパイラは、エラーメッセージが親切です。2つ、わざと間違えて、読み方を見ます。

セミコロンを忘れる

fn main() {
    println!("Hello, world!")
    println!("two");
}
error: expected `;`, found `println`
 --> m.rs:2:30
  |
2 |     println!("Hello, world!")
  |                              ^ help: add `;` here
3 |     println!("two");
  |     ------- unexpected token

error: aborting due to 1 previous error

読むところは、次のとおりです。

  • --> m.rs:2:30: 場所です。2 行目の、30 文字目
  • ^: 問題の位置
  • help: add ';' here: 直し方(; を足す)

変数を書き換える

fn main() {
    let x = 5;
    x = 6;
    println!("{x}");
}
error[E0384]: cannot assign twice to immutable variable `x`
 --> m2.rs:3:5
  |
2 |     let x = 5;
  |         - first assignment to `x`
3 |     x = 6;
  |     ^^^^^ cannot assign twice to immutable variable
  |
help: consider making this binding mutable
  |
2 |     let mut x = 5;
  |         +++

warning: value assigned to `x` is never read
 --> m2.rs:2:13
  |
2 |     let x = 5;
  |             ^ this value is reassigned later and never used
3 |     x = 6;
  |     ----- `x` is overwritten here before the previous value is read
  |
  = note: `#[warn(unused_assignments)]` (part of `#[warn(unused)]`) on by default

error: aborting due to 1 previous error; 1 warning emitted

For more information about this error, try `rustc --explain E0384`.

エラーの後ろに、警告(warning)も出ます。ここでは、error の方だけを見れば足ります。

Rust の変数は、初期状態では、書き換えられません。 書き換えたいときは、let mut x = 5; と書きます。メッセージも、そう教えています。変数の扱いは、次回、詳しく見ます。

E0384 は、エラーの番号です。rustc --explain E0384 で、説明が読めます。

動作確認

確認できたこと

  • 上のコマンドと出力は、すべて、Linux(Rust 1.97.0、Cargo 1.97.0)で、実際に実行した結果です
  • cargo new、cargo run、cargo build、cargo build --release、cargo check、rustc での実行、cargo fmt、cargo clippy が動くこと
  • 2つのエラーメッセージの内容

歴史の出典

  • 年表は、Wikipedia「Rust (programming language)」の記述を、もとにしています。2011年・2013年・2014年・2016〜2017年・2022年の項目は、この1つの出典だけで、他の資料とは、突き合わせていません
  • Rust Foundation の設立日と創設メンバーは、TechCrunch の記事(2021年2月8日)と一致しました
  • エディションと版の対応・日付は、endoflife.date の Rust のページで確認しました。2024 エディションが 1.85 で安定化したことは、Rust 1.85.0 の紹介記事(2025年2月20日付)の紹介でも確認しました
  • 1.0 以降の互換性の約束は、公式の 1.0 発表記事を取得できず、確認できていません
  • 名前の由来は、さび菌と言われていますが、本人の説明までは、確認していません

確認できていないこと

  • Windows と macOS での、rustup の入れ方(公式の案内に基づく手順です)
  • Windows では、実行ファイルが hello.exe になり、パスの区切りが \ になります。出力のパスの部分は、環境で変わります

次回

次回は、変数・型・関数です。さきほどの let mut を入り口に、Java との違いを、並べて見ていきます。

連載の目次(予定)

入門編(8回)

  1. Rust とは / 環境構築 / Hello World(今回)
  2. 変数・型・関数(Java との対比)
  3. 所有権(ムーブ)
  4. 借用と参照
  5. 構造体・enum・match
  6. Result / Option とエラー処理
  7. トレイトとジェネリクス(Java の interface との違い)
  8. ライフタイム入門と、総まとめの CLI(ファイル一覧ツール)