rebar2のrebar3置き換えで嵌まりまくった話

# rebar2のrebar3置き換えで嵌まりまくった話
rebar3が標準ビルドツールになるということで, rebar3置き換えを進めたがそれは苦難の道であった...という話. 
(ちなみに置き換えられませんでした)

もうrebar2を使っている人はいないと思うので非常に今更なのだが, アドベントカレンダーが空いているのと, 4月ぐらいに書いたらしい下書きが残っていたので...^^;;

## rebar3ってそんな良いの？
- eunitの個別実行ができる. (rebar2では壊れています)
- ctでもerl_optsが指定できる.
 - 例えば, warn_export_allをcompileの時だけ付けて, eunit/ctでは外せるなど
- lockファイルが作成できる (hexで同じバージョンに上げ直されても分かるぞ！！)
- 依存ライブラリの更新ができる (rebar2では壊れています)
- test用途などの本来不要な依存ライブラリを別で管理できる
 - ライブラリを使う側には不要なライブラリが入らなくなる
- rebar3 + relxの使い勝手が良い.

などなど...

## 苦難の始まり
### pluginsの互換性がなくなった
全くの別物になりました.
buildにどうしても必要なplugins以外は取り敢えず無効化すれば事足りる.

```erlang:rebar.config
{overrides, [
             {override, [{plugins, []}]}, % all deps applications
             {override, Application, [{plugins, []}]}
            ]}.
```

### raw optionが廃止になった
[issue#110 raw dependencies](https://github.com/erlang/rebar3/issues/110)
rawはそもそも指定するな, もし依存ライブラリで使っているところがあれば, overrideを使えということだが, 不便極まりない.
overrideを使うにしても, depsの量によっては相当な手間である.

しかも, 3.0.0での挙動はトリッキーになっていて,

- 依存ライブラリのrawはDLできるが, compile時にapp.srcがないのでエラーになる
- top levelでrawを指定すると, DL前にエラーになる

という挙動を取る.

流石に, これでは移行が進められないのでplugin ([rebar3_raw_deps](https://github.com/soranoba/rebar3_raw_deps))を作って使うことにした.
.app/.app.srcが作れないと判断された場合に.appを作るという~~頭の悪い~~pluginである.

### rebar.config.scriptの誤動作

rebar2/rebar3両対応パッチを投げた方が良い.
2016/03にrebar3に入った, vsn周りの変更によってrebar.config.scriptが正しく動かなくなっている場合がある.

- [erlware_commons: Fix script so it can compile git-versioned](https://github.com/erlware/erlware_commons/commit/0c1636e75ac9b2cffae8e3dca5ed36f4e9e555ae)
- [rebar3 issue#1119: Uncaught error in rebar_core when compiling "hackney"](https://github.com/erlang/rebar3/issues/1119)

ここらへんを参考にするとよい.

### Port Compilerの微妙な変更, plugin化.
[Port Compiler](http://www.rebar3.org/docs/using-available-plugins#port-compiler)

起動しようとして以下のようなエラーが出た場合は, port driverのcompileができていないのが原因.

```erlang
{{shutdown,{failed_to_start_child,kernel_safe_sup,{on_load_function_failed,eleveldb}}}
```

概ね以下のどちらかの回避方法で逃げることが可能.

#### 回避方法(1): pc pluginを使う
現在も使用可能なoptionのみが使用されていて, かつ, 独自のget-depsが使われていなければこれ.

```erlang
{overrides, [
             {override, Application, [{plugins, [pc]}, 
                                      {provider_hooks, [{pre, [{compile, {pc, compile}}, 
                                                               {clean, {pc, clean}}]}]}
                                     ]}
            ]}.
```

#### 回避方法(2): makeを使う
makeで全て扱えるようになっている場合はこれ.

```erlang
{overrides, [
             {override, Application, [{pre_hooks, [{compile, "make"}]}]}
            ]}.
```

### ct_slave周りの誤動作

rebar2では何もせずに使えたのが, ERL_FLAGSで指定するだけではダメで, `net_kernel:start`が必要になる.
[3.2系からはdist_nodeオプションで指定できるようになる](https://github.com/erlang/rebar3/pull/1152).

[実際の使い方はドキュメントを参照すると良い](http://www.rebar3.org/docs/configuration#distribution)

### ctの実行形式が変更になった

今までapplication毎に別実行になっていたのが, 一括で実行されるようになった.
その為, 環境変数などを使用している場合, 他のapplicationのctに状態が引き継がれてしまうので注意が必要.

## 最後に

恐らく, 躓くのはここら辺だと思う.
なお, 置き換えられなかったのはdialyzer周りがどうオプションを弄っても正しく動かなかったからである.
プロジェクト規模が小さければ, 問題にはならないはずである.

また, elixirのビルドツールであるmixを使うという選択肢もあると思う.
rebar3から[elixirを使う為のplugin](http://www.rebar3.org/docs/using-available-plugins#elixir-dependencies)が一応出ているが, 使ったことはないので使って事がある方がいれば是非記事を書いて欲しい.

----

2016.4の時点の情報のものがあるかもしれないのでご了承ください.