cargoのソースを読んでみよう - 第0回 : Rust環境の構築

# はじめに

最近、世間から注目されている言語をいろいろ眺めているのですが、そのなかで私が興味を持った言語はScalaとRustでした。そのうちのScalaのほうは、例の[Scalaスケーラブルプログラミング](http://book.impress.co.jp/books/1116101021)って本が非常に良くできていて、あれ一冊読むと、もうそれだけで何となく分かったような気になってしまう訳です。従って、「四の五の言わずScalaスケーラブルプログラミングを読め」で済んでしまう。

もう一方のRustの方は、[例の本](https://rust-lang-ja.github.io/the-rust-programming-language-ja/1.6/book/README.html)[^TheBook]を読んでも腑に落ちない部分がいっぱいあるし、[リファレンスマニュアル](https://doc.rust-lang.org/reference.html)もそれほど頼りにならない[^ref]状況で、これはちょっと楽しみがいがあるかな、と思った次第。思えば、20年ほど前、まだISO規格にもなっていないC++を手探りで（以下、おっさんの繰言が続くので省略）。

[^TheBook]: 「例の本」 - 英語版は"[The Book](https://doc.rust-lang.org/book/)"

[^ref]: 「リファレンスマニュアルもそれほど頼りにならない」 - だって公式が"While Rust does not have a specification, the reference tries to describe its working in detail. It tends to be out of date."とか言ってんだもん。[Standard Library API Reference](https://doc.rust-lang.org/std/) のほうはそれなりに使える。

20年前のC++と比べると、Rustの現状は、既にこの言語で書かれたライブラリやアプリケーションがそれなりに豊富に存在して、しかもその多くがオープンソースソフトウェアなところが恵まれています。つまり、お手本がその辺にいっぱい転がっている。ソースを読めてナンボの世界にずっと浸かっていた身としては、読めるソースがたくさんあるというのは大変ありがたい。

さて、そんな中で私が読むのに選んだのはcargoです。何でこれを選んだのかというと、

- それなりの規模の実用的なアプリケーションである
- ネットワークアクセスやコマンドライン解析など、いろいろな要素が入っている
- Rustの公式のツールなので、この言語に造詣のある人間が書いていると期待できる

という理由からです。まあrustupの方でも良かったんですが、そこは気分の問題ということで。

今回は、ソースを読む前の段階として、環境構築をやっていこうと思います。

# 前提

ソースを読んでいくという都合上、バージョンを固定しておかないと後で何を参照していたのか分からなくなるので、ここでは次の環境に固定します:

- 使用コンパイラ: rustc 1.15.1
- 読むソース: cargo 0.16.0

ちょうど1.15.1が出たばかりなので、しばらくは次のバージョンのことを考えなくてもいいですね[^nextver]。

[^nextver]: 「しばらくは次のバージョンのことを考えなくてもいい」 - と言っても、cargo 0.16.0が出た時点でも、masterのheadはだいぶ違うコードになってて困る。

# 環境構築
まあ、各自使い慣れてる環境でいいと思うんですけど、grepで済んだC言語あたりとは違って、Rustの場合、タグジャンプでソースをどんどん参照できる環境を構築しないと読んでられないと思います。そういう環境を作ろうと思うと、私が普段使っているWindowsやNetBSDだと、ちょっといろいろしんどいかなー、という気がしたので、WindowsのノートPCでVirtualBoxを動かし[^vbox]、そこにXubuntu-16.04を入れて、その上に環境を作ることにしました。

[^vbox]: 「VirtualBox」 - なお、rustcは結構メモリ食いなので、仮想マシンには多めのメモリを割り当てたほうがいいです。

私はEmacsをずっと使ってきたので、次のような開発環境を作ることにしました:

- Emacs24
- rustup / cargo
- rustfmt
- racer
- rust-mode
- flycheck-rust
- company-racer

以下、順番に概要を説明します。vim使いの人は適当にやっといてください。

## 前段階

VirtualBoxを使っているので、Guest Additionをビルドするために linux-headers-generic と build-essential を入れたのですが、cargo のビルドにもこいつらは必要になりそうな気がするので、実機環境でも次のようにして入れておいた方がいいでしょう:

```shell-session
% sudo apt-get install linux-headers-generic
% sudo apt-get install build-essential
```

## Emacs環境
Emacsを入れます。と言っても、

```shell-session
% sudo apt-get install emacs24
```

とするだけですが。Rust関連以外のEmacsの基本的な設定については、自分の普段使っている.emacs.dあたりを持ってきて使えるようにしておいてください（投げやり）。なお、私はこの他に fonts-ricty-diminished と mozc-emacs を入れました。

## Rust開発環境

最初に rustup を入れます。この段階では curl も入っていないので、次のようにしました:

```shell-session
% sudo apt-get install curl
% curl -sSf https://sh.rustup.rs | sh
```

すると、 ~/.cargo に rustc や cargo がインストールされます。この段階で自動的に ~/.profile に環境変数の設定が追加されますが、シェルを再起動しないと反映されないため、次のようにして手動で現在のシェルセッションに反映させます(もちろんシェルを再起動してもいいです):

```shell-session
% source ~/.cargo/env
```

次に、 rustfmt (ソースコード整形ツール)と racer (補完ツール)を入れます。これは cargo で簡単に入れることができます:

```shell-session
% cargo install rustfmt
% cargo install racer
```

これらも ~/.cargo の下に入ります。また、ソースを読んでいくと、どうしても標準ライブラリのcrateを参照したくなるので、rustup で rust 本体のソースコードも入れておきます:

```shell-session
% rustup component add rust-src
```

最後に、Emacs 上で Rust のソースを読み書きするためのツールを入れます。melpa からパッケージを持ってきて入れると楽なので、~/.emacs.d/init.el に次のように書いておいて、

```el
(when (>= emacs-major-version 24)
  (require 'package)
  (add-to-list 'package-archives '("melpa" . "http://melpa.org/packages/") t)
  (package-initialize)
  )
```
Emacsを再起動してから(再起動せずeval-regionしてもいいけど) M-x package-list-packages をします。リストの中から次の4つを選んで install してください:

- rust-mode [^rust-mode] - rust 向けメジャーモード
- racer - racer と連携して、タグジャンプや eldoc によるシグネチャ表示の実現
- flycheck-rust - オンザフライな文法チェッカ
- company-racer - Emacs の補完フレームワーク company と racer の連携

[^rust-mode]: 「rust-mode」 - 実は racer の Requires に入ってるので、明示的に入れる必要はない。

そして、これらを有効にするため、~/.emacs.d/init.el に次のように書きます:

```el
(add-to-list 'exec-path (expand-file-name "~/.cargo/bin"))
(require 'company-racer)
(with-eval-after-load 'company
  (add-to-list 'company-backends 'company-racer))
(add-hook 'rust-mode-hook #'racer-mode)
(add-hook 'rust-mode-hook #'flycheck-rust-setup)
(add-hook 'racer-mode-hook #'eldoc-mode)
(add-hook 'racer-mode-hook #'company-mode)
(add-hook 'after-init-hook #'global-flycheck-mode)
```

# cargoのソースを取得する

cargoのソースをgithubから持ってきます。でも、素のXubuntuにはgitが入ってないので、まずはgitを入れるところから:

```shell-session
% sudo apt-get install git
```

そして、リポジトリのクローンと0.16.0のチェックアウト:

```shell-session
% git clone https://github.com/rust-lang/cargo.git
% cd cargo
% git checkout 0.16.0
```

# cargoのビルド

一回ビルドしておくと、cargo が使っている crate のソースにもタグジャンプできるようになって便利。なお、このままだとcrateが依存してるパッケージ（主にCで書かれたライブラリ）が足りないのでビルドに失敗すると思う。タグジャンプしたいだけならビルドに成功する必要はないけれど、ちゃんとビルドを成功させるためにはXubuntuでは次のようなパッケージを入れておく:

```shell-session
% sudo apt-get install pkg-config
% sudo apt-get install libssl-dev
% sudo apt-get install libssh2-1-dev
% sudo apt-get install libgit2-dev
% sudo apt-get install cmake
```

そして、cargo build すれば、多分 target/debug ディレクトリのなかに cargo の実行ファイルができているはずです。

# 準備完了

ためしに emacs で cargo/src/bin/cargo.rs を開いてみましょう:

![image](https://qiita-image-store.s3.amazonaws.com/0/149583/a8856e20-e2ff-f5b6-c4e1-765593ca3eb4.png)

こんな感じになれば成功です。

# おわり
次回からは実際にソース読んでいきます。

# 注釈