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.