$ make
From b5d4cb91f80c833795a2d87050c3674bb7aecdc5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Lo=C3=AFc=20Hoguin?= Erlang.mk can do a lot of things, but it is, first and
-foremost, a build tool. In this chapter we will cover
-the basics of building a project with Erlang.mk. For most of this chapter, we will assume that you are
-using a project generated by Erlang.mk. To build a project, all you have to do is type It will work regardless of your project: OTP applications,
-library applications, NIFs, port drivers or even releases.
-Erlang.mk also automatically downloads and compiles the
-dependencies for your project. All this is possible thanks to a combination of configuration
-and conventions. Most of the conventions come from Erlang/OTP
-itself so any seasoned Erlang developers should feel right at
-home. Erlang.mk gives you control over three steps of the build
-process, allowing you to do a partial build if needed. A build has three phases: first any dependency is fetched
-and built, then the project itself is built and finally a
-release may be generated when applicable. A release is only
-generated for projects specifically configured to do so. Erlang.mk handles those three phases automatically when you
-type The commands detailed in this section are most useful after
-you have a successful build as they allow you to quickly
-redo a step instead of going through everything. This is
-especially useful for large projects or projects that end
-up generating releases. You can build your application and dependencies without
-generating a release by running the following command: To build your application without touching dependencies
-at all, you can use the This command is very useful if you have a lot of dependencies
-and develop on a machine with slow file access, like the
-Raspberry Pi and many other embedded devices. Note that this command may fail if a required dependency
-is missing. You can build all dependencies, and nothing else, by
-running the following command: This will fetch and compile all dependencies and their
-dependencies, recursively. Packages and dependencies are covered
-in the next chapter. It is not possible to build the release without at least
-building the application itself, unless of course if there’s
-no application to begin with. To generate the release, Consult the Releases chapter for more
-information about what releases are and how they are generated. When building your application, Erlang.mk will generate the
-application resource file.
-This file is mandatory for all Erlang applications and is
-found in ebin/$(PROJECT).app. Erlang.mk can build the ebin/$(PROJECT).app in two different
-ways: from the configuration found in the Makefile, or from
-the src/$(PROJECT).app.src file. Erlang.mk automatically fills the
- The name of the OTP application or library.
-
- Short description of the project.
-
- Current version of the project.
-
- The application callback module.
-
- List of the names of all registered processes.
-
- Configuration parameters used by the application.
-
- Other keys you want to add to the application
- List of Erlang/OTP applications this project depends on,
- excluding
- List of applications this project depends on that need
- to be fetched by Erlang.mk.
- There’s no need for quotes or anything. The relevant part of
-the Cowboy Makefile follows, if you need an example: Any space before and after the value is dropped. Dependencies are covered in details in
-the next chapter. The src/$(PROJECT).app.src file is a legacy method of
-building Erlang applications. It was introduced by the original
- The .app.src file serves as a template to generate the .app
-file. Erlang.mk will take it, fill in the When using this method, Erlang.mk cannot fill the If you really can’t live without the legacy method, for one
-reason or another, worry not; Erlang.mk will support it. And
-if you need to create a new project that uses this method, you
-just have to say so when bootstrapping: When building the application resource file, Erlang.mk may
-automatically add an
-The application was built as a dependency of another, or
-
-The legacy method was used, and the .app.src file contained This value is most useful when you need to help your users,
-as it allows you to know which version they run exactly by
-asking them to look in the file, or by running a simple
-command on their production server: Erlang.mk supports a variety of different source file formats.
-The following formats are supported natively: .erl src/ Erlang source ebin/*.beam .core src/ Core Erlang source ebin/*.beam .xrl src/ Leex source src/*.erl .yrl src/ Yecc source src/*.erl .asn1 asn1/ ASN.1 files include/.hrl include/.asn1db src/*.erl .mib mibs/ SNMP MIB files include/.hrl priv/mibs/.bin Files are always searched recursively. The build is ordered, so that files that generate Erlang source
-files are run before, and the resulting Erlang source files are
-then built normally. In addition, Erlang.mk keeps track of header files ( Erlang.mk also comes with plugins for the following formats: .dtl templates/ Django templates ebin/*.beam .proto src/ Protocol buffers ebin/*.beam Erlang.mk provides a few variables that you can use to customize
-the build process and the resulting files. By default, Erlang.mk will set the following options: In other words: warnings as errors, debug info (recommended) and
-enable warnings for exported variables, shadow variables and
-obsolete guard functions. You can redefine this variable in your Makefile to change it
-completely, either before or after including Erlang.mk: You can also filter out some options from the defaults Erlang.mk
-sets, by defining ERLC_OPTS after including Erlang.mk using the
- By default, Erlang.mk will leave this empty. You can redefine this variable in your Makefile.
-Please see the To exclude a module, simply list it in the variable, either
-before or after including Erlang.mk: The first time you run The second time you run Erlang.mk figures out what changed by using the dependency tracking
-feature of Make. Make automatically rebuilds a target if one of its
-dependency has changed (for example if a header file has changed,
-all the source files that include it will be rebuilt), and Erlang.mk
-leverages this feature to cut down on rebuild times. Note that this applies only to building; some other features of
-Erlang.mk will run every time they are called regardless of files
-changed. Erlang.mk keeps track of the dependencies between the different
-files in your project. This information is kept in the $(PROJECT).d
-file in your directory. It is generated if missing, and will be
-generated again after every file change, by default. Dependency tracking is what allows Erlang.mk to know when to
-rebuild Erlang files when header files, behaviors or parse
-transforms have changed. Erlang.mk also automatically keeps
-track of which files should be compiled first, for example
-when you have behaviors used by other modules in your project. If your project is stable, you may want to disable generating
-the dependency tracking file every time you compile. You can
-do this by adding the following line to your Makefile: As you can see, the snippet above uses Otherwise, Erlang.mk can also keep track of the source files generated
-by other means, for example if you generate code from a data
-file in your repository. Erlang.mk provides hooks at different stages of the build process.
-When your goal is to generate Erlang source files, you can
-add your own rules before or after the dependency tracking
-file is generated. To do this, you would add your hook before
-or after including the erlang.mk file. The easiest way is after: In this case we use When using an external script to generate the Erlang source
-file, it is recommended to depend on that script, so that
-the source file gets generated again when the script gets
-modified. If for whatever reason you prefer to hook before including
-Erlang.mk, don’t forget to set the Building typically involves creating a lot of new files. Some
-are reused in rebuilds, some are simply replaced. All can be
-removed safely. Erlang.mk provides two commands to remove them: To clean: Or distclean: That is the question. Note that Erlang.mk will automatically clean some files as
-part of other targets, but it will never run Erlang.mk can do a lot of things, but it is, first and
+foremost, a build tool. In this chapter we will cover
+the basics of building a project with Erlang.mk. For most of this chapter, we will assume that you are
+using a project generated by Erlang.mk. To build a project, all you have to do is type It will work regardless of your project: OTP applications,
+library applications, NIFs, port drivers or even releases.
+Erlang.mk also automatically downloads and compiles the
+dependencies for your project. All this is possible thanks to a combination of configuration
+and conventions. Most of the conventions come from Erlang/OTP
+itself so any seasoned Erlang developers should feel right at
+home. Erlang.mk gives you control over three steps of the build
+process, allowing you to do a partial build if needed. A build has three phases: first any dependency is fetched
+and built, then the project itself is built and finally a
+release may be generated when applicable. A release is only
+generated for projects specifically configured to do so. Erlang.mk handles those three phases automatically when you
+type The commands detailed in this section are most useful after
+you have a successful build as they allow you to quickly
+redo a step instead of going through everything. This is
+especially useful for large projects or projects that end
+up generating releases. You can build your application and dependencies without
+generating a release by running the following command: To build your application without touching dependencies
+at all, you can use the This command is very useful if you have a lot of dependencies
+and develop on a machine with slow file access, like the
+Raspberry Pi and many other embedded devices. Note that this command may fail if a required dependency
+is missing. You can build all dependencies, and nothing else, by
+running the following command: This will fetch and compile all dependencies and their
+dependencies, recursively. Packages and dependencies are covered
+in the next chapter. It is not possible to build the release without at least
+building the application itself, unless of course if there’s
+no application to begin with. To generate the release, Consult the Releases chapter for more
+information about what releases are and how they are generated. When building your application, Erlang.mk will generate the
+application resource file.
+This file is mandatory for all Erlang applications and is
+found in ebin/$(PROJECT).app. Erlang.mk can build the ebin/$(PROJECT).app in two different
+ways: from the configuration found in the Makefile, or from
+the src/$(PROJECT).app.src file. Erlang.mk automatically fills the
+ The name of the OTP application or library.
+
+ Short description of the project.
+
+ Current version of the project.
+
+ The application callback module.
+
+ List of the names of all registered processes.
+
+ Configuration parameters used by the application.
+
+ Other keys you want to add to the application
+ List of Erlang/OTP applications this project depends on,
+ excluding
+ List of applications this project depends on that need
+ to be fetched by Erlang.mk.
+ There’s no need for quotes or anything. The relevant part of
+the Cowboy Makefile follows, if you need an example: Any space before and after the value is dropped. Dependencies are covered in details in
+the next chapter. The src/$(PROJECT).app.src file is a legacy method of
+building Erlang applications. It was introduced by the original
+ The .app.src file serves as a template to generate the .app
+file. Erlang.mk will take it, fill in the When using this method, Erlang.mk cannot fill the If you really can’t live without the legacy method, for one
+reason or another, worry not; Erlang.mk will support it. And
+if you need to create a new project that uses this method, you
+just have to say so when bootstrapping: When building the application resource file, Erlang.mk may
+automatically add an
+The application was built as a dependency of another, or
+
+The legacy method was used, and the .app.src file contained This value is most useful when you need to help your users,
+as it allows you to know which version they run exactly by
+asking them to look in the file, or by running a simple
+command on their production server: Erlang.mk supports a variety of different source file formats.
+The following formats are supported natively: .erl src/ Erlang source ebin/*.beam .core src/ Core Erlang source ebin/*.beam .xrl src/ Leex source src/*.erl .yrl src/ Yecc source src/*.erl .asn1 asn1/ ASN.1 files include/.hrl include/.asn1db src/*.erl .mib mibs/ SNMP MIB files include/.hrl priv/mibs/.bin Files are always searched recursively. The build is ordered, so that files that generate Erlang source
+files are run before, and the resulting Erlang source files are
+then built normally. In addition, Erlang.mk keeps track of header files ( Erlang.mk also comes with plugins for the following formats: .dtl templates/ Django templates ebin/*.beam .proto src/ Protocol buffers ebin/*.beam Erlang.mk provides a few variables that you can use to customize
+the build process and the resulting files. By default, Erlang.mk will set the following options: In other words: warnings as errors, debug info (recommended) and
+enable warnings for exported variables, shadow variables and
+obsolete guard functions. You can redefine this variable in your Makefile to change it
+completely, either before or after including Erlang.mk: You can also filter out some options from the defaults Erlang.mk
+sets, by defining ERLC_OPTS after including Erlang.mk using the
+ By default, Erlang.mk will leave this empty. You can redefine this variable in your Makefile.
+Please see the To exclude a module, simply list it in the variable, either
+before or after including Erlang.mk: The first time you run The second time you run Erlang.mk figures out what changed by using the dependency tracking
+feature of Make. Make automatically rebuilds a target if one of its
+dependency has changed (for example if a header file has changed,
+all the source files that include it will be rebuilt), and Erlang.mk
+leverages this feature to cut down on rebuild times. Note that this applies only to building; some other features of
+Erlang.mk will run every time they are called regardless of files
+changed. Erlang.mk keeps track of the dependencies between the different
+files in your project. This information is kept in the $(PROJECT).d
+file in your directory. It is generated if missing, and will be
+generated again after every file change, by default. Dependency tracking is what allows Erlang.mk to know when to
+rebuild Erlang files when header files, behaviors or parse
+transforms have changed. Erlang.mk also automatically keeps
+track of which files should be compiled first, for example
+when you have behaviors used by other modules in your project. If your project is stable, you may want to disable generating
+the dependency tracking file every time you compile. You can
+do this by adding the following line to your Makefile: As you can see, the snippet above uses Otherwise, Erlang.mk can also keep track of the source files generated
+by other means, for example if you generate code from a data
+file in your repository. Erlang.mk provides hooks at different stages of the build process.
+When your goal is to generate Erlang source files, you can
+add your own rules before or after the dependency tracking
+file is generated. To do this, you would add your hook before
+or after including the erlang.mk file. The easiest way is after: In this case we use When using an external script to generate the Erlang source
+file, it is recommended to depend on that script, so that
+the source file gets generated again when the script gets
+modified. If for whatever reason you prefer to hook before including
+Erlang.mk, don’t forget to set the Building typically involves creating a lot of new files. Some
+are reused in rebuilds, some are simply replaced. All can be
+removed safely. Erlang.mk provides two commands to remove them: To clean: Or distclean: That is the question. Note that Erlang.mk will automatically clean some files as
+part of other targets, but it will never run Building
-How to build
-make
:$ make
What to build
-make
. But sometimes you just want to repeat one or
-two of them.Application
-$ make app
SKIP_DEPS
variable:$ make app SKIP_DEPS=1
Dependencies
-$ make deps
Release
-make
will generally suffice with
-a normal Erlang.mk. A separate target is however available,
-and will take care of building the release, after building
-the application and all dependencies:$ make rel
Application resource file
-PROJECT
is a variable defined in your Makefile and taken
-from the name of the directory when Erlang.mk bootstraps
-your project.Application configuration
-PROJECT
variable when
-bootstrapping a new project, but everything else is up to
-you. None of the values are required to build your project,
-although it is recommended to fill everything relevant to
-your situation.
-
PROJECT
-PROJECT_DESCRIPTION
-PROJECT_VERSION
-PROJECT_MOD
-PROJECT_REGISTERED
-PROJECT_ENV
-PROJECT_APP_EXTRA_KEYS
-.app
file.
- The variable content is written as-is to the .app
file,
- so be sure to format valid Erlang terms. For example:
- PROJECT_APP_EXTRA_KEYS = {maxT, 10000}, {start_phases, [...]}
.
-LOCAL_DEPS
-erts
, kernel
and stdlib
, or list of
- dependencies local to this repository (in APPS_DIR
).
-DEPS
-Legacy method
-rebar
build tool, of which Erlang.mk owes a great deal as it
-is its main inspiration.modules
value
-dynamically, and save the result in ebin/$(PROJECT).app.applications
-key from dependencies automatically, which means you need to
-add them to Erlang.mk and to the .app.src at the same time,
-duplicating the work.$ make -f erlang.mk bootstrap-lib LEGACY=1
Automatic application resource file values
-id
key with information about the
-Git commit (if using Git), or an empty string otherwise.
-It will only do this under specific conditions:
-
{id, "git"}
-1> application:get_all_key(cowboy).
-{ok,[{description,"Small, fast, modular HTTP server."},
- {id,"2.0.0-pre.2-25-g0ffde50-dirty"},
File formats
-
-
-
-
-
-
- Extension
- Location
- Description
- Output
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-.hrl
)
-as described at the end of this chapter. It can also compile
-C code, as described in the NIFs and port drivers
-chapter.
-
-
-
-
-
- Extension
- Location
- Description
- Output
-
-
-
-
-
-
-
-
-
-
-
-
-
-Compilation options
-ERLC_OPTS
-ERLC_OPTS
can be used to pass some options to erlc
, the Erlang
-compiler. Erlang.mk does not restrict any option. Please refer to
-the erlc Manual for the
-full list.:=
operator.ERLC_ASN1_OPTS
-ERLC_ASN1_OPTS
can be used to pass compiler options when compiling
-ASN.1 files. Please refer to the
-asn1ct manual for the full list.ERLC_OPTS
section for instructions.ERLC_EXCLUDE
-ERLC_EXCLUDE
can be used to exclude some modules from the
-compilation. It’s there for handling special cases, you should
-not normally need it.Cold and hot builds
-make
, Erlang.mk will build everything.make
, and all subsequent times, Erlang.mk
-will only rebuild what changed. Erlang.mk has been optimized for
-this use case, as it is the most common during development.Dependency tracking
-
-
-
-
-This section is about the dependency tracking between files
-inside your project, not application dependencies.
-?=
instead of a
-simple equal sign. This is to allow you to temporarily override
-this value when you do make substantial changes to your project
-(including a new header file, new module with dependencies, etc.)
-and want to rebuild the dependency tracking file. You’ll be
-able to use the following command:$ NO_MAKEDEP= make
make clean app
will of course force the
-recompilation of your project.Generating Erlang source
-$(gen_verbose)
to hide the details of
-the build by default. Erlang.mk will simply say what file
-is it currently generating..DEFAULT_GOAL
variable,
-otherwise nothing will get built:Cleaning
-clean
and
-distclean
. clean
removes all the intermediate files that
-were created as a result of building, including the BEAM files,
-the dependency tracking file and the generated documentation.
-distclean
removes these and more, including the downloaded
-dependencies, Dialyzer’s PLT file and the generated release,
-putting your directory back to the state it was before you
-started working on it.$ make clean
$ make distclean
distclean
if
-you don’t explicitly use it.How to build
+make
:$ make
What to build
+make
. But sometimes you just want to repeat one or
+two of them.Application
+$ make app
SKIP_DEPS
variable:$ make app SKIP_DEPS=1
Dependencies
+$ make deps
Release
+make
will generally suffice with
+a normal Erlang.mk. A separate target is however available,
+and will take care of building the release, after building
+the application and all dependencies:$ make rel
Application resource file
+PROJECT
is a variable defined in your Makefile and taken
+from the name of the directory when Erlang.mk bootstraps
+your project.Application configuration
+PROJECT
variable when
+bootstrapping a new project, but everything else is up to
+you. None of the values are required to build your project,
+although it is recommended to fill everything relevant to
+your situation.
+
PROJECT
+PROJECT_DESCRIPTION
+PROJECT_VERSION
+PROJECT_MOD
+PROJECT_REGISTERED
+PROJECT_ENV
+PROJECT_APP_EXTRA_KEYS
+.app
file.
+ The variable content is written as-is to the .app
file,
+ so be sure to format valid Erlang terms. For example:
+ PROJECT_APP_EXTRA_KEYS = {maxT, 10000}, {start_phases, [...]}
.
+LOCAL_DEPS
+erts
, kernel
and stdlib
, or list of
+ dependencies local to this repository (in APPS_DIR
).
+DEPS
+PROJECT = cowboy
+PROJECT_DESCRIPTION = Small, fast, modular HTTP server.
+PROJECT_VERSION = 2.0.0-pre.2
+PROJECT_REGISTERED = cowboy_clock
+
+LOCAL_DEPS = crypto
+DEPS = cowlib ranch
Legacy method
+rebar
build tool, of which Erlang.mk owes a great deal as it
+is its main inspiration.modules
value
+dynamically, and save the result in ebin/$(PROJECT).app.applications
+key from dependencies automatically, which means you need to
+add them to Erlang.mk and to the .app.src at the same time,
+duplicating the work.$ make -f erlang.mk bootstrap-lib LEGACY=1
Automatic application resource file values
+id
key with information about the
+Git commit (if using Git), or an empty string otherwise.
+It will only do this under specific conditions:
+
{id, "git"}
+1> application:get_all_key(cowboy).
+{ok,[{description,"Small, fast, modular HTTP server."},
+ {id,"2.0.0-pre.2-25-g0ffde50-dirty"},
File formats
+
+
+
+
+
+
+ Extension
+ Location
+ Description
+ Output
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+.hrl
)
+as described at the end of this chapter. It can also compile
+C code, as described in the NIFs and port drivers
+chapter.
+
+
+
+
+
+ Extension
+ Location
+ Description
+ Output
+
+
+
+
+
+
+
+
+
+
+
+
+
+Compilation options
+ERLC_OPTS
+ERLC_OPTS
can be used to pass some options to erlc
, the Erlang
+compiler. Erlang.mk does not restrict any option. Please refer to
+the erlc Manual for the
+full list.ERLC_OPTS = -Werror +debug_info +warn_export_vars +warn_shadow_vars +warn_obsolete_guard
ERLC_OPTS = +debug_info
:=
operator.include erlang.mk
+
+ERLC_OPTS := $(filter-out -Werror,$(ERLC_OPTS))
ERLC_ASN1_OPTS
+ERLC_ASN1_OPTS
can be used to pass compiler options when compiling
+ASN.1 files. Please refer to the
+asn1ct manual for the full list.ERLC_OPTS
section for instructions.ERLC_EXCLUDE
+ERLC_EXCLUDE
can be used to exclude some modules from the
+compilation. It’s there for handling special cases, you should
+not normally need it.ERLC_EXCLUDE = cowboy_http2
Cold and hot builds
+make
, Erlang.mk will build everything.make
, and all subsequent times, Erlang.mk
+will only rebuild what changed. Erlang.mk has been optimized for
+this use case, as it is the most common during development.Dependency tracking
+
+
+
+
+This section is about the dependency tracking between files
+inside your project, not application dependencies.
+NO_MAKEDEP ?= 1
?=
instead of a
+simple equal sign. This is to allow you to temporarily override
+this value when you do make substantial changes to your project
+(including a new header file, new module with dependencies, etc.)
+and want to rebuild the dependency tracking file. You’ll be
+able to use the following command:$ NO_MAKEDEP= make
make clean app
will of course force the
+recompilation of your project.Generating Erlang source
+PROJECT = example
+
+include erlang.mk
+
+$(PROJECT).d:: src/generated_mod.erl
+
+src/generated_mod.erl:: gen-mod.sh
+ $(gen_verbose) ./gen-mod.sh $@
$(gen_verbose)
to hide the details of
+the build by default. Erlang.mk will simply say what file
+is it currently generating..DEFAULT_GOAL
variable,
+otherwise nothing will get built:PROJECT = example
+
+.DEFAULT_GOAL = all
+
+$(PROJECT).d:: src/generated_mod.erl
+
+include erlang.mk
+
+src/generated_mod.erl:: gen-mod.sh
+ $(gen_verbose) ./gen-mod.sh $@
Cleaning
+clean
and
+distclean
. clean
removes all the intermediate files that
+were created as a result of building, including the BEAM files,
+the dependency tracking file and the generated documentation.
+distclean
removes these and more, including the downloaded
+dependencies, Dialyzer’s PLT file and the generated release,
+putting your directory back to the state it was before you
+started working on it.$ make clean
$ make distclean
distclean
if
+you don’t explicitly use it.
EUnit is the tool of choice for unit testing. Erlang.mk -automates a few things on top of EUnit, including the -discovery and running of unit tests.
The EUnit user guide
-is the best place to learn how to write tests. Of note is
-that all functions ending with _test
or _test_
will be
-picked up as EUnit test cases.
Erlang.mk will automatically pick up tests found in any of -the Erlang modules of your application. It will also pick up -tests located in the $(TEST_DIR) directory, which defaults -to test/.
It is generally a good practice to hide test code from
-the code you ship to production. With Erlang.mk, you can
-do this thanks to the TEST
macro. It is only defined
-when running tests:
-ifdef(TEST). - -%% Insert tests here. - --endif.
Be careful, however, if you include the EUnit header file,
-as it also defines the TEST
macro. Make sure to only include
-it inside an ifdef
block, otherwise tests will always be
-compiled.
-ifdef(TEST). - --include_lib(\"eunit/include/eunit.hrl\"). - -%% Insert tests here. - --endif.
Erlang.mk will automatically recompile your code when you -perform a normal build after running tests, and vice versa.
The EUNIT_OPTS
variable allows you to specify additional
-EUnit options. Options are documented in the
-EUnit manual.
-At the time of writing, the only available option is verbose
:
The EUNIT_ERL_OPTS
variable allows you to specify options
-to be passed to erl
when running EUnit tests. For example,
-you can load the vm.args and sys.config files:
To run all tests (including EUnit):
$ make tests
To run all tests and static checks (including EUnit):
$ make check
You can also run EUnit separately:
$ make eunit
EUnit will be quiet by default, only outputting errors. -You can easily make it verbose for a single invocation:
$ make eunit EUNIT_OPTS=verbose
Erlang.mk allows you to run all tests from a specific
-module, or a specific test case from that module, using
-the variable t
.
For example, to run all tests from the cow_http_hd
-module (instead of all tests from the entire project),
-one could write:
$ make eunit t=cow_http_hd
Similarly, to run a specific test case:
$ make eunit t=cow_http_hd:parse_accept_test_
To do the same against a multi-application repository,
-you can use the -C
option:
$ make -C apps/my_app eunit t=my_module:hello_test
Note that this also applies to dependencies. From Cowboy, -you can run the following directly:
$ make -C deps/cowlib eunit t=cow_http_hd
Finally, code coverage is available, -but covered in its own chapter.
EUnit is the tool of choice for unit testing. Erlang.mk +automates a few things on top of EUnit, including the +discovery and running of unit tests.
The EUnit user guide
+is the best place to learn how to write tests. Of note is
+that all functions ending with _test
or _test_
will be
+picked up as EUnit test cases.
Erlang.mk will automatically pick up tests found in any of +the Erlang modules of your application. It will also pick up +tests located in the $(TEST_DIR) directory, which defaults +to test/.
It is generally a good practice to hide test code from
+the code you ship to production. With Erlang.mk, you can
+do this thanks to the TEST
macro. It is only defined
+when running tests:
-ifdef(TEST). + +%% Insert tests here. + +-endif.
Be careful, however, if you include the EUnit header file,
+as it also defines the TEST
macro. Make sure to only include
+it inside an ifdef
block, otherwise tests will always be
+compiled.
-ifdef(TEST). + +-include_lib(\"eunit/include/eunit.hrl\"). + +%% Insert tests here. + +-endif.
Erlang.mk will automatically recompile your code when you +perform a normal build after running tests, and vice versa.
The EUNIT_OPTS
variable allows you to specify additional
+EUnit options. Options are documented in the
+EUnit manual.
+At the time of writing, the only available option is verbose
:
EUNIT_OPTS = verbose
The EUNIT_ERL_OPTS
variable allows you to specify options
+to be passed to erl
when running EUnit tests. For example,
+you can load the vm.args and sys.config files:
EUNIT_ERL_OPTS = -args_file rel/vm.args -config rel/sys.config
To run all tests (including EUnit):
$ make tests
To run all tests and static checks (including EUnit):
$ make check
You can also run EUnit separately:
$ make eunit
EUnit will be quiet by default, only outputting errors. +You can easily make it verbose for a single invocation:
$ make eunit EUNIT_OPTS=verbose
Erlang.mk allows you to run all tests from a specific
+module, or a specific test case from that module, using
+the variable t
.
For example, to run all tests from the cow_http_hd
+module (instead of all tests from the entire project),
+one could write:
$ make eunit t=cow_http_hd
Similarly, to run a specific test case:
$ make eunit t=cow_http_hd:parse_accept_test_
To do the same against a multi-application repository,
+you can use the -C
option:
$ make -C apps/my_app eunit t=my_module:hello_test
Note that this also applies to dependencies. From Cowboy, +you can run the following directly:
$ make -C deps/cowlib eunit t=cow_http_hd
Finally, code coverage is available, +but covered in its own chapter.
It is often convenient to be able to keep the build files -used by all your projects in one place. Those files could -be Makefiles, configuration files, templates and more.
Erlang.mk allows you to automatically load plugins from -dependencies. Plugins can do anything, including defining -new variables, defining file templates, hooking themselves -inside the normal Erlang.mk processing or even adding new -rules.
You can load plugins using one of two methods. You can -either load all plugins from a dependency, or just one. -We will also cover conventions about writing external -plugins.
To load plugins from a dependency, all you need to do is add
-the dependency name to DEP_PLUGINS
in addition to the list
-of dependencies.
For example, if you have cowboy
in DEPS
, add cowboy
in
-DEP_PLUGINS
also:
This will load the file plugins.mk in the root folder of -the Cowboy repository.
Now that we know how to load all plugins, let’s take a look -at how to load one specific plugin from a dependency.
To do this, instead of writing only the name of the dependency,
-we will write its name and the path to the plugin file. This
-means that writing DEP_PLUGINS = cowboy
is equivalent to
-writing DEP_PLUGINS = cowboy/plugins.mk
.
Knowing this, if we were to load the plugin mk/dist.mk -from Cowboy and no other, we would write the following in -our Makefile:
The plugins.mk file is a convention. It is meant to load -all the plugins from the dependency. The code for the plugin -can be written directly in plugins.mk or be separate.
If you are providing more than one plugin with your repository, -the recommended way is to create one file per plugin in the -mk/ folder in your repository, and then include those -individual plugins in plugins.mk.
For example, if you have two plugins mk/dist.mk and -mk/templates.mk, you could write the following plugins.mk -file:
The THIS
variable is required to relatively include files.
This allows users to not only be able to select individual -plugins, but also select all plugins from the dependency -in one go if they wish to do so.
Plugins declared in DEP_PLUGINS
are loaded near the end of Erlang.mk.
-That’s why you have access to all previously initialized variables.
-However, if you want your plugin to add common dependencies to
-your applications, a regular is loaded too late in the process.
-You need to use "Early-stage plugins". They are declared using the
-DEP_EARLY_PLUGINS
variable instead. Plugins listed in this variable
-are loaded near the beginning of Erlang.mk Otherwise, they work exactly
-the same.
If you only give the name of a dependency, the default file loaded is -early-plugins.mk. You can specify a filename exactly like you would -have done it with regular plugins.
If the Erlang.mk plugin lives in the same directory or repository as your -application or library, then you can load it exactly like an external -plugin: the dependency name is simply the name of your application or -library.
For example, the following Makefile loads a plugin in the mk -subdirectory:
This also works with early-stage plugins:
Like external plugins, if you do not specify the path to the plugin, it -defaults to plugins.mk or early-plugins.mk, located at the root of -your application:
It is often convenient to be able to keep the build files +used by all your projects in one place. Those files could +be Makefiles, configuration files, templates and more.
Erlang.mk allows you to automatically load plugins from +dependencies. Plugins can do anything, including defining +new variables, defining file templates, hooking themselves +inside the normal Erlang.mk processing or even adding new +rules.
You can load plugins using one of two methods. You can +either load all plugins from a dependency, or just one. +We will also cover conventions about writing external +plugins.
To load plugins from a dependency, all you need to do is add
+the dependency name to DEP_PLUGINS
in addition to the list
+of dependencies.
For example, if you have cowboy
in DEPS
, add cowboy
in
+DEP_PLUGINS
also:
DEPS = cowboy +DEP_PLUGINS = cowboy
This will load the file plugins.mk in the root folder of +the Cowboy repository.
Now that we know how to load all plugins, let’s take a look +at how to load one specific plugin from a dependency.
To do this, instead of writing only the name of the dependency,
+we will write its name and the path to the plugin file. This
+means that writing DEP_PLUGINS = cowboy
is equivalent to
+writing DEP_PLUGINS = cowboy/plugins.mk
.
Knowing this, if we were to load the plugin mk/dist.mk +from Cowboy and no other, we would write the following in +our Makefile:
DEPS = cowboy +DEP_PLUGINS = cowboy/mk/dist.mk
The plugins.mk file is a convention. It is meant to load +all the plugins from the dependency. The code for the plugin +can be written directly in plugins.mk or be separate.
If you are providing more than one plugin with your repository, +the recommended way is to create one file per plugin in the +mk/ folder in your repository, and then include those +individual plugins in plugins.mk.
For example, if you have two plugins mk/dist.mk and +mk/templates.mk, you could write the following plugins.mk +file:
THIS := $(dir $(realpath $(lastword $(MAKEFILE_LIST)))) +include $(THIS)/mk/dist.mk +include $(THIS)/mk/templates.mk
The THIS
variable is required to relatively include files.
This allows users to not only be able to select individual +plugins, but also select all plugins from the dependency +in one go if they wish to do so.
Plugins declared in DEP_PLUGINS
are loaded near the end of Erlang.mk.
+That’s why you have access to all previously initialized variables.
+However, if you want your plugin to add common dependencies to
+your applications, a regular is loaded too late in the process.
+You need to use "Early-stage plugins". They are declared using the
+DEP_EARLY_PLUGINS
variable instead. Plugins listed in this variable
+are loaded near the beginning of Erlang.mk Otherwise, they work exactly
+the same.
If you only give the name of a dependency, the default file loaded is +early-plugins.mk. You can specify a filename exactly like you would +have done it with regular plugins.
# In your application's Makefile +BUILD_DEPS = common_deps +DEP_EARLY_PLUGINS = common_deps
# In the plugin's early-plugins.mk +DEPS += cowboy +TEST_DEPS = ct_helper +dep_ct_helper = git https://github.com/ninenines/ct_helper master
If the Erlang.mk plugin lives in the same directory or repository as your +application or library, then you can load it exactly like an external +plugin: the dependency name is simply the name of your application or +library.
For example, the following Makefile loads a plugin in the mk +subdirectory:
DEP_PLUGINS = $(PROJECT)/mk/dist.mk
This also works with early-stage plugins:
DEP_EARLY_PLUGINS = $(PROJECT)/mk/variables.mk
Like external plugins, if you do not specify the path to the plugin, it +defaults to plugins.mk or early-plugins.mk, located at the root of +your application:
# Loads ./early-plugins.mk +DEP_EARLY_PLUGINS = $(PROJECT) +# Loads ./plugins.mk +DEP_PLUGINS = $(PROJECT)
This is a non-exhaustive list of Erlang.mk plugins, sorted -alphabetically.
An Efene plugin for Erlang.mk. -Efene is an alternative language for the BEAM.
An Elixir plugin for -Erlang.mk. Elixir is an alternative -language for the BEAM.
An Elvis plugin for Erlang.mk. -Elvis is an Erlang style reviewer.
Geas gives aggregated -information on a project and its dependencies, and is available -as an Erlang.mk plugin.
An Hex plugin for Erlang.mk
-using the hexer
tool.
Another Hex plugin for -Erlang.mk, with support for Hex dependency operators.
Jorel is Just anOther RELease -assembler for Erlang/OTP, and is available as an Erlang.mk plugin.
An LFE plugin for Erlang.mk. -LFE, or Lisp Flavoured Erlang, is an alternative -language for the BEAM.
A Mix plugin for Erlang.mk, -to generate a compatible configuration file for -Mix.
A live reload plugin for Erlang.mk.
This is a non-exhaustive list of Erlang.mk plugins, sorted +alphabetically.
An Efene plugin for Erlang.mk. +Efene is an alternative language for the BEAM.
An Elixir plugin for +Erlang.mk. Elixir is an alternative +language for the BEAM.
An Elvis plugin for Erlang.mk. +Elvis is an Erlang style reviewer.
Geas gives aggregated +information on a project and its dependencies, and is available +as an Erlang.mk plugin.
An Hex plugin for Erlang.mk
+using the hexer
tool.
Another Hex plugin for +Erlang.mk, with support for Hex dependency operators.
Jorel is Just anOther RELease +assembler for Erlang/OTP, and is available as an Erlang.mk plugin.
An LFE plugin for Erlang.mk. +LFE, or Lisp Flavoured Erlang, is an alternative +language for the BEAM.
A Mix plugin for Erlang.mk, +to generate a compatible configuration file for +Mix.
A live reload plugin for Erlang.mk.
This chapter explains how to get started using Erlang.mk.
The first step is always to create a new folder that will -contain your project.
$ mkdir hello_joe -$ cd hello_joe
Most people tend to put all their projects side by side in -a common folder. We recommend keeping an organization similar -to your remote repositories. For example, for GitHub users, -put all your projects in a common folder with the same name -as your username. For example $HOME/ninenines/cowboy for -the Cowboy project.
At the time of writing, Erlang.mk is unlikely to be present -in your Erlang distribution, or even in your OS packages.
The next step is therefore to download it:
$ wget https://erlang.mk/erlang.mk
Or:
$ curl -O https://erlang.mk/erlang.mk
Alternatively, just click on this link.
Make sure you put the file inside the folder we created previously.
An OTP application is an Erlang application that has a supervision -tree. In other words, it will always have processes running.
This kind of project can be automatically generated by Erlang.mk.
-All you need to do is use the bootstrap
target:
$ make -f erlang.mk bootstrap
Something similar to the following snippet will then appear -on your screen:
git clone https://github.com/ninenines/erlang.mk .erlang.mk.build -Cloning into '.erlang.mk.build'... -remote: Counting objects: 4035, done. -remote: Compressing objects: 100% (12/12), done. -remote: Total 4035 (delta 8), reused 4 (delta 4), pack-reused 4019 -Receiving objects: 100% (4035/4035), 1.10 MiB | 784.00 KiB/s, done. -Resolving deltas: 100% (2442/2442), done. -Checking connectivity... done. -if [ -f build.config ]; then cp build.config .erlang.mk.build; fi -cd .erlang.mk.build && make -make[1]: Entering directory '/home/essen/tmp/hello_joe/.erlang.mk.build' -awk 'FNR==1 && NR!=1{print ""}1' core/core.mk index/*.mk core/index.mk core/deps.mk plugins/protobuffs.mk core/erlc.mk core/docs.mk core/test.mk plugins/asciidoc.mk plugins/bootstrap.mk plugins/c_src.mk plugins/ci.mk plugins/ct.mk plugins/dialyzer.mk plugins/edoc.mk plugins/elvis.mk plugins/erlydtl.mk plugins/escript.mk plugins/eunit.mk plugins/relx.mk plugins/shell.mk plugins/triq.mk plugins/xref.mk plugins/cover.mk \ - | sed 's/^ERLANG_MK_VERSION = .*/ERLANG_MK_VERSION = 1.2.0-642-gccd2b9f/' > erlang.mk -make[1]: Leaving directory '/home/essen/tmp/hello_joe/.erlang.mk.build' -cp .erlang.mk.build/erlang.mk ./erlang.mk -rm -rf .erlang.mk.build
This is Erlang.mk bootstrapping itself. Indeed, the file you -initially downloaded contains nothing more than the code needed -to bootstrap. This operation is done only once. Consult the -Updating Erlang.mk chapter for more -information.
Of course, the generated project can now be compiled:
$ make
Cheers!
An OTP library is an Erlang application that has no supervision -tree. In other words, it is nothing but modules.
This kind of project can also be generated by Erlang.mk, using
-the bootstrap-lib
target:
$ make -f erlang.mk bootstrap-lib
Erlang.mk will once again bootstrap itself and generate all -the files for your project. You can now compile it:
$ make
Enjoy!
An OTP release is the combination of the Erlang RunTime System (ERTS) -along with all the libraries and files that your node will need -to run. It is entirely self contained, and can often be sent as-is -to your production system and run without any extra setup.
Erlang.mk can of course bootstrap your project to generate releases.
-You can use the bootstrap-rel
target for this purpose:
$ make bootstrap-rel
This target can be combined with bootstrap
or bootstrap-lib
to
-create a project that will build a release:
$ make -f erlang.mk bootstrap-lib bootstrap-rel
It is often very useful to keep the top-level project for -commands useful during operations, and put the components -of the system in separate applications that you will then -depend on. Consult the Packages and dependencies -chapter for more information.
When you run make
from now on, Erlang.mk will compile your
-project and build the release:
$ make - APP hello_joe.app.src - GEN distclean-relx-rel - GEN /home/essen/tmp/hello_joe/relx -===> Starting relx build process ... -===> Resolving OTP Applications from directories: - /home/essen/tmp/hello_joe/ebin - /usr/lib/erlang/lib - /home/essen/tmp/hello_joe/deps -===> Resolved hello_joe_release-1 -===> Including Erts from /usr/lib/erlang -===> release successfully created!
The first time you run this command, Erlang.mk will download -relx, the release building tool. So don’t worry if you see -more output than above.
If building the release is slow, no need to upgrade your -hardware just yet. Just consult the Releases -chapter for various tips to speed up build time during -development.
You can start the release using the ./_rel/hello_joe_release/bin/hello_joe_release
-script, or simply run make run
. The latter will also compile
-your project and build the release if it wasn’t already:
$ make run - APP hello_joe.app.src - GEN distclean-relx-rel -===> Starting relx build process ... -===> Resolving OTP Applications from directories: - /home/essen/tmp/hello_joe/ebin - /usr/lib/erlang/lib - /home/essen/tmp/hello_joe/deps -===> Resolved hello_joe_release-1 -===> Including Erts from /usr/lib/erlang -===> release successfully created! -Exec: /home/essen/tmp/hello_joe/_rel/hello_joe_release/erts-7.0/bin/erlexec -boot /home/essen/tmp/hello_joe/_rel/hello_joe_release/releases/1/hello_joe_release -boot_var ERTS_LIB_DIR /home/essen/tmp/hello_joe/_rel/hello_joe_release/erts-7.0/../lib -env ERL_LIBS /home/essen/tmp/hello_joe/_rel/hello_joe_release/releases/1/lib -config /home/essen/tmp/hello_joe/_rel/hello_joe_release/releases/1/sys.config -args_file /home/essen/tmp/hello_joe/_rel/hello_joe_release/releases/1/vm.args -- console -Root: /home/essen/tmp/hello_joe/_rel/hello_joe_release -/home/essen/tmp/hello_joe/_rel/hello_joe_release -heart_beat_kill_pid = 16389 -Erlang/OTP 18 [erts-7.0] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false] - -Eshell V7.0 (abort with ^G) -(hello_joe@127.0.0.1)1>
Simple as that!
If you already have an application, or you want to have full -control over what files will be created, you can setup Erlang.mk -manually.
Erlang.mk is very easy to setup: all that you need to do is to -create a folder, put Erlang.mk in it, and write a one line -Makefile containing:
For a step by step:
$ mkdir hello_joe -$ cd hello_joe -$ curl https://erlang.mk/erlang.mk -o erlang.mk -$ echo "include erlang.mk" > Makefile -$ make
From that point onward you can create an src/
folder or start
-using templates.
Erlang.mk defaults to tabs when creating files from templates. -This is in part because of a personal preference, and in part -because it is much easier to convert tabs to spaces than the -opposite.
Use the SP
variable if you prefer spaces. Set it to the number
-of spaces per indentation level you want.
For example, if you prefer two spaces per indentation level:
$ make -f erlang.mk bootstrap SP=2
When you bootstrap the project initially, the variable automatically -gets added to the Makefile, so you only need to provide it when -you get started.
It is no secret that Erlang’s OTP behaviors tend to have some -boilerplate. It is rarely an issue of course, except when -creating new modules. That’s why Erlang.mk not only comes with -templates for generating projects, but also individual modules!
You can list all available templates with the list-templates
-target:
$ make list-templates
-Available templates: cowboy_http cowboy_loop cowboy_rest cowboy_ws gen_fsm gen_server ranch_protocol supervisor
To generate a module, let’s say a gen_server
, all you need to
-do is to call make new
with the appropriate arguments:
$ make new t=gen_server n=my_server
This will create a module located in src/my_server.erl
-using the gen_server
template.
This module is automatically compiled the next time you run
-make
:
$ make - ERLC my_server.erl - APP hello_joe.app.src
All that’s left to do is to open it in your favorite editor -and make it do something!
Erlang.mk is a large text file. It can easily take a large part of
-a git diff
or a git grep
command. You can avoid this by telling
-Git that erlang.mk is a binary file.
Add this to your .gitattributes file. This is a file that you -can create at the root of your repository:
erlang.mk -diff
-The erlang.mk file will still appear in diffs and greps, but -as a binary file, meaning its contents won’t be shown by default -anymore.
During development, if you don’t remember the name of a target,
-you can always run make help
:
$ make help -erlang.mk (version 1.2.0-642-gccd2b9f) is distributed under the terms of the ISC License. -Copyright (c) 2013-2016 Loïc Hoguin <essen@ninenines.eu> - -Usage: [V=1] make [target]... - -Core targets: - all Run deps, app and rel targets in that order - app Compile the project - deps Fetch dependencies (if needed) and compile them - search q=... Search for a package in the built-in index - rel Build a release for this project, if applicable - docs Build the documentation for this project - install-docs Install the man pages for this project - check Compile and run all tests and analysis for this project - tests Run the tests for this project - clean Delete temporary and output files from most targets - distclean Delete all temporary and output files - help Display this help and exit - erlang-mk Update erlang.mk to the latest version - -Bootstrap targets: - bootstrap Generate a skeleton of an OTP application - bootstrap-lib Generate a skeleton of an OTP library - bootstrap-rel Generate the files needed to build a release - new t=TPL n=NAME Generate a module NAME based on the template TPL - list-templates List available templates -...
This guide should provide any other answer. If not, please -open a ticket on the official repository -and we will work on improving the guide.
Commercial support is available through Nine Nines. Please contact -Loïc Hoguin by sending an email to contact@ninenines.eu.
This chapter explains how to get started using Erlang.mk.
The first step is always to create a new folder that will +contain your project.
$ mkdir hello_joe +$ cd hello_joe
Most people tend to put all their projects side by side in +a common folder. We recommend keeping an organization similar +to your remote repositories. For example, for GitHub users, +put all your projects in a common folder with the same name +as your username. For example $HOME/ninenines/cowboy for +the Cowboy project.
At the time of writing, Erlang.mk is unlikely to be present +in your Erlang distribution, or even in your OS packages.
The next step is therefore to download it:
$ wget https://erlang.mk/erlang.mk
Or:
$ curl -O https://erlang.mk/erlang.mk
Alternatively, just click on this link.
Make sure you put the file inside the folder we created previously.
An OTP application is an Erlang application that has a supervision +tree. In other words, it will always have processes running.
This kind of project can be automatically generated by Erlang.mk.
+All you need to do is use the bootstrap
target:
$ make -f erlang.mk bootstrap
Something similar to the following snippet will then appear +on your screen:
git clone https://github.com/ninenines/erlang.mk .erlang.mk.build +Cloning into '.erlang.mk.build'... +remote: Counting objects: 4035, done. +remote: Compressing objects: 100% (12/12), done. +remote: Total 4035 (delta 8), reused 4 (delta 4), pack-reused 4019 +Receiving objects: 100% (4035/4035), 1.10 MiB | 784.00 KiB/s, done. +Resolving deltas: 100% (2442/2442), done. +Checking connectivity... done. +if [ -f build.config ]; then cp build.config .erlang.mk.build; fi +cd .erlang.mk.build && make +make[1]: Entering directory '/home/essen/tmp/hello_joe/.erlang.mk.build' +awk 'FNR==1 && NR!=1{print ""}1' core/core.mk index/*.mk core/index.mk core/deps.mk plugins/protobuffs.mk core/erlc.mk core/docs.mk core/test.mk plugins/asciidoc.mk plugins/bootstrap.mk plugins/c_src.mk plugins/ci.mk plugins/ct.mk plugins/dialyzer.mk plugins/edoc.mk plugins/elvis.mk plugins/erlydtl.mk plugins/escript.mk plugins/eunit.mk plugins/relx.mk plugins/shell.mk plugins/triq.mk plugins/xref.mk plugins/cover.mk \ + | sed 's/^ERLANG_MK_VERSION = .*/ERLANG_MK_VERSION = 1.2.0-642-gccd2b9f/' > erlang.mk +make[1]: Leaving directory '/home/essen/tmp/hello_joe/.erlang.mk.build' +cp .erlang.mk.build/erlang.mk ./erlang.mk +rm -rf .erlang.mk.build
This is Erlang.mk bootstrapping itself. Indeed, the file you +initially downloaded contains nothing more than the code needed +to bootstrap. This operation is done only once. Consult the +Updating Erlang.mk chapter for more +information.
Of course, the generated project can now be compiled:
$ make
Cheers!
An OTP library is an Erlang application that has no supervision +tree. In other words, it is nothing but modules.
This kind of project can also be generated by Erlang.mk, using
+the bootstrap-lib
target:
$ make -f erlang.mk bootstrap-lib
Erlang.mk will once again bootstrap itself and generate all +the files for your project. You can now compile it:
$ make
Enjoy!
An OTP release is the combination of the Erlang RunTime System (ERTS) +along with all the libraries and files that your node will need +to run. It is entirely self contained, and can often be sent as-is +to your production system and run without any extra setup.
Erlang.mk can of course bootstrap your project to generate releases.
+You can use the bootstrap-rel
target for this purpose:
$ make bootstrap-rel
This target can be combined with bootstrap
or bootstrap-lib
to
+create a project that will build a release:
$ make -f erlang.mk bootstrap-lib bootstrap-rel
It is often very useful to keep the top-level project for +commands useful during operations, and put the components +of the system in separate applications that you will then +depend on. Consult the Packages and dependencies +chapter for more information.
When you run make
from now on, Erlang.mk will compile your
+project and build the release:
$ make + APP hello_joe.app.src + GEN distclean-relx-rel + GEN /home/essen/tmp/hello_joe/relx +===> Starting relx build process ... +===> Resolving OTP Applications from directories: + /home/essen/tmp/hello_joe/ebin + /usr/lib/erlang/lib + /home/essen/tmp/hello_joe/deps +===> Resolved hello_joe_release-1 +===> Including Erts from /usr/lib/erlang +===> release successfully created!
The first time you run this command, Erlang.mk will download +relx, the release building tool. So don’t worry if you see +more output than above.
If building the release is slow, no need to upgrade your +hardware just yet. Just consult the Releases +chapter for various tips to speed up build time during +development.
You can start the release using the ./_rel/hello_joe_release/bin/hello_joe_release
+script, or simply run make run
. The latter will also compile
+your project and build the release if it wasn’t already:
$ make run + APP hello_joe.app.src + GEN distclean-relx-rel +===> Starting relx build process ... +===> Resolving OTP Applications from directories: + /home/essen/tmp/hello_joe/ebin + /usr/lib/erlang/lib + /home/essen/tmp/hello_joe/deps +===> Resolved hello_joe_release-1 +===> Including Erts from /usr/lib/erlang +===> release successfully created! +Exec: /home/essen/tmp/hello_joe/_rel/hello_joe_release/erts-7.0/bin/erlexec -boot /home/essen/tmp/hello_joe/_rel/hello_joe_release/releases/1/hello_joe_release -boot_var ERTS_LIB_DIR /home/essen/tmp/hello_joe/_rel/hello_joe_release/erts-7.0/../lib -env ERL_LIBS /home/essen/tmp/hello_joe/_rel/hello_joe_release/releases/1/lib -config /home/essen/tmp/hello_joe/_rel/hello_joe_release/releases/1/sys.config -args_file /home/essen/tmp/hello_joe/_rel/hello_joe_release/releases/1/vm.args -- console +Root: /home/essen/tmp/hello_joe/_rel/hello_joe_release +/home/essen/tmp/hello_joe/_rel/hello_joe_release +heart_beat_kill_pid = 16389 +Erlang/OTP 18 [erts-7.0] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false] + +Eshell V7.0 (abort with ^G) +(hello_joe@127.0.0.1)1>
Simple as that!
If you already have an application, or you want to have full +control over what files will be created, you can setup Erlang.mk +manually.
Erlang.mk is very easy to setup: all that you need to do is to +create a folder, put Erlang.mk in it, and write a one line +Makefile containing:
include erlang.mk
For a step by step:
$ mkdir hello_joe +$ cd hello_joe +$ curl https://erlang.mk/erlang.mk -o erlang.mk +$ echo "include erlang.mk" > Makefile +$ make
From that point onward you can create an src/
folder or start
+using templates.
Erlang.mk defaults to tabs when creating files from templates. +This is in part because of a personal preference, and in part +because it is much easier to convert tabs to spaces than the +opposite.
Use the SP
variable if you prefer spaces. Set it to the number
+of spaces per indentation level you want.
For example, if you prefer two spaces per indentation level:
$ make -f erlang.mk bootstrap SP=2
When you bootstrap the project initially, the variable automatically +gets added to the Makefile, so you only need to provide it when +you get started.
It is no secret that Erlang’s OTP behaviors tend to have some +boilerplate. It is rarely an issue of course, except when +creating new modules. That’s why Erlang.mk not only comes with +templates for generating projects, but also individual modules!
You can list all available templates with the list-templates
+target:
$ make list-templates
+Available templates: cowboy_http cowboy_loop cowboy_rest cowboy_ws gen_fsm gen_server ranch_protocol supervisor
To generate a module, let’s say a gen_server
, all you need to
+do is to call make new
with the appropriate arguments:
$ make new t=gen_server n=my_server
This will create a module located in src/my_server.erl
+using the gen_server
template.
This module is automatically compiled the next time you run
+make
:
$ make + ERLC my_server.erl + APP hello_joe.app.src
All that’s left to do is to open it in your favorite editor +and make it do something!
Erlang.mk is a large text file. It can easily take a large part of
+a git diff
or a git grep
command. You can avoid this by telling
+Git that erlang.mk is a binary file.
Add this to your .gitattributes file. This is a file that you +can create at the root of your repository:
erlang.mk -diff
+The erlang.mk file will still appear in diffs and greps, but +as a binary file, meaning its contents won’t be shown by default +anymore.
During development, if you don’t remember the name of a target,
+you can always run make help
:
$ make help +erlang.mk (version 1.2.0-642-gccd2b9f) is distributed under the terms of the ISC License. +Copyright (c) 2013-2016 Loïc Hoguin <essen@ninenines.eu> + +Usage: [V=1] make [target]... + +Core targets: + all Run deps, app and rel targets in that order + app Compile the project + deps Fetch dependencies (if needed) and compile them + search q=... Search for a package in the built-in index + rel Build a release for this project, if applicable + docs Build the documentation for this project + install-docs Install the man pages for this project + check Compile and run all tests and analysis for this project + tests Run the tests for this project + clean Delete temporary and output files from most targets + distclean Delete all temporary and output files + help Display this help and exit + erlang-mk Update erlang.mk to the latest version + +Bootstrap targets: + bootstrap Generate a skeleton of an OTP application + bootstrap-lib Generate a skeleton of an OTP library + bootstrap-rel Generate the files needed to build a release + new t=TPL n=NAME Generate a module NAME based on the template TPL + list-templates List available templates +...
This guide should provide any other answer. If not, please +open a ticket on the official repository +and we will work on improving the guide.
Commercial support is available through Nine Nines. Please contact +Loïc Hoguin by sending an email to contact@ninenines.eu.
This chapter aims to be a brief record of the life of the -Erlang.mk project.
Erlang.mk originates from the Cowboy project. Cowboy started -as a Rebar project and I, Loïc Hoguin, was very happy with it -for a couple years. Over time however I started getting annoyed -and frustrated by a number of things, including bad defaults, -changing defaults and overall slowness.
In particular, at the time I gave up on Rebar, the Cowboy
-test suite was taking about five minutes to run. A quick experiment
-showed I could get much lower times by simply invoking ct_run
-directly. On January 4th, 2013, the Cowboy test suite took less
-than a minute to complete.
Following this success I started removing a little more and, -on the fateful day of January 5th, 2013, removed the dependency -on Rebar entirely. Rebar, and in particular the concept of -dependencies, was, and still is, a pretty strong influence.
Erlang.mk was conceived.
A few months passed and, on May 1st, 2013, the Erlang.mk -repository was created. Erlang.mk was born.
Little did I know how much it would grow.
Erlang.mk would eventually become a much larger file able to -deal with many more projects than just Cowboy. From the birth -of the project, the biggest force for growth was user contributions, -because Erlang.mk appealed to a variety of people with different -needs, needs that Erlang.mk was not fulfilling yet.
The project was split into smaller files focused on a different -feature each, and a build script was written to build the single -Erlang.mk file.
A test suite was contributed by a user, and later taken as a basis -for the current, much more complete test suite. Turns out testing -a Makefile is pretty straightforward.
A package index was added to solve the problem of discovering -Erlang projects.
After trying to see if Erlang build tools could cooperate, the -decision was made to improve compatibility with existing Rebar -projects by patching Rebar out, using Rebar. This feature, called -autopatch, proved very successful and made Erlang.mk compatible -with more than 90% of all Erlang projects.
Erlang.mk documentation was much improved and the Erlang.mk website -was created in the summer of 2015.
Over the year of 2015, Erlang.mk went from curiosity to a serious -alternative to other Erlang build tools. The user base increased -immensely and large projects started using it, including RabbitMQ -from the 3.6.0 release onward.
A bright future lies ahead.
This chapter aims to be a brief record of the life of the +Erlang.mk project.
Erlang.mk originates from the Cowboy project. Cowboy started +as a Rebar project and I, Loïc Hoguin, was very happy with it +for a couple years. Over time however I started getting annoyed +and frustrated by a number of things, including bad defaults, +changing defaults and overall slowness.
In particular, at the time I gave up on Rebar, the Cowboy
+test suite was taking about five minutes to run. A quick experiment
+showed I could get much lower times by simply invoking ct_run
+directly. On January 4th, 2013, the Cowboy test suite took less
+than a minute to complete.
Following this success I started removing a little more and, +on the fateful day of January 5th, 2013, removed the dependency +on Rebar entirely. Rebar, and in particular the concept of +dependencies, was, and still is, a pretty strong influence.
Erlang.mk was conceived.
A few months passed and, on May 1st, 2013, the Erlang.mk +repository was created. Erlang.mk was born.
Little did I know how much it would grow.
Erlang.mk would eventually become a much larger file able to +deal with many more projects than just Cowboy. From the birth +of the project, the biggest force for growth was user contributions, +because Erlang.mk appealed to a variety of people with different +needs, needs that Erlang.mk was not fulfilling yet.
The project was split into smaller files focused on a different +feature each, and a build script was written to build the single +Erlang.mk file.
A test suite was contributed by a user, and later taken as a basis +for the current, much more complete test suite. Turns out testing +a Makefile is pretty straightforward.
A package index was added to solve the problem of discovering +Erlang projects.
After trying to see if Erlang build tools could cooperate, the +decision was made to improve compatibility with existing Rebar +projects by patching Rebar out, using Rebar. This feature, called +autopatch, proved very successful and made Erlang.mk compatible +with more than 90% of all Erlang projects.
Erlang.mk documentation was much improved and the Erlang.mk website +was created in the summer of 2015.
Over the year of 2015, Erlang.mk went from curiosity to a serious +alternative to other Erlang build tools. The user base increased +immensely and large projects started using it, including RabbitMQ +from the 3.6.0 release onward.
A bright future lies ahead.
-Installation -
--Overview -
--Limitations -
--Erlang shell -
--EUnit -
--Common Test -
--Dialyzer -
--Xref -
--Contributing -
-+Installation +
++Overview +
++Limitations +
++Erlang shell +
++EUnit +
++Common Test +
++Dialyzer +
++Xref +
++Contributing +
+Erlang.mk requires GNU Make to be installed. While it will -currently work with GNU Make 3.81, support for this version -is deprecated and will be removed in 2017. We recommend -GNU Make 4.1 or later.
Git and Erlang/OTP must also be installed.
Some functionality requires that Autoconf 2.59 or later be -installed, in order to compile Erlang/OTP. Erlang/OTP may -have further requirements depending on your needs.
Some packages may require additional libraries.
The commands to install packages vary between distributions:
$ pacman -S erlang git make
FreeBSD comes with binary and source packages:
$ pkg install erlang git gmake
On FreeBSD the make
command is BSD Make. Use gmake
instead.
While Apple distributes their own GNU Make, their version is -very old and plagued with numerous bugs. It is recommended -to install a more recent version from either Homebrew or -MacPorts:
$ brew install erlang git homebrew/dupes/make
Homebrew installs GNU Make as gmake
. The make
command
-is the one provided by Apple.
$ sudo port install erlang git gmake
Erlang.mk can be used on Windows inside an MSYS2 environment. -Cygwin, MSYS (the original) and native Windows (both Batch -and PowerShell) are currently not supported.
- Note
- |
-Erlang.mk expects Unix line breaks in most of the files -(LF instead of CRLF). Make sure to configure your text editor -adequately. | -
The rest of this section details how to setup Erlang/OTP and -MSYS2 in order to use Erlang.mk.
Erlang.mk requires Erlang/OTP to be installed. The OTP team -provides binaries of Erlang/OTP for all major and minor releases, -available from the official download page. -It is recommended that you use the 64-bit installer unless -technically impossible. Please follow the instructions from -the installer to complete the installation.
The OTP team also provides a short guide to -installing Erlang/OTP on Windows -if you need additional references.
You can install Erlang/OTP silently using the /S
switch
-on the command line:
C:\Users\essen\Downloads> otp_win64_18.0.exe /S
-The only supported environment on Windows is MSYS2. MSYS2 is
-a lightweight Unix-like environment for Windows that comes
-with the Arch Linux package manager, pacman
.
The MSYS2 project provides a one click installer -and instructions to set things up post-installation.
It is currently not possible to use the installer silently. -Thankfully, the MSYS2 project provides an archive that can -be used in lieu of the installer. The archive however requires -7zip to decompress it.
First, download the -MSYS2 base archive -and extract it under C:\. Assuming you downloaded the -archive as msys2.tar.xz and put it in C:\, you can -use the following commands to extract it:
C:\> 7z x msys2.tar.xz
-C:\> 7z x msys2.tar > NUL
-Then you can run the two commands needed to perform the -post-installation setup:
C:\> C:\msys64\usr\bin\bash -lc "pacman --needed --noconfirm -Sy bash pacman pacman-mirrors msys2-runtime"
-C:\> C:\msys64\usr\bin\bash -lc "pacman --noconfirm -Syu"
-After following these instructions, you can install GNU Make,
-Git and any other required softwares. From an MSYS2 shell,
-you can call pacman
directly:
$ pacman -S git make
You can use pacman -Ss
to search packages. For example,
-to find all packages related to GCC:
$ pacman -Ss gcc
If you are going to compile C/C++ code, you will need to -install this package, as Erlang.mk cannot use the normal -"gcc" package:
$ pacman -S mingw-w64-x86_64-gcc
You can also run commands under the MSYS2 environment from -the Windows command line or batch files. This command will -install GNU Make and Git:
C:\> C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S git make"
-You can use similar bash
commands if you need to run programs
-inside the MSYS2 environment from a batch file.
While most of the basic functionality will just work, there are -still some issues. Erlang.mk needs to be fixed to pass the -right paths when running Erlang scripts. We are working on it. -Erlang.mk is fully tested on both Linux and Windows, but is -lacking tests in the areas not yet covered by this guide, -so expect bugs to be fixed as more tests are added.
Erlang.mk requires GNU Make to be installed. While it will +currently work with GNU Make 3.81, support for this version +is deprecated and will be removed in 2017. We recommend +GNU Make 4.1 or later.
Git and Erlang/OTP must also be installed.
Some functionality requires that Autoconf 2.59 or later be +installed, in order to compile Erlang/OTP. Erlang/OTP may +have further requirements depending on your needs.
Some packages may require additional libraries.
The commands to install packages vary between distributions:
$ pacman -S erlang git make
FreeBSD comes with binary and source packages:
$ pkg install erlang git gmake
On FreeBSD the make
command is BSD Make. Use gmake
instead.
While Apple distributes their own GNU Make, their version is +very old and plagued with numerous bugs. It is recommended +to install a more recent version from either Homebrew or +MacPorts:
$ brew install erlang git homebrew/dupes/make
Homebrew installs GNU Make as gmake
. The make
command
+is the one provided by Apple.
$ sudo port install erlang git gmake
Erlang.mk can be used on Windows inside an MSYS2 environment. +Cygwin, MSYS (the original) and native Windows (both Batch +and PowerShell) are currently not supported.
+ Note
+ |
+Erlang.mk expects Unix line breaks in most of the files +(LF instead of CRLF). Make sure to configure your text editor +adequately. | +
The rest of this section details how to setup Erlang/OTP and +MSYS2 in order to use Erlang.mk.
Erlang.mk requires Erlang/OTP to be installed. The OTP team +provides binaries of Erlang/OTP for all major and minor releases, +available from the official download page. +It is recommended that you use the 64-bit installer unless +technically impossible. Please follow the instructions from +the installer to complete the installation.
The OTP team also provides a short guide to +installing Erlang/OTP on Windows +if you need additional references.
You can install Erlang/OTP silently using the /S
switch
+on the command line:
C:\Users\essen\Downloads> otp_win64_18.0.exe /S
+The only supported environment on Windows is MSYS2. MSYS2 is
+a lightweight Unix-like environment for Windows that comes
+with the Arch Linux package manager, pacman
.
The MSYS2 project provides a one click installer +and instructions to set things up post-installation.
It is currently not possible to use the installer silently. +Thankfully, the MSYS2 project provides an archive that can +be used in lieu of the installer. The archive however requires +7zip to decompress it.
First, download the +MSYS2 base archive +and extract it under C:\. Assuming you downloaded the +archive as msys2.tar.xz and put it in C:\, you can +use the following commands to extract it:
C:\> 7z x msys2.tar.xz
+C:\> 7z x msys2.tar > NUL
+Then you can run the two commands needed to perform the +post-installation setup:
C:\> C:\msys64\usr\bin\bash -lc "pacman --needed --noconfirm -Sy bash pacman pacman-mirrors msys2-runtime"
+C:\> C:\msys64\usr\bin\bash -lc "pacman --noconfirm -Syu"
+After following these instructions, you can install GNU Make,
+Git and any other required softwares. From an MSYS2 shell,
+you can call pacman
directly:
$ pacman -S git make
You can use pacman -Ss
to search packages. For example,
+to find all packages related to GCC:
$ pacman -Ss gcc
If you are going to compile C/C++ code, you will need to +install this package, as Erlang.mk cannot use the normal +"gcc" package:
$ pacman -S mingw-w64-x86_64-gcc
You can also run commands under the MSYS2 environment from +the Windows command line or batch files. This command will +install GNU Make and Git:
C:\> C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S git make"
+You can use similar bash
commands if you need to run programs
+inside the MSYS2 environment from a batch file.
While most of the basic functionality will just work, there are +still some issues. Erlang.mk needs to be fixed to pass the +right paths when running Erlang scripts. We are working on it. +Erlang.mk is fully tested on both Linux and Windows, but is +lacking tests in the areas not yet covered by this guide, +so expect bugs to be fixed as more tests are added.
Erlang.mk comes with integrated support for +Kerl, a shell script that +automates the downloading, building and installing of +Erlang/OTP. It can be used to easily build a specific +Erlang/OTP version (with or without custom build options) +or maintain different versions side by side.
Erlang.mk uses the Git tags from Erlang/OTP to identify
+OTP versions. The most recent tag at the time of writing
+is OTP-20.0.4
, which is a patch release of OTP-20.0
.
+A patch release is a non-official release containing a
+few fixes on top of the official release.
Older versions used a slightly different versioning scheme
+and tag format, for example: OTP_R16B03
. Beware though,
+there also was an OTP_R16B03-1
release that fixed a
+critical issue in the initial release.
The README file for all official Erlang/OTP releases can +be found on erlang.org. +To obtain information about patch releases when they are +released you need to be subscribed to the +erlang-questions mailing list.
Erlang.mk can use a specific version of Erlang/OTP when +interacting with your project. This can be very useful +when you are working with a team because you can define +the version you need in the Makefile and Erlang.mk will +ensure this version is used by everyone in your team.
To pin the version all you need to do is to set the
+ERLANG_OTP
variable in your Makefile before including
+Erlang.mk. For example, to use OTP-20.0.4
:
ERLANG_OTP = OTP-20.0.4
+
+include erlang.mk
The next time you run make
Erlang.mk will build and
+use the version you configured.
Note that there has been reports that this functionality
+is not compatible with the .ONESHELL
feature from
+GNU Make.
Erlang.mk can automatically test your project against +many different Erlang/OTP versions. This functionality +is documented in the Continuous integration chapter.
All of the Kerl variables can be configured directly in the +Makefile. All you need to do is to export them. For example, +to change the installation directory for the Erlang/OTP +versions managed by Kerl, you could add the following to +your Makefile:
export KERL_INSTALL_DIR = $(CURDIR)/erlang
When configuring paths like this, always make sure to provide +an absolute path in the value. Erlang.mk will NOT expand them +automatically for you.
No software is perfect.
It’s very important, when evaluating and when using a tool, -to understand its limitations, so as to avoid making mistakes -and wasting valuable time.
This chapter lists all known limitations of Erlang.mk.
Currently Erlang.mk requires you to install Erlang beforehand. -Installing Erlang is not always easy, particularly if you need -a specific version of Erlang for a specific project.
In addition, the Erlang being used must be in your $PATH
-before you use Erlang.mk.
In the future we envision, Erlang.mk could manage the Erlang
-version you need to use a project. Erlang.mk already does this
-for running tests when using make ci
, so doing this during
-development is just a step away.
Erlang.mk will currently not work properly if the path to the
-project contains spaces. To check if that is the case, use the
-command pwd
.
This issue is due to how Makefiles work. There might be ways -to solve it, we have not given up on it, but it’s very low -priority considering how simple the workaround is.
Erlang source files that depend on other files will have their -modification time updated when they need to be recompiled due -to a dependency having changed. This could cause some editors to -think the file changed when it didn’t.
Erlang.mk must use this method in order to be able to compile
-files in one erlc
invocation. The benefits greatly outweigh
-the issue in this case and so there are currently no plans to
-fix this behavior.
No software is perfect.
It’s very important, when evaluating and when using a tool, +to understand its limitations, so as to avoid making mistakes +and wasting valuable time.
This chapter lists all known limitations of Erlang.mk.
Currently Erlang.mk requires you to install Erlang beforehand. +Installing Erlang is not always easy, particularly if you need +a specific version of Erlang for a specific project.
In addition, the Erlang being used must be in your $PATH
+before you use Erlang.mk.
In the future we envision, Erlang.mk could manage the Erlang
+version you need to use a project. Erlang.mk already does this
+for running tests when using make ci
, so doing this during
+development is just a step away.
Erlang.mk will currently not work properly if the path to the
+project contains spaces. To check if that is the case, use the
+command pwd
.
This issue is due to how Makefiles work. There might be ways +to solve it, we have not given up on it, but it’s very low +priority considering how simple the workaround is.
Erlang source files that depend on other files will have their +modification time updated when they need to be recompiled due +to a dependency having changed. This could cause some editors to +think the file changed when it didn’t.
Erlang.mk must use this method in order to be able to compile
+files in one erlc
invocation. The benefits greatly outweigh
+the issue in this case and so there are currently no plans to
+fix this behavior.
Now that you know how to get started, let’s take a look at -what Erlang.mk can do for you.
Erlang.mk is first and foremost a build tool. It is especially -tailored for Erlang developers and follows widely accepted -practices in the Erlang community.
Erlang.mk will happily build all Erlang-specific files -you throw at it. Other kinds of files too, like C or C++ code -when you are working on a NIF or a port driver.
Erlang.mk embraces the concept of source dependencies. -It can fetch dependency source code using a variety of mechanisms, -including fetching from Git, Mercurial or SVN.
Erlang.mk will automatically generate releases -when applicable. It can also generate escripts.
Erlang.mk comes with a built-in package index. -It is built as an extension of the dependency system and is -meant to be used for discovery purposes.
No package is ever installed, they are only used as dependencies -and are always project-specific. They can be thought of as a -shortcut over plain dependencies.
You can get a list of all packages known to Erlang.mk by using
-the search
target:
$ make search
You can also use this target to search across all packages, for -example to find all packages related to Cowboy:
$ make search q=cowboy
Erlang.mk supports EDoc and Asciidoc.
EDoc generates HTML documentation directly from -your source code.
While it is convenient, ask yourself: if all the documentation is -inside the source code, why not just open the source code directly? -That’s where Asciidoc comes in.
The Asciidoc plugin expects all documentation -to be separate from source. It will generate HTML, PDF, man pages and -more from the documentation you write in the doc/src/ folder in -your repository.
Erlang.mk supports a lot of different testing and static -analysis tools.
The make shell command allows you -to test your project manually. You can automate these -unit tests with EUnit and test -your entire system with Common Test. -Code coverage can of course -be enabled during tests.
Erlang.mk comes with features to make your life easier when -setting up and using Continuous integration.
Not convinced yet? You can read about why you should use Erlang.mk -and its history. And if you’re still not -convinced after that, it’s OK! The world would be boring if -everyone agreed on everything all the time.
Now that you know how to get started, let’s take a look at +what Erlang.mk can do for you.
Erlang.mk is first and foremost a build tool. It is especially +tailored for Erlang developers and follows widely accepted +practices in the Erlang community.
Erlang.mk will happily build all Erlang-specific files +you throw at it. Other kinds of files too, like C or C++ code +when you are working on a NIF or a port driver.
Erlang.mk embraces the concept of source dependencies. +It can fetch dependency source code using a variety of mechanisms, +including fetching from Git, Mercurial or SVN.
Erlang.mk will automatically generate releases +when applicable. It can also generate escripts.
Erlang.mk comes with a built-in package index. +It is built as an extension of the dependency system and is +meant to be used for discovery purposes.
No package is ever installed, they are only used as dependencies +and are always project-specific. They can be thought of as a +shortcut over plain dependencies.
You can get a list of all packages known to Erlang.mk by using
+the search
target:
$ make search
You can also use this target to search across all packages, for +example to find all packages related to Cowboy:
$ make search q=cowboy
Erlang.mk supports EDoc and Asciidoc.
EDoc generates HTML documentation directly from +your source code.
While it is convenient, ask yourself: if all the documentation is +inside the source code, why not just open the source code directly? +That’s where Asciidoc comes in.
The Asciidoc plugin expects all documentation +to be separate from source. It will generate HTML, PDF, man pages and +more from the documentation you write in the doc/src/ folder in +your repository.
Erlang.mk supports a lot of different testing and static +analysis tools.
The make shell command allows you +to test your project manually. You can automate these +unit tests with EUnit and test +your entire system with Common Test. +Code coverage can of course +be enabled during tests.
Erlang.mk comes with features to make your life easier when +setting up and using Continuous integration.
Not convinced yet? You can read about why you should use Erlang.mk +and its history. And if you’re still not +convinced after that, it’s OK! The world would be boring if +everyone agreed on everything all the time.
Erlang.mk can not only build Erlang projects, but also the C code -that some projects come with, like NIFs and port drivers.
There are two ways to build the C code: using a custom Makefile,
-or making Erlang.mk do it directly. The C code will be built
-as needed when you run make
.
The C source code should be located in the $(C_SRC_DIR) directory. -It defaults to c_src/. Should you need to modify it, all you -need to do is to set the variable in your Makefile before including -Erlang.mk:
When this directory exists, Erlang.mk will automatically create a -file named $(C_SRC_ENV). This file defaults to $(C_SRC_DIR)/env.mk. -This can also be changed:
It contains a few variable definitions for the environment used for the build:
ERTS_INCLUDE_DIR
-- Path to the ERTS include files (erl_driver.h, erl_nif.h and more). -
-ERL_INTERFACE_INCLUDE_DIR
-- Path to the Erl_Interface include files (ei.h and related). -
-ERL_INTERFACE_LIB_DIR
-- Path to the Erl_Interface static libraries. -
-Erlang.mk will automatically run make
if it detects a Makefile
-in $(C_SRC_DIR)/Makefile.
The Makefile should have at least two targets: a default target
-(which can be anything, for example all
) which is invoked when
-building the C code, and a clean
target invoked when cleaning
-it.
You can include the env.mk file to benefit from the Erlang -environment detection:
You don’t need to write a Makefile to build C source code, however. -Erlang.mk comes with rules to build both shared libraries and -executables, using the source files it finds in $(C_SRC_DIR).
By default, Erlang.mk will create a shared library. To change -this and create an executable instead, put this in your Makefile -before including Erlang.mk:
The generated file name varies depending on the type of project -you have (shared library or executable) and on the platform you -build the project on.
For shared libraries, the generated file name will be
-$(C_SRC_OUTPUT)$(C_SRC_SHARED_EXTENSION), with the default
-being $(CURDIR)/priv/$(PROJECT) followed by the extension:
-.dll
on Windows, .so
everywhere else.
For executables, the generated file name is
-$(C_SRC_OUTPUT)$(C_SRC_EXECUTABLE_EXTENSION), with the same
-default except for the extension: .exe
on Windows, and otherwise
-nothing.
Erlang.mk sets appropriate compile and linker flags by default. -These flags vary depending on the platform, and can of course -be overriden.
CC
-- The compiler to be used. -
-CFLAGS
-- C compiler flags. -
-CXXFLAGS
-- C++ compiler flags. -
-LDFLAGS
-- Linker flags. -
-LDLIBS
-- Libraries to link against. -
-The source files are automatically gathered from the contents
-of $(C_SRC_DIR). Erlang.mk looks for .c, .C, .cc and .cpp
-source files. You can define the variable SOURCES
to manually
-list the files to compile.
Erlang.mk can not only build Erlang projects, but also the C code +that some projects come with, like NIFs and port drivers.
There are two ways to build the C code: using a custom Makefile,
+or making Erlang.mk do it directly. The C code will be built
+as needed when you run make
.
The C source code should be located in the $(C_SRC_DIR) directory. +It defaults to c_src/. Should you need to modify it, all you +need to do is to set the variable in your Makefile before including +Erlang.mk:
C_SRC_DIR = $(CURDIR)/my_nif_source
When this directory exists, Erlang.mk will automatically create a +file named $(C_SRC_ENV). This file defaults to $(C_SRC_DIR)/env.mk. +This can also be changed:
C_SRC_ENV = $(C_SRC_DIR)/erlang_env.mk
It contains a few variable definitions for the environment used for the build:
ERTS_INCLUDE_DIR
++ Path to the ERTS include files (erl_driver.h, erl_nif.h and more). +
+ERL_INTERFACE_INCLUDE_DIR
++ Path to the Erl_Interface include files (ei.h and related). +
+ERL_INTERFACE_LIB_DIR
++ Path to the Erl_Interface static libraries. +
+Erlang.mk will automatically run make
if it detects a Makefile
+in $(C_SRC_DIR)/Makefile.
The Makefile should have at least two targets: a default target
+(which can be anything, for example all
) which is invoked when
+building the C code, and a clean
target invoked when cleaning
+it.
You can include the env.mk file to benefit from the Erlang +environment detection:
include env.mk
You don’t need to write a Makefile to build C source code, however. +Erlang.mk comes with rules to build both shared libraries and +executables, using the source files it finds in $(C_SRC_DIR).
By default, Erlang.mk will create a shared library. To change +this and create an executable instead, put this in your Makefile +before including Erlang.mk:
C_SRC_TYPE = executable
The generated file name varies depending on the type of project +you have (shared library or executable) and on the platform you +build the project on.
For shared libraries, the generated file name will be
+$(C_SRC_OUTPUT)$(C_SRC_SHARED_EXTENSION), with the default
+being $(CURDIR)/priv/$(PROJECT) followed by the extension:
+.dll
on Windows, .so
everywhere else.
For executables, the generated file name is
+$(C_SRC_OUTPUT)$(C_SRC_EXECUTABLE_EXTENSION), with the same
+default except for the extension: .exe
on Windows, and otherwise
+nothing.
Erlang.mk sets appropriate compile and linker flags by default. +These flags vary depending on the platform, and can of course +be overriden.
CC
++ The compiler to be used. +
+CFLAGS
++ C compiler flags. +
+CXXFLAGS
++ C++ compiler flags. +
+LDFLAGS
++ Linker flags. +
+LDLIBS
++ Libraries to link against. +
+The source files are automatically gathered from the contents
+of $(C_SRC_DIR). Erlang.mk looks for .c, .C, .cc and .cpp
+source files. You can define the variable SOURCES
to manually
+list the files to compile.
In some cases it might be necessary to propagate the flags +you just defined to the sub-Makefiles of your local project. +You generally can’t just export those as this could impact +the building of dependencies.
Makefiles allow you to export variables for specific targets. +When doing this, the variables will be exported only when +this target runs, and not for other targets. It is therefore +possible to export them when building the C code without +impacting other build steps.
By adding this to your Makefile all five variables will be +made available to sub-Makefiles when building C code:
app-c_src: export CC += +app-c_src: export CFLAGS += +app-c_src: export CPPFLAGS += +app-c_src: export LDFLAGS += +app-c_src: export LDLIBS +=
Appending an empty string to the existing value is necessary +because Makefiles expect an assignment for target-specific +exports. Alternatively you can set a new value:
app-c_src: export CFLAGS = -O3
Erlang.mk relies on Relx for generating releases. This -chapter covers the Erlang.mk-specific bits. Consult the -Relx website for more information.
Erlang.mk will create a release if it detects a Relx configuration -file in the $(RELX_CONFIG) location. This defaults to -$(CURDIR)/relx.config. You can override it by defining -the variable before including Erlang.mk:
Relx does not need to be installed. Erlang.mk will download -and build it automatically.
The Relx executable will be saved in the $(RELX) file. This -location defaults to $(CURDIR)/relx and can be overriden.
You can specify additional Relx options using the RELX_OPTS
-variable. For example, to enable dev_mode
:
While you can specify the output directory for the release
-in the Relx options directly, Erlang.mk provides a specific
-variable for it: RELX_OUTPUT_DIR
. It defaults to the _rel
-directory. You can also override it:
Now that you’re all set, all you need to do is generate the -release. As mentioned before, Erlang.mk will automatically -generate it when it detects the $(RELX_CONFIG) file. This -means the following command will also build the release:
$ make
If you need to generate the release, and only the release,
-the rel
target can be used:
$ make rel
Erlang.mk always generates a tarball alongside the release,
-which can be directly uploaded to a server. The tarball is
-located at $(RELX_OUTPUT_DIR)/<name>/<name>-<vsn>.tar.gz
.
Erlang.mk provides a convenience function for running the -release with one simple command:
$ make run
This command will also build the project and generate the -release if they weren’t already. It starts the release in -console mode, meaning you will also have a shell ready to -use to check things as needed.
Erlang.mk provides a relup
target for generating release
-upgrades. Release upgrades allow updating the code and the
-state of a running release without restarting it.
Once your changes are done, you need to update the version -of the application(s) that will be updated. You also need -to update the version of the release.
For each application that needs to be updated, an -appup file -must be written. Refer to the Erlang/OTP documentation -for more details.
For the purpose of this section, assume the initial release
-version was 1
, and the new version is 2
. The name of the
-release will be example
.
Once all this is done, you can build the tarball for the -release upgrade:
$ make relup
This will create an archive at the root directory of the
-release, $RELX_OUTPUT_DIR/example/example-2.tar.gz
.
Move the archive to the correct location on the running -node. From the release’s root directory:
$ mkdir releases/2/ -$ mv path/to/example-2.tar.gz releases/2/
Finally, upgrade the release:
$ bin/example_release upgrade "2/example_release"
Or on Windows:
$ bin/example_release.cmd upgrade "2/example_release"
Your release was upgraded!
There is a workaround to get the semver value which is -generated by Relx based on VCS history.
Create a file rel/version with only one line inside:
{{ release_version }}
Add/Update the overlay
section of your relx.config
:
{overlay, [ - {template, "rel/version", "version"} -]}.
When you run make rel
it creates the file $(RELX_OUTPUT_DIR)/example/version
-which contains the version value generated by Relx.
$ cat _rel/app/release -1.0.0+build.11.ref5612aa0
In your Makefile
you can use this simple snippet to get the version,
-but please keep in mind that this should depend on the rel
target:
For example:
Would output:
$ make myrecipe -... -===> Starting relx build process ... -===> Resolving OTP Applications from directories: - /home/username/example/apps - /home/username/example/deps - /usr/lib/erlang/lib - /home/username/example/_rel -===> Resolved example-0.3.10+build.11.ref5612aa0 -===> Including Erts from /usr/lib/erlang -===> release successfully created! -===> tarball /home/username/example/_rel/example/example-0.3.10+build.11.ref5612aa0.tar.gz successfully created! -echo APP_VERSION = 0.3.10+build.11.ref5612aa0 -APP_VERSION = 0.3.10+build.11.ref5612aa0
Erlang.mk relies on Relx for generating releases. This +chapter covers the Erlang.mk-specific bits. Consult the +Relx website for more information.
Erlang.mk will create a release if it detects a Relx configuration +file in the $(RELX_CONFIG) location. This defaults to +$(CURDIR)/relx.config. You can override it by defining +the variable before including Erlang.mk:
RELX_CONFIG = $(CURDIR)/webchat.config
Relx does not need to be installed. Erlang.mk will download +and build it automatically.
The Relx executable will be saved in the $(RELX) file. This +location defaults to $(CURDIR)/relx and can be overriden.
You can specify additional Relx options using the RELX_OPTS
+variable. For example, to enable dev_mode
:
RELX_OPTS = -d true
While you can specify the output directory for the release
+in the Relx options directly, Erlang.mk provides a specific
+variable for it: RELX_OUTPUT_DIR
. It defaults to the _rel
+directory. You can also override it:
RELX_OUTPUT_DIR = /path/to/staging/directory
Now that you’re all set, all you need to do is generate the +release. As mentioned before, Erlang.mk will automatically +generate it when it detects the $(RELX_CONFIG) file. This +means the following command will also build the release:
$ make
If you need to generate the release, and only the release,
+the rel
target can be used:
$ make rel
Erlang.mk always generates a tarball alongside the release,
+which can be directly uploaded to a server. The tarball is
+located at $(RELX_OUTPUT_DIR)/<name>/<name>-<vsn>.tar.gz
.
Erlang.mk provides a convenience function for running the +release with one simple command:
$ make run
This command will also build the project and generate the +release if they weren’t already. It starts the release in +console mode, meaning you will also have a shell ready to +use to check things as needed.
Erlang.mk provides a relup
target for generating release
+upgrades. Release upgrades allow updating the code and the
+state of a running release without restarting it.
Once your changes are done, you need to update the version +of the application(s) that will be updated. You also need +to update the version of the release.
For each application that needs to be updated, an +appup file +must be written. Refer to the Erlang/OTP documentation +for more details.
For the purpose of this section, assume the initial release
+version was 1
, and the new version is 2
. The name of the
+release will be example
.
Once all this is done, you can build the tarball for the +release upgrade:
$ make relup
This will create an archive at the root directory of the
+release, $RELX_OUTPUT_DIR/example/example-2.tar.gz
.
Move the archive to the correct location on the running +node. From the release’s root directory:
$ mkdir releases/2/ +$ mv path/to/example-2.tar.gz releases/2/
Finally, upgrade the release:
$ bin/example_release upgrade "2/example_release"
Or on Windows:
$ bin/example_release.cmd upgrade "2/example_release"
Your release was upgraded!
There is a workaround to get the semver value which is +generated by Relx based on VCS history.
Create a file rel/version with only one line inside:
{{ release_version }}
Add/Update the overlay
section of your relx.config
:
{overlay, [ + {template, "rel/version", "version"} +]}.
When you run make rel
it creates the file $(RELX_OUTPUT_DIR)/example/version
+which contains the version value generated by Relx.
$ cat _rel/app/release +1.0.0+build.11.ref5612aa0
In your Makefile
you can use this simple snippet to get the version,
+but please keep in mind that this should depend on the rel
target:
$(shell cat $(RELX_OUTPUT_DIR)/$(RELX_REL_NAME)/version)
For example:
include erlang.mk + +APP_VERSION = $(shell cat $(RELX_OUTPUT_DIR)/$(RELX_REL_NAME)/version) +myrecipe: all + echo APP_VERSION = $(APP_VERSION)
Would output:
$ make myrecipe +... +===> Starting relx build process ... +===> Resolving OTP Applications from directories: + /home/username/example/apps + /home/username/example/deps + /usr/lib/erlang/lib + /home/username/example/_rel +===> Resolved example-0.3.10+build.11.ref5612aa0 +===> Including Erts from /usr/lib/erlang +===> release successfully created! +===> tarball /home/username/example/_rel/example/example-0.3.10+build.11.ref5612aa0.tar.gz successfully created! +echo APP_VERSION = 0.3.10+build.11.ref5612aa0 +APP_VERSION = 0.3.10+build.11.ref5612aa0
Erlang.mk allows you to package Relx releases as -self-extracting archives. These archives contain all the -files in the release and come in the form of a script that -will extract and run the release automatically.
This allows you to package the release as a single file -that can then be executed.
This feature is currently experimental. Feedback is much -appreciated.
To generate a self-extracting release, all you need to do
-is pass the SFX=1
variable to Make when you build the
-release:
$ make SFX=1
This will create a self-extracting archive in
-$RELX_OUTPUT_DIR/<name>.run
. For example if the release
-is named hello_world
and $RELX_OUTPUT_DIR
is the default,
-the file will be located at _rel/hello_world.run
.
Simply execute the script to get started:
$ ./_rel/hello_world.run -Exec: /tmp/tmp.3eeEq7E1ta/erts-8.1/bin/erlexec ... -Root: /tmp/tmp.3eeEq7E1ta -/tmp/tmp.3eeEq7E1ta -Erlang/OTP 19 [erts-8.1] [source] [64-bit] [smp:4:4] ... - -Eshell V8.1 (abort with ^G) -(hello_world@localhost)1>
As you can see the archive is extracted to a temporary -directory before the release can be started.
The self-extracting script currently only supports starting
-the release in console
mode.
Erlang.mk allows you to package Relx releases as +self-extracting archives. These archives contain all the +files in the release and come in the form of a script that +will extract and run the release automatically.
This allows you to package the release as a single file +that can then be executed.
This feature is currently experimental. Feedback is much +appreciated.
To generate a self-extracting release, all you need to do
+is pass the SFX=1
variable to Make when you build the
+release:
$ make SFX=1
This will create a self-extracting archive in
+$RELX_OUTPUT_DIR/<name>.run
. For example if the release
+is named hello_world
and $RELX_OUTPUT_DIR
is the default,
+the file will be located at _rel/hello_world.run
.
Simply execute the script to get started:
$ ./_rel/hello_world.run +Exec: /tmp/tmp.3eeEq7E1ta/erts-8.1/bin/erlexec ... +Root: /tmp/tmp.3eeEq7E1ta +/tmp/tmp.3eeEq7E1ta +Erlang/OTP 19 [erts-8.1] [source] [64-bit] [smp:4:4] ... + +Eshell V8.1 (abort with ^G) +(hello_world@localhost)1>
As you can see the archive is extracted to a temporary +directory before the release can be started.
The self-extracting script currently only supports starting
+the release in console
mode.
Erlang.mk provides a convenient target for starting a shell -with all the paths set properly to experiment with your code.
The SHELL_DEPS
variable can be used to define dependencies
-that are only to be used when the make shell
command is called.
-For example, if you want to use kjell as your shell:
Dependencies are downloaded and compiled the first time you
-run the make shell
command.
You can customize the executable used to start the Erlang shell.
-To continue with our example, if you want to use kjell as your
-shell, you also need to change SHELL_ERL
and point it to the
-kjell
executable:
You can specify additional options to be used when starting the
-shell using the SHELL_OPTS
variable:
Any of the usual erl
options can be used, including -eval
:
To start the shell, all you need is the following command:
$ make shell
The shell can be stopped as usual with a double Ctrl+C or the
-command q().
.
Erlang.mk provides a convenient target for starting a shell +with all the paths set properly to experiment with your code.
The SHELL_DEPS
variable can be used to define dependencies
+that are only to be used when the make shell
command is called.
+For example, if you want to use kjell as your shell:
SHELL_DEPS = kjell
Dependencies are downloaded and compiled the first time you
+run the make shell
command.
You can customize the executable used to start the Erlang shell.
+To continue with our example, if you want to use kjell as your
+shell, you also need to change SHELL_ERL
and point it to the
+kjell
executable:
SHELL_ERL = $(DEPS_DIR)/kjell/bin/kjell
You can specify additional options to be used when starting the
+shell using the SHELL_OPTS
variable:
SHELL_OPTS = -setcookie chocolate
Any of the usual erl
options can be used, including -eval
:
SHELL_OPTS = -eval 'my_app:run()'
To start the shell, all you need is the following command:
$ make shell
The shell can be stopped as usual with a double Ctrl+C or the
+command q().
.
This chapter describes how to update the erlang.mk file -in your repository.
The first time you use Erlang.mk, it will bootstrap itself. -It always uses the most recent version for this, so you don’t -have to update after creating your project.
Later on though, updating becomes a necessity. Erlang.mk -developers and contributors relentlessly improve the project -and add new features; it would be a waste not to benefit -from this.
That’s why updating Erlang.mk is so simple. All you need
-to do is to call make erlang-mk
:
$ make erlang-mk -git clone https://github.com/ninenines/erlang.mk .erlang.mk.build -Cloning into '.erlang.mk.build'... -remote: Counting objects: 4035, done. -remote: Compressing objects: 100% (12/12), done. -remote: Total 4035 (delta 8), reused 4 (delta 4), pack-reused 4019 -Receiving objects: 100% (4035/4035), 1.10 MiB | 1000.00 KiB/s, done. -Resolving deltas: 100% (2442/2442), done. -Checking connectivity... done. -if [ -f build.config ]; then cp build.config .erlang.mk.build; fi -cd .erlang.mk.build && make -make[1]: Entering directory '/home/essen/tmp/emkg/hello_joe/.erlang.mk.build' -awk 'FNR==1 && NR!=1{print ""}1' core/core.mk index/*.mk core/index.mk core/deps.mk plugins/protobuffs.mk core/erlc.mk core/docs.mk core/test.mk plugins/asciidoc.mk plugins/bootstrap.mk plugins/c_src.mk plugins/ci.mk plugins/ct.mk plugins/dialyzer.mk plugins/edoc.mk plugins/elvis.mk plugins/erlydtl.mk plugins/escript.mk plugins/eunit.mk plugins/relx.mk plugins/shell.mk plugins/triq.mk plugins/xref.mk plugins/cover.mk \ - | sed 's/^ERLANG_MK_VERSION = .*/ERLANG_MK_VERSION = 1.2.0-642-gccd2b9f/' > erlang.mk -make[1]: Leaving directory '/home/essen/tmp/emkg/hello_joe/.erlang.mk.build' -cp .erlang.mk.build/erlang.mk ./erlang.mk -rm -rf .erlang.mk.build
All that’s left to do is to commit the file!
Yep, it’s that easy.
Erlang.mk allows you to customize which components are to be included
-in the erlang.mk file. The WITHOUT
variable allows you to
-remove components from the default Erlang.mk build. The build.config
-file lets you define exactly what goes in (including your own code!),
-and in what order.
The WITHOUT
file contains the list of components to exclude from
-the build. For example, to exclude the package index and the EDoc
-plugin when bootstrapping your application:
$ make -f erlang.mk bootstrap WITHOUT="index plugins/edoc"
The generated Erlang.mk will never include those components when
-you update it, until you change your mind and use the WITHOUT
-variable again when you upgrade:
$ make erlang-mk WITHOUT=index
The build.config file is automatically used when you bootstrap
-Erlang.mk or when you update it with make erlang-mk
.
The build.config file contains the list of all files that will -be built into the resulting erlang.mk file. You can start from -the most recent version -and customize to your needs.
You can also name the file differently or put it in a separate folder
-by modifying the value for ERLANG_MK_BUILD_CONFIG
. You can also
-tell Erlang.mk to use a different temporary directory by changing
-the ERLANG_MK_BUILD_DIR
variable.
This chapter describes how to update the erlang.mk file +in your repository.
The first time you use Erlang.mk, it will bootstrap itself. +It always uses the most recent version for this, so you don’t +have to update after creating your project.
Later on though, updating becomes a necessity. Erlang.mk +developers and contributors relentlessly improve the project +and add new features; it would be a waste not to benefit +from this.
That’s why updating Erlang.mk is so simple. All you need
+to do is to call make erlang-mk
:
$ make erlang-mk +git clone https://github.com/ninenines/erlang.mk .erlang.mk.build +Cloning into '.erlang.mk.build'... +remote: Counting objects: 4035, done. +remote: Compressing objects: 100% (12/12), done. +remote: Total 4035 (delta 8), reused 4 (delta 4), pack-reused 4019 +Receiving objects: 100% (4035/4035), 1.10 MiB | 1000.00 KiB/s, done. +Resolving deltas: 100% (2442/2442), done. +Checking connectivity... done. +if [ -f build.config ]; then cp build.config .erlang.mk.build; fi +cd .erlang.mk.build && make +make[1]: Entering directory '/home/essen/tmp/emkg/hello_joe/.erlang.mk.build' +awk 'FNR==1 && NR!=1{print ""}1' core/core.mk index/*.mk core/index.mk core/deps.mk plugins/protobuffs.mk core/erlc.mk core/docs.mk core/test.mk plugins/asciidoc.mk plugins/bootstrap.mk plugins/c_src.mk plugins/ci.mk plugins/ct.mk plugins/dialyzer.mk plugins/edoc.mk plugins/elvis.mk plugins/erlydtl.mk plugins/escript.mk plugins/eunit.mk plugins/relx.mk plugins/shell.mk plugins/triq.mk plugins/xref.mk plugins/cover.mk \ + | sed 's/^ERLANG_MK_VERSION = .*/ERLANG_MK_VERSION = 1.2.0-642-gccd2b9f/' > erlang.mk +make[1]: Leaving directory '/home/essen/tmp/emkg/hello_joe/.erlang.mk.build' +cp .erlang.mk.build/erlang.mk ./erlang.mk +rm -rf .erlang.mk.build
All that’s left to do is to commit the file!
Yep, it’s that easy.
Erlang.mk allows you to customize which components are to be included
+in the erlang.mk file. The WITHOUT
variable allows you to
+remove components from the default Erlang.mk build. The build.config
+file lets you define exactly what goes in (including your own code!),
+and in what order.
The WITHOUT
file contains the list of components to exclude from
+the build. For example, to exclude the package index and the EDoc
+plugin when bootstrapping your application:
$ make -f erlang.mk bootstrap WITHOUT="index plugins/edoc"
The generated Erlang.mk will never include those components when
+you update it, until you change your mind and use the WITHOUT
+variable again when you upgrade:
$ make erlang-mk WITHOUT=index
The build.config file is automatically used when you bootstrap
+Erlang.mk or when you update it with make erlang-mk
.
The build.config file contains the list of all files that will +be built into the resulting erlang.mk file. You can start from +the most recent version +and customize to your needs.
You can also name the file differently or put it in a separate folder
+by modifying the value for ERLANG_MK_BUILD_CONFIG
. You can also
+tell Erlang.mk to use a different temporary directory by changing
+the ERLANG_MK_BUILD_DIR
variable.
Why would you choose Erlang.mk, if not for its -many features? This chapter will -attempt to answer that.
Erlang.mk is as fast as it gets.
Erlang.mk will group the compilation of files so as to avoid -running the BEAM more than necessary. This saves many seconds -compared to traditional Makefiles, even on small projects.
Erlang.mk will not try to be too smart. It provides a simple -solution that works for most people, and gives additional -options for projects that run into edge cases, often in the -form of extra variables or rules to be defined.
Erlang.mk is a Makefile.
You could use Erlang.mk directly without configuring anything -and it would just work. But you can also extend it greatly -either through configuration or hooks, and you can of course -add your own rules to the Makefile.
In all cases: for configuration, hooks or custom rules, you -have all the power of Unix at your disposal, and can call -any utility or even any language interpreter you want, -every time you need to. Erlang.mk also allows you to write -scripts in this small language called Erlang directly inside -your Makefile if you ever need to…
Erlang.mk is a Makefile.
Which means Erlang.mk is a simple text file. You can edit a -text file. Nothing stops you. If you run into any bug, or -behavior that does not suit you, you can just open the -erlang.mk file in your favorite editor, fix and/or comment -a few lines, save, and try again. It’s as simple as it gets.
Currently using a binary build tool? Good luck with that.
Erlang.mk isn’t written in Erlang.
That’s not a good thing, you say? Well, here’s one thing -that Erlang.mk and Makefiles can do for you that Erlang -build tool can’t easily: choose what version of Erlang is -to be used for compiling the project.
This really is a one-liner in Erlang.mk (a few more lines
-if you also let it download and build Erlang directly)
-and allows for even greater things, like testing your
-project across all supported Erlang versions in one small
-command: make -k ci
.
Erlang.mk doesn’t care what your dependencies are written in.
Erlang.mk will happily compile any dependency, as long as -they come with a Makefile. The dependency can be written -in C, C++ or even Javascript… Who cares, really? If you -need Erlang.mk to fetch it, then Erlang.mk will fetch it -and compile it as needed.
If you are planning to put your project in the middle of -a Make or Automake-based build environment, then the most -logical thing to do is to use a Makefile.
Erlang.mk will happily sit in such an environment and behave -as you expect it to.
Why would you choose Erlang.mk, if not for its +many features? This chapter will +attempt to answer that.
Erlang.mk is as fast as it gets.
Erlang.mk will group the compilation of files so as to avoid +running the BEAM more than necessary. This saves many seconds +compared to traditional Makefiles, even on small projects.
Erlang.mk will not try to be too smart. It provides a simple +solution that works for most people, and gives additional +options for projects that run into edge cases, often in the +form of extra variables or rules to be defined.
Erlang.mk is a Makefile.
You could use Erlang.mk directly without configuring anything +and it would just work. But you can also extend it greatly +either through configuration or hooks, and you can of course +add your own rules to the Makefile.
In all cases: for configuration, hooks or custom rules, you +have all the power of Unix at your disposal, and can call +any utility or even any language interpreter you want, +every time you need to. Erlang.mk also allows you to write +scripts in this small language called Erlang directly inside +your Makefile if you ever need to…
Erlang.mk is a Makefile.
Which means Erlang.mk is a simple text file. You can edit a +text file. Nothing stops you. If you run into any bug, or +behavior that does not suit you, you can just open the +erlang.mk file in your favorite editor, fix and/or comment +a few lines, save, and try again. It’s as simple as it gets.
Currently using a binary build tool? Good luck with that.
Erlang.mk isn’t written in Erlang.
That’s not a good thing, you say? Well, here’s one thing +that Erlang.mk and Makefiles can do for you that Erlang +build tool can’t easily: choose what version of Erlang is +to be used for compiling the project.
This really is a one-liner in Erlang.mk (a few more lines
+if you also let it download and build Erlang directly)
+and allows for even greater things, like testing your
+project across all supported Erlang versions in one small
+command: make -k ci
.
Erlang.mk doesn’t care what your dependencies are written in.
Erlang.mk will happily compile any dependency, as long as +they come with a Makefile. The dependency can be written +in C, C++ or even Javascript… Who cares, really? If you +need Erlang.mk to fetch it, then Erlang.mk will fetch it +and compile it as needed.
If you are planning to put your project in the middle of +a Make or Automake-based build environment, then the most +logical thing to do is to use a Makefile.
Erlang.mk will happily sit in such an environment and behave +as you expect it to.
Placeholder chapter.
Placeholder chapter.