Rust高速ビルド環境構築帳

# はじめに
## 嘘導入
光陰矢の如しとは言いますが，もう年末になってしまいました．  
年末と言えば，そう，**サンタクロースの追跡**ミッションの時期ですね．  
毎年サンタクロースの追跡のために専用のシステムを開発する多種多様なエンジニアが世界で**5000兆人**，給料は**クリスマスツリーについている星**払いで動員されているというのは有名な話です．  
しかしながら，**亜光速**で世界を翔けるトナカイに乗るサンタを捕捉するのは尋常な事ではありません！**ゴウランガ!**  
高いパフォーマンスは必要ですし，ガベージコレクタが走って`Stop the World`が起ころうものならその一瞬でサンタは地平線の彼方へ消えてしまいます．**ウカツ!**  
そこで，WST(World Santa Tracking)協会は今年のサンタ追跡システムの一部にRust言語を使用することを決定しました．  
そのために，Rust環境を構築する手順を記事にすることにしました．

## 導入
ナマステ！ neruneruna7です． 上に書いてあることは全て嘘です．

[学生団体IDEAのアドベントカレンダー](https://qiita.com/advent-calendar/2023/idea)，その2日目の記事となります．

近頃，Rust言語の話題を目にすることが増えてきました．かくいう私も好んで使用しています．  
そこで，自分での再確認の意味も込めて，Rustの環境構築手順を記事にすることにしました．  

Rustといえばビルド時間が長いことで知られています．  
そこで，本記事では**高速なビルド**ができる，**快適**なRust環境を構築することを**目的**としています．  

WslとUbuntuのインストールが完了している前提で進めます．

# 環境
環境構築をする環境ですが，以下の通りです．
```
Windows11: 22h2
wsl: 2.0.9.0
Ubuntu: Microsoft Storeから取得するUbuntu どのバージョンでも問題ないと思います（未検証）
```
自身の普段使用しているRust環境はUbuntu22.04上に構築しています．  

<details><summary>おまけ</summary>

バージョン表記のないUbuntuを普段使いしていないのは，気軽に*爆破*できるようにしたいためです．
世に諸行無常の響きあり...使っていればいつか肥大したり，壊れることもあるでしょう．  
そんな時に，動かないUbuntuを**御神体として祀ってお祓いをし，さらに念仏を唱える**...わけにもいきません．

デフォルトディストリビューションにしていない構築することで，気軽に爆破，再構築できるようにしたいのです．  

:::note warn
だったらDockerを使えって話ではある．
:::
正直言えば，ただ単に気持ちの問題です．  

チーム開発等の場合は，Dockerで構築して爆破した方が良いでしょう．  
**Dockerドッカーン！！**

:::note alert
Dockerドッカーン！！と Twiter | X 上でリプライしたところ，なぜか相手のDockerとWslを破壊するという事故が発生しました．
くれぐれも乱用にはお気を付けください．
:::

*芸術は爆発だ！！*
</details>


# 基本の環境構築
## Ubuntuの準備
WslとUbuntuのインストールが完了している前提で進めます．  

まずは，以下のコマンドを実行します．
```bash
sudo apt update
sudo apt upgrade
```

次に．build-essentialをインストールします. 
```bash
sudo apt install build-essential
```

これでRustをインストールする準備が整いました！

## Rustインストール
次のコマンドを実行します
```
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
```
途中で選択肢が出てきますが，基本的には何も入力せずにエンターキーを押し，デフォルトのままインストールで問題ないでしょう．  

インストールが完了したら，**ターミナルを再起動**しましょう．

それでは，Rustをインストールできたか確認しましょう
`rustup` `rustc` `cargo`の3つがインストールされているはずです．
`rustup -V` `rustc -V` `cargo -V` をターミナルで実行します．
```
$ rustup -V
rustup 1.26.0 (5af9b9484 2023-04-05)
info: This is the version for the rustup toolchain manager, not the rustc compiler.
info: The currently active `rustc` version is `rustc 1.74.1 (a28077b28 2023-12-04)`

$ rustc -V
rustc 1.74.1 (a28077b28 2023-12-04)

$ cargo -V
cargo 1.74.1 (ecb9851af 2023-10-18)
```
以上のような結果が出力されれば，無事にインストール完了です．  

### インストールされたものは何？
ところで，これら3つはそれぞれ何なのでしょうか？  

`rustc`は**コンパイラ**です．直接使うことはほぼありません．  

`rustup`とは，Rustの**インストーラー**および**バージョン管理ツール**です．  
これにより，インストールが簡単に行えたり，複数のバージョンのコンパイラを管理することができます．例えるならば，`pyenv`などが似ているでしょうか？ 違ったらすみません．  

`cargo`とは，Rustの**ビルドツール**および**パッケージマネージャ**です．基本的にはこれを介してコンパイラを呼ぶことになります．またライブラリの依存関係管理なども行います．例えるならば，`npm`などが近いですね．

`cargo`は非常に多くの機能を持っています．
- ビルド
- 実行
- テスト
- フォーマッタ
- 静的解析(リンタ)
- ドキュメントのビルド
- ライブラリの公開...etc

さらに，ユーザによって開発されたサブコマンドによって，多数の便利なツールが公開されています．


# 高速にビルドできる環境構築
ここまででRustの基本的な環境は構築できましたが，より快適な環境を構築していきましょう!

## 便利なサブコマンドのインストール
Rustには便利なサブコマンドが多数公開されています．今回は`cargo-binstall`と`cargo-watch`を導入します．

Rustのサブコマンドのインストールはインストール時にコンパイルします．  
これにより，**バチクソコンパイル時間がなっっっっっがい**わけですが，`cargo-binstall`を導入することによって大幅に短縮できることがあります．  

なぜなら，`cargo-binstall`では，実行バイナリをダウンロードしてインストールするからです．コンパイルする時間が無いわけですね．  
実行バイナリをダウンロード可能な場合は数秒でインストールが完了するため，非常に便利です．できない場合は`cargo install`にフォールバックします．

`cargo-watch`は，プロジェクトの変更を監視し，自動で指定したcargoコマンドを実行します．

```
cargo install cargo-binstall
```
インストール長かったですね...  
binstallのインストール完了後にwatchを`binstall`してください
```
cargo binstall cargo-watch
```
一瞬で終わりましたね！

## sccache, moldのインストール
まずは，ストレージの容量を利用することで高速化するツールです．
sccacheとは，Mozillaの開発する共有コンパイルキャッシュツールです．2回目以降のビルドを高速化します．しかしリンク時間は変わらないため，そこがネックになります．

次は，CPUの利用率を高めることで高速化するツールです．リンクを高速化します．
moldとは，Rui Ueyama氏が開発するリンカです．現代のCPUはマルチコアのものが多いですが，これまでのリンカはその能力を活用できていませんでした．マルチコアを活かすことで高速に動作するリンカです．

これら2つを使用することで，高速にビルドできる環境を構築します．

以下のコマンドを実行します．
```bash
cargo binstall sccache
sudo apt install mold
```

Rustでsccacheを使う手段の1つとして，`RUSTC_WRAPPER`環境変数を設定というものがあります.
しかし，環境変数をいちいち設定するのは面倒なので，`.bashrc`に記述します．

```
export RUSTC_WRAPPER=$(which sccache)
```

一度ターミナルを再起動しておきましょう．

これで高速にビルドする環境ができました！  
適当なRustプロジェクトを作って，ビルド | 実行時に`mold --run cargo run`のようにコマンドを実行することで，最初よりもよりも高速にビルドできます！

## さらに体感速度の向上を目指して
これまでで
- コンパイル時間の短縮  
- リンク時間の短縮  

を図ってきました．

もちろんビルドは速くなっていますが，依然としてRustのビルドとは時間がかかるものです．  
ところで，Rustのコンパイラ自体はインクリメンタルビルド（増分ビルド）を採用しており，また高速化できるように細かい最適化が加えられているそうです．
そもそもとして，一度の**変更が多ければ**時間はかかりますし，初回コンパイルはキャッシュもインクリメンタルビルドも**効かない**のでどうしても遅いです．  

ならば，ビルド自体を**コードを書いてる最中**に，**細かい単位で繰り返せば**よいのです．

そこで，`cargo-watch`を使用して，できるだけビルド時間が気にならないようにしていきましょう．

することは簡単です．Rustで開発しているときに，以下のコマンドを裏で実行しておくだけです．
```
cargo watch -s 'mold -run cargo build'
```
これにより，変更するたびに（ctrl + sで保存するたびに）ビルドが走ります．  

また，
```
cargo watch -x fmt -s 'mold -run cargo build'
```
のようにすれば，保存時に毎回フォーマットしたりと好きなようにできます．
（実際は，保存時フォーマットはエディタの設定で行ったほうが快適でしょう．）

これでさらに快適にビルドすることができます．

### 欠点
これはすなわち，ストレージ容量を利用して高速化しています．
保存のたびにビルドが走るということで，targetフォルダが**肥大化**します．  
気づけば**数十GB**に膨れ上がっているというのはザラです． （プロジェクトの大きさにもよりますが）

普通に開発しているだけでも大きくなるのがtargetフォルダです．

そこで，定期的に`cargo clean`コマンドを実行して綺麗に掃除しておきましょう

プロジェクトが多数ある場合，`cargo-clean-recursive`をインストールして使用するのもおすすめです．

# まとめ
Rustはコンパイル時間の長い言語ですが，これらによりだいぶ気にならなくなります．  
- cargo-binstall
- cargo-watch
- sccache
- mold
- cargo-clean-recursive

また，ここでは紹介していませんが，cargoのサブコマンドには便利で高機能なものがたくさんあります．  
より快適な開発環境を目指していきたいですね．

### それではみなさん，よい年末を！！  

:::note warn
<details><summary>年末の注意点</summary>
学生でソフトウェアエンジニアリングを学んでいるみなさん，年末はお酒を飲む機会が増えると思います．普段あまりお酒を飲まなくて，あまり慣れていないということもよくあるんじゃないでしょうか．  

そんなみなさん，必ず，必ずビニール袋は携行しましょう．とにかくすぐに準備できるところに携行しましょう．  **ゾルトラーク[^1]** は突然やってきます．

いきなり目の前でゾルトラークしても即座に防御魔法を展開できるように準備しましょう．

年末シーズンではないですが，筆者は1度やらかしました．しかも電車内で...

[^1]: 漫画，葬送のフリーレンに出てくる魔法
</details>


:::


# 参考文献
- [Install Rust](https://www.rust-lang.org/tools/install)
- [WSL2で作るRustのWindows開発環境: Rustが征く(1)](https://zenn.dev/dozo/articles/56a3fa90dbfb50)
- [moldとcargo watchを併用してより快適な開発環境を作る](https://qiita.com/kyamamoto9120/items/2081bc44c6c987b9ec29)
- [mold](https://github.com/rui314/mold)
- [sccache](https://github.com/mozilla/sccache)
- [rustup, rustc, cargoの位置付けと違い](https://zenn.dev/scirexs/articles/9de58f5033232c)
- [はじめに - Rustプログラミング言語](https://www.rust-lang.org/ja/learn/get-started)
- [lldを凌駕する高速な新リンカmold](https://www.infoq.com/jp/news/2022/01/mold-linker-1-0/)
- [コンパイルキャッシュでRustのビルド時間を短縮しよう](https://qiita.com/tatsuya6502/items/76b28a6786a1ddc9d479)
- [Rust の開発環境を整える手順](https://note.com/whitebeard/n/n4d4db62e69ea)
- [Rustのプロジェクトを一括でcleanするツールを作った](https://igaguri.hatenablog.com/entry/2020/06/07/133847)
- [Rustのビルドを高速化する方法](https://postd.cc/fast-rust-builds/)
- [How to speed up the Rust compiler one last time](https://blog.mozilla.org/nnethercote/2020/09/08/how-to-speed-up-the-rust-compiler-one-last-time/)