Fork me on GitHub

rebar3_document

本文档为erlang rebar3的官方文档,所有内容都是官方doc上誊抄下来的,便于转为pdf,用于线下上下班路上无聊时学习的。如有任何侵权,请联系我:243818817@qq.com

[TOC]

Getting Started


Backwards Compatibility
We attempt very limited backwards compatibility with previous rebar versions’configurations and will try to call out important changes in the documentation.

Installing Erlang

Install Erlang as you usually would; rebar3 does not bundle it. People using Windows can get the binaries from erlang.org, and most linux or unix-like distributions can get those from package managers. OSX is fine with Homebrew.

People wanting to run multiple versions or a source compilation can use either kerl , erln8, or the instructions from erlang.org.

Debian and Ubuntu derivatives have a history of having broken up the Erlang standard release into sub-libraries packages that are not all installed by default and will end up with missing packages compared to other installs. Be sure to install the extra Erlang packages and development packages for everything to work fine, or switch to one of the methods for source installs.

Installing Binary

Download a nightly binary here. Ensure it is executable (chmod +x) and simply copy to a directory in your $PATH.

It is common to create a directory ~/bin/ to place commands like rebar3 and add it to your path with export PATH=~/bin/:$PATH in your ~/.bashrc, ~/.zshrc or equivalent.

Windows users who want to use the code from PowerShell or cmd.exe (rather than a terminal emulator) must ensure that a rebar3.cmdfile is added:


Text

1
2
3
4
@echo off
setlocal
set rebarscript=%~f0
escript.exe "%rebarscript:.cmd=%" %*

The source installation that follows creates the file automatically.

Installing from Source


shell

1
2
3
$ git clone https://github.com/erlang/rebar3.git
$ cd rebar3
$ ./bootstrap

And now you have the script rebar3 and can copy it to somewhere in your $PATH as described in the previous section. Windows users should also include the rebar3.cmd for the util to work in PowerShell or cmd.exe.

Extracting and Upgrading

An additional way to install and run rebar3 can be found under the local namespace. rebar3 local install will extract the contents of the escript to ~/.cache/rebar3/lib and create a shell script ~/.cache/rebar3/bin/rebar3:


shell

1
2
3
4
$ ./rebar3 local install
===> Extracting rebar3 libs to ~/.cache/rebar3/lib...
===> Writing rebar3 run script ~/.cache/rebar3/bin/rebar3...
===> Add to $PATH for use: export PATH=$PATH:~/.cache/rebar3/bin

Plus, rebar3 local upgrade will fetch the latest stable escript from s3 and install the same way:


shell

1
2
3
4
$ rebar3 local upgrade
===> Extracting rebar3 libs to ~/.cache/rebar3/lib...
===> Writing rebar3 run script ~/.cache/rebar3/bin/rebar3...
===> Add to $PATH for use: export PATH=$PATH:~/.cache/rebar3/bin

Creating a New Project


shell

1
2
3
4
5
6
7
8
9
10
$ rebar3 new release myrelease
===> Writing apps/myrelease/src/myrelease_app.erl
===> Writing apps/myrelease/src/myrelease_sup.erl
===> Writing apps/myrelease/src/myrelease.app.src
===> Writing rebar.config
===> Writing config/sys.config
===> Writing config/vm.args
===> Writing .gitignore
===> Writing LICENSE
===> Writing README.md

Continue on to Basic Usage to learn more on how to use rebar3.

Basic Usage

Overview of using rebar3 for project building.


OTP Only
Rebar3 only handles OTP-structured projects, consisting of applications and/or a release. Previous versions of rebar would build any Erlang source files it encountered in subdirectories and not require a project adhere to OTP standards.

New App or Release

There are two main ways to organize code with rebar3 projects: either as a single application, or as an umbrella project.

Single application projects contain a lone top-level application at the root of the directory, with its Erlang source modules directly inside a src/ directory. This format is applicable to libraries to be published on github or in hex with the objective of making them shareable to the world, but can also be used with Releases, which allow to ship an Erlang runtime system that boots the application directly.

Umbrella projects’ defining characteristic is that they can contain multiple top-level Erlang/OTP applications, usually within a top-level apps/ or lib/ directory. Each of these applications may contain its own rebar.config file. This format is applicable to only for releases with one or more top-level applications.

