Building an OTP release including Lager with rebar and reltool


September 2014.
Image

Building an OTP release including Lager with rebar and reltool.

Create your app the usual way:

rebar create-app appid=testapplager

Add the following to rebar.config:

{lib_dirs,["deps"]}.
{sub_dirs, ["rel"]}.
{deps, [
{lager, ".*", {
git, "git://github.com/basho/lager.git", "master"}
}
]}.
{erl_opts, [{parse_transform, lager_transform}]}.

Add some code to your app, get the dependencies and compile.

rebar get-deps
rebar compile

Create a node configuration

mkdir rel && cd rel
rebar create-node nodeid=testapplager

Set the different paths to the dependencies and your app in reltool.config:

{sys, [
{lib_dirs, ["../deps"]},
{erts, [{mod_cond, derived}, {app_file, strip}]},
{app_file, strip},
{rel, "testapplager", "1",
[
kernel,
stdlib,
sasl,
lager,
testapplager
]},
{rel, "start_clean", "",
[
kernel,
stdlib
]},
{boot_rel, "testapplager"},
{profile, embedded},
{incl_cond, exclude},
{excl_archive_filters, [".*"]}, %% Do not archive built libs
{excl_sys_filters, ["^bin/.*", "^erts.*/bin/(dialyzer|typer)",
"^erts.*/(doc|info|include|lib|man|src)"]},
{excl_app_filters, ["\.gitignore"]},
{app, sasl, [{incl_cond, include}]},
{app, stdlib, [{incl_cond, include}]},
{app, kernel, [{incl_cond, include}]},
{app, lager, [{incl_cond, include}]},
{app, testapplager, [{mod_cond, app}, {incl_cond, include}, {lib_dir, ".."}]}
]}.

{target_dir, "testapplager"}.

{overlay, [
{mkdir, "log/sasl"},
{copy, "files/erl", "\{\{erts_vsn\}\}/bin/erl"},
{copy, "files/nodetool", "\{\{erts_vsn\}\}/bin/nodetool"},
{copy, "files/testapplager", "bin/testapplager"},
{copy, "files/testapplager.cmd", "bin/testapplager.cmd"},
{copy, "files/start_erl.cmd", "bin/start_erl.cmd"},
{copy, "files/install_upgrade.escript", "bin/install_upgrade.escript"},
{copy, "files/sys.config", "releases/\{\{rel_vsn\}\}/sys.config"},
{copy, "files/vm.args", "releases/\{\{rel_vsn\}\}/vm.args"}
]}.

Try to build the release:

rebar generate

Failure!

ERROR: generate failed while processing /root/some-sub-folder/testapplager/rel: {'EXIT',{{badmatch,{error,"Application compiler is used in release \"testapplager\" and cannot be excluded"}},
[{rebar_reltool,generate,2,
[{file,"src/rebar_reltool.erl"},{line,50}]},
{rebar_core,run_modules,4,[{file,"src/rebar_core.erl"},{line,425}]},
{rebar_core,execute,5,[{file,"src/rebar_core.erl"},{line,359}]},
{rebar_core,process_dir0,6,[{file,"src/rebar_core.erl"},{line,223}]},
{rebar_core,process_dir,4,[{file,"src/rebar_core.erl"},{line,130}]},
{rebar_core,process_each,5,[{file,"src/rebar_core.erl"},{line,296}]},
{rebar_core,process_dir0,6,[{file,"src/rebar_core.erl"},{line,199}]},
{rebar_core,process_dir,4,
[{file,"src/rebar_core.erl"},{line,130}]}]}}

The problem is that reltool won't include any package by default. This means that lager can't get its dependencies built into the release.

To solve this problem, either change the include condition to:

{incl_cond, derived},

Or manually include the dependencies:

{app, goldrush, [{incl_cond, include}]},
{app, syntax_tools, [{incl_cond, include}]},
{app, compiler, [{incl_cond, include}]},

Then rebuild your release.