[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 を使ってきた立場から、並べるとこうなります。
| 観点 | Java | Rust |
|---|---|---|
| 実行の形 | バイトコードを、JVM が実行する | 機械語の実行ファイルを作る |
| メモリの管理 | GC が、使われなくなった物を片付ける | 所有権の決まりで、コンパイル時に決める(GC なし) |
| 値がないこと | null | Option(第6回) |
| エラー | 例外(throw / catch) | Result(第6回) |
| 型 | 静的型付け | 静的型付け(型推論が強い) |
表の「第6回」は、あとの回で扱います。今回は、「コンパイルして、実行ファイルができる」ことと、「GC がない」ことだけを、覚えておけば足ります。
歴史
Rust は、Mozilla の社員だった Graydon Hoare が、個人のプロジェクトとして、2006年に作り始めた言語です。名前は、さび菌(rust fungus)に由来すると、言われています。
| 年 | できごと |
|---|---|
| 2006 | Graydon Hoare が、個人のプロジェクトとして、作り始める |
| 2009 | Mozilla が、公式に支援を始める |
| 2011 | コンパイラが、OCaml 製から、Rust 自身で書かれたもの(セルフホスト)に切り替わる。LLVM を使う |
| 2012年1月 | 最初の公開版 0.1 が出る |
| 2013 | Hoare が、プロジェクトの中心から退く。GC が、言語から取り除かれ、所有権が中心になる |
| 2014年3月 | 言語の変更を、RFC(提案書)で決める仕組みが始まる |
| 2015年5月15日 | Rust 1.0。最初の安定版 |
| 2016〜2017 | Firefox が、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 で選びます。エディションの違うクレート同士でも、組み合わせて使えます。
| エディション | 入った版 | 日付 |
|---|---|---|
| 2015 | 1.0 | 2015年5月15日 |
| 2018 | 1.31 | 2018年12月6日 |
| 2021 | 1.56 | 2021年10月21日 |
| 2024 | 1.85 | 2025年2月20日 |
cargo new で作ったプロジェクトは、そのときの最新のエディションで始まります。後で見る Cargo.toml に、edition = "2024" と書かれているのは、そのためです。古いエディションのプロジェクトは、そのまま動かせます。
環境を作る
Rust の道具は、rustup が入れます。rustup は、Rust のバージョンを入れ替えたり、更新したりする、管理用のツールです。入ると、次の 3 つが使えるようになります。
rustc: コンパイラcargo: ビルドとパッケージの管理(普段は、こちらを使います)rustup: バージョンの管理
Windows
- rustup.rs から、
rustup-init.exeをダウンロードして、実行します - C++ のビルドツール(Microsoft C++ Build Tools)が必要です。無ければ、画面の案内に沿って入れます
- 終わったら、ターミナルを開き直します
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 --release | 474,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回)
- Rust とは / 環境構築 / Hello World(今回)
- 変数・型・関数(Java との対比)
- 所有権(ムーブ)
- 借用と参照
- 構造体・enum・match
- Result / Option とエラー処理
- トレイトとジェネリクス(Java の interface との違い)
- ライフタイム入門と、総まとめの CLI(ファイル一覧ツール)