Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save ajiyoshi-vg/7c1ad1076607a9f3aecb to your computer and use it in GitHub Desktop.
Save ajiyoshi-vg/7c1ad1076607a9f3aecb to your computer and use it in GitHub Desktop.

Erlang で、relx と sync を使ったお手軽自動リロード開発環境コトハジメ

relx コトハジメ の内容を把握している読者を想定しています。

Dockerイメージなどを開発環境にしていると、なるべく実際に動く環境に近いような動作環境でテストしたくなります。

一方で、開発環境というのはなるべく手間なく勝手にコンパイルやテストが走ったり、変更点を勝手にリロードしてほしいものです。

relx を使ってリリースイメージに近いような環境でソフトウェアを起動しつつ、 sync を使って自動コンパイル&リロードする環境を作ろうというのがこの記事の趣旨です。

サンプルプロジェクトを用意

$ mkdir myapp
$ cd myapp
$ cp /path/to/rebar .
$ cp /path/to/relx .
$ ./rebar create-app appid=myapp
==> myapp (create-app)
Writing src/myapp.app.src
Writing src/myapp_app.erl
Writing src/myapp_sup.erl

普通です。 rebar のテンプレートでアプリのひな形を作ります。

relx の設定(自動リロードなし)を用意

dev_relx.config

{release, {myapp, "0.0.1"},
    [sasl, myapp]}.
{extended_start_script, true}.
{output_dir, "dev"}.

コンパイルし、relxリリースを作る

$ ./rebar get-deps compile
==> myapp (get-deps)
==> myapp (compile)
Compiled src/myapp_app.erl
Compiled src/myapp_sup.erl

$ ./relx -c dev_relx.config
===> Starting relx build process ...
===> Resolving OTP Applications from directories:
          /home/y-sudo/project/0206/myapp/ebin
          /home/y-sudo/kerl/R16B03-1/lib
===> Resolved myapp-0.0.1
===> Including Erts from /home/y-sudo/kerl/R16B03-1
===> release successfully created!

私はこういうのは Makefile にしちゃうのが好みです。

relx 起動

$ ./dev/myapp/bin/myapp console
(中略)
([email protected])1>

無事起動しました。ここまでは voluntas さんの記事の通りです。

([email protected])1> q().

終了しときます。

sync を準備 & relxの設定を変更

sync という Erlangアプリがあり、ファイルシステムを監視して、ソースコードが変更されたら自動コンパイル&リロードしてくれる素敵なアプリです。

ただ、sync は開発用途のソフトウェアで sync:go() してやらないと監視を開始してくれません。それはそれでもっともだと思いますが、 開発用Dockerイメージなどではイメージ起動したら勝手にソースの更新チェックとかしてほしいです。結局 console 開くことにはなるけど、毎度 sync:go() 叩くのも面倒です。

そこで sync:go() するだけの auto_syncer というアプリケーションを作ったので、こいつを使ってやります。

rebar.config

{deps, [
    {auto_syncer, ".*", {git, "https://github.com/ajiyoshi/auto_syncer.git"}}
]}.

rebar.config のdepsに追加

dev_relx.config

{release, {myapp, "0.0.1"},
    [sasl, myapp, auto_syncer]}.
{extended_start_script, true}.
{output_dir, "dev"}.

auto_syncer をリリースに含めてやります

リリース作成してアプリケーションを起動

$ ./rebar get-deps
==> myapp (get-deps)
Pulling auto_syncer from {git,"https://github.com/ajiyoshi/auto_syncer.git"}
Cloning into 'auto_syncer'...
==> auto_syncer (get-deps)
Pulling sync from {git,"https://github.com/rustyio/sync.git"}
Cloning into 'sync'...
==> sync (get-deps)

$ ./rebar compile
==> sync (compile)
Compiled src/sync.erl
Compiled src/sync_notify.erl
Compiled src/sync_scanner.erl
Compiled src/sync_options.erl
Compiled src/sync_utils.erl
==> auto_syncer (compile)
Compiled src/auto_syncer_app.erl
Compiled src/auto_syncer_sup.erl
==> myapp (compile)

$ ./relx -c dev_relx.config
===> Starting relx build process ...
===> Resolving OTP Applications from directories:
          /home/y-sudo/project/0206/myapp/ebin
          /home/y-sudo/project/0206/myapp/deps
          /home/y-sudo/kerl/R16B03-1/lib
===> Resolved myapp-0.0.1
===> Including Erts from /home/y-sudo/kerl/R16B03-1
===> release successfully created!

これで、アプリケーションを起動するだけでソースコードを自動コンパイル&リロードしてくれるリリースビルドができました。起動してみます。

$ ./dev/myapp/bin/myapp console
(中略)
([email protected])1>

ソースコードを適当に変更したら、自動リロードされます

src/myapp_app.src を適当に編集。

-module(myapp_app).

-behaviour(application).

%% Application callbacks
-export([start/2, stop/1]).
-export([hello/0]).

%% ===================================================================
%% Application callbacks
%% ===================================================================

start(_StartType, _StartArgs) ->
    myapp_sup:start_link().

stop(_State) ->
    ok.

hello() ->
    hello.

勝手にコンパイル&リロード

([email protected])1>
=INFO REPORT==== 8-Feb-2015::14:24:41 ===
/home/y-sudo/project/0206/myapp/src/myapp_app.erl:0: Recompiled.

=INFO REPORT==== 8-Feb-2015::14:24:41 ===
myapp_app: Reloaded! (Beam changed.)

([email protected])2> myapp_app:hello().
hello

便利。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment