From bdfcb324f780c90de199b908837875dfc9b2e439 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Hoguin?= Date: Wed, 2 Sep 2015 18:17:15 +0200 Subject: Add dependency tracking (makedep) This is a very large change of a central part of Erlang.mk. I will admit that I am not quite confident on that one. If you do have issues following this change, please open a ticket and I will look at it immediately. At this point, it works for me, but I wouldn't be surprised to hear about a few minor issues. This commit introduces a dependency file $(PROJECT).d which contains Makefile rules between Erlang source files and headers, behaviors and parse_transforms. This allows us to rebuild only the files that are needed. The $(PROJECT).d is generated automatically when missing, and when any of the files change. It is possible to hook before and after this generation, by defining a $(PROJECT).d:: rule. This allows users to generate Erlang files which are then compiled by Erlang.mk automatically (and to track their dependencies, of course). Here goes nothing... --- doc/src/guide/app.asciidoc | 267 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 267 insertions(+) create mode 100644 doc/src/guide/app.asciidoc (limited to 'doc/src/guide/app.asciidoc') diff --git a/doc/src/guide/app.asciidoc b/doc/src/guide/app.asciidoc new file mode 100644 index 0000000..880221a --- /dev/null +++ b/doc/src/guide/app.asciidoc @@ -0,0 +1,267 @@ +== Building + +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 link:getting_started.asciidoc[generated by Erlang.mk]. + +=== How to build + +To build a project, all you have to do is type `make`: + +[source,bash] +$ make + +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. + +=== What to build + +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 `make`. But sometimes you just want to repeat one or +two of them. + +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. + +==== Application + +You can build your application specifically, without +looking at handling dependencies or generating a release, +by running the following command: + +[source,bash] +$ make app + +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. + +==== Dependencies + +You can build all dependencies, and nothing else, by +running the following command: + +[source,bash] +$ make deps + +This will fetch and compile all dependencies and their +dependencies, recursively. + +link:deps.asciidoc[Packages and dependencies] are covered +in the next chapter. + +==== Release + +You can generate the release, skipping the steps for building +the application and dependencies, by running the following +command: + +[source,bash] +$ make rel + +This command can be useful if nothing changed except the +release configuration files. + +Consult the link:relx.asciidoc[Releases] chapter for more +information about what releases are and how they are generated. + +Note that this command may fail if a required dependency +is missing. + +=== Application resource file + +When building your application, Erlang.mk will generate the +http://www.erlang.org/doc/man/app.html[application resource file]. +This file is mandatory for all Erlang applications and is +found in 'ebin/$(PROJECT).app'. + +`PROJECT` is a variable defined in your Makefile and taken +from the name of the directory when Erlang.mk bootstraps +your project. + +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. + +==== Application configuration + +Erlang.mk automatically fills the `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`:: + The name of the OTP application or library. +`PROJECT_DESCRIPTION`:: + Short description of the project. +`PROJECT_VERSION`:: + Current version of the project. +`PROJECT_REGISTERED`:: + List of the names of all registered processes. +`OTP_DEPS`:: + List of Erlang/OTP applications this project depends on, + excluding `erts`, `kernel` and `stdlib`. +`DEPS`:: + 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: + +[source,make] +---- +PROJECT = cowboy +PROJECT_DESCRIPTION = Small, fast, modular HTTP server. +PROJECT_VERSION = 2.0.0-pre.2 +PROJECT_REGISTERED = cowboy_clock + +OTP_DEPS = crypto +DEPS = cowlib ranch +---- + +Any space before and after the value is dropped. + +link:deps.asciidoc[Dependencies] are covered in details in +the next chapter. + +==== Legacy method + +The 'src/$(PROJECT).app.src' file is a legacy method of +building Erlang applications. It was introduced by the original +`rebar` build tool, of which Erlang.mk owes a great deal as it +is its main inspiration. + +The '.app.src' file serves as a template to generate the '.app' +file. Erlang.mk will take it, fill in the `modules` value +dynamically, and save the result in 'ebin/$(PROJECT).app'. + +When using this method, Erlang.mk cannot fill the `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. + +=== File formats + +Erlang.mk supports a variety of different source file formats. +The following formats are supported natively: + +[cols="<,3*^",options="header"] +|=== +| Extension | Location | Description | Output +| .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 (`.hrl`) +as described at the end of this chapter. It can also compile +C code, as described in the link:ports.asciidoc[NIFs and port drivers] +chapter. + +Erlang.mk also comes with plugins for the following formats: + +[cols="<,3*^",options="header"] +|=== +| Extension | Location | Description | Output +| .dtl | templates/ | Django templates | ebin/*.beam +| .proto | src/ | Protocol buffers | ebin/*.beam +|=== + +=== Cold and hot builds + +The first time you run `make`, Erlang.mk will build everything. + +The second time you run `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. + +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. + +=== Dependency tracking + +NOTE: This section is about the dependency tracking between files +inside your project, not application dependencies. + +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. + +=== Cleaning + +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: `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. + +To clean: + +[source,bash] +$ make clean + +Or distclean: + +[source,bash] +$ make distclean + +That is the question. + +Note that Erlang.mk will automatically clean some files as +part of other targets, but it will never run `distclean` if +you don't explicitly use it. -- cgit v1.2.3