Migrating to Relx
July 7, 2015
Recently I migrated a bunch of Erlang projects at CHEF to use
relx to build the release instead of
reltool. An easy way to get started with relx in your project is to try out
concrete if you're working with rebar2, or
get in on rebar3. I recently migrated
chatterbox to rebar3 and it's been
great (just don't keep your common_tests in a directory called common_test).
relx is a breath of fresh air after working with reltool. There will always
be a soft spot in my heart for
node_package
Including dependencies
The biggest problem I encountered with relx was that my release's lib
directory contained way fewer libraries than the reltool version of the
release.
It turns out that relx is really smart about dependencies. It's up to you to
include your application's direct dependencies in your relx.config file, but
relx handles all their dependencies for you.
Well, at least it tries to.
relx figures out what your dependencies depend on by looking at their
.app.src files. Or maybe the compiled .app files. If the application you're
including has done a good job with that, relx can take that information and run
with it. If it hasn't done a good job, you have two real options:
Fix it
If it's your repo, you can update the repo's .app.src with the right
dependencies. If it's not, you can open a pull request.
Manually manage the dependency
If you opened a PR to fix it, you might not be able to wait for it to get
merged. You also might not be able to upgrade to the latest version of that
application. In that case you can add those dependencies to relx.config.
This is the standard way to handle this, although I found no documentation
of this, what I assume is a common occurrence. Tristan was kind enough to
confirm this for me in IRC.
A Simple Case: boundary/folsom
The project (chef-mover) I was migrating when I encountered the problem included an older version of folsom. They know about it Issue 82, and they've fixed it PR 83, but not in the version I was locked to.
relx.config (abridged):
{release,{mover,"12.2.0"},[
mover,
bear, %% Add this!
folsom %% This was here already
]}.
But, adding bear here wasn't enough. I also needed to add it to my
mover.app.src:
{application, mover,
[{description, ""},
{vsn, "12.2.0"},
{applications, [kernel,
stdlib,
%% ...
bear, %% Add this!
folsom %% And this!
]},
{mod, {mover_app, []}}
]}.
I tried this same technique with other dependencies in mover, but it turned out
that this only applies to application dependencies. library dependencies don't
need to be added to .app.src; however, the way they need to be handled in
relx.config is a little different.
relx.config (stil abridged):
{release,{mover,"12.2.0"},[
mover,
bear,
folsom,
{chef_db, load}, %% Use this syntax to keep the app from starting
{chef_objects, load} %% As many times as you need
]}.
Conclusion
I hope this helps you. I thought at first that the only way to manage this
problem was to fix the dependencies' .app.src. The good news here is that
having this in your relx.config and the dependencies' .app.src is just
redundant. So it won't break anything when we upgrade mover to the latest
folsom.