rebarについて調べた

# rebarについて調べた

rebarの使い方をちゃんと理解しようと思い、その際にまとめた内容です。

## rebarとは

rebarとは、Erlangアプリケーションやポートドライバ等の、コンパイル・テスト・リリースを簡単に行う事ができる統合ビルドツールです。

rebar自体にescriptを含んでいるので配布やプロジェクトに直接含める事が簡単にできます。またErlang/OTPの標準的な慣習に沿ったプロジェクト構成に従うので、ビルド時の設定作業が少なくて済みます。更にモジュール/ライブラリの依存関係管理もしてくれるので、ユーザーはGithub等のリポジトリからライブラリを簡単に再利用できます。

すばら。

## インストール

rebarのインストールはmacだとhomebrewでインストールできます。Windowsの場合はわかりません。すいませんがGoogle先生に聞いて下さい。

```bash
$ brew install rebar
```

ソースからコンパイルしたい場合は以下の様にGithubからソースをとってきてビルドしてください。

```bash
$ git clone git://github.com/rebar/rebar.git
$ cd rebar
$ ./bootstrap
$ mv rebar /path/to/your/bin
```

Githubにバイナリがあるのでそれをパスの通ったフォルダに入れても良いです。

```bash
$ wget https://github.com/rebar/rebar/wiki/rebar
$ mv rebar /path/to/bin
```

## 使い方

