環境構築, Buildまで -Rust編-

# Windows 10 で Rust のインストール

## Rustとは

Rustとは

>Mozillaが応援している言語
Microsoftも注目している
2006年から開発が始まった新しめの言語
2016年、2017年、2018年のStack Overflow Developer Surveyで「最も愛されているプログラミング言語」で一位を獲得している
C/C++と同等の処理速度
C/C++の代替えを目指している
静的に型が付く、コンパイラ言語
静的に変数の寿命もわかり、自動でメモリを解放（GCより速い！）
関数内部限定での極めて賢い型推論
C/C++と比べて極めて安全
オブジェクト指向ではないし関数型言語でもない新たな概念を持つ
デフォルトでスレッドセーフが保証された変数達
C++のムーブセマンティクスを言語レベルでサポート
C++と違い、制約付きのテンプレートがある
DSL作成可能で健全なマクロ
タプル、代数的データ型とマッチ式もあります
標準でテスト機能が付いている
標準でパッケージマネージャーがある

Rustをインストールすると三つのcommandが使えるようになります。

>Rustのインストールをするrustup。
Rustのコンパイラrustc。
パッケージマネージャーのcargo。

主に触るのはcargoだけ。


## 1. 環境構築インストール
https://www.rust-lang.org/tools/install
rust の公式ページ に従って
rustup-init.exe
をインストール。

環境変数PATHに

```
%USERPROFILE%/.cargo/bin
```

を追加するよう言われるので追加。

<!--rustup set default-host x86_64-pc-windows-msvc しておく。-->

ビルドにVC Build Tools が必要とのことなのでインストール。
https://visualstudio.microsoft.com/ja/downloads/

>Microsoftの Visual Studioページ トップ下
→「すべてのダウンロード」
→Visual Studio 2019 のツール
→Build Tools for Visual Studio 2019 を選択。

インストーラーが起動するので、画面から 
"Visual C++ Build Tool" 
を選択。設定はデフォルトのまま選択。

## 2. 実際にコードをコンパイル及び実行

#### 1. 単体コード

```
$ rustc main.rs
$ ./main
```

#### 2. Rustのパッケージマネージャー"Cargo"を使用

Cargo はRustのビルドシステムおよびパッケージマネージャ

```
//プロジェクトが生成されます。
cargo new プロジェクト名

//そしてcd コマンドでできたプロジェクトの中に入り以下
cargo run
```

```
# リリース版をビルド
cargo build --release
# 実行（実行ファイルの位置は各自確認）
./target/release/demo
```

## PS. Rustコンパイラの処理の流れ

Rustのプログラムは以下のようなステップから構成されており、上から順に処理されている。

>.rsファイルをパースし、ASTを生成
マクロの展開、名前解決、#[cfg] アトリビュートの解釈
ASTをHIRに変換
型推論、型解析
HIRをMIRに変換
MIRをLLVM IRに変換、最適化
.o ファイルをリンク
.rsファイルのパース

パーサはlibsyntax crateにまとまっている。一般的なパーサと同じく、字句を解析しASTを作る。

rust/src/libsysntax/codemap.rsでもともとのソースコードの位置の情報とASTのノードをマッピングしている。CodeMapのフィールドの1つであるfilesにファイルの情報がFileMapというデータ構造で入っている。また、CodeMapの先頭からの絶対的な位置がSpanというデータ構造に格納される。
StringReader がFileMapをもとに、文字列の情報を次々に読んでいき、TokenStream 生成する。
TokenStreamはTokenTreeのシーケンスであり、TokenTreeはTokenと区切り文字で構成されている。

Parser がTokenStreamをもとにASTを生成している。parse_ から始まるいくつかの関数がパースする際のエントリーポイントになっている。また、ASTはrust/src/libsysntax/ast.rs で定義されている。
ASTの内容を確認したい場合、rustc -Z ast-json ファイル名 を実行すれば、ASTがJSON形式で表示される。

また、StringReaderとParserはパース中に必要な情報を保持する ParseSess に紐付いており、無駄なコピーが発生しないようになっている。

## PS. Rustコンパイラの流れ(2)
Rust
Rustコンパイラは同梱のrustbuildというツールでビルドされる。これはRustとPython2で書かれている。 README.md にも説明が書かれているが、ここで改めて説明をしてみる。

./x.py は src/bootstrap/bootstrap.py にリンクされている。これは次のような動作をする。

設定ファイル (config.mk または config.toml) を読む。
bootstrap.py はTOMLパーサーを持たないため、この時点では config.toml はアドホックな方法で解析される。したがって、 vendor, locked-deps, cargo, rustc, build キーの記述には気をつける必要がある。例えば cargo = ".." を cargo=".." と書くと認識されない。
必要なら、 src/stage0.txt を読み、インターネットからstage0コンパイラ(ビルド済みのRustコンパイラ)を取得する。
必要なら、rustbuild自身をビルドする。 cargo build --manifest-path src/bootstrap/Cargo.toml が実行される。
rustbuildを呼び出す。 build/bootstrap/debug/bootstrap "$@" が実行される。
rustbuildの本体はRustで書かれている。特に重要なのが step.rs である。ここにMakefileのような依存関係が記述されている。

./x.py build をしたときのrustbuildの手順は大雑把にいうと次の通りである。

stage0コンパイラを用いて、stage1コンパイラをビルドする。(stage0標準ライブラリにリンクされる)
stage1コンパイラを用いて、stage1標準ライブラリをビルドする。
stage1コンパイラを用いて、stage2コンパイラをビルドする。(stage1標準ライブラリにリンクされる)
stage1標準ライブラリはそのままstage2標準ライブラリとして用いられる。
このように2回コンパイルが必要なのは、Rustがバージョン間でABI互換性を保たないことに由来する。

ここでstage0コンパイラのバージョンをV0とし、現在作ろうとしているコンパイラのバージョンをV1とする。すると、各ステージのコンパイラと標準ライブラリのバージョンは以下のようになる。

stage0コンパイラ: V0 ABIでコンパイルされているV0のコンパイラ
stage0標準ライブラリ: V0 ABIでコンパイルされているライブラリ
stage1コンパイラ: V0 ABIでコンパイルされているV1のコンパイラ
stage1標準ライブラリ: V1 ABIでコンパイルされているライブラリ (=stage2標準ライブラリ)
stage2コンパイラ: V1 ABIでコンパイルされているV1のコンパイラ
stage0やstage2のように、自身と互換なABIでコンパイルされているコンパイラをfull host compilerという。

full host compilerが必要なのは、しばしばコンパイラプラグインのビルドが必要なためである。コンパイラプラグインはコンパイラ自身にリンクされるプログラムだから、stage1コンパイラはコンパイラプラグインを正しく扱うことができない。

なお、Rustで最もよく使われるコンパイラプラグインの形式はおそらく手続きマクロ(proc-macro)である。

>RustコンパイラはRustで書かれている。
最初のRustはstage0といい、既にあるバイナリをダウンロードする。
Rustコンパイラはデフォルトで2回ビルドされる。
こうしないと手続きマクロが動かない。