Skip to content
Permalink
Browse files

add Erlang/OTP example

  • Loading branch information
Pouriya-Jahanbakhsh authored and dgiagio committed Nov 15, 2018
1 parent 599d6b3 commit bb2364dc9de3739fe96d1e1aa8bb941060ed4aba
Showing with 228 additions and 0 deletions.
  1. +228 −0 examples/erlang/README.md
@@ -0,0 +1,228 @@
You need to have [`Erlang/OTP`](http://erlang.org), [`Rebar3`](http://rebar3.org) (Erlang build tool) and `warp-packer` installed to create self-contained binary Erlang release.

## Linux
Create new application using `rebar3`:
```sh
~ $ rebar3 new app foo && cd foo
```
```txt
===> Writing foo/src/foo_app.erl
===> Writing foo/src/foo_sup.erl
===> Writing foo/src/foo.app.src
===> Writing foo/rebar.config
===> Writing foo/.gitignore
===> Writing foo/LICENSE
===> Writing foo/README.md
```
```sh
~/foo $
```

Make a directory (e.g. `config`) to place `warp` launcher in it:
```sh
~/foo $ mkdir config
```
Create `./config/launch` file with below contents:
```sh
#!/bin/sh
DIR="$(cd "$(dirname "$0")" ; pwd -P)"
APP=$DIR/bin/{{release_name}}
exec $APP $@
```
We used [`mustache`](https://mustache.github.io/) template to let `rebar3` place your release name in script dynamically. Here it is `foo`.

Make launcher file executable:
```sh
~/foo $ chmod a+x config/launch
```

Edit `rebar.config` file and add `relx` section:
```erlang
% ...
{relx, [{release, { foo, "0.1.0" }, [foo, sasl]},
{dev_mode, false},
{include_erts, true}, % To include Erlang runtime system
{extended_start_script, true}, % Should be true
{overlay, [{template, "./config/launch", "launch"}]}] % copies our launcher file to release directory
}.
% ...
```

Make a release:
```sh
~/foo $ rebar3 release
```
```text
===> Verifying dependencies...
===> Compiling foo
===> Starting relx build process ...
===> Resolving OTP Applications from directories:
/opt/foo/_build/default/lib
/usr/local/lib/erlang/lib
/opt/foo/_build/default/rel
===> Resolved foo-0.1.0
===> Including Erts from /usr/local/lib/erlang
===> release successfully created!
```
Now launcher file should be in your release directory:
```sh
~/foo $ ls _build/default/rel/foo
bin erts-10.1 launch lib releases
```

Before running `warp-packer`, It's better to test release itself:
```sh
~/foo $ ./_build/default/rel/foo/bin/foo start
~/foo $ ./_build/default/rel/foo/bin/foo ping
pong
~/foo $ ./_build/default/rel/foo/bin/foo stop
ok
```

Build self-contained binary file from release:
```sh
~/foo $ warp-packer -a linux-x64 -i _build/default/rel/foo -e launch -o foo
```
```text
Compressing input directory "_build/default/rel/foo"...
Creating self-contained application binary "foo"...
All done
```

Test it:
```sh
~/foo $ ./foo start
```
```sh
~/foo $ ./foo ping
pong
```
```sh
~/foo $ ./foo remote_console
Erlang/OTP 21 [erts-10.1] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [hipe]
Eshell V10.1 (abort with ^G)
(foo@localhost)1>
BREAK: (a)bort (c)ontinue (p)roc info (i)nfo (l)oaded
(v)ersion (k)ill (D)b-tables (d)istribution
```
```sh
~/foo $ ./foo stop
ok
```
```sh
~/foo $ ./foo ping
Node foo@localhost not responding to pings.
```

#### Advanced
You can place `warp` command in `rebar.config`. Then `rebar3` will run it when you are making release:
```erlang
% ...
{post_hooks, [{release, "warp-packer -a linux-x64 -i _build/default/rel/foo -e launch -o foo"}]}.
% ...
```
Now make release:
```sh
~/foo $ rebar3 release
```
```text
===> Verifying dependencies...
===> Compiling foo
===> Starting relx build process ...
===> Resolving OTP Applications from directories:
/opt/foo/_build/default/lib
/usr/local/lib/erlang/lib
/opt/foo/_build/default/rel
===> Resolved foo-0.1.0
===> Including Erts from /usr/local/lib/erlang
===> release successfully created!
Compressing input directory "_build/default/rel/foo"...
Creating self-contained application binary "foo"...
All done
```

Note that `rebar3` uses a templating approach to make an application structure. If you built `rebar3`by yourself, and did not use its escript, Its own templates are placed in `/path/to/installed/rebar3/priv/templates`.
You can place your `launch` file there and add below lines at the end of `app.template`:
```erlang
% ...
{file, "launch", "{{name}}/config/launch"}. % copies launch file to YourApp/config/launch
{chmod, "{{name}}/config/launch", 8#755}. % makes file executable
```
Also edit `app_rebar.config` and place our `relx` and `post_hooks` at the end of file:
```erlang
% ...
{relx, [{release, { {{name}}, "0.1.0" },
[{{name}}, sasl]},
{dev_mode, false},
{include_erts, true},
{extended_start_script, true},
{overlay, [{template, "./config/launch", "launch"}]}]
}.
{post_hooks, [{release, "warp-packer -a linux-x64 -i _build/default/rel/{{name}} -e launch -o {{name}}"}]}.
```
In above `{{name}}` is what you will pass to `rebar3 new app` as application name. Recompile `rebar3` itself again:
```sh
/path/to/rebar3 $ ./bootsrtap
...
```

Create new application again:
```sh
~ $ rebar3 new app bar && cd bar
```
```text
===> Writing bar/src/bar_app.erl
===> Writing bar/src/bar_sup.erl
===> Writing bar/src/bar.app.src
===> Writing bar/rebar.config
===> Writing bar/.gitignore
===> Writing bar/LICENSE
===> Writing bar/README.md
===> Writing bar/config/launch
```
Make a release:
```sh
~/bar $ rebar3 release
```
```text
===> Verifying dependencies...
===> Compiling bar
===> Starting relx build process ...
===> Resolving OTP Applications from directories:
/opt/bar/_build/default/lib
/usr/local/lib/erlang/lib
===> Resolved bar-0.1.0
===> Including Erts from /usr/local/lib/erlang
===> release successfully created!
Compressing input directory "_build/default/rel/bar"...
Creating self-contained application binary "bar"...
All done
```

Test it:
```sh
~/bar $ ./bar start
```
```sh
~/bar $ ./bar ping
pong
```
```sh
~/bar $ ./bar stop
ok
```

Also you can add it for `rebar3 new release | lib` or [build your own template](https://www.rebar3.org/docs/using-templates#section-custom-templates) and add it to your template.

0 comments on commit bb2364d

Please sign in to comment.
You can’t perform that action at this time.