Rebar3 comes with templates for creating either types of project, callable through the rebar3 new <template> <project-name>command. The <template> value can be any of:

  • app:a stateful OTP application with a supervision tree, as a single application project.
  • lib:a library OTP application (without supervision trees), useful for grouping together various modules, as a single application project.
  • release: an umbrella project ready to be released
  • escript: a special form of single application project that can be built as a runnable script.
  • plugin: structure for a rebar3 plugin.

For example:


shell

1
2
3
4
5
6
7
8
$ rebar3 new app myapp
===> Writing myapp/src/myapp_app.erl
===> Writing myapp/src/myapp_sup.erl
===> Writing myapp/src/myapp.app.src
===> Writing myapp/rebar.config
===> Writing myapp/.gitignore
===> Writing myapp/LICENSE
===> Writing myapp/README.md

For more information on new and available options check the docs on commands and to learn how to create and use custom templates go to the templates tutorial.

Adding Dependencies

Dependencies are listed in rebar.config file under the deps key:


Erlang

1
2
3
4
5
6

{deps, [
{cowboy, "1.0.1"}, % package
{cowboy, {git, "git://github.com/ninenines/cowboy.git", {tag, "1.0.1"}}} % alternatively, source
]
}.

Version in SCM Dep Ignored
Note that while rebar3 supports the old format for a dependency to allow backwards compatibility, such as {cowboy, ".*", {git, "git://github.com/ninenines/cowboy.git", {tag, "1.0.1"}}}, the second element, in this case ".*", is ignored.

Now you can add the dep to one of your project’s application’s .app.src file under applications so that Erlang knows the dependency is required for yours to work:


Erlang

1
2
3
4
5
6
7
8
9
10
11
12
13
{application, <APPNAME>,
[{description, ""},
{vsn, "<APPVSN>"},
{registered, []},
{modules, []},
{applications, [
kernel
,stdlib
,cowboy
]},
{mod, {<APPNAME>_app, []}},
{env, []}
]}.

For more information on dependency handling view the dependency documentation.

Building

Only one command, compile, is required to fetch dependencies and compile all applications.


Text

1
2
3
4
5
6
7
8
9
10

$ rebar3 compile
==> Verifying dependencies...
==> Fetching cowboy
==> Fetching ranch
==> Fetching cowlib
==> Compiling cowlib
==> Compiling ranch
==> Compiling cowboy
==> Compiling myapp

Dependencies Always Fetched

Unlike previous rebar releases with rebar3 the dependencies are fetched and compiled if they are not found when running a command like compile. This is achieved through provider dependencies you can read about in the plugin tutorial.

Output Format

Output for installing dependencies, building releases and any other output written to disk is found in the _builddirectory at the root of the project.


shell

1
2
3
4
5
6
_build/
└── default
└── lib
├── cowboy
├── cowlib
└── ranch

More about profiles and the _build directory can be found in the profiles documentation page.

Testing

Tests by default are expected to be found under the test/ directory, aside from eunit found within individual modules.

Dependencies that are only needed for running tests can be placed in the test profile:


Erlang

1
2
3
4
5
6
7
{profiles, [
{test, [
{deps, [
{meck, {git, "git://github.com/eproxus/meck.git", {tag, "0.8.2"}}}
]}
]}
]}.

Now the first time rebar3 ct is run meck will be installed to _build/test/lib/. But it will not be added to rebar.lock.


shell

1
2
3
4
_build/
└── test
└── lib
└── meck

Releases and Target Systems

Releases are built using relx.


Relx and Not Reltool. Unlike previous rebar version, reltool is not provided with a rebar3 interface at all. However, if you still want to use reltool you can access it since it comes with Erlang/OTP.

Creating a new project with a release structure and default relx config in the rebar.config file run:


shell

1
2
3
4
5
6
7
8
9
10
$ rebar3 new release myrel
===> Writing myrel/apps/myrel/src/myrel_app.erl
===> Writing myrel/apps/myrel/src/myrel_sup.erl
===> Writing myrel/apps/myrel/src/myrel.app.src
===> Writing myrel/rebar.config
===> Writing myrel/config/sys.config
===> Writing myrel/config/vm.args
===> Writing myrel/.gitignore
===> Writing myrel/LICENSE
===> Writing myrel/README.md

