Rebar3: The Standard Erlang Build Tool
Rebar3 is the standard build tool for Erlang, handling project scaffolding, dependency fetching from hex.pm or git, compilation, and packaging into OTP releases. It replaced the older rebar with a more predictable plugin system and a lock file (rebar.lock) that pins dependency versions so builds are reproducible across machines. Unlike make-based workflows common in early Erlang projects, rebar3 understands OTP application structure natively, so commands like rebar3 compile or rebar3 shell just work once you've generated a project with rebar3 new.
Cricket analogy: Think of rebar3's lock file like a scorer noting the exact playing XI and pitch conditions for a Test match at the WACA — anyone rerunning the analysis later gets the identical setup, not a guess at who played.
Project Structure and Dependencies
Running rebar3 new app myapp generates a compliant OTP application skeleton: src/myapp_app.erl and src/myapp_sup.erl implementing the application and supervisor behaviours, a myapp.app.src resource file, and a starter rebar.config. Dependencies go in the {deps, [...]} tuple — either a hex.pm package and version like {cowboy, "2.10.0"}, or a git tuple like {jsx, {git, Url, {tag, "v3.1.0"}}}. On the first rebar3 compile, rebar3 resolves the dependency graph and writes the exact resolved versions into rebar.lock, which should be committed alongside rebar.config.
Cricket analogy: Declaring {deps, [{cowboy, "2.10.0"}]} in rebar.config is like a franchise auction squad list specifying exact players by name and price, rather than a vague 'we'll pick some bowlers' — hex.pm is the auction house supplying them.
$ rebar3 new app myapp
$ cd myapp
$ cat rebar.config
{erl_opts, [debug_info]}.
{deps, [
{cowboy, "2.10.0"},
{jsx, {git, "https://github.com/talentdeficit/jsx.git", {tag, "v3.1.0"}}}
]}.
{relx, [
{release, {myapp, "0.1.0"}, [myapp, sasl]},
{dev_mode, true},
{include_erts, false}
]}.
{profiles, [
{prod, [
{relx, [{dev_mode, false}, {include_erts, true}]}
]}
]}.
$ rebar3 compile
$ rebar3 shell
$ rebar3 as prod releaseBuilding Releases with Relx
rebar3 release (backed by the bundled relx plugin) bundles your compiled application code together with an Erlang runtime system (ERTS) and boot scripts into a single self-contained tarball, ready to copy onto a server with no separately installed Erlang required. Profiles declared under {profiles, [...]} let the same rebar.config produce different builds for different purposes — a prod profile typically disables dev_mode and sets include_erts to true, while the default profile favors fast iteration over a fully bundled artifact.
Cricket analogy: Building a release with relx is like packing a touring squad's full kit — bats, pads, medical staff, visas — into one travel case for an away series, rather than assuming gear will be available on arrival; the ERTS runtime travels with the app the same way.
rebar3 shell compiles your project and drops you into an Erlang REPL with every application already started — edit a module, run rebar3 compile in another terminal (or c(module) inside the shell), and the running system picks up the new code immediately, which is invaluable for interactive development.
Testing, Analysis, and Common Commands
Beyond compiling and releasing, rebar3 wraps the standard OTP testing and analysis tools behind consistent subcommands: rebar3 eunit runs EUnit-based unit tests, rebar3 ct runs Common Test suites, rebar3 dialyzer performs static success-typing analysis (building and reusing a PLT of cached type information), and rebar3 cover reports which lines of code your test run actually exercised. Because these all read the same rebar.config, a single command like rebar3 do eunit, cover can chain steps together in CI.
Cricket analogy: Running rebar3 dialyzer is like a team's analyst reviewing years of match footage to flag a batter's technical flaw before it costs a Test match, catching type mismatches through static success typing before the code ever runs.
- rebar3 is the de facto standard build tool for Erlang, replacing ad-hoc Makefiles with OTP-aware project scaffolding.
- rebar3 new app <name> and rebar3 new lib <name> generate a compliant OTP application skeleton.
- Dependencies are declared in the {deps, [...]} tuple in rebar.config and can come from hex.pm or git.
- rebar.lock pins exact dependency versions so builds are reproducible across machines and CI.
- rebar3 release (via the bundled relx plugin) packages the app and ERTS into a deployable tarball.
- Profiles such as prod let you vary build settings (e.g., dev_mode, include_erts) without duplicating config.
- rebar3 eunit, rebar3 ct, rebar3 dialyzer, and rebar3 cover integrate testing and static analysis into the same tool.
Practice what you learned
1. What file does rebar3 use to pin exact dependency versions for reproducible builds?
2. Which command starts an interactive Erlang shell with your project's applications already compiled and loaded?
3. Which plugin does rebar3 use under the hood to assemble a deployable OTP release?
4. In rebar.config, how would you declare a dependency fetched directly from a git repository at a specific tag?
5. What is the purpose of rebar3 profiles like `prod`?
Was this page helpful?
You May Also Like
Hot Code Reloading
Understand how the BEAM VM loads new module versions into a running system without downtime, and how to do it safely.
Testing Erlang with EUnit
Learn how to write, organize, and run unit tests for Erlang code using the built-in EUnit framework.
Erlang and Distributed Systems
Explore how Erlang nodes connect, communicate transparently, and stay resilient across a distributed cluster.
Related Reading
Related Study Notes in Programming
Browse all study notesApache Spark Study Notes
Programming · 30 topics
ProgrammingApache Flink Study Notes
Programming · 30 topics
ProgrammingHadoop Study Notes
Programming · 30 topics
ProgrammingSnowflake Study Notes
Programming · 30 topics
ProgrammingApache Airflow Study Notes
Programming · 30 topics
Programmingdbt (Data Build Tool) Study Notes
Programming · 30 topics