はじめに
Elixir中心で学んできましたが、kernelやVMのコードを見るとなるErlangを知る必要があると痛感。そして、見ていくと、プロジェクトはどうなっているんだろうか、depsはどのように定義されているのか、気になり始め、調べるに至りました。ここではその学んだ内容を書きます。
Projectを作成する方法には以下の二つの方法があるようです。
-
rebar3 資料リンク
mix new <project>
と同じようにrebar3 new ....
で作ります。その他、mix
と同様にコマンドが多々あります。 -
erlang.mk 資料リンク
数百のテンプレートが用意されており、各々に応じたsrc
とerlang.mk
が作成されます。
mix
のようなコマンドは無く、make
コマンド処理される。
本記事では、rebar3
についてまとめます。ただし、対象はMacOSでのものです。
rebar3
って何
Erlangの標準ビルトツールで
- オープンソースに沿って公開されたErlangのいろいろなツールを統合するもの
- そして、プロジェクト構成結合をする役割を持つもの
要は各ツールのまとめをやり、モジュール取り込み(deps)を行うもの。
rebar3
はErlangで作られ、escriptによる実行ファイルです。
rebar3
のインストール
予めインストールされた仮のrebar3
を実行する事により新たなrebar3
をインストールします。
まず、brew
またはasdf
でrebar3
をインストールし、そのコマンドにより、新しく~/.cache/rebar3
ローカルにインストールします。
rebar3
をインストールするためにrebar3
が必要とはすごくおかしい気がしますが、brew
などで取得したものはrebar3
の実行ファイルのみで、以下の方法では展開先~/.cache/rebar3
にlibが展開され、利用できるようになっていて違っています。
一度、展開したら、予め用意したrebar3
は不要でアンインストールまたは削除可能です。
- ローカルへインストール
$ rebar3 local install
===> Extracting rebar3 libs to ~/.cache/rebar3/lib...
===> Writing rebar3 run script ~/.cache/rebar3/bin/rebar3...
===> Add to $PATH for use: export PATH=$PATH:~/.cache/rebar3/bin
upgradeします。
$ rebar3 local upgrade
===> Extracting rebar3 libs to ~/.cache/rebar3/lib...
===> Writing rebar3 run script ~/.cache/rebar3/bin/rebar3...
===> Add to $PATH for use: export PATH=$PATH:~/.cache/rebar3/bin
PATHを設定します。各shellの環境設定に。(zshrc
など)
export PATH=$PATH:~/.cache/rebar3/bin
最後に元々あるrebar3
は不要となり、uninstalまたは削除lしておきます。
- ソースからインストール
brew
などで仮のrebar3
をインストールせず、この手順をやれば問題ないと思えますが、資料がこの順番で紹介され、なぜなのか、わかりません。
$ git clone https://github.com/erlang/rebar3.git
$ cd rebar3
$ ./bootstrap
rebar3
の実行ファイルが展開されるので、それ以降は「ローカルへインストール」の手順です。
./rebar3 local install
|
|
展開するディレクトリーは実行できれば良いのでどこでもかまいません。rebar3 local install
により固定~/.cache/rebar3
に展開され、処理後は上記ディレクトリーは削除すれば良い。
$ rebar3 new <template> <project-name>
- 新しくProjectを作る
projectの用途により各テンプレートが用意され、その指定により.app、src/code
を生成します。
<template>の種類
app
: アプリケーションのprojectを作ります。
lib
: ライブラリー作成
release
: リリース用のprojectを作る。
umbrella
: Erlangではponcho
の構成でなく、umbrella
構成が標準のようです。
escript
: 実行ファイルを作る時のproject作成
plugin
: plugin を作成
cmake
: C/C++のコードのMakefileを作成する。コード展開はない。
例、$ rebar3 new app myapp
--> 以下の構成ファイルに展開されます。
myapp
├── LICENSE
├── README.md
├── rebar.config
└── src
├── myapp.app.src
├── myapp_app.erl
└── myapp_sup.erl
$ rebar3 compile
- コンパイルする
new
で各ファイルを展開したものをコンパイルし、_build
ディレクトリーに展開されます。
上記myappの場合
├── _build
│ └── default
│ └── lib
│ └── myapp
│ ├── ebin
│ │ ├── myapp.app
│ │ ├── myapp_app.beam
│ │ └── myapp_sup.beam
│ ├── include -> ../../../../include
│ ├── priv -> ../../../../priv
│ └── src -> ../../../../src
$ rebar3 shell
- projectを実行する。
mix run
の代わりにrebar3 shell
で実行します。
$ rebar3 shell
===> Verifying dependencies...
===> Analyzing applications...
===> Compiling myapp
Erlang/OTP 25 [erts-13.0.3] [source] [64-bit] [smp:12:12] [ds:12:12:10] [async-threads:1] [jit:ns]
Eshell V13.0.3 (abort with ^G)
1> ===> Booted myapp
1>
$ rebar3 help
-- タスク一覧と詳細表示
$ rebar3 help
により各タスクの一覧が表示されます。
各タスクのhelp表示は$ rebar3 help <task>
です。
例、
$ rebar3 help compile
Compile apps .app.src and .erl files.
Usage: rebar3 compile [-d]
-d, --deps_only Only compile dependencies, no project apps will be
built.
Projectの定義ファイル(.app
or .app.src
)
Projectの情報は.app
または .app.src
の拡張子のファイルに定義します。
%% 項目名 値 値属性 Default
{application, Application, %% atom()
[{description, Description}, %% string() ""
{id, Id}, %% string() ""
{vsn, Vsn}, %% string() ""
{modules, Modules}, %% [Module] []
{maxP, MaxP}, %% int() infinity
{maxT, MaxT}, %% int() infinity
{registered, Names}, %% [Name] []
{included_applications, Apps}, %% [App] []
{optional_applications, Apps}, %% [App] []
{applications, Apps}, %% [App] []
{env, Env}, %% [{Par,Val}] []
{mod, Start}, %% {Module,StartArgs} {}
{start_phases, Phases}, %% [{Phase,PhaseArgs}] undefined
{runtime_dependencies, RTDeps}]}. %% [ApplicationVersion] []
例のmyapp
の場合
{application, myapp,
[{description, "An OTP application"},
{vsn, "0.1.0"},
{registered, []},
{mod, {myapp_app, []}},
{applications,
[kernel,
stdlib
]},
{env,[]},
{modules, []},
{licenses, ["Apache-2.0"]},
{links, []}
]}.
deps
の定義はどこに
rebar.config
のファイルに定義され、そこからローカル(_build/
)に展開されるようになっています。Elixirでのdeps/
ディレクトリーはなく、コンパイル実行によりすべて_build/
に展開されるようになっています。
例、rebar.config
の一部deps
の部分、参考資料から抜粋して適当セットしました。
{deps, [
{erldns,
{git, "https://github.com/tsloughter/erldns.git",
{branch, "revamp"}}},
{dns,
{git, "https://github.com/tsloughter/dns_erlang.git",
{branch, "hex-deps"}}},
recon,
eql,
jsx,
{uuid, "1.7.5", {pkg, uuid_erl}},
{elli, "~> 3.2.0"},
{grpcbox, "~> 0.11.0"}
]}.
展開結果--dns
部分の詳細です。
_build
└── default
├── lib
│ ├── base32
│ ├── dns
│ │ ├── LICENSE
│ │ ├── Makefile
│ │ ├── README.markdown
│ │ ├── asn1
│ │ │ └── DNS-ASN1.asn1
│ │ ├── asngen
│ │ │ ├── DNS-ASN1.asn1db
│ │ │ ├── DNS-ASN1.beam
│ │ │ ├── DNS-ASN1.erl
│ │ │ └── DNS-ASN1.hrl
│ │ ├── ebin
│ │ │ ├── DNS-ASN1.beam
│ │ │ ├── dns.app
│ │ │ ├── dns.beam
│ │ │ ├── dns_record.beam
│ │ │ ├── dns_record_info.beam
│ │ │ └── dnssec.beam
│ │ ├── include
│ │ │ ├── DNS-ASN1.hrl
│ │ │ ├── dns.hrl
│ │ │ ├── dns_records.hrl
│ │ │ ├── dns_terms.hrl
│ │ │ ├── dns_tests.hrl
│ │ │ ├── dnssec_tests.hrl
│ │ │ └── rebar_version.hrl
│ │ ├── priv
│ │ │ ├── dnssec_samples.txt
│ │ │ ├── index.html
│ │ │ ├── overview.edoc
│ │ │ ├── rrdata_wire_samples.txt
│ │ │ └── tsig_wire_samples.txt
│ │ ├── rebar.config
│ │ ├── rebar.lock
│ │ └── src
│ │ ├── DNS-ASN1.asn1db
│ │ ├── DNS-ASN1.erl
│ │ ├── dns.app.src
│ │ ├── dns.erl
│ │ ├── dns_record.erl
│ │ ├── dns_record_info.erl
│ │ └── dnssec.erl
│ └── myapp
circuits_i2c
は使えるのか
のrebar.config
のタグから
{deps, [
{circuits_i2c, "1.2.1"}
]}.
でpackageを取り込めるか、確かめましたが、エラーが発生し、ビルトできませんでした。
Hex
からダウンロードし、そのpackageを使う事はできるようになっていますが、問題が発生し、処置が必要なようです。
まとめ
Elixir/Mixと違い、rebar3
はなんか使いにくいとの印象。慣れの問題かもしれない。
Elixirではdeps
ディレトリー然り、config
など区別され、分かり易いが、Erlangでは_build
内に詰め込んでいる。Erlang(旧)からElixir(新)と流れ、やはり新しいのは昔のものの改良版で使いやすいの当然なんだろう。
それと、ElixirからErlangを呼ぶ事は普通だが、その逆ってできるんだろうか、疑問になる。他にも疑問だらけだが、今はerlangの仕組みがわかり、コードを追えれば良いと思うので。深く調べる事はしない。