Looking in rebar.config we find a couple elements that were not there in our application example.


Erlang

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{relx, [{release, {myrel, "0.0.1"},
[myrel]},

{dev_mode, true},
{include_erts, false},

{extended_start_script, true}
]
}.

{profiles, [
{prod, [{relx, [{dev_mode, false},
{include_erts, true}]}
]}
]}.

This configuration provides some nice defaults for building a release with relx for development (default profile) and for production (prod profile). When building a release for production we’ll most likely want to create a target system (include erts) and definitely will not want the release to contain symlinks to apps (dev_mode false).


shell

1
2
3
4
5
6
7
8
9
10
$ rebar3 release
===> Verifying default dependencies...
===> Compiling myrel
===> Starting relx build process ...
===> Resolving OTP Applications from directories:
_build/default/lib
/usr/lib/erlang/lib
===> Resolved myrel-0.1.0
===> Dev mode enabled, release will be symlinked
===> release successfully created!

Relx dev_mode Since the default profile’s config for the release sets dev_mode to true the applications for the release found under _build/rel/myrel/lib are symlinks to _build/lib and apps/myrel. So as you develop and recompile your app you do not need to recreate the release but simply restart the node or reload the modules.

With the default rebar.config, creating a compressed archive of the release as a target system is as simple as setting the profile to prod and running tar:


shell

1
2
3
4
5
6
7
8
9
10
11
$ rebar3 as prod tar
===> Verifying default dependencies...
===> Compiling myrel
===> Starting relx build process ...
===> Resolving OTP Applications from directories:
.../myrel/apps
/usr/lib/erlang/lib
===> Resolved myrel-0.1.0
===> Including Erts from /usr/lib/erlang
===> release successfully created!
===> tarball myrel/_build/rel/myrel/myrel-0.1.0.tar.gz successfully created!

For more details go to the release section.

Configuration

Global (all-commands) configuration

Rebar3 supports some options that will impact the behaviour of the tool wholesale. Those are defined as OS environment variables, as follows:


shell

1
2
3
4
5
6
7
8
9
10
REBAR_PROFILE="term"         # force a base profile
HEX_CDN="https://..." # change the Hex endpoint for a private one
REBAR_CONFIG="rebar3.config" # changes the name of rebar.config files
QUIET=1 # only display errors
DEBUG=1 # show debug output
# "QUIET=1 DEBUG=1" displays both errors and warnings
REBAR_COLOR="low" # reduces amount of color in output if supported
REBAR_CACHE_DIR # override where rebar3 stores config and cache data
http_proxy # standard proxy ENV variable is respected
https_proxy # standard proxy ENV variable is respected

Alias

Aliases allow to create new commands out of existing ones, as if they were run one after the other:


Erlang

1
{alias, [{check, [eunit, {ct, "--sys_config=config/app.config"}]}]}.

Arguments (as with a command line) can be passed by replacing Provider with {Provider, Args}.

Artifacts

Artifacts are a list of files that are required to exist after a successful compilation (including any compile hooks) other than Erlang modules. This is useful to let rebar3 figure out if a dependency with some non-Erlang artifacts was successfully built or not. Examples where this can be useful include identifying C code built for shared libraries, rendered templates, or that an escript was properly generated.

If a dependency is found to already be built (meaning its .app file’s list of modules matches its .beam files and all its artifacts exist) it will not have the compilation provider or its hooks called on it during a subsequent run of rebar3.


Erlang

1
{artifacts, [file:filename_all()]}.

What the paths are relative to depends on if it is defined at the top level of an umbrella project or not. For example, let’s say we have a project my_project that contains an application my_app under apps/my_app/ that we build an escript from. Then we want to tell rebar3 to not consider the configuration in my_project/rebar.config, since it is the top level rebar.config of an umbrella. The artifact will be relative to the profile_dir, which by default is _build/default/:


Erlang

1
2
3
4
5
{escript_name, rebar3}.

{provider_hooks, [{post, [{compile, escriptize}]}]}.