[公式wiki](https://github.com/rebar/rebar/wiki)に詳細な情報があります。迷ったらとりあえずここで調べると良いと思います。

### 前提

rebarは標準的なOTPアプリケーション構成の慣習に沿って実行されます。OTPアプリケーションのフォルダ構成は以下の様になります。

```
myapp
├── src
│     └── myapp.app.src
├── ebin
│     └── myapp.app
├── priv
├── include
├── (test)
└── (c_src)
```

`ebin/myapp.app`は`src/myapp.app.src`をテンプレートとして、rebarがコンパイル時に生成します。この時、ebin以下にあるモジュールをmyapp.appのモジュール指定(module)に追加してくれます。

### rebar.config

`rebar.config`に実行時のオプションを記述する事ができます。オプションの詳細は[こちら](https://github.com/rebar/rebar/wiki/Rebar-commands#options)を参照してください。

### ヘルプ関連

rebarについて調べたい時は、以下のオプションをつけてrebarを実行します。テンプレートについては後述します。

```bash
# コマンド一覧を表示
$ rebar -c

# commandの説明を表示
$ rebar help <command>

# バージョンを表示
$ rebar --version

# 使用可能なテンプレートとテンプレートに渡すパラメータ名を表示
$ rebar list-templates 
```

### よく使うコマンド

頻繁に使用されるであろうコマンドです。

```bash
# ソースコードをコンパイル
$ rebar compile
```

`src`の中のソースコードをコンパイルして、`ebin`の中にbeam(Erlangの実行)ファイルを配置します。また、`src/myapp.app.src`をテンプレートに、`ebin/myapp.app`ファイルを生成します。
コンパイルをサポートしているファイル[こちら](https://github.com/rebar/rebar/wiki/Rebar-commands#supported-source-formats)を参照してください。

```bash
# eunitを実行
$ rebar eunit
```

eunitテストを実行します。eunitについては[こちら](http://www.erlang.org/doc/apps/eunit/index.html)を参照してください。

```bash
# ドキュメントを生成
$ rebar doc
```

edocを使ってドキュメントを生成します。edocについては [こちら](http://www.erlang.org/doc/apps/edoc/index.html)を参照してください。

```bash
# 実行ファイル・テストモジュールを削除
$ rebar clean
```

コンパイル時にできた実行ファイルやテストモジュールを削除します。

### 依存関係管理に関するコマンド

rebarはアプリ/モジュール/ライブラリの依存関係管理をしてくれますが、その依存関係は`rebar.config`のdepsタプルに記述します。
depsタプルの構成は

```erlang
{ deps, [ Dependency1, Dependency2, ... ] }.
```

となります。各Dependencyは更に

```erlang
{ App, VsnRegex, Source }
```

と分解できます。各要素は以下の通りです。

- App : OTPアプリケーション名のアトムか文字列

- VsnRegex : OTPアプリケーションの対象バージョンにマッチする正規表現

- Source : OTPアプリケーションのフェッチ先を表すタプル

Sourceは更に以下のタプルに分解できます。

```erlang
{ VmsType, URL, Target }
```

さらに見ていくと、

- VmsType : バージョン管理システムの種類、git/hg(mercury)/bzr(bazzar)を指定できます

- URL : リポジトリのURL

- Target : 該当リポジトリ内のブランチ/タグ/リビジョン/コミット

となり、Targetは以下の3タイプあります。

- ブランチ指定

```erlang
{ branch, "master" }. % masterブランチ
{ branch, "hoge" }. % hogeブランチ
```

以下の２つは同じ意味となります。

```erlang
{ git, Url, "" }.
{ git, Url, { branch, "HEAD" } }.
```

- タグ指定

```erlang
{ tag, "v1.0.0" }. % v1.0.0のタグ
```

- リビジョン/コミット指定

コミットは文字列で指定します。

```erlang
"15bc558d8222b011e2588efbd86c01d68ad73e60"
```

また、各Dependencyタプルの後ろに、[raw] を付ける事ができます。このrawオプションを付けると、標準的なOTPアプリの構造でないアプリも許容するようになります。(例えば、`src/target_app.app.src`や`ebin/target_app.app`がないものなど)

wikiにあるサンプルを見てみましょう。

```erlang
{ deps, [
    % OTPアプリ名 : em
    % 対象バージョン : 全て
    % 取得先 : https://github.com/sheyll/erlymock.git のmasterブランチ
    { em, ".*", { git, "https://github.com/sheyll/erlymock.git" } },

    % OTPアプリ名 : nano_trace
    % 対象バージョン : 全て
    % 取得先 : https://github.com/sheyll/nano_trace.git の feature/rebar-migrationブランチ
    { nano_trace, ".*", { git, "https://github.com/sheyll/nano_trace.git", { branch, "feature/rebar-migration" } } },

    % OTPアプリ名 : mochiweb
    % 対象バージョン : 2.3.2
    % 取得先 : https://github.com/mochi/mochiweb.git の v2.3.2タグ
    { mochiweb, "2.3.2", {git, "https://github.com/mochi/mochiweb.git", {tag, "v2.3.2"}}},

    % mochiwebをコミットでの指定
    % 取得先 : https://github.com/mochi/mochiweb.git の
    %              masterブランチの 15bc558d8222b011e2588efbd86c01d68ad73e60 のコミット
    % {mochiweb, "2.3.2", {git, "https://github.com/mochi/mochiweb.git",
    %                                       "15bc558d8222b011e2588efbd86c01d68ad73e60"},

    % アプリ名 : rebar
    % 対象バージョン : 全て
    % 取得先 : git://github.com/rebar/rebar.git の masterブランチ
    % rawオプションがついているので標準的なOTPアプリの構成でなくても良い
    { rebar, ".*", {git, "git://github.com/rebar/rebar.git", {branch, "master"}}, [raw]}
   ]}.
```

それではコマンドを見ていきましょう。なお、以下のコマンドは全て`rebar.config`に指定してある関連OTPアプリケーションが対象となります。

```bash
# 関連OTPアプリをdepsフォルダに配置する
$ rebar get-deps

# 関連OTPアプリをupdateする
$ rebar update-deps

# 関連OTPアプリを表示する
$ rebar check-deps

# 関連OTPアプリの詳細を表示する
$ rebar list-deps

# 関連OTPアプリを削除する
$ rebar delete-deps
```

### 雛形作成に関するコマンド

rebarは各種ソースファイルの雛形をテンプレートから作成する事もできます。アプリケーション、モジュール、ライブラリ、テスト等のテンプレートがあり、自分でテンプレートを作成する事もできます。(rebar list-templatesで確認できます)

雛形作成は以下の様にテンプレート名と、テンプレートに渡すパラメータと値のオプションを付けて実行します。

```bash
# rebar create の基本形
$ rebar create template=<テンプレート名> <パラメータ>=<値>
```

```bash
# OTPアプリケーションの雛形作成
$ rebar create template=simpleapp appid=<アプリ名>
```

OTPアプリケーションの雛形として、`*.app.src`ファイル、アプリケーションビヘイビア、スーパバイザビヘイビアのソースファイルが生成されます。

```bash
$ rebar create template=simpleapp appid=myapp
==> sample (create)
Writing src/myapp.app.src
Writing src/myapp_app.erl
Writing src/myapp_sup.erl
```

```bash
# ライブラリの雛形作成
$ rebar create template=simplelib libid=<ライブラリ名>
```

ライブラリの雛形として、`*.app.src`ファイル、`*.erl`ファイルが生成されます。

```bash
$ rebar create template=simplelib libid=mylib
==> sample (create)
Writing src/mylib.app.src
Writing src/mylib.erl
```

```bash
# リリース用Reltool関連ファイル
$ rebar create template=simplenode nodeid=<ノード名>
```

Reltool関連ファイルの雛形が生成されます。リリースに関する制御については[こちら](https://github.com/rebar/rebar/wiki/Release-handling)を参照してください。

```bash
$ rebar create template=simplenode nodeid=mynode
==> sample (create)
Writing reltool.config
Writing files/erl
Writing files/nodetool
Writing files/mynode
Writing files/sys.config
Writing files/vm.args
Writing files/mynode.cmd
Writing files/start_erl.cmd
Writing files/install_upgrade.escript
```

これら3つのコマンドは、以下のエイリアスがあります。

```bash
# 以下の2つは同じ意味
$ rebar create template=simpleapp appid=myapp
$ rebar create-app appid=myapp

# 以下の2つは同じ意味
$ rebar create template=simplelib libid=mylib
$ rebar create-lib libid=mylib

# 以下の2つは同じ意味
$ rebar create template=simplenode nodeid=mynode
$ rebar create-node nodeid=mynode
```

その他のテンプレートとしては以下があります。

```bash
# gen_serverビヘイビアのコールバックモジュール
$ rebar create template=simplesrv srvid=mysrv
==> sample (create)
Writing src/mysrv.erl

# gen_fsmビヘイビアのコールバックモジュール
$ rebar create template=simplefsm fsmid=myfsm
==> sample (create)
Writing src/myfsm.erl

# モジュールとそのテスト
$ rebar create template=simplemod modid=mymod
==> sample (create)
Writing src/mymod.erl
Writing test/mymod_tests.erl

# common test suite
$ rebar create template=ctsuite testmod=mytest
==> sample (create)
Writing test/mytest_SUITE.erl

# CのNIF(Native Implemented Function)モジュール
$ rebar create template=basicnif module=mymodule
==> sample (create)
Writing src/mymodule.erl
Writing c_src/mymodule.c
```

#### ユーザー定義テンプレート

テンプレートを追加したい場合は、`~/.rebar/templates/`にテンプレートファイルを配置すれば使用できるようになります。ユーザー定義のテンプレートは[配布サイト](https://github.com/mbbx6spp/rebar-templates)がいくつかあるので、そこから探してくると良いでしょう。

### リリース関連

```bash
# リリース用ファイルの雛形作成
$ rebar generate
```

`reltool`を使ってリリースパッケージを生成します。詳しくは[wiki](https://github.com/rebar/rebar/wiki/Release-handling)を参照してください。また、 [こちら](https://gist.github.com/voluntas/4243786)にErlangのリリースについての解りやすい解説があります。

```bash
# アップグレード用ファイルの雛形作成
$ rebar generate-upgrade
```

アップグレードパッケージを生成します。詳しくは[wiki](https://github.com/rebar/rebar/wiki/Upgrades)を参照してください。

### その他

```bash
# common test suiteを実行
$ rebar ct
```

common test suiteを実行します。common testについては[こちら](http://erlang.org/doc/man/common_test.html)を参照してください。

```bash
# escriptファイルを生成
$ rebar escriptize
```

`ebin`の中にescriptファイルを生成します。escriptについては[こちら](http://www.erlang.org/doc/man/escript.html)を参照してください。

```bash
# xrefを実行
$ rebar xref
```

xrefを走らせます。xrefについては[こちら](http://www.erlang.org/doc/man/xref.html)を参照してください。

## まとめ

rebarについて調べた事をまとめました、ほぼ[wiki](https://github.com/rebar/rebar/wiki)に書いてある事が全てですけどね。「統合」ビルドツールという事だけあってかなり多機能です。
リリースやアップグレード周りのコマンドに関しては、本格的にリリース作業・アップグレード作業をやった事が無いのでいまいちピンときませんでした。きっとバリバリErlangを使ってみないとありがたみは解らないのかもしれません。