From bb2364dc9de3739fe96d1e1aa8bb941060ed4aba Mon Sep 17 00:00:00 2001 From: Pouriya-Jahanbakhsh Date: Thu, 15 Nov 2018 04:23:17 +0330 Subject: [PATCH] add Erlang/OTP example --- examples/erlang/README.md | 228 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 228 insertions(+) create mode 100644 examples/erlang/README.md diff --git a/examples/erlang/README.md b/examples/erlang/README.md new file mode 100644 index 0000000..b71b0e5 --- /dev/null +++ b/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.