{artifacts, ["bin/rebar3"]}.

If instead it isn’t an umbrella but with my_app being the top level directory the artifact defined in rebar.config is relative to the application’s output directory, in this case _build/default/lib/my_app/ but we can use a template to define it from profile_dir as well:


Erlang

1
2
3
4
5
{escript_name, rebar3}.

{provider_hooks, [{post, [{compile, escriptize}]}]}.

{artifacts, ["{{profile_dir}}/bin/rebar3"]}.

All available template key are listed in the table below.

Template key Description
profile_dir The base output directory with the profile string appended, default: _build/default/.
base_dir The base output directory, default: _build.
out_dir The application’s output directory, default: _build/default/lib//.

One more example would be using artifacts within an override, in this case for eleveldb:


Erlang

1
2
3
4
5
{overrides,
[{override, eleveldb, [{artifacts, ["priv/eleveldb.so"]},
...
]
}]}.

The artifact is define on the application eleveldb so it is relative to the output directory, meaning the path used above is the same as if we used “/priv/eleveldb.so“.

Compilation

Compiler options can be set with erl_opts, available options are listed in the Erlang compile module’s documentation.

1
{erl_opts, []}.

Additionally it is possible to set platform specific options.

1
2
3
4
5
6
7
8
 {erl_opts, [{platform_define,
"(linux|solaris|freebsd|darwin)",
'HAVE_SENDFILE'},
{platform_define, "(linux|freebsd)",
'BACKLOG', 128},
{platform_define, "R13",
'old_inets'}]
}.

A separate compile option is one to declare modules to compile before all others:

1
{erl_first_files, ["src/mymodule.erl", "src/mymodule.erl"]}.

And some other general options exist:

