Skip to content

Instantly share code, notes, and snippets.

@tsloughter
Last active August 29, 2015 14:05
Show Gist options
  • Save tsloughter/4b862e4481cdb189cc05 to your computer and use it in GitHub Desktop.
Save tsloughter/4b862e4481cdb189cc05 to your computer and use it in GitHub Desktop.
Rebar3

The Rebar3 Manifesto

Warning: Rebar3 works for me, probably won't work for you yet.

Rebar has been an important tool for many years and many Erlang developers, but for various reasons it has come to show it's age very quickly. The code has become overly complex, especially the transitive dependency management, and became clear to me and a few others that a partial rewrite was required.

The prevalence of rebar configs in projects meant backwards compatability was a must, however features have been both added and removed.

OTP standards

rebar3 is OTP or nothing. It is for building Erlang apps and any other code in the project through plugins. If non-OTP Erlang is required the user must provide their own functionality around building that code, a Makefile for example. Relying on OTP standards simplifies the logic used by rebar to build a project.

Code Structure

Tasks

Tasks are implemented through the rebar_provider behaviour and do the work to fulfill a user's command. Before rebar3 commands were run by finding modules which export a function of the same name. In rebar3 the provider is matched by command name and the dependencies of said provider are found, to be run before the task provider. For example, in rebar3 the compile task depends on the dependencies being installed. Thus, instead of rebar get-deps compile -r you can simply run rebar compile. More on dependencies below.

Example:

-module(rebar_prv_something).

-behaviour(rebar_provider).

-export([init/1,
         do/1]).

-include("rebar.hrl").

-define(PROVIDER, something).
-define(DEPS, []).

%% ===================================================================
%% Public API
%% ===================================================================

-spec init(rebar_config:config()) -> {ok, rebar_config:config()}.
init(State) ->
    State1 = rebar_config:add_provider(State, #provider{name = ?PROVIDER,
                                                        provider_impl = ?MODULE,
                                                        bare = false,
                                                        deps = ?DEPS,
                                                        example = "rebar something",
                                                        short_desc = "",
                                                        desc = "",
                                                        opts = []}),
    {ok, State1}.

-spec do(rebar_config:config()) -> {ok, rebar_config:config()} | relx:error().
do(Config) ->
    %% Do something
    {ok, Config}.
Compilers

Problem: too many. The rebar source was bloated with all sorts of compilers (protofbuffs, neotoma, lfe, ...) which will be moved to plugins.

Templates

A new templating task has been added called new. Templates for creating whole rebar based projects, either a lib (single app) or release based (mulitple app), are available for starting a new project.

Releases

Use of reltool has been removed and replaced by relx. This doesn't stop ues of reltool as a plugin or manually, but reltool is less complete and requires duplicating features from relx within rebar.

Commands

Command Description
compile Build project
update Update package index
pkgs List available packages
shell Run shell with project apps in path
escriptize Create escript from project

The following commands are still in the works.

Command Description
release Build release of project with relx
tar Package release into tarball
new Create new project from template
eunit Eunit testing
ct Run Common Test Suites
do Run multiple tasks in sequence

Repeatable Builds

Troutwine

Leiningen creator Phil Hagelberg on repetable builds.

Top level version of dep wins, if on the same level there are two versions the greater wins. Fuzzy matching and ranges are discouraged.

{deps, [
       {cowboy, "1.0.0"}
       ,{gproc, ".*", {git, "git://github.com/uwiger/gproc.git", "master"}}
       ]}.

Running rebar compile will gen generate the following rebar.lock:

[{<<"gproc">>,<<"0.3.1">>,
  {git,"git://github.com/uwiger/gproc.git",
       "54a3b200155e94f1bd9afc752e4dd4630b2508b1"}},
 {<<"ranch">>,<<"1.0.0">>,
  <<"https://s3.amazonaws.com/rebar_packages/generic/6.1/ranch/1.0.0/ranch-1.0.0.tar.gz">>},
 {<<"cowlib">>,<<"1.0.0">>,
  <<"https://s3.amazonaws.com/rebar_packages/generic/6.1/cowlib/1.0.0/cowlib-1.0.0.tar.gz">>},
 {<<"cowboy">>,<<"1.0.0">>,
  <<"https://s3.amazonaws.com/rebar_packages/generic/6.1/cowboy/1.0.0/cowboy-1.0.0.tar.gz">>}].

Binary Packages

$ rebar update
===> Updating package index...
$ rebar pkgs
....
cowboy:
    Versions: 0.8.1, 0.8.2, 0.8.3, 0.8.4, 0.8.5, 0.10.0, 0.8.6, 0.9.0, 1.0.0, 0.8.0
Key Path and Index

rebar_publish is used to build packages for various architectures and versions of erts.

The packages are uploaded to S3 under the key:

/generic/ErtsVsn/AppName/Version/AppName-Version.tar.gz

Or in the case that the app contains platform specific code:

/SystemArch/GlibcVsn/ErtsVsn/AppName/Version/AppName-Version.tar.gz

The app's info is also inserted to a collection in Orchestrate:

{
  "name": "erlydtl",
  "vsn": "0.9.0",
  "erts": "6.1",
  "link": "https://s3.amazonaws.com/rebar_packages/generic/6.1/erlydtl/0.9.0/erlydtl.tar.gz",
  "deps": [],
  "arch": "generic"
}

rebar_publish contains another release rp_web which provides an API for retrieving the package index.

/packages?arch=x86_64-unknown-linux-gnu&erts=6.1&glibc=2.19

This query will return all packages for generic packages built for erts-6.1 as well as any that contain native code for the specific architecture and glibc.

Logging

New colorful logging which can be turned off when rebar is used programmaticly and not through the command line.

Plugins

Implemented as providers.

Future

  • Dialyzer
@jadeallenx
Copy link

This sounds great! Thank you very much for all of your efforts to make this tool really work well. 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment