本文档为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 | @echo off |
The source installation that follows creates the file automatically.
Installing from Source
shell
1 | $ git clone https://github.com/erlang/rebar3.git |
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 | $ ./rebar3 local install |
Plus, rebar3 local upgrade will fetch the latest stable escript from s3 and install the same way:
shell
1 | $ rebar3 local upgrade |
Creating a New Project
shell
1 | $ rebar3 new release myrelease |
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 releasedescript:
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 | $ rebar3 new app myapp |
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 |
|
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 | {application, <APPNAME>, |
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 |
|
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 _build
directory at the root of the project.
shell
1 | _build/ |
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 | {profiles, [ |
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 | _build/ |
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 | $ rebar3 new release myrel |
Looking in rebar.config we find a couple elements that were not there in our application example.
Erlang
1 | {relx, [{release, {myrel, "0.0.1"}, |
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 | $ rebar3 release |
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 | $ rebar3 as prod tar |
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 | REBAR_PROFILE="term" # force a base profile |
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 | {escript_name, 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 | {escript_name, 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 | {overrides, |
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 | {erl_opts, [{platform_define, |
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 | {validate_app_modules, true}. % Make sure modules in .app match those found in code |
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 | {ct_first_files, [...]}. % {erl_first_files, ...} but for CT |
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 | -type warning() :: no_return | no_unused | no_improper_lists | no_fun_app | |
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 | {dist_node, [ |
Directories
The following options exist for directories; the value chosen below is the default value
1 | %% directory for artifacts produced by rebar3 |
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 | {escript_main_app, AppName}. % specify which app is the escript app |
Because of the structure of escript building, options at the top-level rebar.config file only are used to build an escript.
EUnit
1 | {eunit_first_files, [...]}. % {erl_first_files, ...} but for CT |
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 | {overrides, [{add, app_name(), [{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 | {overrides, [{override, [{erl_opts, [debug_info]}]}]}. |
Another example could be to remove warnings_as_errors as a compiler option for all applications:
1 | {overrides, [ |
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 | -type hook() :: {atom(), string()} |
An example for building merl with rebar3 by using pre_hooks:
1 |
|
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 | {provider_hooks, [{pre, [{compile, clean}]} |
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 | {xref_warnings,false}. |