1
2
3
4
5
6
{validate_app_modules, true}. % Make sure modules in .app match those found in code
{app_vars_file, undefined | Path}. % file containing elements to put in all generated app files
%% Paths the compiler outputs when reporting warnings or errors
%% relative (default), build (all paths are in _build, default prior
%% to 3.2.0, and absolute are valid options
{compiler_source_format, relative}.

Other Erlang-Other Erlang-Other Erlang-related compilers are supported with their own configuration options:

  • Leex compiler with {xrl_opts, […]}
  • SNMP MIB Compiler with {mib_opts, […]}
  • Yecc compiler with {yrl_opts, […]}

Common Test

1
2
3
{ct_first_files, [...]}. % {erl_first_files, ...} but for CT
{ct_opts, [...]}. % same as options for ct:run_test(...)
{ct_readable, true | false}. % disable rebar3 modifying CT output in the shell

Reference of common test options for ct_opts:
http://www.erlang.org/doc/man/ct.html#run_test-1

A special option allows to load a default sys.config set of entries using {ct_opts, [{sys_config, [“name.of.config”]}]}

Options often exist mirroring those that can be specified in Commands arguments.

Cover

Enable code coverage in tests with {cover_enabled, true}. Then the cover provider can be run after tests to show reports. The option {cover_opts, [verbose]} can be used to force coverage reports be printed to the terminal rather than just in files. Specific modules can be blacklisted from code coverage by adding {cover_excl_mods, [Modules]} to the config file. Applications can be blacklisted as a whole with the {cover_excl_apps, [AppNames]} option.

Dialyzer

1
2
3
4
5
6
7
8
9
10
11
12
13
14
-type warning() :: no_return | no_unused | no_improper_lists | no_fun_app | 
no_match | no_opaque | no_fail_call | no_contracts | no_behaviours |
no_undefined_callbacks | unmatched_returns | error_handling | race_conditions |
overspecs | underspecs | specdiffs

{dialyzer, [{warnings, [warning()]},
{get_warnings, boolean()},
{plt_apps, top_level_deps | all_deps} % default: top_level_deps
{plt_extra_apps, [atom()]},
{plt_location, local | file:filename()},
{plt_prefix, string()},
{base_plt_apps, [atom(), ...]},
{base_plt_location, global | file:filename()},
{base_plt_prefix, string()}]}.

For information on suppressing warnings in modules see the Requesting or Suppressing Warnings in Source Files section of the Dialyzer documentation.

Distribution

Multiple providers and plugins may demand to support distributed Erlang. Generally, the configuration for all such commands (such as ct and shell) respect the following configuration values:

1
2
3
4
{dist_node, [
{setcookie, 'atom-cookie'},
{name | sname, 'nodename'},
]}.

Directories

The following options exist for directories; the value chosen below is the default value

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
%% directory for artifacts produced by rebar3
{base_dir, "_build"}.
%% directory in '<base_dir>/<profile>/' where deps go
{deps_dir, "lib"}.
%% where rebar3 operates from; defaults to the current working directory
{root_dir, "."}.
%% where checkout dependencies are to be located
{checkouts_dir, "_checkouts"}.
%% directory in '<base_dir>/<profile>/' where plugins go
{plugins_dir, "plugins"}.
%% directories where OTP applications for the project can be located
{project_app_dirs, ["apps/*", "lib/*", "."]}.
%% Directories where source files for an OTP application can be found
{src_dirs, ["src"]}.
%% Paths to miscellaneous Erlang files to compile for an app
%% without including them in its modules list
{extra_src_dirs, []}.
%% Paths the compiler outputs when reporting warnings or errors
%% relative (default), build (all paths are in _build, default prior
%% to 3.2.0, and absolute are valid options
{compiler_source_format, relative}.

Furthermore, rebar3 stores some of its configuration data in ~/.config/rebar3 and cache some data in ~/.cache/rebar3. Both can be overridden by specifying {global_rebar_dir, “./some/path”}.

EDoc

All options supported by EDoc can be put in {edoc_opts, […]}.

Escript

Full details at the escriptize command. Example configuration values below.

1
2
3
4
5
6
{escript_main_app, AppName}. % specify which app is the escript app
{escript_name, "FinalName"}. % name of final generated escript
{escript_incl_apps, [App]}. % apps (other than the main one and its deps) to be included
{escript_emu_args, "%%! -escript main Module\n"}. % emulator args
{escript_shebang, "#!/usr/bin/env escript\n"}. % executable line
{escript_comment, "%%\n"}. % comment at top of escript file

Because of the structure of escript building, options at the top-level rebar.config file only are used to build an escript.

EUnit

1
2
3
{eunit_first_files, [...]}. % {erl_first_files, ...} but for CT
{eunit_opts, [...]}. % same as options for eunit:test(Tests, ...)
{eunit_tests, [...]}. % same as Tests argument in eunit:test(Tests, ...)

Eunit Options reference: http://www.erlang.org/doc/man/eunit.html#test-2

Minimum OTP Version

A minimum version of Erlang/OTP can be specified which causes a build to fail if an earlier version is being used to build the application.

1
{minimum_otp_vsn, "17.4"}.

Overrides

Overrides allow to modify the configuration of a dependency from a higher level application. They are meant to allow quick fixes and workarounds, although we do recommend working on permanent fixes that make it to the target app’s configuration when possible.

Overrides come in 3 flavours: add, override on app and override on all.

1
2
3
4
5
6
{overrides, [{add, app_name(), [{atom(), any()}]},
{del, app_name(), [{atom(), any()}]},
{override, app_name(), [{atom(), any()}]},
{add, [{atom(), any()}]},
{del, [{atom(), any()}]},
{override, [{atom(), any()}]}]}.

These are applied to dependencies, and dependencies can have their own overrides as well that are applied. in the order overrides on all, per app overrides, per app additions.

As an example, this can be used to force all the dependencies to be compiled with debug_info by default, and to force no_debug_info in case the production profile is used.

1
2
3
4
5
6
{overrides, [{override, [{erl_opts, [debug_info]}]}]}.

{profiles, [{prod, [{overrides, [{override, [{erl_opts,[no_debug_info]}]}]},
{relx, [{dev_mode, false},
{include_erts, true}]}]}
]}.

Another example could be to remove warnings_as_errors as a compiler option for all applications:

1
2
3
4
5
6
{overrides, [
%% For all apps:
{del, [{erl_opts, [warnings_as_errors]}]},
%% Or for just one app:
{del, one_app, [{erl_opts, [warnings_as_errors]}]}
]}.

Hooks

There are two types of hooks: shell hooks and provider hooks. They both apply to the same type of providers.

Shell Hooks

Hooks provide a way to run arbitrary shell commands before or after hookable providers, optionally first matching on the type of system to choose which hook to run. Shell hooks are run after provider hooks.

1
2
3
4
5
-type hook() :: {atom(), string()}
| {string(), atom(), string()}.

{pre_hooks, [hook()]}.
{post_hooks, [hook()]}.

An example for building merl with rebar3 by using pre_hooks:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

{pre_hooks, [{"(linux|darwin|solaris)", compile,
"make -C \"$REBAR_DEPS_DIR/merl\" all -W test"},

{"(freebsd|netbsd|openbsd)", compile,
"gmake -C \"$REBAR_DEPS_DIR/merl\" all"},

{"win32", compile,
"make -C \"%REBAR_DEPS_DIR%/merl\" all -W test"},

{eunit, "erlc -I include/erlydtl_preparser.hrl -o test
test/ erlydtl_extension_testparser.yrl"},

{"(linux|darwin|solaris)", eunit,
"make -C \"$REBAR_DEPS_DIR/merl\" test"},

{"(freebsd|netbsd|openbsd)", eunit,
"gmake -C \"$REBAR_DEPS_DIR/merl\" test"},

{"win32", eunit, "make -C \"%REBAR_DEPS_DIR%/merl\" test"}
]}.
Behaviour of post_hooks
A post_hooks entry will only be called if its hookable provider was successful. This means that if you add a post_hooks entry for eunit, it will only be called if your EUnit tests are able to finish successfully.

Provider Hooks

Providers are also able to be used as hooks. The following hook runs clean before compile runs. To execute commands in a namespace a tuple is used as second argument. Provider hooks are run before shell hooks.

1
2
{provider_hooks, [{pre, [{compile, clean}]}
{post, [{compile, {erlydtl, compile}}]}]}

Hookable Points in Providers

Only specific built-in providers support hooks attached to them. Control depends on whether the provider operates on the project’s applications (each application and dependency) or if it’s expected to only run on the project at large.

Provider hooks are run before shell hooks.

Hook before and after
clean each application and dependency, and/or before and after all top-level applications are compiled*
ct the entire run
compile each application and dependency, and/or before and after all top-level applications are compiled*
edoc the entire run
escriptize the entire run
eunit the entire run
release the entire run
tar the entire run
erlc_compile compilation of the beam files for an app
app_compile building of the .app file from .app.src for an app

These hooks are, by default, running for every application, because dependencies may specify their own hook in their own context. The distinction is that in some cases (umbrella apps), hooks can be defined on many levels (omitting overrides):

  • the rebar.config file at the application root
  • each top-level app’s (in apps/ or libs/) rebar.config
  • each dependency’s rebar.config

By default, when there is no umbrella app, the hook defined in the top-level rebar.config is attributed to be part of the top-level app. This allows the hook to keep working for a dependency when the library is later published.

If however the hook is defined in rebar.config at the root of a project with umbrella applications, the hooks will be run before/after the task runs for all of the top-level applications.

To preserve the per-app behaviour in an umbrella project, hooks must instead be defined within each application’s rebar.config.

Shell

The rebar3 shell REPL will automatically boot applications if a relx entry is found, but apps to be started by the shell can be specified explicitly with {shell, [{apps, [App]}]}.

Other options include:

Option Value Description
apps [app1, app2, …] Applications to be booted by the shell. Overtakes the relx entry values
config “path/to/a/file.config” Loads a .config file (such as sys.config) for the applications to be booted by the shell.
script_file “path/to/a/file.escript” Evaluates a given escript before booting the applications for a node.

XRef

1
2
3
4
5
6
7
{xref_warnings,false}.
{xref_extra_paths,[]}.
{xref_checks,[undefined_function_calls,undefined_functions,locals_not_used,
exports_not_used,deprecated_function_calls,
deprecated_functions]}.
{xref_queries,[{"(xc - uc) || (xu - x - b - (\"mod\":\".*foo\"/\"4\"))", []}]}.
{xref_ignores, [{M, F}, {M, F, A}]}.
感谢您的赞赏,赚点辛苦奶粉钱