aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile7
-rw-r--r--README.asciidoc18
-rw-r--r--README.legacy.md137
-rw-r--r--README.md353
-rw-r--r--appveyor.yml4
-rw-r--r--build.config3
-rw-r--r--circle.yml13
-rw-r--r--core/compat.mk17
-rw-r--r--core/core.mk13
-rw-r--r--core/deps.mk138
-rw-r--r--core/erlc.mk119
-rw-r--r--core/test.mk6
-rw-r--r--doc/src/guide/app.asciidoc39
-rw-r--r--doc/src/guide/architecture.asciidoc5
-rw-r--r--doc/src/guide/asciidoc.asciidoc83
-rw-r--r--doc/src/guide/book.asciidoc12
-rw-r--r--doc/src/guide/ci.asciidoc1
-rw-r--r--doc/src/guide/common_test.asciidoc90
-rw-r--r--doc/src/guide/compat.asciidoc8
-rw-r--r--doc/src/guide/contributing.asciidoc115
-rw-r--r--doc/src/guide/coverage.asciidoc1
-rw-r--r--doc/src/guide/deps.asciidoc5
-rw-r--r--doc/src/guide/dialyzer.asciidoc72
-rw-r--r--doc/src/guide/edoc.asciidoc47
-rw-r--r--doc/src/guide/escripts.asciidoc1
-rw-r--r--doc/src/guide/eunit.asciidoc121
-rw-r--r--doc/src/guide/external_plugins.asciidoc3
-rw-r--r--doc/src/guide/external_plugins_list.asciidoc48
-rw-r--r--doc/src/guide/getting_started.asciidoc43
-rw-r--r--doc/src/guide/history.asciidoc65
-rw-r--r--doc/src/guide/installation.asciidoc8
-rw-r--r--doc/src/guide/limitations.asciidoc1
-rw-r--r--doc/src/guide/overview.asciidoc39
-rw-r--r--doc/src/guide/ports.asciidoc19
-rw-r--r--doc/src/guide/property_based_testing.asciidoc5
-rw-r--r--doc/src/guide/releases.asciidoc1
-rw-r--r--doc/src/guide/shell.asciidoc1
-rw-r--r--doc/src/guide/updating.asciidoc1
-rw-r--r--doc/src/guide/why.asciidoc3
-rw-r--r--doc/src/guide/xref.asciidoc1
-rw-r--r--index/bitcask.mk2
-rw-r--r--index/brod.mk7
-rw-r--r--index/bullet.mk2
-rw-r--r--index/dhtcrawler.mk7
-rw-r--r--index/elvis.mk2
-rw-r--r--index/gen_coap.mk7
-rw-r--r--index/geode.mk7
-rw-r--r--index/i18n.mk7
-rw-r--r--index/itweet.mk7
-rw-r--r--index/jesse.mk4
-rw-r--r--index/jsone.mk7
-rw-r--r--index/kafka_protocol.mk7
-rw-r--r--index/mimerl.mk7
-rw-r--r--index/nksip.mk7
-rw-r--r--index/oauth2c.mk7
-rw-r--r--index/ptrackerl.mk7
-rw-r--r--index/slack.mk7
-rw-r--r--index/supervisor3.mk7
-rw-r--r--index/xref_runner.mk2
-rw-r--r--plugins/asciidoc.mk8
-rw-r--r--plugins/bootstrap.mk27
-rw-r--r--plugins/c_src.mk139
-rw-r--r--plugins/ct.mk34
-rw-r--r--plugins/dialyzer.mk19
-rw-r--r--plugins/edoc.mk6
-rw-r--r--plugins/elvis.mk39
-rw-r--r--plugins/erlydtl.mk33
-rw-r--r--plugins/escript.mk4
-rw-r--r--plugins/eunit.mk34
-rw-r--r--plugins/relx.mk4
-rw-r--r--test/Makefile149
-rw-r--r--test/core_app.mk52
-rw-r--r--test/core_compat.mk58
-rw-r--r--test/core_deps.mk118
-rw-r--r--test/core_plugins.mk12
-rw-r--r--test/core_upgrade.mk50
-rw-r--r--test/plugin_asciidoc.mk158
-rw-r--r--test/plugin_bootstrap.mk83
-rw-r--r--test/plugin_c_src.mk89
-rw-r--r--test/plugin_ct.mk226
-rw-r--r--test/plugin_dialyzer.mk240
-rw-r--r--test/plugin_edoc.mk112
-rw-r--r--test/plugin_erlydtl.mk12
-rw-r--r--test/plugin_eunit.mk210
-rw-r--r--test/plugin_shell.mk12
85 files changed, 2701 insertions, 1003 deletions
diff --git a/Makefile b/Makefile
index 1e838d2..dd437e2 100644
--- a/Makefile
+++ b/Makefile
@@ -61,3 +61,10 @@ clean:
docs:
$(MAKE) -f core/core.mk -f core/docs.mk -f plugins/asciidoc.mk asciidoc
+
+up:
+ git clone [email protected]:ninenines/erlang.mk.git gh-pages
+ cd gh-pages && git checkout gh-pages
+ cd gh-pages && make
+ cd gh-pages && git push origin gh-pages
+ rm -rf gh-pages
diff --git a/README.asciidoc b/README.asciidoc
new file mode 100644
index 0000000..c397291
--- /dev/null
+++ b/README.asciidoc
@@ -0,0 +1,18 @@
+= Erlang.mk
+
+A build tool for Erlang that just works.
+
+http://erlang.mk/ - http://erlang.mk/guide/[User guide]
+
+Embrace the power and simplicity of Makefiles.
+
+[source,make]
+PROJECT = webchat
+DEPS = cowboy
+include erlang.mk
+
+http://erlang.mk/guide/getting_started.html[Get started]
+
+Tested and supported on
+http://erlang.mk/guide/installation.html#_on_unix[Linux, FreeBSD, OSX]
+and http://erlang.mk/guide/installation.html#_on_windows[Windows].
diff --git a/README.legacy.md b/README.legacy.md
new file mode 100644
index 0000000..a992977
--- /dev/null
+++ b/README.legacy.md
@@ -0,0 +1,137 @@
+Old Erlang.mk documentation
+===========================
+
+This documentation reminds here until it gets moved to the
+official documentation on http://erlang.mk/guide/.
+
+Extending Erlang.mk
+-------------------
+
+You may add additional operations to them by using the double
+colons. Make will run all targets sharing the same name when
+invoked.
+
+``` Makefile
+clean::
+ @rm anotherfile
+```
+
+You can enable verbose mode by calling Make with the variable
+`V` set to 1.
+
+``` bash
+$ make V=1
+```
+
+Parallel execution
+------------------
+
+*Parallel execution is currently enabled (experimental).*
+
+Parallel execution can be enabled through the use of the
+`-j` option. The following output showcases concurrent
+downloading of dependencies.
+
+``` bash
+$ make -j32
+Cloning into '/home/essen/ninenines/cowboy/deps/ranch'...
+Cloning into '/home/essen/ninenines/cowboy/deps/cowlib'...
+```
+
+The `-O` option will ensure that output from different
+targets is grouped, which is particularly useful when
+running tests with different frameworks at the same time.
+The disadvantage of this option however is that there is
+no output until the target is completed.
+
+The``MAKEFLAGS` variable can be used to set it permanently
+on your system. It can be set in your `.zshrc`, `.bashrc`
+or equivalent file.
+
+``` bash
+MAKEFLAGS="-j32 -O"
+```
+
+EDoc plugin
+-----------
+
+This plugin is available by default.
+
+EDoc options can be specified in Erlang format by defining
+the `EDOC_OPTS` variable. For more information please see
+`erl -man edoc`.
+
+ErlyDTL plugin
+--------------
+
+This plugin is available by default. It adds automatic
+compilation of ErlyDTL templates found in `templates/*.dtl`
+or any subdirectory.
+
+By default it ignores names of subdirectories and compiles
+`a/b/templatename.dtl` into `templatename_dtl.beam`. To include
+subdirectories names in the compiled module name add
+`DTL_FULL_PATH=1` into your Makefile - `a/b/templatename.dtl`
+will be compiled into `a_b_templatename_dtl.beam`.
+
+Escript plugin
+--------------
+
+This plugin is available by default. It adds the following
+target:
+
+`escript` which creates a shell-executable archive named
+the same as your `$(PROJECT)`, containing the following files
+from your application and its dependencies:
+
+* `*.beam`
+* contents of `priv/`
+* `sys.config` for your application
+
+There are a number of optional configuration parameters:
+
+* `ESCRIPT_NAME` if a different output file is required
+* `ESCRIPT_COMMENT` to alter the comment line in the escript header
+* `ESCRIPT_BEAMS` for the paths searched for `*.beam` files to include
+* `ESCRIPT_SYS_CONFIG` defaults to `rel/sys.config`
+* `ESCRIPT_EMU_ARGS` for the parameters used to start the VM
+* `ESCRIPT_SHEBANG` for the line used by your shell to start `escript`
+* `ESCRIPT_STATIC` for non-beam directories to be included as well
+
+Refer to http://www.erlang.org/doc/man/escript.html for
+more information on `escript` functionality in general.
+
+Triq plugin
+-----------
+
+This plugin is available by default. It adds the following
+target:
+
+`triq` will check all the properties found in `ebin` or
+the test directory specified in `TEST_DIR`.
+
+You can use the `t` variable to give a specific module
+or function to run, for example:
+
+``` bash
+$ make triq t=cow_http_hd
+```
+
+Or:
+
+``` bash
+$ make triq t=cow_http_hd:prop_parse_accept
+```
+
+Xref plugin
+------------
+
+This plugin is available by default. It adds the following
+target:
+
+`xref` Erlang Xref Runner (inspired in rebar's rebar_xref)
+
+The `XREF_CONFIG` variable specifies the location of the
+configuration file which holds the checks to be applied.
+If there is no `xref.config` all `xref` checks will be
+applied to the binaries located in the `/ebin` directory.
diff --git a/README.md b/README.md
deleted file mode 100644
index 600ce50..0000000
--- a/README.md
+++ /dev/null
@@ -1,353 +0,0 @@
-erlang.mk
-=========
-
-A build tool for Erlang that just works.
-
-[Check out our upcoming user guide!](doc/src/guide/book.asciidoc)
-
-The README only contains legacy documentation that was not moved to
-the guide yet. Check there if you don't find what you're looking for.
-
-Requirements
-------------
-
-`erlang.mk` requires GNU Make and expects to be ran in a standard
-unix environment with Erlang installed and in the `$PATH`.
-
-Common workflow
----------------
-
-A common workflow when editing a file would be to run `make` regularly
-to see if it compiles (or less often `make clean app` if you want to
-recompile everything), followed by `make dialyze` to see if there are
-any type errors and then `make tests` to run the test suites. The
-result of the test runs can be browsed from the `logs/index.html` file.
-
-Compiling and dependencies
---------------------------
-
-Gone! [Check out our upcoming user guide!](doc/src/guide/book.asciidoc)
-
-Releases
---------
-
-If a `relx.config` file is present, erlang.mk will download `relx`
-automatically and build the release into the `_rel` folder. This
-is the default command when the file exists.
-
-No special configuration is required for this to work.
-
-Extending Erlang.mk
--------------------
-
-You may add additional operations to them by using the double
-colons. Make will run all targets sharing the same name when
-invoked.
-
-``` Makefile
-clean::
- @rm anotherfile
-```
-
-You can enable verbose mode by calling Make with the variable
-`V` set to 1.
-
-``` bash
-$ make V=1
-```
-
-Parallel execution
-------------------
-
-*Parallel execution is currently disabled.*
-
-Parallel execution can be enabled through the use of the
-`-j` option. The following output showcases concurrent
-downloading of dependencies.
-
-``` bash
-$ make -j32
-Cloning into '/home/essen/ninenines/cowboy/deps/ranch'...
-Cloning into '/home/essen/ninenines/cowboy/deps/cowlib'...
-```
-
-The `-O` option will ensure that output from different
-targets is grouped, which is particularly useful when
-running tests with different frameworks at the same time.
-The disadvantage of this option however is that there is
-no output until the target is completed.
-
-The``MAKEFLAGS` variable can be used to set it permanently
-on your system. It can be set in your `.zshrc`, `.bashrc`
-or equivalent file.
-
-``` bash
-MAKEFLAGS="-j32 -O"
-```
-
-C/C++ compiler plugin
----------------------
-
-This plugin is available by default. It is meant to
-simplify the management of projects that include C
-and/or C++ source code, like NIFs for example.
-
-If the file `$(C_SRC_DIR)/Makefile` exists, then the plugin
-simply calls it when needed. Otherwise it tries to compile
-it directly.
-
-You can use a different directory than `./c_src` by setting
-the `C_SRC_DIR` variable.
-
-You can override the output file by setting the `C_SRC_OUTPUT`
-variable.
-
-You can override the temporary file containing information
-about Erlang's environment by setting the `C_SRC_ENV` variable.
-This file is automatically generated on first run.
-
-The `CC`, `CXX`, `CFLAGS`, `CXXFLAGS`, `LDLIBS` and `LDFLAGS` variables
-may be modified or replaced with any value of your choosing.
-The defaults are system dependent.
-
-Common_test plugin
-------------------
-
-This plugin is available by default. It adds the following
-target:
-
-`ct` runs all test suites for this application.
-
-There is nothing to configure to use it, simply create your
-test suites in the `./test/` directory and erlang.mk will
-figure everything out automatically.
-
-You can override the list of suites that will run when using
-`make tests` by setting the `CT_SUITES` variable.
-
-You can add extra `ct_run` options by defining the `CT_OPTS`
-variable. For more information please see `erl -man ct_run`.
-
-You can run an individual test suite by using the special `ct-*`
-targets. For example if you have a common_test suite named `spdy`
-and you want to run only this suite and not the others, you can
-use the `make ct-spdy` command.
-
-Dialyzer plugin
----------------
-
-This plugin is available by default. It adds the following
-targets:
-
-`plt` builds the PLT file for this application.
-
-`dialyze` runs Dialyzer.
-
-The PLT file is built in `./$(PROJECT).plt` by default.
-You can override this location by setting the `DIALYZER_PLT`
-variable.
-
-The `PLT_APPS` variable lists the applications that will be
-included in the PLT file. There is no need to specify `erts`,
-`kernel`, `stdlib` or the project's dependencies here, as they
-are automatically added.
-
-Dialyzer options can be modified by defining the `DIALYZER_OPTS`
-variable. The directories to be analyzed can be overriden using
-the `DIALYZER_DIRS` variable. It defaults to analyzing source
-files recursively found in `src/`. For more information please
-see `erl -man dialyzer`.
-
-EDoc plugin
------------
-
-This plugin is available by default.
-
-EDoc options can be specified in Erlang format by defining
-the `EDOC_OPTS` variable. For more information please see
-`erl -man edoc`.
-
-Elvis plugin
-------------
-
-This plugin is available by default. It adds the following
-target:
-
-`elvis` runs Elvis style checker for this application.
-
-The `ELVIS_CONFIG` variable specifies the location of the
-configuration file which holds the rules to be applied.
-If there's no `elvis.config` file the default one will be
-downloaded. When the `ELVIS` variable points to a non-existing
-file then the `elvis` executable will be downloaded as well.
-Any other option should go in the `ELVIS_OPTS` variable.
-
-ErlyDTL plugin
---------------
-
-This plugin is available by default. It adds automatic
-compilation of ErlyDTL templates found in `templates/*.dtl`
-or any subdirectory.
-
-By default it ignores names of subdirectories and compiles
-`a/b/templatename.dtl` into `templatename_dtl.beam`. To include
-subdirectories names in the compiled module name add
-`DTL_FULL_PATH=1` into your Makefile - `a/b/templatename.dtl`
-will be compiled into `a_b_templatename_dtl.beam`.
-
-Escript plugin
---------------
-
-This plugin is available by default. It adds the following
-target:
-
-`escript` which creates a shell-executable archive named
-the same as your `$(PROJECT)`, containing the following files
-from your application and its dependencies:
-
-* `*.beam`
-* contents of `priv/`
-* `sys.config` for your application
-
-There are a number of optional configuration parameters:
-
-* `ESCRIPT_NAME` if a different output file is required
-* `ESCRIPT_COMMENT` to alter the comment line in the escript header
-* `ESCRIPT_BEAMS` for the paths searched for `*.beam` files to include
-* `ESCRIPT_SYS_CONFIG` defaults to `rel/sys.config`
-* `ESCRIPT_EMU_ARGS` for the parameters used to start the VM
-* `ESCRIPT_SHEBANG` for the line used by your shell to start `escript`
-* `ESCRIPT_STATIC` for non-beam directories to be included as well
-
-Refer to http://www.erlang.org/doc/man/escript.html for
-more information on `escript` functionality in general.
-
-EUnit plugin
-------------
-
-This plugin is available by default. It adds the following
-target:
-
-`eunit` which runs all the EUnit tests found in `ebin` or
-the test directory specified in `TEST_DIR`.
-
-`EUNIT_OPTS` can be used to specify EUnit-specific options
-(e.g. `verbose`) that will be used when calling
-`eunit:test/2`. This configuration parameter is empty
-by default.. Note that EUnit options are specified as
-a comma-separated list of options.
-
-Relx plugin
------------
-
-This plugin is available by default.
-
-You can change the location of the `relx` executable
-(downloaded automatically) by defining the `RELX` variable,
-and the location of the configuration file by defining
-the `RELX_CONFIG` variable.
-
-The URL used to download `relx` can be overriden by setting
-the `RELX_URL` variable.
-
-You can change the generated releases location by setting
-the `RELX_OUTPUT_DIR` variable. Any other option should go
-in the `RELX_OPTS` variable.
-
-If `RELX_OPTS` includes the `-o` option (instead of using
-`RELX_OUTPUT_DIR`, then that option must be the first in
-the list, otherwise erlang.mk will fail to find it and
-will not be able to clean up the release directory.
-
-Shell plugin
-------------
-
-This plugin is available by default.
-
-`SHELL_DEPS` adds the specified modules only when `make shell`
-or `make build-shell-deps` is run. For example, to include a module
-reloader and TDD test runner, one might add `SHELL_DEPS = tddreloader`
-to the Makefile.
-
-You can add extra `erl` options by defining the `SHELL_OPTS` variable.
-For more information please see `erl -man erl`.
-
-`SHELL_PATH` adds paths to the shell's library search path. By default
-this option sets the paths to `-pa ../$(PROJECT)/ebin $(DEPS_DIR)/*/ebin`.
-
-Triq plugin
------------
-
-This plugin is available by default. It adds the following
-target:
-
-`triq` will check all the properties found in `ebin` or
-the test directory specified in `TEST_DIR`.
-
-You can use the `t` variable to give a specific module
-or function to run, for example:
-
-``` bash
-$ make triq t=cow_http_hd
-```
-
-Or:
-
-``` bash
-$ make triq t=cow_http_hd:prop_parse_accept
-```
-
-Xref plugin
-------------
-
-This plugin is available by default. It adds the following
-target:
-
-`xref` Erlang Xref Runner (inspired in rebar's rebar_xref)
-
-The `XREF_CONFIG` variable specifies the location of the
-configuration file which holds the checks to be applied.
-If there is no `xref.config` all `xref` checks will be
-applied to the binaries located in the `/ebin` directory.
-
-Contributing
-------------
-
-You can contribute by providing feedback, creating patches,
-adding packages to the index or new features as plugins.
-
-To add a package to the index, please use the `pkg_add.sh`
-script. To use it, first fork the repository, then please
-follow the example below:
-
-``` bash
-$ git clone https://github.com/$YOURUSERNAME/erlang.mk
-$ cd erlang.mk
-$ ./pkg_add.sh cowboy git https://github.com/ninenines/cowboy 1.0.0 http://ninenines.eu "Small, fast and modular HTTP server."
-$ git push origin master
-```
-
-Then open a pull request. The arguments given to the script
-are, in order, the project name, the download method used,
-the repository URL, the commit/tag/branch/version to pull,
-a link to the package's website and finally its description.
-Make sure to put double quotes around the description.
-
-You can submit as many packages as you want in one pull
-request as long as you follow the instructions above.
-
-For patches or plugins, you have to edit the `core/*.mk`
-or `plugins/*.mk` files. If you submit a new plugin, you also
-need to add it to the `build.config` file.
-
-Make sure to keep the commit title short, to have a single
-commit per package/feature/fix and you're good to submit
-a pull request! And again, please don't forget to run make
-and to commit the updated erlang.mk or index files along
-with your other changes. Thanks!
-
-Support
--------
-
- * Official IRC Channel: #ninenines on irc.freenode.net
- * [Mailing Lists](http://lists.ninenines.eu)
diff --git a/appveyor.yml b/appveyor.yml
index b82bcd3..3df8dff 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -3,5 +3,5 @@ build_script:
- C:\msys64\usr\bin\bash -lc "pacman --noconfirm -Sy"
- C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S gcc git make"
test_script:
-- C:\msys64\usr\bin\bash -lc "cd $APPVEYOR_BUILD_FOLDER && make -j 32 -k check"
-- C:\msys64\usr\bin\bash -lc "cd $APPVEYOR_BUILD_FOLDER && make -j 32 -k check LEGACY=1"
+- C:\msys64\usr\bin\bash -lc "cd $APPVEYOR_BUILD_FOLDER && make -j 8 -k check"
+- C:\msys64\usr\bin\bash -lc "cd $APPVEYOR_BUILD_FOLDER && make -j 8 -k check LEGACY=1"
diff --git a/build.config b/build.config
index 674035e..41c2f0f 100644
--- a/build.config
+++ b/build.config
@@ -10,6 +10,7 @@ core/index
core/deps
# Plugins that must run before Erlang code gets compiled.
+plugins/erlydtl
plugins/protobuffs
# Core modules, continued.
@@ -27,8 +28,6 @@ plugins/ci
plugins/ct
plugins/dialyzer
plugins/edoc
-plugins/elvis
-plugins/erlydtl
plugins/escript
plugins/eunit
plugins/relx
diff --git a/circle.yml b/circle.yml
index b1feef7..b651411 100644
--- a/circle.yml
+++ b/circle.yml
@@ -1,6 +1,7 @@
general:
- artifacts:
- - "test/pkgs.log"
+ branches:
+ ignore:
+ - gh-pages
dependencies:
cache_directories:
@@ -9,13 +10,13 @@ dependencies:
pre:
- sudo apt-get update
- - sudo apt-get install autoconf2.59 gcc
+ - sudo apt-get install autoconf2.59 gcc parallel
- cd $HOME/bin && ln -s /usr/bin/autoconf2.59 autoconf
- cd $HOME/bin && ln -s /usr/bin/autoheader2.59 autoheader
- - CI_OTP=OTP-18.0.2 make -f core/core.mk -f plugins/ci.mk ci-prepare:
+ - CI_OTP=OTP-18.2.1 make -f core/core.mk -f plugins/ci.mk ci-prepare:
timeout: 3600
test:
override:
- - source $HOME/erlang/OTP-18.0.2/activate && make -j 32 -k check
- - source $HOME/erlang/OTP-18.0.2/activate && make -j 32 -k check LEGACY=1
+ - source $HOME/erlang/OTP-18.2.1/activate && make -j 32 -k check
+ - source $HOME/erlang/OTP-18.2.1/activate && make -j 32 -k check LEGACY=1
diff --git a/core/compat.mk b/core/compat.mk
index f936768..eff4915 100644
--- a/core/compat.mk
+++ b/core/compat.mk
@@ -6,7 +6,7 @@
# We strip out -Werror because we don't want to fail due to
# warnings when used as a dependency.
-compat_prepare_erlc_opts = $(shell echo "$1" | sed 's/, */,/')
+compat_prepare_erlc_opts = $(shell echo "$1" | sed 's/, */,/g')
define compat_convert_erlc_opts
$(if $(filter-out -Werror,$1),\
@@ -14,11 +14,18 @@ $(if $(filter-out -Werror,$1),\
$(shell echo $1 | cut -b 2-)))
endef
+define compat_erlc_opts_to_list
+[$(call comma_list,$(foreach o,$(call compat_prepare_erlc_opts,$1),$(call compat_convert_erlc_opts,$o)))]
+endef
+
define compat_rebar_config
-{deps, [$(call comma_list,$(foreach d,$(DEPS),\
- {$(call dep_name,$d),".*",{git,"$(call dep_repo,$d)","$(call dep_commit,$d)"}}))]}.
-{erl_opts, [$(call comma_list,$(foreach o,$(call compat_prepare_erlc_opts,$(ERLC_OPTS)),\
- $(call compat_convert_erlc_opts,$o)))]}.
+{deps, [
+$(call comma_list,$(foreach d,$(DEPS),\
+ $(if $(filter hex,$(call dep_fetch,$d)),\
+ {$(call dep_name,$d)$(comma)"$(call dep_repo,$d)"},\
+ {$(call dep_name,$d)$(comma)".*"$(comma){git,"$(call dep_repo,$d)"$(comma)"$(call dep_commit,$d)"}})))
+]}.
+{erl_opts, $(call compat_erlc_opts_to_list,$(ERLC_OPTS))}.
endef
$(eval _compat_rebar_config = $$(compat_rebar_config))
diff --git a/core/core.mk b/core/core.mk
index 407b940..5733496 100644
--- a/core/core.mk
+++ b/core/core.mk
@@ -30,9 +30,11 @@ PROJECT_VERSION ?= rolling
V ?= 0
verbose_0 = @
+verbose_2 = set -x;
verbose = $(verbose_$(V))
gen_verbose_0 = @echo " GEN " $@;
+gen_verbose_2 = set -x;
gen_verbose = $(gen_verbose_$(V))
# Temporary files directory.
@@ -76,15 +78,13 @@ endif
# Core targets.
-.NOTPARALLEL:
-
all:: deps app rel
# Noop to avoid a Make warning when there's nothing to do.
rel::
- $(verbose) echo -n
+ $(verbose) :
-check:: clean app tests
+check:: tests
clean:: clean-crashdump
@@ -192,8 +192,11 @@ ERLANG_MK_BUILD_DIR ?= .erlang.mk.build
erlang-mk:
git clone $(ERLANG_MK_REPO) $(ERLANG_MK_BUILD_DIR)
+ifdef ERLANG_MK_COMMIT
+ cd $(ERLANG_MK_BUILD_DIR) && git checkout $(ERLANG_MK_COMMIT)
+endif
if [ -f $(ERLANG_MK_BUILD_CONFIG) ]; then cp $(ERLANG_MK_BUILD_CONFIG) $(ERLANG_MK_BUILD_DIR)/build.config; fi
- cd $(ERLANG_MK_BUILD_DIR) && $(if $(ERLANG_MK_COMMIT),git checkout $(ERLANG_MK_COMMIT) &&) $(MAKE)
+ $(MAKE) -C $(ERLANG_MK_BUILD_DIR)
cp $(ERLANG_MK_BUILD_DIR)/erlang.mk ./erlang.mk
rm -rf $(ERLANG_MK_BUILD_DIR)
diff --git a/core/deps.mk b/core/deps.mk
index 76f54d7..16a2f88 100644
--- a/core/deps.mk
+++ b/core/deps.mk
@@ -43,6 +43,7 @@ export NO_AUTOPATCH
# Verbosity.
dep_verbose_0 = @echo " DEP " $(1);
+dep_verbose_2 = set -x;
dep_verbose = $(dep_verbose_$(V))
# Core targets.
@@ -62,7 +63,7 @@ endif
$(verbose) mkdir -p $(ERLANG_MK_TMP)
$(verbose) for dep in $(ALL_DEPS_DIRS) ; do \
if grep -qs ^$$dep$$ $(ERLANG_MK_TMP)/deps.log; then \
- echo -n; \
+ :; \
else \
echo $$dep >> $(ERLANG_MK_TMP)/deps.log; \
if [ -f $$dep/GNUmakefile ] || [ -f $$dep/makefile ] || [ -f $$dep/Makefile ]; then \
@@ -81,7 +82,10 @@ endif
# While Makefile file could be GNUmakefile or makefile,
# in practice only Makefile is needed so far.
define dep_autopatch
- if [ -f $(DEPS_DIR)/$(1)/Makefile ]; then \
+ if [ -f $(DEPS_DIR)/$(1)/erlang.mk ]; then \
+ $(call erlang,$(call dep_autopatch_appsrc.erl,$(1))); \
+ $(call dep_autopatch_erlang_mk,$(1)); \
+ elif [ -f $(DEPS_DIR)/$(1)/Makefile ]; then \
if [ 0 != `grep -c "include ../\w*\.mk" $(DEPS_DIR)/$(1)/Makefile` ]; then \
$(call dep_autopatch2,$(1)); \
elif [ 0 != `grep -ci rebar $(DEPS_DIR)/$(1)/Makefile` ]; then \
@@ -89,12 +93,7 @@ define dep_autopatch
elif [ -n "`find $(DEPS_DIR)/$(1)/ -type f -name \*.mk -not -name erlang.mk -exec grep -i rebar '{}' \;`" ]; then \
$(call dep_autopatch2,$(1)); \
else \
- if [ -f $(DEPS_DIR)/$(1)/erlang.mk ]; then \
- $(call erlang,$(call dep_autopatch_appsrc.erl,$(1))); \
- $(call dep_autopatch_erlang_mk,$(1)); \
- else \
- $(call erlang,$(call dep_autopatch_app.erl,$(1))); \
- fi \
+ $(call erlang,$(call dep_autopatch_app.erl,$(1))); \
fi \
else \
if [ ! -d $(DEPS_DIR)/$(1)/src/ ]; then \
@@ -106,8 +105,11 @@ define dep_autopatch
endef
define dep_autopatch2
+ if [ -f $(DEPS_DIR)/$1/src/$1.app.src.script ]; then \
+ $(call erlang,$(call dep_autopatch_appsrc_script.erl,$(1))); \
+ fi; \
$(call erlang,$(call dep_autopatch_appsrc.erl,$(1))); \
- if [ -f $(DEPS_DIR)/$(1)/rebar.config -o -f $(DEPS_DIR)/$(1)/rebar.config.script ]; then \
+ if [ -f $(DEPS_DIR)/$(1)/rebar -o -f $(DEPS_DIR)/$(1)/rebar.config -o -f $(DEPS_DIR)/$(1)/rebar.config.script ]; then \
$(call dep_autopatch_fetch_rebar); \
$(call dep_autopatch_rebar,$(1)); \
else \
@@ -127,7 +129,7 @@ define dep_autopatch_erlang_mk
endef
else
define dep_autopatch_erlang_mk
- echo -n
+ :
endef
endif
@@ -179,7 +181,7 @@ define dep_autopatch_rebar.erl
file:write_file("$(call core_native_path,$(DEPS_DIR)/$1/Makefile)", Text, [append])
end,
Escape = fun (Text) ->
- re:replace(Text, "\\\\$$$$", "\$$$$$$$$", [global, {return, list}])
+ re:replace(Text, "\\\\$$", "\$$$$", [global, {return, list}])
end,
Write("IGNORE_DEPS += edown eper eunit_formatters meck node_package "
"rebar_lock_deps_plugin rebar_vsn_plugin reltool_util\n"),
@@ -245,67 +247,16 @@ define dep_autopatch_rebar.erl
Write(io_lib:format("COMPILE_FIRST +=~s\n", [Names]))
end
end(),
- FindFirst = fun(F, Fd) ->
- case io:parse_erl_form(Fd, undefined) of
- {ok, {attribute, _, compile, {parse_transform, PT}}, _} ->
- [PT, F(F, Fd)];
- {ok, {attribute, _, compile, CompileOpts}, _} when is_list(CompileOpts) ->
- case proplists:get_value(parse_transform, CompileOpts) of
- undefined -> [F(F, Fd)];
- PT -> [PT, F(F, Fd)]
- end;
- {ok, {attribute, _, include, Hrl}, _} ->
- case file:open("$(call core_native_path,$(DEPS_DIR)/$1/include/)" ++ Hrl, [read]) of
- {ok, HrlFd} -> [F(F, HrlFd), F(F, Fd)];
- _ ->
- case file:open("$(call core_native_path,$(DEPS_DIR)/$1/src/)" ++ Hrl, [read]) of
- {ok, HrlFd} -> [F(F, HrlFd), F(F, Fd)];
- _ -> [F(F, Fd)]
- end
- end;
- {ok, {attribute, _, include_lib, "$(1)/include/" ++ Hrl}, _} ->
- {ok, HrlFd} = file:open("$(call core_native_path,$(DEPS_DIR)/$1/include/)" ++ Hrl, [read]),
- [F(F, HrlFd), F(F, Fd)];
- {ok, {attribute, _, include_lib, Hrl}, _} ->
- case file:open("$(call core_native_path,$(DEPS_DIR)/$1/include/)" ++ Hrl, [read]) of
- {ok, HrlFd} -> [F(F, HrlFd), F(F, Fd)];
- _ -> [F(F, Fd)]
- end;
- {ok, {attribute, _, import, {Imp, _}}, _} ->
- case file:open("$(call core_native_path,$(DEPS_DIR)/$1/src/)" ++ atom_to_list(Imp) ++ ".erl", [read]) of
- {ok, ImpFd} -> [Imp, F(F, ImpFd), F(F, Fd)];
- _ -> [F(F, Fd)]
- end;
- {eof, _} ->
- file:close(Fd),
- [];
- _ ->
- F(F, Fd)
- end
- end,
- fun() ->
- ErlFiles = filelib:wildcard("$(call core_native_path,$(DEPS_DIR)/$1/src/)*.erl"),
- First0 = lists:usort(lists:flatten([begin
- {ok, Fd} = file:open(F, [read]),
- FindFirst(FindFirst, Fd)
- end || F <- ErlFiles])),
- First = lists:flatten([begin
- {ok, Fd} = file:open("$(call core_native_path,$(DEPS_DIR)/$1/src/)" ++ atom_to_list(M) ++ ".erl", [read]),
- FindFirst(FindFirst, Fd)
- end || M <- First0, lists:member("$(call core_native_path,$(DEPS_DIR)/$1/src/)" ++ atom_to_list(M) ++ ".erl", ErlFiles)]) ++ First0,
- Write(["COMPILE_FIRST +=", [[" ", atom_to_list(M)] || M <- First,
- lists:member("$(call core_native_path,$(DEPS_DIR)/$1/src/)" ++ atom_to_list(M) ++ ".erl", ErlFiles)], "\n"])
- end(),
Write("\n\nrebar_dep: preprocess pre-deps deps pre-app app\n"),
Write("\npreprocess::\n"),
Write("\npre-deps::\n"),
Write("\npre-app::\n"),
PatchHook = fun(Cmd) ->
case Cmd of
- "make -C" ++ Cmd1 -> "$$$$\(MAKE) -C" ++ Escape(Cmd1);
- "gmake -C" ++ Cmd1 -> "$$$$\(MAKE) -C" ++ Escape(Cmd1);
- "make " ++ Cmd1 -> "$$$$\(MAKE) -f Makefile.orig.mk " ++ Escape(Cmd1);
- "gmake " ++ Cmd1 -> "$$$$\(MAKE) -f Makefile.orig.mk " ++ Escape(Cmd1);
+ "make -C" ++ Cmd1 -> "$$\(MAKE) -C" ++ Escape(Cmd1);
+ "gmake -C" ++ Cmd1 -> "$$\(MAKE) -C" ++ Escape(Cmd1);
+ "make " ++ Cmd1 -> "$$\(MAKE) -f Makefile.orig.mk " ++ Escape(Cmd1);
+ "gmake " ++ Cmd1 -> "$$\(MAKE) -f Makefile.orig.mk " ++ Escape(Cmd1);
_ -> Escape(Cmd)
end
end,
@@ -317,10 +268,10 @@ define dep_autopatch_rebar.erl
{'get-deps', Cmd} ->
Write("\npre-deps::\n\t" ++ PatchHook(Cmd) ++ "\n");
{compile, Cmd} ->
- Write("\npre-app::\n\tCC=$$$$\(CC) " ++ PatchHook(Cmd) ++ "\n");
+ Write("\npre-app::\n\tCC=$$\(CC) " ++ PatchHook(Cmd) ++ "\n");
{Regex, compile, Cmd} ->
case rebar_utils:is_arch(Regex) of
- true -> Write("\npre-app::\n\tCC=$$$$\(CC) " ++ PatchHook(Cmd) ++ "\n");
+ true -> Write("\npre-app::\n\tCC=$$\(CC) " ++ PatchHook(Cmd) ++ "\n");
false -> ok
end;
_ -> ok
@@ -328,7 +279,7 @@ define dep_autopatch_rebar.erl
end
end(),
ShellToMk = fun(V) ->
- re:replace(re:replace(V, "(\\\\$$$$)(\\\\w*)", "\\\\1(\\\\2)", [global]),
+ re:replace(re:replace(V, "(\\\\$$)(\\\\w*)", "\\\\1(\\\\2)", [global]),
"-Werror\\\\b", "", [{return, list}, global])
end,
PortSpecs = fun() ->
@@ -362,10 +313,10 @@ define dep_autopatch_rebar.erl
case PortSpecs of
[] -> ok;
_ ->
- Write("\npre-app::\n\t$$$$\(MAKE) -f c_src/Makefile.erlang.mk\n"),
- PortSpecWrite(io_lib:format("ERL_CFLAGS = -finline-functions -Wall -fPIC -I ~s/erts-~s/include -I ~s\n",
+ Write("\npre-app::\n\t$$\(MAKE) -f c_src/Makefile.erlang.mk\n"),
+ PortSpecWrite(io_lib:format("ERL_CFLAGS = -finline-functions -Wall -fPIC -I \\"~s/erts-~s/include\\" -I \\"~s\\"\n",
[code:root_dir(), erlang:system_info(version), code:lib_dir(erl_interface, include)])),
- PortSpecWrite(io_lib:format("ERL_LDFLAGS = -L ~s -lerl_interface -lei\n",
+ PortSpecWrite(io_lib:format("ERL_LDFLAGS = -L \\"~s\\" -lerl_interface -lei\n",
[code:lib_dir(erl_interface, lib)])),
[PortSpecWrite(["\n", E, "\n"]) || E <- OsEnv],
FilterEnv = fun(Env) ->
@@ -400,17 +351,18 @@ define dep_autopatch_rebar.erl
_ -> ""
end,
"\n\nall:: ", Output, "\n\n",
- "%.o: %.c\n\t$$$$\(CC) -c -o $$$$\@ $$$$\< $$$$\(CFLAGS) $$$$\(ERL_CFLAGS) $$$$\(DRV_CFLAGS) $$$$\(EXE_CFLAGS)\n\n",
- "%.o: %.C\n\t$$$$\(CXX) -c -o $$$$\@ $$$$\< $$$$\(CXXFLAGS) $$$$\(ERL_CFLAGS) $$$$\(DRV_CFLAGS) $$$$\(EXE_CFLAGS)\n\n",
- "%.o: %.cc\n\t$$$$\(CXX) -c -o $$$$\@ $$$$\< $$$$\(CXXFLAGS) $$$$\(ERL_CFLAGS) $$$$\(DRV_CFLAGS) $$$$\(EXE_CFLAGS)\n\n",
- "%.o: %.cpp\n\t$$$$\(CXX) -c -o $$$$\@ $$$$\< $$$$\(CXXFLAGS) $$$$\(ERL_CFLAGS) $$$$\(DRV_CFLAGS) $$$$\(EXE_CFLAGS)\n\n",
+ "%.o: %.c\n\t$$\(CC) -c -o $$\@ $$\< $$\(CFLAGS) $$\(ERL_CFLAGS) $$\(DRV_CFLAGS) $$\(EXE_CFLAGS)\n\n",
+ "%.o: %.C\n\t$$\(CXX) -c -o $$\@ $$\< $$\(CXXFLAGS) $$\(ERL_CFLAGS) $$\(DRV_CFLAGS) $$\(EXE_CFLAGS)\n\n",
+ "%.o: %.cc\n\t$$\(CXX) -c -o $$\@ $$\< $$\(CXXFLAGS) $$\(ERL_CFLAGS) $$\(DRV_CFLAGS) $$\(EXE_CFLAGS)\n\n",
+ "%.o: %.cpp\n\t$$\(CXX) -c -o $$\@ $$\< $$\(CXXFLAGS) $$\(ERL_CFLAGS) $$\(DRV_CFLAGS) $$\(EXE_CFLAGS)\n\n",
[[Output, ": ", K, " = ", ShellToMk(V), "\n"] || {K, V} <- lists:reverse(MergeEnv(FilterEnv(Env)))],
- Output, ": $$$$\(foreach ext,.c .C .cc .cpp,",
- "$$$$\(patsubst %$$$$\(ext),%.o,$$$$\(filter %$$$$\(ext),$$$$\(wildcard", Input, "))))\n",
- "\t$$$$\(CC) -o $$$$\@ $$$$\? $$$$\(LDFLAGS) $$$$\(ERL_LDFLAGS) $$$$\(DRV_LDFLAGS) $$$$\(EXE_LDFLAGS)",
- case filename:extension(Output) of
- [] -> "\n";
- _ -> " -shared\n"
+ Output, ": $$\(foreach ext,.c .C .cc .cpp,",
+ "$$\(patsubst %$$\(ext),%.o,$$\(filter %$$\(ext),$$\(wildcard", Input, "))))\n",
+ "\t$$\(CC) -o $$\@ $$\? $$\(LDFLAGS) $$\(ERL_LDFLAGS) $$\(DRV_LDFLAGS) $$\(EXE_LDFLAGS)",
+ case {filename:extension(Output), $(PLATFORM)} of
+ {[], _} -> "\n";
+ {_, darwin} -> "\n";
+ _ -> " -shared\n"
end])
end,
[PortSpec(S) || S <- PortSpecs]
@@ -469,7 +421,7 @@ define dep_autopatch_app.erl
false -> ok;
true ->
{ok, [{application, '$(1)', L0}]} = file:consult(App),
- Mods = filelib:fold_files("$(call core_native_path,$(DEPS_DIR)/$1/src)", "\\\\.erl$$$$", true,
+ Mods = filelib:fold_files("$(call core_native_path,$(DEPS_DIR)/$1/src)", "\\\\.erl$$", true,
fun (F, Acc) -> [list_to_atom(filename:rootname(filename:basename(F)))|Acc] end, []),
L = lists:keystore(modules, 1, L0, {modules, Mods}),
ok = file:write_file(App, io_lib:format("~p.~n", [{application, '$(1)', L}]))
@@ -479,6 +431,15 @@ define dep_autopatch_app.erl
halt()
endef
+define dep_autopatch_appsrc_script.erl
+ AppSrc = "$(call core_native_path,$(DEPS_DIR)/$1/src/$1.app.src)",
+ AppSrcScript = AppSrc ++ ".script",
+ Bindings = erl_eval:new_bindings(),
+ {ok, Conf} = file:script(AppSrcScript, Bindings),
+ ok = file:write_file(AppSrc, io_lib:format("~p.~n", [Conf])),
+ halt()
+endef
+
define dep_autopatch_appsrc.erl
AppSrcOut = "$(call core_native_path,$(DEPS_DIR)/$1/src/$1.app.src)",
AppSrcIn = case filelib:is_regular(AppSrcOut) of false -> "$(call core_native_path,$(DEPS_DIR)/$1/ebin/$1.app)"; true -> AppSrcOut end,
@@ -565,10 +526,11 @@ $(DEPS_DIR)/$(call dep_name,$1):
exit 17; \
fi
$(verbose) mkdir -p $(DEPS_DIR)
- $(dep_verbose) $(call dep_fetch_$(strip $(call dep_fetch,$1)),$1)
- $(verbose) if [ -f $(DEPS_DIR)/$(DEP_NAME)/configure.ac -o -f $(DEPS_DIR)/$(DEP_NAME)/configure.in ]; then \
- echo " AUTO " $(DEP_STR); \
- cd $(DEPS_DIR)/$(DEP_NAME) && autoreconf -Wall -vif -I m4; \
+ $(dep_verbose) $(call dep_fetch_$(strip $(call dep_fetch,$(1))),$(1))
+ $(verbose) if [ -f $(DEPS_DIR)/$(1)/configure.ac -o -f $(DEPS_DIR)/$(1)/configure.in ] \
+ && [ ! -f $(DEPS_DIR)/$(1)/configure ]; then \
+ echo " AUTO " $(1); \
+ cd $(DEPS_DIR)/$(1) && autoreconf -Wall -vif -I m4; \
fi
- $(verbose) if [ -f $(DEPS_DIR)/$(DEP_NAME)/configure ]; then \
echo " CONF " $(DEP_STR); \
@@ -591,7 +553,7 @@ ifeq ($(filter $(1),$(NO_AUTOPATCH)),)
git clone https://github.com/rabbitmq/rabbitmq-codegen.git $(DEPS_DIR)/rabbitmq-codegen; \
fi \
else \
- $(call dep_autopatch,$(DEP_NAME)) \
+ $$(call dep_autopatch,$(DEP_NAME)) \
fi
endif
endef
diff --git a/core/erlc.mk b/core/erlc.mk
index 02524b4..695cc83 100644
--- a/core/erlc.mk
+++ b/core/erlc.mk
@@ -19,25 +19,32 @@ COMPILE_MIB_FIRST_PATHS = $(addprefix mibs/,$(addsuffix .mib,$(COMPILE_MIB_FIRST
# Verbosity.
app_verbose_0 = @echo " APP " $(PROJECT);
+app_verbose_2 = set -x;
app_verbose = $(app_verbose_$(V))
appsrc_verbose_0 = @echo " APP " $(PROJECT).app.src;
+appsrc_verbose_2 = set -x;
appsrc_verbose = $(appsrc_verbose_$(V))
makedep_verbose_0 = @echo " DEPEND" $(PROJECT).d;
+makedep_verbose_2 = set -x;
makedep_verbose = $(makedep_verbose_$(V))
erlc_verbose_0 = @echo " ERLC " $(filter-out $(patsubst %,%.erl,$(ERLC_EXCLUDE)),\
$(filter %.erl %.core,$(?F)));
+erlc_verbose_2 = set -x;
erlc_verbose = $(erlc_verbose_$(V))
xyrl_verbose_0 = @echo " XYRL " $(filter %.xrl %.yrl,$(?F));
+xyrl_verbose_2 = set -x;
xyrl_verbose = $(xyrl_verbose_$(V))
asn1_verbose_0 = @echo " ASN1 " $(filter %.asn1,$(?F));
+asn1_verbose_2 = set -x;
asn1_verbose = $(asn1_verbose_$(V))
mib_verbose_0 = @echo " MIB " $(filter %.bin %.mib,$(?F));
+mib_verbose_2 = set -x;
mib_verbose = $(mib_verbose_$(V))
ifneq ($(wildcard src/),)
@@ -45,10 +52,10 @@ ifneq ($(wildcard src/),)
# Targets.
ifeq ($(wildcard ebin/test),)
-app:: $(PROJECT).d
+app:: deps $(PROJECT).d
$(verbose) $(MAKE) --no-print-directory app-build
else
-app:: clean $(PROJECT).d
+app:: clean deps $(PROJECT).d
$(verbose) $(MAKE) --no-print-directory app-build
endif
@@ -78,7 +85,7 @@ endef
endif
app-build: ebin/$(PROJECT).app
- $(verbose) echo -n
+ $(verbose) :
# Source files.
@@ -130,51 +137,79 @@ $(PROJECT).d:: $(XRL_FILES) $(YRL_FILES)
# Erlang and Core Erlang files.
define makedep.erl
+ E = ets:new(makedep, [bag]),
+ G = digraph:new([acyclic]),
ErlFiles = lists:usort(string:tokens("$(ERL_FILES)", " ")),
- Modules = [{filename:basename(F, ".erl"), F} || F <- ErlFiles],
- Add = fun (Dep, Acc) ->
- case lists:keyfind(atom_to_list(Dep), 1, Modules) of
- {_, DepFile} -> [DepFile|Acc];
- false -> Acc
+ Modules = [{list_to_atom(filename:basename(F, ".erl")), F} || F <- ErlFiles],
+ Add = fun (Mod, Dep) ->
+ case lists:keyfind(Dep, 1, Modules) of
+ false -> ok;
+ {_, DepFile} ->
+ {_, ModFile} = lists:keyfind(Mod, 1, Modules),
+ ets:insert(E, {ModFile, DepFile}),
+ digraph:add_vertex(G, Mod),
+ digraph:add_vertex(G, Dep),
+ digraph:add_edge(G, Mod, Dep)
end
end,
- AddHd = fun (Dep, Acc) ->
- case {Dep, lists:keymember(Dep, 2, Modules)} of
- {"src/" ++ _, false} -> [Dep|Acc];
- {"include/" ++ _, false} -> [Dep|Acc];
- _ -> Acc
+ AddHd = fun (F, Mod, DepFile) ->
+ case file:open(DepFile, [read]) of
+ {error, enoent} -> ok;
+ {ok, Fd} ->
+ F(F, Fd, Mod),
+ {_, ModFile} = lists:keyfind(Mod, 1, Modules),
+ ets:insert(E, {ModFile, DepFile})
end
end,
- CompileFirst = fun (Deps) ->
- First0 = [case filename:extension(D) of
- ".erl" -> filename:basename(D, ".erl");
- _ -> []
- end || D <- Deps],
- case lists:usort(First0) of
- [] -> [];
- [[]] -> [];
- First -> ["COMPILE_FIRST +=", [[" ", F] || F <- First], "\n"]
- end
+ Attr = fun
+ (F, Mod, behavior, Dep) -> Add(Mod, Dep);
+ (F, Mod, behaviour, Dep) -> Add(Mod, Dep);
+ (F, Mod, compile, {parse_transform, Dep}) -> Add(Mod, Dep);
+ (F, Mod, compile, Opts) when is_list(Opts) ->
+ case proplists:get_value(parse_transform, Opts) of
+ undefined -> ok;
+ Dep -> Add(Mod, Dep)
+ end;
+ (F, Mod, include, Hrl) ->
+ case filelib:is_file("include/" ++ Hrl) of
+ true -> AddHd(F, Mod, "include/" ++ Hrl);
+ false ->
+ case filelib:is_file("src/" ++ Hrl) of
+ true -> AddHd(F, Mod, "src/" ++ Hrl);
+ false -> false
+ end
+ end;
+ (F, Mod, include_lib, "$1/include/" ++ Hrl) -> AddHd(F, Mod, "include/" ++ Hrl);
+ (F, Mod, include_lib, Hrl) -> AddHd(F, Mod, "include/" ++ Hrl);
+ (F, Mod, import, {Imp, _}) ->
+ case filelib:is_file("src/" ++ atom_to_list(Imp) ++ ".erl") of
+ false -> ok;
+ true -> Add(Mod, Imp)
+ end;
+ (_, _, _, _) -> ok
end,
- Depend = [begin
- case epp:parse_file(F, ["include/"], []) of
- {ok, Forms} ->
- Deps = lists:usort(lists:foldl(fun
- ({attribute, _, behavior, Dep}, Acc) -> Add(Dep, Acc);
- ({attribute, _, behaviour, Dep}, Acc) -> Add(Dep, Acc);
- ({attribute, _, compile, {parse_transform, Dep}}, Acc) -> Add(Dep, Acc);
- ({attribute, _, file, {Dep, _}}, Acc) -> AddHd(Dep, Acc);
- (_, Acc) -> Acc
- end, [], Forms)),
- case Deps of
- [] -> "";
- _ -> [F, "::", [[" ", D] || D <- Deps], "; @touch \$$@\n", CompileFirst(Deps)]
- end;
- {error, enoent} ->
- []
+ MakeDepend = fun(F, Fd, Mod) ->
+ case io:parse_erl_form(Fd, undefined) of
+ {ok, {attribute, _, Key, Value}, _} ->
+ Attr(F, Mod, Key, Value),
+ F(F, Fd, Mod);
+ {eof, _} ->
+ file:close(Fd);
+ _ ->
+ F(F, Fd, Mod)
end
+ end,
+ [begin
+ Mod = list_to_atom(filename:basename(F, ".erl")),
+ {ok, Fd} = file:open(F, [read]),
+ MakeDepend(MakeDepend, Fd, Mod)
end || F <- ErlFiles],
- ok = file:write_file("$(1)", Depend),
+ Depend = sofs:to_external(sofs:relation_to_family(sofs:relation(ets:tab2list(E)))),
+ CompileFirst = [X || X <- lists:reverse(digraph_utils:topsort(G)), [] =/= digraph:in_neighbours(G, X)],
+ ok = file:write_file("$(1)", [
+ [[F, "::", [[" ", D] || D <- Deps], "; @touch \$$@\n"] || {F, Deps} <- Depend],
+ "\nCOMPILE_FIRST +=", [[" ", atom_to_list(CF)] || CF <- CompileFirst], "\n"
+ ]),
halt()
endef
@@ -209,13 +244,13 @@ ifeq ($(wildcard src/$(PROJECT).app.src),)
$(app_verbose) printf "$(subst $(newline),\n,$(subst ",\",$(call app_file,$(GITDESCRIBE),$(MODULES))))" \
> ebin/$(PROJECT).app
else
- $(verbose) if [ -z "$$(grep -E '^[^%]*{\s*modules\s*,' src/$(PROJECT).app.src)" ]; then \
+ $(verbose) if [ -z "$$(grep -e '^[^%]*{\s*modules\s*,' src/$(PROJECT).app.src)" ]; then \
echo "Empty modules entry not found in $(PROJECT).app.src. Please consult the erlang.mk README for instructions." >&2; \
exit 1; \
fi
$(appsrc_verbose) cat src/$(PROJECT).app.src \
| sed "s/{[[:space:]]*modules[[:space:]]*,[[:space:]]*\[\]}/{modules, \[$(call comma_list,$(MODULES))\]}/" \
- | sed "s/{id,[[:space:]]*\"git\"}/{id, \"$(GITDESCRIBE)\"}/" \
+ | sed "s/{id,[[:space:]]*\"git\"}/{id, \"$(subst /,\/,$(GITDESCRIBE))\"}/" \
> ebin/$(PROJECT).app
endif
diff --git a/core/test.mk b/core/test.mk
index d7b0bfe..12ff208 100644
--- a/core/test.mk
+++ b/core/test.mk
@@ -29,6 +29,11 @@ test-dir:
$(call core_find,$(TEST_DIR)/,*.erl) -pa ebin/
endif
+ifeq ($(wildcard src),)
+test-build:: ERLC_OPTS=$(TEST_ERLC_OPTS)
+test-build:: clean deps test-deps
+ $(verbose) $(MAKE) --no-print-directory test-dir ERLC_OPTS="$(TEST_ERLC_OPTS)"
+else
ifeq ($(wildcard ebin/test),)
test-build:: ERLC_OPTS=$(TEST_ERLC_OPTS)
test-build:: clean deps test-deps $(PROJECT).d
@@ -46,3 +51,4 @@ clean-test-dir:
ifneq ($(wildcard $(TEST_DIR)/*.beam),)
$(gen_verbose) rm -f $(TEST_DIR)/*.beam
endif
+endif
diff --git a/doc/src/guide/app.asciidoc b/doc/src/guide/app.asciidoc
index 1320577..99ff052 100644
--- a/doc/src/guide/app.asciidoc
+++ b/doc/src/guide/app.asciidoc
@@ -1,3 +1,4 @@
+[[building]]
== Building
Erlang.mk can do a lot of things, but it is, first and
@@ -5,7 +6,7 @@ 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].
+using a project xref:getting_started[generated by Erlang.mk].
=== How to build
@@ -46,13 +47,18 @@ up generating releases.
==== Application
-You can build your application specifically, without
-looking at handling dependencies or generating a release,
-by running the following command:
+You can build your application and dependencies without
+generating a release by running the following command:
[source,bash]
$ make app
+To build your application without touching dependencies
+at all, you can use the `SKIP_DEPS` variable:
+
+[source,bash]
+$ make app SKIP_DEPS=1
+
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.
@@ -71,27 +77,26 @@ $ make deps
This will fetch and compile all dependencies and their
dependencies, recursively.
-link:deps.asciidoc[Packages and dependencies] are covered
+xref:deps[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:
+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, `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:
[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
+Consult the xref:relx[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
@@ -147,7 +152,7 @@ DEPS = cowlib ranch
Any space before and after the value is dropped.
-link:deps.asciidoc[Dependencies] are covered in details in
+xref:deps[Dependencies] are covered in details in
the next chapter.
==== Legacy method
@@ -220,7 +225,7 @@ 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]
+C code, as described in the xref:ports[NIFs and port drivers]
chapter.
Erlang.mk also comes with plugins for the following formats:
diff --git a/doc/src/guide/architecture.asciidoc b/doc/src/guide/architecture.asciidoc
deleted file mode 100644
index f96606b..0000000
--- a/doc/src/guide/architecture.asciidoc
+++ /dev/null
@@ -1,5 +0,0 @@
-== Architecture
-
-// @todo Write it.
-
-Placeholder chapter.
diff --git a/doc/src/guide/asciidoc.asciidoc b/doc/src/guide/asciidoc.asciidoc
index 6ba43ec..cc8336b 100644
--- a/doc/src/guide/asciidoc.asciidoc
+++ b/doc/src/guide/asciidoc.asciidoc
@@ -1,5 +1,82 @@
-== Asciidoc documentation
+[[asciidoc]]
+== AsciiDoc documentation
-// @todo Write it.
+Erlang.mk provides rules for generating documentation from
+AsciiDoc files. It can automatically build a user guide PDF,
+chunked HTML documentation and Unix manual pages.
-Placeholder chapter.
+=== Requirements
+
+It is necessary to have http://asciidoc.org/[AsciiDoc],
+http://xmlsoft.org/XSLT/xsltproc2.html[xsltproc] and
+http://dblatex.sourceforge.net/[dblatex] installed on your
+system for Erlang.mk to generate documentation from AsciiDoc sources.
+
+=== Writing AsciiDoc documentation
+
+http://asciidoc.org/[AsciiDoc] is a text document format for
+writing notes, documentation, articles, books, ebooks, slideshows,
+web pages, man pages and blogs. AsciiDoc files can be translated
+to many formats including HTML, PDF, EPUB, man page.
+
+The http://asciidoc.org/userguide.html[AsciiDoc user guide]
+describes the AsciiDoc syntax.
+
+The https://github.com/ninenines/erlang.mk/tree/master/doc/src/guide[Erlang.mk user guide]
+is written in AsciiDoc and can be used as an example. The entry
+file is https://github.com/ninenines/erlang.mk/blob/master/doc/src/guide/book.asciidoc[book.asciidoc].
+
+Erlang.mk expects you to put your documentation in a specific
+location. This is 'doc/src/guide/' for the user guide, and
+'doc/src/manual/' for the function reference. In the case of
+the user guide, the entry point is always 'doc/src/guide/book.asciidoc'.
+
+For manual pages, it is good practice to use section 3 for
+modules, and section 7 for the application itself.
+
+=== Configuration
+
+All of the AsciiDoc related configuration can be done directly
+inside the files themselves.
+
+=== Usage
+
+To build all documentation:
+
+[source,bash]
+$ make docs
+
+To build only the AsciiDoc documentation:
+
+[source,bash]
+$ make asciidoc
+
+To build only the user guide:
+
+[source,bash]
+$ make asciidoc-guide
+
+To build only the manual:
+
+[source,bash]
+$ make asciidoc-manual
+
+To install man pages on Unix:
+
+[source,bash]
+$ make install-docs
+
+Erlang.mk allows customizing the installation path and sections
+of the man pages to be installed. The `MAN_INSTALL_PATH` variable
+defines where man pages will be installed. It defaults to
+'/usr/local/share/man'. The `MAN_SECTIONS` variable defines
+which manual sections are to be installed. It defaults to `3 7`.
+
+To install man pages to a custom location:
+
+[source,bash]
+$ make install-docs MAN_INSTALL_PATH=/opt/share/man
+
+Note that you may need to run the install commands using
+`sudo` or equivalent if the location is not writeable by
+your user.
diff --git a/doc/src/guide/book.asciidoc b/doc/src/guide/book.asciidoc
index f084e6f..a39b907 100644
--- a/doc/src/guide/book.asciidoc
+++ b/doc/src/guide/book.asciidoc
@@ -1,4 +1,5 @@
// a2x: --dblatex-opts "-P latex.output.revhistory=0 -P doc.publisher.show=0 -P index.numbered=0"
+// a2x: --xsltproc-opts "--stringparam use.id.as.filename 1"
// a2x: -d book --attribute tabsize=4
= Erlang.mk User Guide
@@ -14,6 +15,7 @@ include::updating.asciidoc[Updating Erlang.mk]
include::limitations.asciidoc[Limitations]
+[[code]]
= Code
include::app.asciidoc[Building]
@@ -28,12 +30,14 @@ include::escripts.asciidoc[Escripts]
include::compat.asciidoc[Compatibility with other build tools]
+[[docs]]
= Documentation
include::asciidoc.asciidoc[Asciidoc documentation]
include::edoc.asciidoc[EDoc comments]
+[[tests]]
= Tests
include::shell.asciidoc[Erlang shell]
@@ -42,8 +46,6 @@ include::eunit.asciidoc[EUnit]
include::common_test.asciidoc[Common Test]
-include::property_based_testing.asciidoc[Property based testing]
-
include::coverage.asciidoc[Code coverage]
include::ci.asciidoc[Continuous integration]
@@ -52,16 +54,18 @@ include::dialyzer.asciidoc[Dialyzer]
include::xref.asciidoc[Xref]
+[[plugins]]
= Third-party plugins
include::external_plugins.asciidoc[External plugins]
+include::external_plugins_list.asciidoc[List of plugins]
+
+[[about]]
= About Erlang.mk
include::why.asciidoc[Why erlang.mk?]
include::history.asciidoc[Short history]
-include::architecture.asciidoc[Architecture]
-
include::contributing.asciidoc[Contributing]
diff --git a/doc/src/guide/ci.asciidoc b/doc/src/guide/ci.asciidoc
index 8a96ed4..24cfc05 100644
--- a/doc/src/guide/ci.asciidoc
+++ b/doc/src/guide/ci.asciidoc
@@ -1,3 +1,4 @@
+[[ci]]
== Continuous integration
// @todo Write it.
diff --git a/doc/src/guide/common_test.asciidoc b/doc/src/guide/common_test.asciidoc
index 7daeae5..aec8747 100644
--- a/doc/src/guide/common_test.asciidoc
+++ b/doc/src/guide/common_test.asciidoc
@@ -1,5 +1,91 @@
+[[ct]]
== Common Test
-// @todo Write it.
+Common Test is Erlang's functional testing framework.
+Erlang.mk automates the discovery and running of Common
+Test suites.
-Placeholder chapter.
+=== Writing tests
+
+The http://www.erlang.org/doc/apps/common_test/write_test_chapter.html[Common Test user guide]
+is the best place to learn how to write tests. Erlang.mk
+requires that file names for test suites end with '_SUITE.erl'
+and that the files be located in the '$(TEST_DIR)' directory.
+This defaults to 'test/'.
+
+=== Configuration
+
+The `CT_OPTS` variable allows you to set extra Common Test
+options. Options are documented in the
+http://www.erlang.org/doc/apps/common_test/run_test_chapter.html[Common Test user guide].
+You can use it to set Common Test hooks, for example:
+
+[source,make]
+CT_OPTS = -ct_hooks cowboy_ct_hook
+
+The `CT_SUITES` variable can be used to override what
+Common Test suites Erlang.mk will be aware of. It does
+not normally need to be set as Erlang.mk will find the
+test suites automatically.
+
+The name of the suite is the part before `_SUITE.erl`.
+If the file is named 'http_SUITE.erl', the test suite
+is `http`:
+
+[source,make]
+CT_SUITES = http ws
+
+=== Usage
+
+To run all tests (including Common Test):
+
+[source,bash]
+$ make tests
+
+To run all tests and static checks (including Common Test):
+
+[source,bash]
+$ make check
+
+You can also run Common Test separately:
+
+[source,bash]
+$ make ct
+
+Erlang.mk will create targets for all test suites it finds.
+If you have a file named 'test/http_SUITE.erl', then the
+target `ct-http` will run that specific test suite:
+
+[source,bash]
+$ make ct-http
+
+Erlang.mk provides a convenient way to run a specific
+group or a specific test case within a specific group,
+using the variable `t`. Note that this only applies to
+suite-specific targets, like the `ct-http` example above.
+
+To run all tests from the `http_compress` group in the
+`http_SUITE` test suite, write:
+
+[source,bash]
+$ make ct-http t=http_compress
+
+Similarly, to run a specific test case in that group:
+
+[source,bash]
+$ make ct-http t=http_compress:headers_dupe
+
+To do the same against a multi-application repository,
+you can use the `-C` option:
+
+[source,bash]
+$ make -C apps/my_app ct-http t=my_group:my_case
+
+Note that this also applies to dependencies. When using Cowboy
+as a dependency, you can run the following directly:
+
+[source,bash]
+$ make -C deps/cowboy ct-http t=http_compress
+
+Finally, xref:coverage[code coverage] is available,
+but covered in its own chapter.
diff --git a/doc/src/guide/compat.asciidoc b/doc/src/guide/compat.asciidoc
index 61386e7..8c8f935 100644
--- a/doc/src/guide/compat.asciidoc
+++ b/doc/src/guide/compat.asciidoc
@@ -1,3 +1,4 @@
+[[compat]]
== Compatibility with other build tools
Erlang.mk tries its best to be compatible with the other Erlang
@@ -20,7 +21,7 @@ and adds a Makefile to the project that Erlang.mk can then
use for building:
_Autoload_ is documented in more details in the
-link:deps.asciidoc[Packages and dependencies] chapter.
+xref:deps[Packages and dependencies] chapter.
=== Erlang.mk projects as Rebar dependencies
@@ -49,11 +50,12 @@ the `DEPS` and `ERLC_OPTS` variables, among others. This
means that the Rebar family builds your project much the
same way as Erlang.mk.
+// @todo Sanity check chapter.
Careful though! Different build tools have different fetching
strategies. If some applications provide differing dependencies,
they might be fetched differently by other build tools. Check
-the link:sanity_check.asciidoc[Sanity check] chapter to find
-out how to detect such issues.
+the upcoming Sanity check chapter to find out how to detect such
+issues.
You can automatically generate this file when you build
your application, by making it a dependency of the `app`
diff --git a/doc/src/guide/contributing.asciidoc b/doc/src/guide/contributing.asciidoc
index e712788..58e5de6 100644
--- a/doc/src/guide/contributing.asciidoc
+++ b/doc/src/guide/contributing.asciidoc
@@ -1,5 +1,116 @@
+[[contributing]]
== Contributing
-// @todo Write it.
+You are welcome and encouraged to contribute.
-Placeholder chapter.
+This is how.
+
+=== Priorities
+
+From the most important to the least important:
+
+* Bugs
+* Package issues/additions
+* Refactoring
+* Features
+
+=== Bugs
+
+If you have found a bug, you should open a ticket. Include
+everything relevant including the command you used, output,
+a link to the code that triggers the issue, why you think
+this is a bug, etc.
+
+If you think you have found a bug but you are not sure, you
+should open a ticket as previously explained.
+
+If you have found a bug and you need it to be solved RIGHT
+NOW, open a ticket as previously explained.
+
+Once you have opened a ticket, be patient, try to answer
+questions in a timely manner and confirm that the bug was
+indeed fixed when it is.
+
+If you can't be patient, either try to solve the bug and
+contribute the fix back or become a paying customer.
+
+=== Code
+
+The code is located in the 'core/\*.mk' and 'plugins/\*.mk' files.
+The tests are located in the 'test/Makefile' and 'test/*.mk' files.
+
+If you have a fix or a hack for a bug, you should open a
+pull request. Any fix should include a test case that fails
+before the fix and is working after.
+
+If you have a test case that reproduces a bug, but no fix for
+it, you should open a pull request.
+
+Changes need to be tested with at least the `make check`
+command. A specific test case can be tested using `make check c=CASE`
+with `CASE` the name of the target to run. Output can be
+modulated using the `V` variable, which is an integer
+from 0 to 4. A typical use would be `make check c=dialyzer V=3`.
+The value 4 is particular and shows expanded commands right
+before they are executed.
+
+To run tests in parallel, use the `-j` option. It is generally
+a good idea to also use the `-k` option to run all tests even
+if one fails. For example: `make check -j 32 -k`.
+
+Some changes should be tested against all packages. Continue
+reading for more details on testing them.
+
+=== Packages
+
+You can search existing packages using the `make search q=STRING`
+command. This can be done both from an Erlang.mk project or
+directly from the Erlang.mk repository.
+
+Packages can be added to the index using the `pkg_add.sh` script.
+
+[source,bash]
+----
+$ git clone https://github.com/$YOURUSERNAME/erlang.mk
+$ cd erlang.mk
+$ ./pkg_add.sh cowboy git https://github.com/ninenines/cowboy 1.0.0
+ http://ninenines.eu "Small, fast and modular HTTP server."
+$ git push origin master
+----
+
+Before sending a pull request, you should test your package.
+You can use the following command: `make check p=PACKAGE`,
+where `PACKAGE` is the name of the package, for example
+`cowboy`.
+
+To test all packages, the `make packages` command can be used.
+This can take a long time. Some packages will fail with certain
+versions of Erlang, or if a prerequisite is missing from your system.
+You can of course speed things up using the `-j` and `-k` flags.
+
+After all packages have been tested, you can run the command
+`make summary` to know what changed since the previous run.
+
+=== Documentation
+
+The documentation is always right.
+
+If you think you have found a mistake in the documentation,
+this is a bug. You can either open a ticket or send a pull
+request.
+
+To make sure that the documentation changes work, install
+the listed xref:asciidoc[Requirements] on your system and
+run `make docs`.
+
+=== Feature requests
+
+If you have an awesome idea or need something that Erlang.mk
+doesn't provide yet, open a ticket. Provide as much detail as
+possible.
+
+If you have code, great! Open a pull request as previously
+explained.
+
+If not, you can still improve your feature request by writing
+the related documentation.
diff --git a/doc/src/guide/coverage.asciidoc b/doc/src/guide/coverage.asciidoc
index 5e74f36..f33f878 100644
--- a/doc/src/guide/coverage.asciidoc
+++ b/doc/src/guide/coverage.asciidoc
@@ -1,3 +1,4 @@
+[[coverage]]
== Code coverage
// @todo Write it.
diff --git a/doc/src/guide/deps.asciidoc b/doc/src/guide/deps.asciidoc
index 9335439..eb6f2f0 100644
--- a/doc/src/guide/deps.asciidoc
+++ b/doc/src/guide/deps.asciidoc
@@ -1,3 +1,4 @@
+[[deps]]
== Packages and dependencies
Erlang.mk can fetch and compile the dependencies that your
@@ -72,7 +73,7 @@ dep_leveldb = git https://github.com/basho/leveldb 2.1.3
This dependency will be built before your application, so
you could easily copy the resulting shared file into your
'priv/' directory as part of the build process. More information
-about that in the link:ports.asciidoc[NIFs and port drivers]
+about that in the xref:ports[NIFs and port drivers]
chapter.
Another variable, `LOCAL_DEPS`, allows specifying runtime
@@ -333,7 +334,7 @@ Erlang.mk will also export the `REBAR_DEPS_DIR` variable for
compatibility with Rebar build tools, as long as they are
recent enough.
-=== Dependencies local to the repository
+=== Many applications in one repository
In addition to the dependencies that are fetched, Erlang.mk
also allows you to have dependencies local to your repository.
diff --git a/doc/src/guide/dialyzer.asciidoc b/doc/src/guide/dialyzer.asciidoc
index 7377c82..58fe53f 100644
--- a/doc/src/guide/dialyzer.asciidoc
+++ b/doc/src/guide/dialyzer.asciidoc
@@ -1,5 +1,73 @@
+[[dialyzer]]
== Dialyzer
-// @todo Write it.
+Dialyzer is a tool that will detect discrepancies in your
+program. It does so using a technique known as success
+typing analysis which has the advantage of providing no
+false positives. Dialyzer is able to detect type errors,
+dead code and more.
-Placeholder chapter.
+Erlang.mk provides a wrapper around Dialyzer.
+
+=== How it works
+
+Dialyzer requires a PLT file to work. The PLT file contains
+the analysis information from all applications which are not
+expected to change, or rarely do. These would be all the
+dependencies of the application or applications you are
+currently working on, including standard applications in
+Erlang/OTP itself.
+
+Dialyzer can generate this PLT file. Erlang.mk includes rules
+to automatically generate the PLT file when it is missing.
+
+Once the PLT file is generated, Dialyzer can perform the
+analysis in record time.
+
+=== Configuration
+
+In a typical usage scenario, no variable needs to be set.
+The defaults should be enough. Do note however that the
+dependencies need to be set properly using the `DEPS` and
+`LOCAL_DEPS` variables.
+
+The `DIALYZER_PLT` file indicates where the PLT file will
+be written to (and read from). By default this is
+'$(PROJECT).plt' in the project's directory. Note that
+the `DIALYZER_PLT` variable is exported and is understood
+by Dialyzer directly.
+
+The `PLT_APPS` variable can be used to add additional
+applications to the PLT. You can either list application
+names or paths to these applications.
+
+Erlang.mk defines two variables for specifying options
+for the analysis: `DIALYZER_DIRS` and `DIALYZER_OPTS`.
+The former one defines which directories should be part
+of the analysis. The latter defines what extra warnings
+Dialyzer should report.
+
+Note that Erlang.mk enables the race condition warnings
+by default. As it can take considerably large resources
+to run, you may want to disable it on larger projects.
+
+=== Usage
+
+To perform an analysis, run the following command:
+
+[source,bash]
+$ make dialyze
+
+This will create the PLT file if it doesn't exist.
+
+The analysis will also be performed when you run the
+following command, alongside tests:
+
+[source,bash]
+$ make check
+
+You can use the `plt` target to create the PLT file if
+it doesn't exist. This is normally not necessary as
+Dialyzer creates it automatically.
+
+The PLT file will be removed when you run `make distclean`.
diff --git a/doc/src/guide/edoc.asciidoc b/doc/src/guide/edoc.asciidoc
index f54d447..9fc1a74 100644
--- a/doc/src/guide/edoc.asciidoc
+++ b/doc/src/guide/edoc.asciidoc
@@ -1,5 +1,48 @@
+[[edoc]]
== EDoc comments
-// @todo Write it.
+Erlang.mk provides a thin wrapper on top of EDoc, an application
+that generates documentation based on comments found in modules.
-Placeholder chapter.
+=== Writing EDoc comments
+
+The http://www.erlang.org/doc/apps/edoc/chapter.html[EDoc user guide]
+explains everything you need to know about EDoc comments.
+
+=== Configuration
+
+The `EDOC_OPTS` variable allows you to specify additional
+EDoc options. Options are documented in the
+http://www.erlang.org/doc/man/edoc.html#run-2[EDoc manual].
+
+A common use for this variable is to enable Markdown in doc
+comments, using the `edown` application:
+
+[source,make]
+DOC_DEPS = edown
+EDOC_OPTS = {doclet, edown_doclet}
+
+=== Usage
+
+To build all documentation, you would typically use:
+
+[source,bash]
+$ make docs
+
+Do note, however, that EDoc comments will only be generated
+automatically if the 'doc/overview.edoc' file exists. If you
+do not want that file and still want to generate doc comments,
+two solutions are available.
+
+You can generate EDoc documentation directly:
+
+[source,bash]
+$ make edoc
+
+You can enable automatic generation on `make docs` by adding
+the following to your Makefile:
+
+[source,make]
+----
+docs:: edoc
+----
diff --git a/doc/src/guide/escripts.asciidoc b/doc/src/guide/escripts.asciidoc
index fcc6080..3d68c77 100644
--- a/doc/src/guide/escripts.asciidoc
+++ b/doc/src/guide/escripts.asciidoc
@@ -1,3 +1,4 @@
+[[escript]]
== Escripts
// @todo Write it.
diff --git a/doc/src/guide/eunit.asciidoc b/doc/src/guide/eunit.asciidoc
index 1a16776..496b674 100644
--- a/doc/src/guide/eunit.asciidoc
+++ b/doc/src/guide/eunit.asciidoc
@@ -1,5 +1,122 @@
+[[eunit]]
== EUnit
-// @todo Write 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.
-Placeholder chapter.
+=== Writing tests
+
+The http://www.erlang.org/doc/apps/eunit/chapter.html[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:
+
+[source,erlang]
+----
+-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.
+
+[source,erlang]
+----
+-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.
+
+=== Configuration
+
+The `EUNIT_OPTS` variable allows you to specify additional
+EUnit options. Options are documented in the
+http://www.erlang.org/doc/man/eunit.html#test-2[EUnit manual].
+At the time of writing, the only available option is `verbose`:
+
+[source,make]
+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:
+
+[source,make]
+EUNIT_ERL_OPTS = -args_file rel/vm.args -config rel/sys.config
+
+=== Usage
+
+To run all tests (including EUnit):
+
+[source,bash]
+$ make tests
+
+To run all tests and static checks (including EUnit):
+
+[source,bash]
+$ make check
+
+You can also run EUnit separately:
+
+[source,bash]
+$ make eunit
+
+EUnit will be quiet by default, only outputting errors.
+You can easily make it verbose for a single invocation:
+
+[source,bash]
+$ 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:
+
+[source,bash]
+$ make eunit t=cow_http_hd
+
+Similarly, to run a specific test case:
+
+[source,bash]
+$ make eunit t=cow_http_hd:parse_accept_test_
+
+To do the same against a multi-application repository,
+you can use the `-C` option:
+
+[source,bash]
+$ 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:
+
+[source,bash]
+$ make -C deps/cowlib eunit t=cow_http_hd
+
+Finally, xref:coverage[code coverage] is available,
+but covered in its own chapter.
diff --git a/doc/src/guide/external_plugins.asciidoc b/doc/src/guide/external_plugins.asciidoc
index 027b1b9..d3dafaa 100644
--- a/doc/src/guide/external_plugins.asciidoc
+++ b/doc/src/guide/external_plugins.asciidoc
@@ -1,3 +1,4 @@
+[[plugins_usage]]
== External plugins
It is often convenient to be able to keep the build files
@@ -60,7 +61,7 @@ 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 eaxmple, if you have two plugins 'mk/dist.mk' and
+For example, if you have two plugins 'mk/dist.mk' and
'mk/templates.mk', you could write the following 'plugins.mk'
file:
diff --git a/doc/src/guide/external_plugins_list.asciidoc b/doc/src/guide/external_plugins_list.asciidoc
new file mode 100644
index 0000000..f30797f
--- /dev/null
+++ b/doc/src/guide/external_plugins_list.asciidoc
@@ -0,0 +1,48 @@
+[[plugins_list]]
+== List of plugins
+
+This is a non-exhaustive list of Erlang.mk plugins, sorted
+alphabetically.
+
+=== efene.mk
+
+An https://github.com/ninenines/efene.mk[Efene plugin] for Erlang.mk.
+http://efene.org/[Efene] is an alternative language for the BEAM.
+
+=== elixir.mk
+
+An https://github.com/botsunit/elixir.mk[Elixir plugin] for
+Erlang.mk. http://elixir-lang.org/[Elixir] is an alternative
+language for the BEAM.
+
+=== elvis.mk
+
+An https://github.com/inaka/elvis.mk[Elvis plugin] for Erlang.mk.
+Elvis is an https://github.com/inaka/elvis[Erlang style reviewer].
+
+=== geas
+
+https://github.com/crownedgrouse/geas[Geas] gives aggregated
+information on a project and its dependencies, and is available
+as an Erlang.mk plugin.
+
+=== hexer.mk
+
+An https://github.com/inaka/hexer.mk[Hex plugin] for Erlang.mk.
+Hex is a https://hex.pm/[package manager for the Elixir ecosystem].
+
+=== lfe.mk
+
+An https://github.com/ninenines/lfe.mk[LFE plugin] for Erlang.mk.
+LFE, or http://lfe.io/[Lisp Flavoured Erlang], is an alternative
+language for the BEAM.
+
+=== mix.mk
+
+A https://github.com/botsunit/mix.mk[Mix plugin] for Erlang.mk,
+to generate a compatible configuration file for
+http://elixir-lang.org/getting-started/mix-otp/introduction-to-mix.html[Mix].
+
+=== reload.mk
+
+A https://github.com/bullno1/reload.mk[live reload plugin] for Erlang.mk.
diff --git a/doc/src/guide/getting_started.asciidoc b/doc/src/guide/getting_started.asciidoc
index 34280d1..ef2f6e8 100644
--- a/doc/src/guide/getting_started.asciidoc
+++ b/doc/src/guide/getting_started.asciidoc
@@ -1,3 +1,4 @@
+[[getting_started]]
== Getting started
This chapter explains how to get started using Erlang.mk.
@@ -74,7 +75,7 @@ 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
-link:updating.asciidoc[Updating Erlang.mk] chapter for more
+xref:updating[Updating Erlang.mk] chapter for more
information.
Of course, the generated project can now be compiled:
@@ -125,7 +126,7 @@ $ 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 link:deps.asciidoc[Packages and dependencies]
+depend on. Consult the xref:deps[Packages and dependencies]
chapter for more information.
When you run `make` from now on, Erlang.mk will compile your
@@ -150,7 +151,7 @@ _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 link:relx.asciidoc[Releases]
+hardware just yet. Just consult the xref:relx[Releases]
chapter for various tips to speed up build time during
development.
@@ -183,6 +184,25 @@ Eshell V7.0 (abort with ^G)
Simple as that!
+=== Using spaces instead of tabs
+
+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:
+
+[source,bash]
+$ 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.
+
=== Using templates
It is no secret that Erlang's OTP behaviors tend to have some
@@ -217,6 +237,23 @@ $ make
All that's left to do is to open it in your favorite editor
and make it do something!
+=== Hiding Erlang.mk from git
+
+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.
+
=== Getting help
During development, if you don't remember the name of a target,
diff --git a/doc/src/guide/history.asciidoc b/doc/src/guide/history.asciidoc
index 41eec09..9202743 100644
--- a/doc/src/guide/history.asciidoc
+++ b/doc/src/guide/history.asciidoc
@@ -1,5 +1,66 @@
+[[history]]
== Short history
-// @todo Write it.
+This chapter aims to be a brief record of the life of the
+Erlang.mk project.
-Placeholder chapter.
+=== Before Erlang.mk
+
+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.
+
+=== Lifetime of the project
+
+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.
diff --git a/doc/src/guide/installation.asciidoc b/doc/src/guide/installation.asciidoc
index f03dafa..cc18e7f 100644
--- a/doc/src/guide/installation.asciidoc
+++ b/doc/src/guide/installation.asciidoc
@@ -1,3 +1,4 @@
+[[installation]]
== Installation
This chapter explains how to setup your system in
@@ -95,6 +96,13 @@ to find all packages related to GCC:
[source,bash]
$ 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:
+
+[source,bash]
+$ 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:
diff --git a/doc/src/guide/limitations.asciidoc b/doc/src/guide/limitations.asciidoc
index 86ca918..1bf33d2 100644
--- a/doc/src/guide/limitations.asciidoc
+++ b/doc/src/guide/limitations.asciidoc
@@ -1,3 +1,4 @@
+[[limitations]]
== Limitations
No software is perfect.
diff --git a/doc/src/guide/overview.asciidoc b/doc/src/guide/overview.asciidoc
index a81dd7a..8fa57fe 100644
--- a/doc/src/guide/overview.asciidoc
+++ b/doc/src/guide/overview.asciidoc
@@ -1,3 +1,4 @@
+[[overview]]
== Overview
Now that you know how to get started, let's take a look at
@@ -9,20 +10,20 @@ 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 link:app.asciidoc[Erlang-specific files]
+Erlang.mk will happily build all xref:building[Erlang-specific files]
you throw at it. Other kinds of files too, like C or C++ code
-when you are working on link:ports.asciidoc[a NIF or a port driver].
+when you are working on xref:ports[a NIF or a port driver].
-Erlang.mk embraces the concept of link:deps.asciidoc[source dependencies].
+Erlang.mk embraces the concept of xref:deps[source dependencies].
It can fetch dependency source code using a variety of mechanisms,
including fetching from Git, Mercurial or SVN.
-Erlang.mk will automatically link:relx.asciidoc[generate releases]
-when applicable. It can also link:escripts.asciidoc[generate escripts].
+Erlang.mk will automatically xref:relx[generate releases]
+when applicable. It can also xref:escript[generate escripts].
=== Exploring the package index
-Erlang.mk comes with a link:deps.asciidoc[built-in package index].
+Erlang.mk comes with a xref:deps[built-in package index].
It is built as an extension of the dependency system and is
meant to be used for discovery purposes.
@@ -46,14 +47,14 @@ $ make search q=cowboy
Erlang.mk supports _EDoc_ and _Asciidoc_.
-link:edoc.asciidoc[EDoc] generates HTML documentation directly from
+xref:edoc[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 link:asciidoc.asciidoc[Asciidoc] plugin expects all documentation
+The xref:asciidoc[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.
@@ -63,26 +64,24 @@ your repository.
Erlang.mk supports a lot of different testing and static
analysis tools.
-The link:shell.asciidoc[make shell] command allows you
+The xref:shell[make shell] command allows you
to test your project manually. You can automate these
-unit tests with link:eunit.asciidoc[EUnit] and test
-your entire system with link:common_test.asciidoc[Common Test].
-link:property_based_testing.asciidoc[Property based testing]
-with Triq is a strong alternative to writing unit tests
-manually. link:coverage.asciidoc[Code coverage] can of course
+unit tests with xref:eunit[EUnit] and test
+your entire system with xref:ct[Common Test].
+xref:coverage[Code coverage] can of course
be enabled during tests.
Erlang.mk comes with features to make your life easier when
-setting up and using link:ci.asciidoc[Continuous integration].
+setting up and using xref:ci[Continuous integration].
On the static analysis side of things, Erlang.mk comes with
-support for link:dialyzer.asciidoc[Dialyzer], link:xref.asciidoc[Xref]
-and link:elvis.asciidoc[Elvis], performing success typing
-analysis, cross reference and style reviewing.
+support for xref:dialyzer[Dialyzer] and xref:xref[Xref],
+to perform success typing analysis and cross referencing
+of the code.
=== Need more?
-Not convinced yet? You can read about link:why.asciidoc[why you should use Erlang.mk]
-and its link:history.asciidoc[history]. And if you're still not
+Not convinced yet? You can read about xref:why[why you should use Erlang.mk]
+and its xref:history[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.
diff --git a/doc/src/guide/ports.asciidoc b/doc/src/guide/ports.asciidoc
index b4527fb..02c636f 100644
--- a/doc/src/guide/ports.asciidoc
+++ b/doc/src/guide/ports.asciidoc
@@ -1,3 +1,4 @@
+[[ports]]
== NIFs and port drivers
Erlang.mk can not only build Erlang projects, but also the C code
@@ -35,8 +36,6 @@ It contains a few variable definitions for the environment used for the build:
`ERL_INTERFACE_LIB_DIR`::
Path to the Erl_Interface static libraries.
-// @todo We should remove this file on clean, not distclean.
-
=== Using a custom Makefile
Erlang.mk will automatically run `make` if it detects a Makefile
@@ -66,9 +65,19 @@ before including Erlang.mk:
[source,make]
C_SRC_TYPE = executable
-The generated file will be saved to '$(C_SRC_OUTPUT)'. It
-defaults to '$(CURDIR)/priv/$(PROJECT).so', the filename
-adequately fitting a Unix shared library.
+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
diff --git a/doc/src/guide/property_based_testing.asciidoc b/doc/src/guide/property_based_testing.asciidoc
deleted file mode 100644
index c652b2b..0000000
--- a/doc/src/guide/property_based_testing.asciidoc
+++ /dev/null
@@ -1,5 +0,0 @@
-== Property based testing
-
-// @todo Write it.
-
-Placeholder chapter.
diff --git a/doc/src/guide/releases.asciidoc b/doc/src/guide/releases.asciidoc
index e7b1333..46183e6 100644
--- a/doc/src/guide/releases.asciidoc
+++ b/doc/src/guide/releases.asciidoc
@@ -1,3 +1,4 @@
+[[relx]]
== Releases
Erlang.mk relies on _Relx_ for generating releases. This
diff --git a/doc/src/guide/shell.asciidoc b/doc/src/guide/shell.asciidoc
index 083c160..a527253 100644
--- a/doc/src/guide/shell.asciidoc
+++ b/doc/src/guide/shell.asciidoc
@@ -1,3 +1,4 @@
+[[shell]]
== Erlang shell
Erlang.mk provides a convenient target for starting a shell
diff --git a/doc/src/guide/updating.asciidoc b/doc/src/guide/updating.asciidoc
index ecd4a70..61d913d 100644
--- a/doc/src/guide/updating.asciidoc
+++ b/doc/src/guide/updating.asciidoc
@@ -1,3 +1,4 @@
+[[updating]]
== Updating Erlang.mk
This chapter describes how to update the 'erlang.mk' file
diff --git a/doc/src/guide/why.asciidoc b/doc/src/guide/why.asciidoc
index 3a84940..e91b64c 100644
--- a/doc/src/guide/why.asciidoc
+++ b/doc/src/guide/why.asciidoc
@@ -1,7 +1,8 @@
+[[why]]
== Why Erlang.mk
Why would you choose Erlang.mk, if not for its
-link:overview.asciidoc[many features]? This chapter will
+xref:overview[many features]? This chapter will
attempt to answer that.
=== Erlang.mk is fast
diff --git a/doc/src/guide/xref.asciidoc b/doc/src/guide/xref.asciidoc
index 889aa41..44ed190 100644
--- a/doc/src/guide/xref.asciidoc
+++ b/doc/src/guide/xref.asciidoc
@@ -1,3 +1,4 @@
+[[xref]]
== Xref
// @todo Write it.
diff --git a/index/bitcask.mk b/index/bitcask.mk
index 2bc7af8..31930f3 100644
--- a/index/bitcask.mk
+++ b/index/bitcask.mk
@@ -4,4 +4,4 @@ pkg_bitcask_description = because you need another a key/value storage engine
pkg_bitcask_homepage = https://github.com/basho/bitcask
pkg_bitcask_fetch = git
pkg_bitcask_repo = https://github.com/basho/bitcask
-pkg_bitcask_commit = master
+pkg_bitcask_commit = develop
diff --git a/index/brod.mk b/index/brod.mk
new file mode 100644
index 0000000..2650f2c
--- /dev/null
+++ b/index/brod.mk
@@ -0,0 +1,7 @@
+PACKAGES += brod
+pkg_brod_name = brod
+pkg_brod_description = Kafka client in Erlang
+pkg_brod_homepage = https://github.com/klarna/brod
+pkg_brod_fetch = git
+pkg_brod_repo = https://github.com/klarna/brod.git
+pkg_brod_commit = master
diff --git a/index/bullet.mk b/index/bullet.mk
index 32f07dd..e365674 100644
--- a/index/bullet.mk
+++ b/index/bullet.mk
@@ -3,5 +3,5 @@ pkg_bullet_name = bullet
pkg_bullet_description = Simple, reliable, efficient streaming for Cowboy.
pkg_bullet_homepage = http://ninenines.eu
pkg_bullet_fetch = git
-pkg_bullet_repo = https://github.com/extend/bullet
+pkg_bullet_repo = https://github.com/ninenines/bullet
pkg_bullet_commit = master
diff --git a/index/dhtcrawler.mk b/index/dhtcrawler.mk
deleted file mode 100644
index 0d15138..0000000
--- a/index/dhtcrawler.mk
+++ /dev/null
@@ -1,7 +0,0 @@
-PACKAGES += dhtcrawler
-pkg_dhtcrawler_name = dhtcrawler
-pkg_dhtcrawler_description = dhtcrawler is a DHT crawler written in erlang. It can join a DHT network and crawl many P2P torrents.
-pkg_dhtcrawler_homepage = https://github.com/kevinlynx/dhtcrawler
-pkg_dhtcrawler_fetch = git
-pkg_dhtcrawler_repo = https://github.com/kevinlynx/dhtcrawler
-pkg_dhtcrawler_commit = master
diff --git a/index/elvis.mk b/index/elvis.mk
index ac6d76a..b9ca83d 100644
--- a/index/elvis.mk
+++ b/index/elvis.mk
@@ -4,4 +4,4 @@ pkg_elvis_description = Erlang Style Reviewer
pkg_elvis_homepage = https://github.com/inaka/elvis
pkg_elvis_fetch = git
pkg_elvis_repo = https://github.com/inaka/elvis
-pkg_elvis_commit = 0.2.4
+pkg_elvis_commit = master
diff --git a/index/gen_coap.mk b/index/gen_coap.mk
new file mode 100644
index 0000000..58c9799
--- /dev/null
+++ b/index/gen_coap.mk
@@ -0,0 +1,7 @@
+PACKAGES += gen_coap
+pkg_gen_coap_name = gen_coap
+pkg_gen_coap_description = Generic Erlang CoAP Client/Server
+pkg_gen_coap_homepage = https://github.com/gotthardp/gen_coap
+pkg_gen_coap_fetch = git
+pkg_gen_coap_repo = https://github.com/gotthardp/gen_coap
+pkg_gen_coap_commit = master
diff --git a/index/geode.mk b/index/geode.mk
new file mode 100644
index 0000000..4eaec34
--- /dev/null
+++ b/index/geode.mk
@@ -0,0 +1,7 @@
+PACKAGES += geode
+pkg_geode_name = geode
+pkg_geode_description = geohash/proximity lookup in pure, uncut erlang.
+pkg_geode_homepage = https://github.com/bradfordw/geode
+pkg_geode_fetch = git
+pkg_geode_repo = https://github.com/bradfordw/geode
+pkg_geode_commit = master
diff --git a/index/i18n.mk b/index/i18n.mk
new file mode 100644
index 0000000..f3f2c89
--- /dev/null
+++ b/index/i18n.mk
@@ -0,0 +1,7 @@
+PACKAGES += i18n
+pkg_i18n_name = i18n
+pkg_i18n_description = International components for unicode from Erlang (unicode, date, string, number, format, locale, localization, transliteration, icu4e)
+pkg_i18n_homepage = https://github.com/erlang-unicode/i18n
+pkg_i18n_fetch = git
+pkg_i18n_repo = https://github.com/erlang-unicode/i18n
+pkg_i18n_commit = master
diff --git a/index/itweet.mk b/index/itweet.mk
deleted file mode 100644
index 704362b..0000000
--- a/index/itweet.mk
+++ /dev/null
@@ -1,7 +0,0 @@
-PACKAGES += itweet
-pkg_itweet_name = itweet
-pkg_itweet_description = Twitter Stream API on ibrowse
-pkg_itweet_homepage = http://inaka.github.com/itweet/
-pkg_itweet_fetch = git
-pkg_itweet_repo = https://github.com/inaka/itweet
-pkg_itweet_commit = v2.0
diff --git a/index/jesse.mk b/index/jesse.mk
index ae96908..b36b699 100644
--- a/index/jesse.mk
+++ b/index/jesse.mk
@@ -1,7 +1,7 @@
PACKAGES += jesse
pkg_jesse_name = jesse
pkg_jesse_description = jesse (JSon Schema Erlang) is an implementation of a json schema validator for Erlang.
-pkg_jesse_homepage = https://github.com/klarna/jesse
+pkg_jesse_homepage = https://github.com/for-GET/jesse
pkg_jesse_fetch = git
-pkg_jesse_repo = https://github.com/klarna/jesse
+pkg_jesse_repo = https://github.com/for-GET/jesse
pkg_jesse_commit = master
diff --git a/index/jsone.mk b/index/jsone.mk
new file mode 100644
index 0000000..cf7378e
--- /dev/null
+++ b/index/jsone.mk
@@ -0,0 +1,7 @@
+PACKAGES += jsone
+pkg_jsone_name = jsone
+pkg_jsone_description = An Erlang library for encoding, decoding JSON data.
+pkg_jsone_homepage = https://github.com/sile/jsone.git
+pkg_jsone_fetch = git
+pkg_jsone_repo = https://github.com/sile/jsone.git
+pkg_jsone_commit = master
diff --git a/index/kafka_protocol.mk b/index/kafka_protocol.mk
new file mode 100644
index 0000000..8a9fb2f
--- /dev/null
+++ b/index/kafka_protocol.mk
@@ -0,0 +1,7 @@
+PACKAGES += kafka_protocol
+pkg_kafka_protocol_name = kafka_protocol
+pkg_kafka_protocol_description = Kafka protocol Erlang library
+pkg_kafka_protocol_homepage = https://github.com/klarna/kafka_protocol
+pkg_kafka_protocol_fetch = git
+pkg_kafka_protocol_repo = https://github.com/klarna/kafka_protocol.git
+pkg_kafka_protocol_commit = master
diff --git a/index/mimerl.mk b/index/mimerl.mk
new file mode 100644
index 0000000..6a613d1
--- /dev/null
+++ b/index/mimerl.mk
@@ -0,0 +1,7 @@
+PACKAGES += mimerl
+pkg_mimerl_name = mimerl
+pkg_mimerl_description = library to handle mimetypes
+pkg_mimerl_homepage = https://github.com/benoitc/mimerl
+pkg_mimerl_fetch = git
+pkg_mimerl_repo = https://github.com/benoitc/mimerl
+pkg_mimerl_commit = master
diff --git a/index/nksip.mk b/index/nksip.mk
new file mode 100644
index 0000000..b74ccfc
--- /dev/null
+++ b/index/nksip.mk
@@ -0,0 +1,7 @@
+PACKAGES += nksip
+pkg_nksip_name = nksip
+pkg_nksip_description = Erlang SIP application server
+pkg_nksip_homepage = https://github.com/kalta/nksip
+pkg_nksip_fetch = git
+pkg_nksip_repo = https://github.com/kalta/nksip
+pkg_nksip_commit = master
diff --git a/index/oauth2c.mk b/index/oauth2c.mk
deleted file mode 100644
index 101e45d..0000000
--- a/index/oauth2c.mk
+++ /dev/null
@@ -1,7 +0,0 @@
-PACKAGES += oauth2c
-pkg_oauth2c_name = oauth2c
-pkg_oauth2c_description = Erlang OAuth2 Client
-pkg_oauth2c_homepage = https://github.com/kivra/oauth2_client
-pkg_oauth2c_fetch = git
-pkg_oauth2c_repo = https://github.com/kivra/oauth2_client
-pkg_oauth2c_commit = master
diff --git a/index/ptrackerl.mk b/index/ptrackerl.mk
deleted file mode 100644
index fe7061e..0000000
--- a/index/ptrackerl.mk
+++ /dev/null
@@ -1,7 +0,0 @@
-PACKAGES += ptrackerl
-pkg_ptrackerl_name = ptrackerl
-pkg_ptrackerl_description = Pivotal Tracker API Client written in Erlang
-pkg_ptrackerl_homepage = https://github.com/inaka/ptrackerl
-pkg_ptrackerl_fetch = git
-pkg_ptrackerl_repo = https://github.com/inaka/ptrackerl
-pkg_ptrackerl_commit = master
diff --git a/index/slack.mk b/index/slack.mk
new file mode 100644
index 0000000..f01bd1c
--- /dev/null
+++ b/index/slack.mk
@@ -0,0 +1,7 @@
+PACKAGES += slack
+pkg_slack_name = slack
+pkg_slack_description = Minimal slack notification OTP library.
+pkg_slack_homepage = https://github.com/DonBranson/slack
+pkg_slack_fetch = git
+pkg_slack_repo = https://github.com/DonBranson/slack.git
+pkg_slack_commit = 1.0.0
diff --git a/index/supervisor3.mk b/index/supervisor3.mk
new file mode 100644
index 0000000..09356f6
--- /dev/null
+++ b/index/supervisor3.mk
@@ -0,0 +1,7 @@
+PACKAGES += supervisor3
+pkg_supervisor3_name = supervisor3
+pkg_supervisor3_description = OTP supervisor with additional strategies
+pkg_supervisor3_homepage = https://github.com/klarna/supervisor3
+pkg_supervisor3_fetch = git
+pkg_supervisor3_repo = https://github.com/klarna/supervisor3.git
+pkg_supervisor3_commit = master
diff --git a/index/xref_runner.mk b/index/xref_runner.mk
index 80ebce4..b058d6a 100644
--- a/index/xref_runner.mk
+++ b/index/xref_runner.mk
@@ -4,4 +4,4 @@ pkg_xref_runner_description = Erlang Xref Runner (inspired in rebar xref)
pkg_xref_runner_homepage = https://github.com/inaka/xref_runner
pkg_xref_runner_fetch = git
pkg_xref_runner_repo = https://github.com/inaka/xref_runner
-pkg_xref_runner_commit = 0.2.0
+pkg_xref_runner_commit = 0.2.3
diff --git a/plugins/asciidoc.mk b/plugins/asciidoc.mk
index baf4d3b..ab7fa4b 100644
--- a/plugins/asciidoc.mk
+++ b/plugins/asciidoc.mk
@@ -8,12 +8,12 @@ MAN_SECTIONS ?= 3 7
docs:: asciidoc
-asciidoc: distclean-asciidoc doc-deps asciidoc-guide asciidoc-manual
+asciidoc: asciidoc-guide asciidoc-manual
ifeq ($(wildcard doc/src/guide/book.asciidoc),)
asciidoc-guide:
else
-asciidoc-guide:
+asciidoc-guide: distclean-asciidoc doc-deps
a2x -v -f pdf doc/src/guide/book.asciidoc && mv doc/src/guide/book.pdf doc/guide.pdf
a2x -v -f chunked doc/src/guide/book.asciidoc && mv doc/src/guide/book.chunked/ doc/html/
endif
@@ -21,7 +21,7 @@ endif
ifeq ($(wildcard doc/src/manual/*.asciidoc),)
asciidoc-manual:
else
-asciidoc-manual:
+asciidoc-manual: distclean-asciidoc doc-deps
for f in doc/src/manual/*.asciidoc ; do \
a2x -v -f manpage $$f ; \
done
@@ -36,7 +36,7 @@ install-docs:: install-asciidoc
install-asciidoc: asciidoc-manual
for s in $(MAN_SECTIONS); do \
mkdir -p $(MAN_INSTALL_PATH)/man$$s/ ; \
- install -g 0 -o 0 -m 0644 doc/man$$s/*.gz $(MAN_INSTALL_PATH)/man$$s/ ; \
+ install -g `id -u` -o `id -g` -m 0644 doc/man$$s/*.gz $(MAN_INSTALL_PATH)/man$$s/ ; \
done
endif
diff --git a/plugins/bootstrap.mk b/plugins/bootstrap.mk
index dbd115f..d608d28 100644
--- a/plugins/bootstrap.mk
+++ b/plugins/bootstrap.mk
@@ -11,8 +11,8 @@ help::
" 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-app n=NAME Create a new local OTP application NAME" \
- " new-lib n=NAME Create a new local OTP library NAME" \
+ " new-app in=NAME Create a new local OTP application NAME" \
+ " new-lib in=NAME Create a new local OTP library NAME" \
" new t=TPL n=NAME Generate a module NAME based on the template TPL" \
" new t=T n=N in=APP Generate a module NAME based on the template TPL in APP" \
" list-templates List available templates"
@@ -49,6 +49,8 @@ define bs_appsrc_lib
]}.
endef
+# To prevent autocompletion issues with ZSH, we add "include erlang.mk"
+# separately during the actual bootstrap.
ifdef SP
define bs_Makefile
PROJECT = $p
@@ -58,17 +60,21 @@ PROJECT_VERSION = 0.0.1
# Whitespace to be used when creating files from templates.
SP = $(SP)
-include erlang.mk
endef
else
define bs_Makefile
PROJECT = $p
-include erlang.mk
+PROJECT_DESCRIPTION = New project
+PROJECT_VERSION = 0.0.1
+
endef
endif
define bs_apps_Makefile
PROJECT = $p
+PROJECT_DESCRIPTION = New project
+PROJECT_VERSION = 0.0.1
+
include $(call core_relpath,$(dir $(ERLANG_MK_FILENAME)),$(APPS_DIR)/app)/erlang.mk
endef
@@ -166,6 +172,11 @@ code_change(_OldVsn, State, _Extra) ->
{ok, State}.
endef
+define tpl_module
+-module($(n)).
+-export([]).
+endef
+
define tpl_cowboy_http
-module($(n)).
-behaviour(cowboy_http_handler).
@@ -344,7 +355,7 @@ endef
# Plugin-specific targets.
define render_template
- $(verbose) echo "$${_$(1)}" > $(2)
+ $(verbose) printf -- '$(subst $(newline),\n,$(subst %,%%,$(subst ','\'',$(subst $(tab),$(WS),$(call $(1))))))\n' > $(2)
endef
ifndef WS
@@ -355,10 +366,6 @@ WS = $(tab)
endif
endif
-$(foreach template,$(filter bs_% tpl_%,$(.VARIABLES)), \
- $(eval _$(template) = $$(subst $$(tab),$$(WS),$$($(template)))) \
- $(eval export _$(template)))
-
bootstrap:
ifneq ($(wildcard src/),)
$(error Error: src/ directory already exists)
@@ -366,6 +373,7 @@ endif
$(eval p := $(PROJECT))
$(eval n := $(PROJECT)_sup)
$(call render_template,bs_Makefile,Makefile)
+ $(verbose) echo "include erlang.mk" >> Makefile
$(verbose) mkdir src/
ifdef LEGACY
$(call render_template,bs_appsrc,src/$(PROJECT).app.src)
@@ -379,6 +387,7 @@ ifneq ($(wildcard src/),)
endif
$(eval p := $(PROJECT))
$(call render_template,bs_Makefile,Makefile)
+ $(verbose) echo "include erlang.mk" >> Makefile
$(verbose) mkdir src/
ifdef LEGACY
$(call render_template,bs_appsrc_lib,src/$(PROJECT).app.src)
diff --git a/plugins/c_src.mk b/plugins/c_src.mk
index a74d945..518ba9e 100644
--- a/plugins/c_src.mk
+++ b/plugins/c_src.mk
@@ -7,12 +7,33 @@
C_SRC_DIR ?= $(CURDIR)/c_src
C_SRC_ENV ?= $(C_SRC_DIR)/env.mk
-C_SRC_OUTPUT ?= $(CURDIR)/priv/$(PROJECT).so
+C_SRC_OUTPUT ?= $(CURDIR)/priv/$(PROJECT)
C_SRC_TYPE ?= shared
# System type and C compiler/flags.
-ifeq ($(PLATFORM),darwin)
+ifeq ($(PLATFORM),msys2)
+ C_SRC_OUTPUT_EXECUTABLE_EXTENSION ?= .exe
+ C_SRC_OUTPUT_SHARED_EXTENSION ?= .dll
+else
+ C_SRC_OUTPUT_EXECUTABLE_EXTENSION ?=
+ C_SRC_OUTPUT_SHARED_EXTENSION ?= .so
+endif
+
+ifeq ($(C_SRC_TYPE),shared)
+ C_SRC_OUTPUT_FILE = $(C_SRC_OUTPUT)$(C_SRC_OUTPUT_SHARED_EXTENSION)
+else
+ C_SRC_OUTPUT_FILE = $(C_SRC_OUTPUT)$(C_SRC_OUTPUT_EXECUTABLE_EXTENSION)
+endif
+
+ifeq ($(PLATFORM),msys2)
+# We hardcode the compiler used on MSYS2. The default CC=cc does
+# not produce working code. The "gcc" MSYS2 package also doesn't.
+ CC = /mingw64/bin/gcc
+ export CC
+ CFLAGS ?= -O3 -std=c99 -finline-functions -Wall -Wmissing-prototypes
+ CXXFLAGS ?= -O3 -finline-functions -Wall
+else ifeq ($(PLATFORM),darwin)
CC ?= cc
CFLAGS ?= -O3 -std=c99 -arch x86_64 -finline-functions -Wall -Wmissing-prototypes
CXXFLAGS ?= -O3 -arch x86_64 -finline-functions -Wall
@@ -27,10 +48,15 @@ else ifeq ($(PLATFORM),linux)
CXXFLAGS ?= -O3 -finline-functions -Wall
endif
-CFLAGS += -fPIC -I $(ERTS_INCLUDE_DIR) -I $(ERL_INTERFACE_INCLUDE_DIR)
-CXXFLAGS += -fPIC -I $(ERTS_INCLUDE_DIR) -I $(ERL_INTERFACE_INCLUDE_DIR)
+ifneq ($(PLATFORM),msys2)
+ CFLAGS += -fPIC
+ CXXFLAGS += -fPIC
+endif
-LDLIBS += -L $(ERL_INTERFACE_LIB_DIR) -lerl_interface -lei
+CFLAGS += -I"$(ERTS_INCLUDE_DIR)" -I"$(ERL_INTERFACE_INCLUDE_DIR)"
+CXXFLAGS += -I"$(ERTS_INCLUDE_DIR)" -I"$(ERL_INTERFACE_INCLUDE_DIR)"
+
+LDLIBS += -L"$(ERL_INTERFACE_LIB_DIR)" -lerl_interface -lei
# Verbosity.
@@ -67,15 +93,15 @@ OBJECTS = $(addsuffix .o, $(basename $(SOURCES)))
COMPILE_C = $(c_verbose) $(CC) $(CFLAGS) $(CPPFLAGS) -c
COMPILE_CPP = $(cpp_verbose) $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c
-app:: $(C_SRC_ENV) $(C_SRC_OUTPUT)
+app:: $(C_SRC_ENV) $(C_SRC_OUTPUT_FILE)
-test-build:: $(C_SRC_ENV) $(C_SRC_OUTPUT)
+test-build:: $(C_SRC_ENV) $(C_SRC_OUTPUT_FILE)
-$(C_SRC_OUTPUT): $(OBJECTS)
+$(C_SRC_OUTPUT_FILE): $(OBJECTS)
$(verbose) mkdir -p priv/
$(link_verbose) $(CC) $(OBJECTS) \
$(LDFLAGS) $(if $(filter $(C_SRC_TYPE),shared),-shared) $(LDLIBS) \
- -o $(C_SRC_OUTPUT)
+ -o $(C_SRC_OUTPUT_FILE)
%.o: %.c
$(COMPILE_C) $(OUTPUT_OPTION) $<
@@ -92,13 +118,13 @@ $(C_SRC_OUTPUT): $(OBJECTS)
clean:: clean-c_src
clean-c_src:
- $(gen_verbose) rm -f $(C_SRC_OUTPUT) $(OBJECTS)
+ $(gen_verbose) rm -f $(C_SRC_OUTPUT_FILE) $(OBJECTS)
endif
ifneq ($(wildcard $(C_SRC_DIR)),)
$(C_SRC_ENV):
- $(verbose) $(ERL) -eval "file:write_file(\"$(C_SRC_ENV)\", \
+ $(verbose) $(ERL) -eval "file:write_file(\"$(call core_native_path,$(C_SRC_ENV))\", \
io_lib:format( \
\"ERTS_INCLUDE_DIR ?= ~s/erts-~s/include/~n\" \
\"ERL_INTERFACE_INCLUDE_DIR ?= ~s~n\" \
@@ -115,3 +141,94 @@ distclean-c_src-env:
-include $(C_SRC_ENV)
endif
+
+# Templates.
+
+define bs_c_nif
+#include "erl_nif.h"
+
+static int loads = 0;
+
+static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)
+{
+ /* Initialize private data. */
+ *priv_data = NULL;
+
+ loads++;
+
+ return 0;
+}
+
+static int upgrade(ErlNifEnv* env, void** priv_data, void** old_priv_data, ERL_NIF_TERM load_info)
+{
+ /* Convert the private data to the new version. */
+ *priv_data = *old_priv_data;
+
+ loads++;
+
+ return 0;
+}
+
+static void unload(ErlNifEnv* env, void* priv_data)
+{
+ if (loads == 1) {
+ /* Destroy the private data. */
+ }
+
+ loads--;
+}
+
+static ERL_NIF_TERM hello(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{
+ if (enif_is_atom(env, argv[0])) {
+ return enif_make_tuple2(env,
+ enif_make_atom(env, "hello"),
+ argv[0]);
+ }
+
+ return enif_make_tuple2(env,
+ enif_make_atom(env, "error"),
+ enif_make_atom(env, "badarg"));
+}
+
+static ErlNifFunc nif_funcs[] = {
+ {"hello", 1, hello}
+};
+
+ERL_NIF_INIT($n, nif_funcs, load, NULL, upgrade, unload)
+endef
+
+define bs_erl_nif
+-module($n).
+
+-export([hello/1]).
+
+-on_load(on_load/0).
+on_load() ->
+ PrivDir = case code:priv_dir(?MODULE) of
+ {error, _} ->
+ AppPath = filename:dirname(filename:dirname(code:which(?MODULE))),
+ filename:join(AppPath, "priv");
+ Path ->
+ Path
+ end,
+ erlang:load_nif(filename:join(PrivDir, atom_to_list(?MODULE)), 0).
+
+hello(_) ->
+ erlang:nif_error({not_loaded, ?MODULE}).
+endef
+
+new-nif:
+ifneq ($(wildcard $(C_SRC_DIR)/$n.c),)
+ $(error Error: $(C_SRC_DIR)/$n.c already exists)
+endif
+ifneq ($(wildcard src/$n.erl),)
+ $(error Error: src/$n.erl already exists)
+endif
+ifdef in
+ $(verbose) $(MAKE) -C $(APPS_DIR)/$(in)/ new-nif n=$n in=
+else
+ $(verbose) mkdir -p $(C_SRC_DIR) src/
+ $(call render_template,bs_c_nif,$(C_SRC_DIR)/$n.c)
+ $(call render_template,bs_erl_nif,src/$n.erl)
+endif
diff --git a/plugins/ct.mk b/plugins/ct.mk
index fb4b1ca..4d0c020 100644
--- a/plugins/ct.mk
+++ b/plugins/ct.mk
@@ -1,7 +1,7 @@
# Copyright (c) 2013-2015, Loïc Hoguin <[email protected]>
# This file is part of erlang.mk and subject to the terms of the ISC License.
-.PHONY: ct distclean-ct
+.PHONY: ct apps-ct distclean-ct
# Configuration.
@@ -31,22 +31,44 @@ help::
CT_RUN = ct_run \
-no_auto_compile \
-noinput \
- -pa $(CURDIR)/ebin $(DEPS_DIR)/*/ebin $(TEST_DIR) \
+ -pa $(CURDIR)/ebin $(DEPS_DIR)/*/ebin $(APPS_DIR)/*/ebin $(TEST_DIR) \
-dir $(TEST_DIR) \
-logdir $(CURDIR)/logs
ifeq ($(CT_SUITES),)
-ct:
+ct: $(if $(IS_APP),,apps-ct)
else
-ct: test-build
+ct: test-build $(if $(IS_APP),,apps-ct)
$(verbose) mkdir -p $(CURDIR)/logs/
- $(gen_verbose) $(CT_RUN) -suite $(addsuffix _SUITE,$(CT_SUITES)) $(CT_OPTS)
+ $(gen_verbose) $(CT_RUN) -sname ct_$(PROJECT) -suite $(addsuffix _SUITE,$(CT_SUITES)) $(CT_OPTS)
+endif
+
+ifneq ($(ALL_APPS_DIRS),)
+define ct_app_target
+apps-ct-$1:
+ $(MAKE) -C $1 ct IS_APP=1
+endef
+
+$(foreach app,$(ALL_APPS_DIRS),$(eval $(call ct_app_target,$(app))))
+
+apps-ct: test-build $(addprefix apps-ct-,$(ALL_APPS_DIRS))
+endif
+
+ifndef t
+CT_EXTRA =
+else
+ifeq (,$(findstring :,$t))
+CT_EXTRA = -group $t
+else
+t_words = $(subst :, ,$t)
+CT_EXTRA = -group $(firstword $(t_words)) -case $(lastword $(t_words))
+endif
endif
define ct_suite_target
ct-$(1): test-build
$(verbose) mkdir -p $(CURDIR)/logs/
- $(gen_verbose) $(CT_RUN) -suite $(addsuffix _SUITE,$(1)) $(CT_OPTS)
+ $(gen_verbose) $(CT_RUN) -sname ct_$(PROJECT) -suite $(addsuffix _SUITE,$(1)) $(CT_EXTRA) $(CT_OPTS)
endef
$(foreach test,$(CT_SUITES),$(eval $(call ct_suite_target,$(test))))
diff --git a/plugins/dialyzer.mk b/plugins/dialyzer.mk
index 709b43f..8c2710f 100644
--- a/plugins/dialyzer.mk
+++ b/plugins/dialyzer.mk
@@ -9,9 +9,8 @@ DIALYZER_PLT ?= $(CURDIR)/.$(PROJECT).plt
export DIALYZER_PLT
PLT_APPS ?=
-DIALYZER_DIRS ?= --src -r src
-DIALYZER_OPTS ?= -Werror_handling -Wrace_conditions \
- -Wunmatched_returns # -Wunderspecs
+DIALYZER_DIRS ?= --src -r $(wildcard src) $(ALL_APPS_DIRS)
+DIALYZER_OPTS ?= -Werror_handling -Wrace_conditions -Wunmatched_returns # -Wunderspecs
# Core targets.
@@ -27,6 +26,18 @@ help::
# Plugin-specific targets.
+define filter_opts.erl
+ Opts = binary:split(<<"$1">>, <<"-">>, [global]),
+ Filtered = lists:reverse(lists:foldl(fun
+ (O = <<"pa ", _/bits>>, Acc) -> [O|Acc];
+ (O = <<"D ", _/bits>>, Acc) -> [O|Acc];
+ (O = <<"I ", _/bits>>, Acc) -> [O|Acc];
+ (_, Acc) -> Acc
+ end, [], Opts)),
+ io:format("~s~n", [[["-", O] || O <- Filtered]]),
+ halt().
+endef
+
$(DIALYZER_PLT): deps app
$(verbose) dialyzer --build_plt --apps erts kernel stdlib $(PLT_APPS) $(OTP_DEPS) $(LOCAL_DEPS) $(DEPS)
@@ -40,4 +51,4 @@ dialyze:
else
dialyze: $(DIALYZER_PLT)
endif
- $(verbose) dialyzer --no_native $(DIALYZER_DIRS) $(DIALYZER_OPTS)
+ $(verbose) dialyzer --no_native `$(call erlang,$(call filter_opts.erl,$(ERLC_OPTS)))` $(DIALYZER_DIRS) $(DIALYZER_OPTS)
diff --git a/plugins/edoc.mk b/plugins/edoc.mk
index 6f0a82d..7b4331b 100644
--- a/plugins/edoc.mk
+++ b/plugins/edoc.mk
@@ -9,13 +9,15 @@ EDOC_OPTS ?=
# Core targets.
-docs:: distclean-edoc edoc
+ifneq ($(wildcard doc/overview.edoc),)
+docs:: edoc
+endif
distclean:: distclean-edoc
# Plugin-specific targets.
-edoc: doc-deps
+edoc: distclean-edoc doc-deps
$(gen_verbose) $(ERL) -eval 'edoc:application($(PROJECT), ".", [$(EDOC_OPTS)]), halt().'
distclean-edoc:
diff --git a/plugins/elvis.mk b/plugins/elvis.mk
deleted file mode 100644
index 58823b5..0000000
--- a/plugins/elvis.mk
+++ /dev/null
@@ -1,39 +0,0 @@
-# Copyright (c) 2015, Erlang Solutions Ltd.
-# This file is part of erlang.mk and subject to the terms of the ISC License.
-
-.PHONY: elvis distclean-elvis
-
-# Configuration.
-
-ELVIS_CONFIG ?= $(CURDIR)/elvis.config
-
-ELVIS ?= $(CURDIR)/elvis
-export ELVIS
-
-ELVIS_URL ?= https://github.com/inaka/elvis/releases/download/0.2.5/elvis
-ELVIS_CONFIG_URL ?= https://github.com/inaka/elvis/releases/download/0.2.5/elvis.config
-ELVIS_OPTS ?=
-
-# Core targets.
-
-help::
- $(verbose) printf "%s\n" "" \
- "Elvis targets:" \
- " elvis Run Elvis using the local elvis.config or download the default otherwise"
-
-distclean:: distclean-elvis
-
-# Plugin-specific targets.
-
-$(ELVIS):
- $(gen_verbose) $(call core_http_get,$(ELVIS),$(ELVIS_URL))
- $(verbose) chmod +x $(ELVIS)
-
-$(ELVIS_CONFIG):
- $(verbose) $(call core_http_get,$(ELVIS_CONFIG),$(ELVIS_CONFIG_URL))
-
-elvis: $(ELVIS) $(ELVIS_CONFIG)
- $(verbose) $(ELVIS) rock -c $(ELVIS_CONFIG) $(ELVIS_OPTS)
-
-distclean-elvis:
- $(gen_verbose) rm -rf $(ELVIS)
diff --git a/plugins/erlydtl.mk b/plugins/erlydtl.mk
index 072da50..5fde292 100644
--- a/plugins/erlydtl.mk
+++ b/plugins/erlydtl.mk
@@ -14,6 +14,20 @@ dtl_verbose = $(dtl_verbose_$(V))
# Core targets.
+DTL_FILES = $(sort $(call core_find,$(DTL_PATH),*.dtl))
+
+ifneq ($(DTL_FILES),)
+
+ifdef DTL_FULL_PATH
+BEAM_FILES += $(addprefix ebin/,$(patsubst %.dtl,%_dtl.beam,$(subst /,_,$(DTL_FILES:$(DTL_PATH)%=%))))
+else
+BEAM_FILES += $(addprefix ebin/,$(patsubst %.dtl,%_dtl.beam,$(notdir $(DTL_FILES))))
+endif
+
+# Rebuild templates when the Makefile changes.
+$(DTL_FILES): $(MAKEFILE_LIST)
+ @touch $@
+
define erlydtl_compile.erl
[begin
Module0 = case "$(strip $(DTL_FULL_PATH))" of
@@ -32,21 +46,8 @@ define erlydtl_compile.erl
halt().
endef
-ifneq ($(wildcard src/),)
-
-DTL_FILES = $(sort $(call core_find,$(DTL_PATH),*.dtl))
-
-ifdef DTL_FULL_PATH
-BEAM_FILES += $(addprefix ebin/,$(patsubst %.dtl,%_dtl.beam,$(subst /,_,$(DTL_FILES:$(DTL_PATH)%=%))))
-else
-BEAM_FILES += $(addprefix ebin/,$(patsubst %.dtl,%_dtl.beam,$(notdir $(DTL_FILES))))
-endif
-
-# Rebuild templates when the Makefile changes.
-$(DTL_FILES): $(MAKEFILE_LIST)
- @touch $@
-
-ebin/$(PROJECT).app:: $(DTL_FILES)
+ebin/$(PROJECT).app:: $(DTL_FILES) | ebin/
$(if $(strip $?),\
- $(dtl_verbose) $(call erlang,$(call erlydtl_compile.erl,$?,-pa ebin/ $(DEPS_DIR)/erlydtl/ebin/)))
+ $(dtl_verbose) $(call erlang,$(call erlydtl_compile.erl,$?),-pa ebin/ $(DEPS_DIR)/erlydtl/ebin/))
+
endif
diff --git a/plugins/escript.mk b/plugins/escript.mk
index 42133eb..16f8ba6 100644
--- a/plugins/escript.mk
+++ b/plugins/escript.mk
@@ -6,6 +6,8 @@
# Configuration.
ESCRIPT_NAME ?= $(PROJECT)
+ESCRIPT_FILE ?= $(ESCRIPT_NAME)
+
ESCRIPT_COMMENT ?= This is an -*- erlang -*- file
ESCRIPT_BEAMS ?= "ebin/*", "deps/*/ebin/*"
@@ -51,7 +53,7 @@ define ESCRIPT_RAW
' ]),'\
' file:change_mode(Escript, 8#755)'\
'end,'\
-'Ez("$(ESCRIPT_NAME)"),'\
+'Ez("$(ESCRIPT_FILE)"),'\
'halt().'
endef
diff --git a/plugins/eunit.mk b/plugins/eunit.mk
index 2adf4a6..a2e22ff 100644
--- a/plugins/eunit.mk
+++ b/plugins/eunit.mk
@@ -2,11 +2,12 @@
# Copyright (c) 2015, Loïc Hoguin <[email protected]>
# This file is contributed to erlang.mk and subject to the terms of the ISC License.
-.PHONY: eunit
+.PHONY: eunit apps-eunit
# Configuration
EUNIT_OPTS ?=
+EUNIT_ERL_OPTS ?=
# Core targets.
@@ -28,7 +29,7 @@ define eunit.erl
_ -> ok
end
end,
- case eunit:test([$(call comma_list,$(1))], [$(EUNIT_OPTS)]) of
+ case eunit:test($1, [$(EUNIT_OPTS)]) of
ok -> ok;
error -> halt(2)
end,
@@ -40,11 +41,28 @@ define eunit.erl
halt()
endef
-EUNIT_EBIN_MODS = $(notdir $(basename $(call core_find,ebin/,*.beam)))
-EUNIT_TEST_MODS = $(notdir $(basename $(call core_find,$(TEST_DIR)/,*.beam)))
-EUNIT_MODS = $(foreach mod,$(EUNIT_EBIN_MODS) $(filter-out \
- $(patsubst %,%_tests,$(EUNIT_EBIN_MODS)),$(EUNIT_TEST_MODS)),{module,'$(mod)'})
+EUNIT_ERL_OPTS += -pa $(TEST_DIR) $(DEPS_DIR)/*/ebin $(APPS_DIR)/*/ebin ebin
+ifdef t
+ifeq (,$(findstring :,$(t)))
+eunit: test-build
+ $(gen_verbose) $(call erlang,$(call eunit.erl,['$(t)']),$(EUNIT_ERL_OPTS))
+else
eunit: test-build
- $(gen_verbose) $(ERL) -pa $(TEST_DIR) $(DEPS_DIR)/*/ebin ebin \
- -eval "$(subst $(newline),,$(subst ",\",$(call eunit.erl,$(EUNIT_MODS))))"
+ $(gen_verbose) $(call erlang,$(call eunit.erl,fun $(t)/0),$(EUNIT_ERL_OPTS))
+endif
+else
+EUNIT_EBIN_MODS = $(notdir $(basename $(ERL_FILES) $(BEAM_FILES)))
+EUNIT_TEST_MODS = $(notdir $(basename $(call core_find,$(TEST_DIR)/,*.erl)))
+
+EUNIT_MODS = $(foreach mod,$(EUNIT_EBIN_MODS) $(filter-out \
+ $(patsubst %,%_tests,$(EUNIT_EBIN_MODS)),$(EUNIT_TEST_MODS)),'$(mod)')
+
+eunit: test-build $(if $(IS_APP),,apps-eunit)
+ $(gen_verbose) $(call erlang,$(call eunit.erl,[$(call comma_list,$(EUNIT_MODS))]),$(EUNIT_ERL_OPTS))
+
+ifneq ($(ALL_APPS_DIRS),)
+apps-eunit:
+ $(verbose) for app in $(ALL_APPS_DIRS); do $(MAKE) -C $$app eunit IS_APP=1; done
+endif
+endif
diff --git a/plugins/relx.mk b/plugins/relx.mk
index 5aa6196..a27992d 100644
--- a/plugins/relx.mk
+++ b/plugins/relx.mk
@@ -22,7 +22,7 @@ endif
ifeq ($(IS_DEP),)
ifneq ($(wildcard $(RELX_CONFIG)),)
-rel:: distclean-relx-rel relx-rel
+rel:: relx-rel
endif
endif
@@ -34,7 +34,7 @@ $(RELX):
$(gen_verbose) $(call core_http_get,$(RELX),$(RELX_URL))
$(verbose) chmod +x $(RELX)
-relx-rel: $(RELX) rel-deps
+relx-rel: $(RELX) rel-deps app
$(verbose) $(RELX) -c $(RELX_CONFIG) $(RELX_OPTS)
distclean-relx-rel:
diff --git a/test/Makefile b/test/Makefile
index 4779c9f..f01e3ab 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -12,8 +12,7 @@ endif
# Temporary application name, taken from rule name.
-APP = $(subst -,_,$@)
-APP_TO_CLEAN = $(subst -,_,$(patsubst clean-%,%,$@))
+APP = test_$(subst -,_,$@)
# Erlang, quickly!
@@ -61,6 +60,7 @@ OTP_MASTER = https://raw.githubusercontent.com/erlang/otp/master
# V=1: Show test commands.
# V=2: Also show normal Erlang.mk output.
# V=3: Also show verbose Erlang.mk output.
+# V=4: Also show a trace of each command after expansion.
V ?= 0
@@ -82,7 +82,7 @@ else ifeq ($V,2)
i = @echo == $@:
else
t =
- v = V=1
+ v = V=$(shell echo $$(($(V)-2)))
i = @echo == $@:
endif
@@ -92,8 +92,8 @@ endif
all:: core
-clean:: clean-core
- $t rm -rf erl_crash.dump packages/
+clean::
+ $t rm -rf erl_crash.dump packages/ test_*/
build:
$i "Generate a bleeding edge Erlang.mk"
@@ -101,11 +101,10 @@ build:
# Core.
-.PHONY: core clean-core
+.PHONY: core
define include_core
core:: core-$1
-clean-core:: clean-core-$1
include core_$1.mk
@@ -117,7 +116,6 @@ $(eval $(foreach t,$(patsubst %.mk,%,$(patsubst core_%,%,$(wildcard core_*.mk)))
define include_plugin
all:: $1
-clean:: clean-$1
include plugin_$1.mk
@@ -128,14 +126,10 @@ $(eval $(foreach t,$(patsubst %.mk,%,$(patsubst plugin_%,%,$(wildcard plugin_*.m
# Tests that don't easily fit into other categories.
core:: core-clean-crash-dump core-distclean-tmp core-help
-clean-core:: clean-core-clean-crash-dump clean-core-distclean-tmp clean-core-help
-.PHONY: core-clean-crash-dump core-distclean-tmp core-help clean-core-clean-crash-dump clean-core-distclean-tmp clean-core-help
+.PHONY: core-clean-crash-dump core-distclean-tmp core-help
-clean-core-clean-crash-dump clean-core-distclean-tmp clean-core-help:
- $t rm -rf $(APP_TO_CLEAN)/
-
-core-clean-crash-dump: build clean-core-clean-crash-dump
+core-clean-crash-dump: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -151,7 +145,7 @@ core-clean-crash-dump: build clean-core-clean-crash-dump
$i "Check that the crash dump is removed"
$t test ! -e $(APP)/erl_crash.dump
-core-distclean-tmp: build clean-core-distclean-tmp
+core-distclean-tmp: build clean
$i "Bootstrap a new OTP application named $(APP)"
$t mkdir $(APP)/
@@ -167,7 +161,7 @@ core-distclean-tmp: build clean-core-distclean-tmp
$i "Check that .erlang.mk directory got removed"
$t test ! -e $(APP)/.erlang.mk
-core-help: build clean-core-help
+core-help: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -180,13 +174,14 @@ core-help: build clean-core-help
# Packages.
PACKAGES = $(foreach pkg,$(sort $(wildcard ../index/*.mk)),$(notdir $(basename $(pkg))))
+EXCLUDE_FROM_CHECK = [rabbitmq_codegen]
packages: $(addprefix pkg-,$(PACKAGES))
define pkg_target
.PHONY: pkg-$1
-pkg-$1: clean build
+pkg-$1: build clean
# Make sure $@ is defined inside the define.
$(eval @ = pkg-$1)
@@ -202,14 +197,6 @@ pkg-$1: clean build
$i "Add package $1 to the Makefile"
$t perl -ni.bak -e 'print;if ($$$$.==1) {print "DEPS = $1\n"}' packages/$1_pkg/Makefile
- $(if $(filter amqp_client,$1),
- $i "Set RABBITMQ_CLIENT_PATCH"
- $(eval PATCHES := RABBITMQ_CLIENT_PATCH=1))
-
- $(if $(filter rabbit,$1),
- $i "Set RABBITMQ_SERVER_PATCH"
- $(eval PATCHES := RABBITMQ_SERVER_PATCH=1))
-
$i "Compile package $1"
$t if ! ( cd packages/$1_pkg/ && $(MAKE) $(PATCHES) $v ); then \
echo "$1: compile error" >> packages/errors.log; \
@@ -224,8 +211,9 @@ pkg-$1: clean build
$i "Check that all applications and their modules can be loaded"
$t if ! ( cd packages/$1_pkg/ && $(ERL) -pa deps/*/ebin/ -eval " \
- Apps = [list_to_atom(App) || \"deps/\" ++ App \
+ Apps0 = [list_to_atom(App) || \"deps/\" ++ App \
<- filelib:wildcard(\"deps/*\")], \
+ Apps = [App || App <- Apps0, not lists:member(App, $(EXCLUDE_FROM_CHECK))], \
[begin \
io:format(\"Loading application ~p~n\", [App]), \
case application:load(App) of \
@@ -257,8 +245,9 @@ pkg-$1: clean build
$i "Check that all applications and their modules can still be loaded"
$t if ! ( cd packages/$1_pkg/ && $(ERL) -pa deps/*/ebin/ -eval " \
- Apps = [list_to_atom(App) || \"deps/\" ++ App \
+ Apps0 = [list_to_atom(App) || \"deps/\" ++ App \
<- filelib:wildcard(\"deps/*\")], \
+ Apps = [App || App <- Apps0, not lists:member(App, $(EXCLUDE_FROM_CHECK))], \
[begin \
io:format(\"Loading application ~p~n\", [App]), \
case application:load(App) of \
@@ -314,92 +303,13 @@ endef
# The following tests are slowly being converted.
# Do NOT use -j with legacy tests.
-.PHONY: legacy clean-legacy ct eunit tests-cover docs
+.PHONY: legacy clean-legacy tests-cover
-legacy: clean-legacy ct eunit tests-cover docs pkgs
+legacy: clean-legacy tests-cover
clean-legacy:
$t rm -rf app1
-ct: app1
- $i "ct: Testing ct and related targets."
- $i "Setting up test suite."
- $t mkdir -p app1/test
- $t printf "%s\n" \
- "-module(m_SUITE)." \
- "-export([all/0, testcase1/1])." \
- "all() -> [testcase1]." \
- "testcase1(_) -> 2 = m:succ(1)." \
- > app1/test/m_SUITE.erl
- $t $(MAKE) -C app1 ct $v
- $i "Checking files created by '$(MAKE) ct'."
- $t [ -e app1/test/m_SUITE.beam ]
- $t [ -e app1/ebin/m.beam ]
- $t [ -e app1/logs ]
- $i "Checking that '$(MAKE) clean' does not delete logs."
- $t $(MAKE) -C app1 clean $v
- $t [ -e app1/logs ]
- $i "Testing target 'ct-mysuite' where mysuite_SUITE is a test suite."
- $t $(MAKE) -C app1 ct-m $v
- $i "Checking that '$(MAKE) ct' returns non-zero for a failing suite."
- $t printf "%s\n" \
- "-module(failing_SUITE)." \
- "-export([all/0, testcase1/1])." \
- "all() -> [testcase1]." \
- "testcase1(_) -> 42 = m:succ(1)." \
- > app1/test/failing_SUITE.erl
- $t ! $(MAKE) -C app1 ct-failing $v
- $i "Checking that '$(MAKE) distclean-ct' deletes logs."
- $t $(MAKE) -C app1 distclean-ct $v
- $t [ ! -e app1/logs ]
- $t [ -e app1/ebin/m.beam ]
- $i "Cleaning up test data."
- $t rm -rf app1/test
- $i "Test 'ct' passed."
-
-eunit: app1
- $i "eunit: Testing the 'eunit' target."
- $i "Running eunit test case inside module src/t.erl"
- $t $(call create-module-t)
- $t $(MAKE) -C app1 distclean $v
- $t $(MAKE) -C app1 eunit $v
- $i "Checking that the eunit test in module t."
- $t echo t | cmp app1/test-eunit.log -
- $t rm app1/test-eunit.log
- $i "Running eunit tests in a separate directory."
- $t mkdir -p app1/eunit
- $t printf '%s\n' \
- '-module(t_tests).' \
- '-include_lib("eunit/include/eunit.hrl").' \
- 'succ_test() ->' \
- ' ?assertEqual(2, t:succ(1)),' \
- ' os:cmd("echo t_tests >> test-eunit.log").' \
- > app1/eunit/t_tests.erl
- $t printf '%s\n' \
- '-module(x_tests).' \
- '-include_lib("eunit/include/eunit.hrl").' \
- 'succ_test() ->' \
- ' ?assertEqual(2, t:succ(1)),' \
- ' os:cmd("echo x_tests >> test-eunit.log").' \
- > app1/eunit/x_tests.erl
- $t $(MAKE) -C app1 distclean TEST_DIR=eunit $v
- $t $(MAKE) -C app1 eunit TEST_DIR=eunit $v
- $i "Checking that '$(MAKE) eunit' didn't run the tests in t_tests twice, etc."
- $t printf "%s\n" t t_tests x_tests | cmp app1/test-eunit.log -
- $t rm app1/test-eunit.log
- $i "Checking that '$(MAKE) eunit' returns non-zero for a failing test."
- $t rm -f app1/eunit/*
- $t printf "%s\n" \
- "-module(t_tests)." \
- '-include_lib("eunit/include/eunit.hrl").' \
- "succ_test() ->" \
- " ?assertEqual(42, t:succ(1))." \
- > app1/eunit/t_tests.erl
- $t $(MAKE) -C app1 distclean TEST_DIR=eunit $v
- $t ! $(MAKE) -C app1 eunit TEST_DIR=eunit $v
- $t rm -rf app1/eunit app1/src/t.erl app1/test-eunit.log
- $i "Test 'eunit' passed."
-
# TODO: do coverage for 'tests' instead of 'eunit ct' when triq is fixed
tests-cover: app1
$i "tests-cover: Testing 'eunit' and 'ct' with COVER=1"
@@ -435,29 +345,6 @@ tests-cover: app1
$t $(MAKE) -C app1 clean $v
$i "Test 'tests-cover' passed."
-docs: app1
- $i "docs: Testing EDoc including DOC_DEPS."
- $t printf "%s\n" \
- "PROJECT = app1" \
- "DOC_DEPS = edown" \
- "dep_edown = git https://github.com/uwiger/edown.git 0.7" \
- "EDOC_OPTS = {doclet, edown_doclet}" \
- "include erlang.mk" \
- "distclean:: distclean-doc-md" \
- "distclean-doc-md:" \
- " rm -rf doc/*.md" \
- > app1/Makefile-doc
- $i "Downloading doc deps (edown) and building docs."
- $t $(MAKE) -C app1 -f Makefile-doc docs $v
- $i "Checking that '$(MAKE) docs' using edown generated a markdown file."
- $t [ -e app1/doc/m.md ]
- $i "Checking that '$(MAKE) distclean' deletes all generated doc files."
- $t $(MAKE) -C app1 -f Makefile-doc distclean $v
- $t [ "`ls app1/doc/`" = "" ]
- $i "Cleaning up test data."
- $t rm app1/Makefile-doc
- $i "Test 'docs' passed."
-
define app1_setup
$i "Setting up app."
$t mkdir -p app1
diff --git a/test/core_app.mk b/test/core_app.mk
index 0f1af19..4570d9d 100644
--- a/test/core_app.mk
+++ b/test/core_app.mk
@@ -2,19 +2,13 @@
CORE_APP_CASES = appsrc-change asn1 auto-git-id erlc-exclude erlc-opts erlc-opts-filter error generate-erl generate-erl-include generate-erl-prepend hrl hrl-recursive makefile-change mib no-app no-makedep pt pt-erlc-opts xrl xrl-include yrl yrl-include
CORE_APP_TARGETS = $(addprefix core-app-,$(CORE_APP_CASES))
-CORE_APP_CLEAN_TARGETS = $(addprefix clean-,$(CORE_APP_TARGETS))
-.PHONY: core-app $(CORE_APP_TARGETS) clean-core-app $(CORE_APP_CLEAN_TARGETS)
-
-clean-core-app: $(CORE_APP_CLEAN_TARGETS)
-
-$(CORE_APP_CLEAN_TARGETS):
- $t rm -rf $(APP_TO_CLEAN)/
+.PHONY: core-app $(CORE_APP_TARGETS)
core-app: $(CORE_APP_TARGETS)
ifdef LEGACY
-core-app-appsrc-change: build clean-core-app-appsrc-change
+core-app-appsrc-change: build clean
$i "Bootstrap a new OTP application named $(APP)"
$t mkdir $(APP)/
@@ -34,7 +28,7 @@ core-app-appsrc-change: build clean-core-app-appsrc-change
$t rm $(APP)/EXPECT
endif
-core-app-asn1: build clean-core-app-asn1
+core-app-asn1: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -155,7 +149,7 @@ endif
[{module, M} = code:load_file(M) || M <- Mods], \
halt()"
-core-app-auto-git-id: build clean-core-app-auto-git-id
+core-app-auto-git-id: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -203,7 +197,7 @@ endif
true = ID =/= [], \
halt()"
-core-app-erlc-exclude: build clean-core-app-erlc-exclude
+core-app-erlc-exclude: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -231,7 +225,7 @@ core-app-erlc-exclude: build clean-core-app-erlc-exclude
[{module, M} = code:load_file(M) || M <- Mods], \
halt()"
-core-app-erlc-opts: build clean-core-app-erlc-opts
+core-app-erlc-opts: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -258,7 +252,7 @@ core-app-erlc-opts: build clean-core-app-erlc-opts
false = proplists:is_defined(debug_info, proplists:get_value(options, girl:module_info(compile))), \
halt()"
-core-app-erlc-opts-filter: build clean-core-app-erlc-opts-filter
+core-app-erlc-opts-filter: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -285,7 +279,7 @@ core-app-erlc-opts-filter: build clean-core-app-erlc-opts-filter
false = proplists:is_defined(debug_info, proplists:get_value(options, girl:module_info(compile))), \
halt()"
-core-app-error: build clean-core-app-error
+core-app-error: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -302,7 +296,7 @@ core-app-error: build clean-core-app-error
$i "Check that trying to build returns non-zero"
$t ! $(MAKE) -C $(APP) $v
-core-app-generate-erl: build clean-core-app-generate-erl
+core-app-generate-erl: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -408,7 +402,7 @@ endif
[{module, M} = code:load_file(M) || M <- Mods], \
halt()"
-core-app-generate-erl-include: build clean-core-app-generate-erl-include
+core-app-generate-erl-include: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -470,7 +464,7 @@ core-app-generate-erl-include: build clean-core-app-generate-erl-include
[{module, M} = code:load_file(M) || M <- Mods], \
halt()"
-core-app-generate-erl-prepend: build clean-core-app-generate-erl-prepend
+core-app-generate-erl-prepend: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -579,7 +573,7 @@ endif
[{module, M} = code:load_file(M) || M <- Mods], \
halt()"
-core-app-hrl: build clean-core-app-hrl
+core-app-hrl: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -668,7 +662,7 @@ endif
[{module, M} = code:load_file(M) || M <- Mods], \
halt()"
-core-app-hrl-recursive: build clean-core-app-hrl-recursive
+core-app-hrl-recursive: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -759,7 +753,7 @@ endif
[{module, M} = code:load_file(M) || M <- Mods], \
halt()"
-core-app-makefile-change: build clean-core-app-makefile-change
+core-app-makefile-change: build clean
$i "Bootstrap a new OTP application named $(APP)"
$t mkdir $(APP)/
@@ -784,7 +778,7 @@ core-app-makefile-change: build clean-core-app-makefile-change
$t find $(APP) -type f -newer $(APP)/Makefile | sort | diff $(APP)/EXPECT -
$t rm $(APP)/EXPECT
-core-app-mib: build clean-core-app-mib
+core-app-mib: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -892,7 +886,7 @@ endif
[{module, M} = code:load_file(M) || M <- Mods], \
halt()"
-core-app-no-app: build clean-core-app-no-app
+core-app-no-app: build clean
$i "Bootstrap a project without an OTP library"
$t mkdir $(APP)/
@@ -903,7 +897,7 @@ core-app-no-app: build clean-core-app-no-app
$i "Build the project"
$t $(MAKE) -C $(APP) $v
-core-app-no-makedep: build clean-core-app-no-makedep
+core-app-no-makedep: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -1016,7 +1010,7 @@ endif
[{module, M} = code:load_file(M) || M <- Mods], \
halt()"
-core-app-pt: build clean-core-app-pt
+core-app-pt: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -1049,7 +1043,7 @@ core-app-pt: build clean-core-app-pt
[{module, M} = code:load_file(M) || M <- Mods], \
halt()"
-core-app-pt-erlc-opts: build clean-core-app-pt-erlc-opts
+core-app-pt-erlc-opts: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -1089,7 +1083,7 @@ core-app-pt-erlc-opts: build clean-core-app-pt-erlc-opts
[{module, M} = code:load_file(M) || M <- Mods], \
halt()"
-core-app-xrl: build clean-core-app-xrl
+core-app-xrl: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -1190,7 +1184,7 @@ endif
[{module, M} = code:load_file(M) || M <- Mods], \
halt()"
-core-app-xrl-include: build clean-core-app-xrl-include
+core-app-xrl-include: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -1334,7 +1328,7 @@ endif
[{module, M} = code:load_file(M) || M <- Mods], \
halt()"
-core-app-yrl: build clean-core-app-yrl
+core-app-yrl: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -1432,7 +1426,7 @@ endif
[{module, M} = code:load_file(M) || M <- Mods], \
halt()"
-core-app-yrl-include: build clean-core-app-yrl-include
+core-app-yrl-include: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
diff --git a/test/core_compat.mk b/test/core_compat.mk
index 06d5211..8d6cabc 100644
--- a/test/core_compat.mk
+++ b/test/core_compat.mk
@@ -2,22 +2,17 @@
#
# Note: autopatch functionality is covered separately.
-CORE_COMPAT_CASES = auto-rebar rebar rebar-deps rebar-deps-pkg rebar-erlc-opts rebar-pt
+CORE_COMPAT_CASES = auto-rebar rebar rebar-deps-git rebar-deps-hex rebar-deps-pkg rebar-erlc-opts rebar-pt
CORE_COMPAT_TARGETS = $(addprefix core-compat-,$(CORE_COMPAT_CASES))
-CORE_COMPAT_CLEAN_TARGETS = $(addprefix clean-,$(CORE_COMPAT_TARGETS))
REBAR_BINARY = https://github.com/rebar/rebar/releases/download/2.6.0/rebar
+REBAR3_BINARY = https://s3.amazonaws.com/rebar3/rebar3
-.PHONY: core-compat $(CORE_COMPAT_TARGETS) clean-core-compat $(CORE_COMPAT_CLEAN_TARGETS)
-
-clean-core-compat: $(CORE_COMPAT_CLEAN_TARGETS)
-
-$(CORE_COMPAT_CLEAN_TARGETS):
- $t rm -rf $(APP_TO_CLEAN)/
+.PHONY: core-compat $(CORE_COMPAT_TARGETS)
core-compat: $(CORE_COMPAT_TARGETS)
-core-compat-auto-rebar: build clean-core-compat-auto-rebar
+core-compat-auto-rebar: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -59,7 +54,7 @@ core-compat-auto-rebar: build clean-core-compat-auto-rebar
$i "Use rebar to build the application"
$t cd $(APP) && ./rebar compile $v
-core-compat-rebar: build clean-core-compat-rebar
+core-compat-rebar: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -98,7 +93,7 @@ core-compat-rebar: build clean-core-compat-rebar
$i "Use rebar to build the application"
$t cd $(APP) && ./rebar compile $v
-core-compat-rebar-deps: build clean-core-compat-rebar-deps
+core-compat-rebar-deps-git: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -130,7 +125,39 @@ core-compat-rebar-deps: build clean-core-compat-rebar-deps
$i "Use rebar to build the application"
$t cd $(APP) && ./rebar get-deps compile $v
-core-compat-rebar-deps-pkg: build clean-core-compat-rebar-deps-pkg
+core-compat-rebar-deps-hex: build clean
+
+ $i "Bootstrap a new OTP library named $(APP)"
+ $t mkdir $(APP)/
+ $t cp ../erlang.mk $(APP)/
+ $t $(MAKE) -C $(APP) -f erlang.mk bootstrap-lib $v
+
+ $i "Add Cowboy as a dependency"
+ $t perl -ni.bak -e 'print;if ($$.==1) {print "DEPS = cowboy\ndep_cowboy = hex 1.0.0\n"}' $(APP)/Makefile
+
+ $i "Run 'make rebar.config'"
+ $t $(MAKE) -C $(APP) rebar.config $v
+
+ $i "Check that rebar.config was created"
+ $t test -f $(APP)/rebar.config
+
+ $i "Check that Cowboy is listed in rebar.config"
+ $t $(ERL) -eval " \
+ {ok, C} = file:consult(\"$(APP)/rebar.config\"), \
+ {_, [{cowboy, \"1.0.0\"}]} = lists:keyfind(deps, 1, C), \
+ halt()"
+
+ $i "Distclean the application"
+ $t $(MAKE) -C $(APP) distclean $v
+
+ $i "Download rebar3"
+ $t curl -s -L -o $(APP)/rebar3 $(REBAR3_BINARY)
+ $t chmod +x $(APP)/rebar3
+
+ $i "Use rebar to build the application"
+ $t cd $(APP) && ./rebar3 compile $v
+
+core-compat-rebar-deps-pkg: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -162,7 +189,7 @@ core-compat-rebar-deps-pkg: build clean-core-compat-rebar-deps-pkg
$i "Use rebar to build the application"
$t cd $(APP) && ./rebar get-deps compile $v
-core-compat-rebar-erlc-opts: build clean-core-compat-rebar-erlc-opts
+core-compat-rebar-erlc-opts: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -211,7 +238,7 @@ core-compat-rebar-erlc-opts: build clean-core-compat-rebar-erlc-opts
$i "Use rebar to build the application"
$t cd $(APP) && ./rebar compile $v
-core-compat-rebar-pt: build clean-core-compat-rebar-pt
+core-compat-rebar-pt: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -226,7 +253,7 @@ core-compat-rebar-pt: build clean-core-compat-rebar-pt
$t perl -ni.bak -e 'print;if ($$.==1) {print "DEPS = lager\n"}' $(APP)/Makefile
$i "Add the lager_transform parse_transform to ERLC_OPTS"
- $t echo "ERLC_OPTS += +'{parse_transform, lager_transform}'" >> $(APP)/Makefile
+ $t echo "ERLC_OPTS += +'{parse_transform, lager_transform}' +'{lager_truncation_size, 1234}'" >> $(APP)/Makefile
$i "Build the application"
$t $(MAKE) -C $(APP) $v
@@ -242,6 +269,7 @@ core-compat-rebar-pt: build clean-core-compat-rebar-pt
{ok, C} = file:consult(\"$(APP)/rebar.config\"), \
{_, Opts} = lists:keyfind(erl_opts, 1, C), \
true = lists:member({parse_transform, lager_transform}, Opts), \
+ true = lists:member({lager_truncation_size, 1234}, Opts), \
halt()"
# For the new build method, we have to simulate keeping the .app file
diff --git a/test/core_deps.mk b/test/core_deps.mk
index 4c734f9..f145754 100644
--- a/test/core_deps.mk
+++ b/test/core_deps.mk
@@ -1,25 +1,13 @@
# Core: Packages and dependencies.
-CORE_DEPS_CASES = apps apps-conflict apps-deep-conflict apps-dir apps-new-app apps-new-lib apps-new-tpl apps-only build-c-8cc build-c-imagejs build-erl build-js dep-commit dir doc fetch-cp fetch-custom fetch-fail-bad fetch-fail-unknown fetch-git fetch-git-submodule fetch-hex fetch-hg fetch-legacy fetch-svn ignore mv mv-rebar no-autopatch no-autopatch-erlang-mk no-autopatch-rebar order-first order-top otp pkg rel search shell skip test
+CORE_DEPS_CASES = apps apps-conflict apps-deep-conflict apps-dir apps-new-app apps-new-lib apps-new-tpl apps-only autopatch-rebar build-c-8cc build-c-imagejs build-erl build-js dep-commit dir doc fetch-cp fetch-custom fetch-fail-bad fetch-fail-unknown fetch-git fetch-git-submodule fetch-hex fetch-hg fetch-legacy fetch-svn ignore mv mv-rebar no-autopatch no-autopatch-erlang-mk no-autopatch-rebar order-first order-top otp pkg rel search shell skip test
CORE_DEPS_TARGETS = $(addprefix core-deps-,$(CORE_DEPS_CASES))
-CORE_DEPS_CLEAN_TARGETS = $(addprefix clean-,$(CORE_DEPS_TARGETS))
-.PHONY: core-deps $(CORE_DEPS_TARGETS) clean-core-deps $(CORE_DEPS_CLEAN_TARGETS)
-
-clean-core-deps: $(CORE_DEPS_CLEAN_TARGETS) clean-core-deps-mv-moved clean-core-deps-mv-rebar-moved
-
-$(CORE_DEPS_CLEAN_TARGETS):
- $t rm -rf $(APP_TO_CLEAN)/
-
-clean-core-deps-mv-moved:
- $t rm -rf core_deps_mv-moved/
-
-clean-core-deps-mv-rebar-moved:
- $t rm -rf core_deps_mv_rebar-moved/
+.PHONY: core-deps $(CORE_DEPS_TARGETS)
core-deps: $(CORE_DEPS_TARGETS)
-core-deps-apps: build clean-core-deps-apps
+core-deps-apps: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -113,7 +101,7 @@ endif
[{module, M} = code:load_file(M) || M <- Mods], \
halt()"
-core-deps-apps-conflict: build clean-core-deps-apps-conflict
+core-deps-apps-conflict: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -132,7 +120,7 @@ core-deps-apps-conflict: build clean-core-deps-apps-conflict
$i "Check that Cowlib wasn't fetched"
$t test ! -e $(APP)/deps/cowlib
-core-deps-apps-deep-conflict: build clean-core-deps-apps-deep-conflict
+core-deps-apps-deep-conflict: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -151,7 +139,7 @@ core-deps-apps-deep-conflict: build clean-core-deps-apps-deep-conflict
$i "Check that Cowlib wasn't fetched"
$t test ! -e $(APP)/deps/cowlib
-core-deps-apps-dir: build clean-core-deps-apps-dir
+core-deps-apps-dir: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -222,7 +210,7 @@ endif
$i "Check that all relevant files were removed"
$t test ! -e $(APP)/deps
-core-deps-apps-new-app: build clean-core-deps-apps-new-app
+core-deps-apps-new-app: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -267,7 +255,7 @@ endif
{module, my_server} = code:load_file(my_server), \
halt()"
-core-deps-apps-new-lib: build clean-core-deps-apps-new-lib
+core-deps-apps-new-lib: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -306,7 +294,7 @@ endif
{module, my_server} = code:load_file(my_server), \
halt()"
-core-deps-apps-new-tpl: build clean-core-deps-apps-new-tpl
+core-deps-apps-new-tpl: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -338,7 +326,7 @@ core-deps-apps-new-tpl: build clean-core-deps-apps-new-tpl
[{module, M} = code:load_file(M) || M <- Mods], \
halt()"
-core-deps-apps-only: build clean-core-deps-apps-only
+core-deps-apps-only: build clean
$i "Create a multi application repository with no root application"
$t mkdir $(APP)/
@@ -391,8 +379,28 @@ core-deps-apps-only: build clean-core-deps-apps-only
$i "Check that all relevant files were removed"
$t test ! -e $(APP)/deps
+core-deps-autopatch-rebar: build clean
+
+ $i "Bootstrap a new OTP library named $(APP)"
+ $t mkdir $(APP)/
+ $t cp ../erlang.mk $(APP)/
+ $t $(MAKE) -C $(APP) -f erlang.mk bootstrap-lib $v
+
+ $i "Add erlsha2 to the list of dependencies"
+ $t perl -ni.bak -e 'print;if ($$.==1) {print "DEPS = erlsha2\n"}' $(APP)/Makefile
+
+ $i "Build the application"
+ $t $(MAKE) -C $(APP) $v
+
+ $i "Check that erlsha2 was fetched and built"
+ $t test -d $(APP)/deps/erlsha2
+ $t test -f $(APP)/deps/erlsha2/ebin/erlsha2.beam
+ifneq ($(PLATFORM),msys2)
+ $t test -f $(APP)/deps/erlsha2/priv/erlsha2_nif.so
+endif
+
ifneq ($(PLATFORM),msys2)
-core-deps-build-c-8cc: build clean-core-deps-build-c-8cc
+core-deps-build-c-8cc: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -420,7 +428,7 @@ core-deps-build-c-8cc: build clean-core-deps-build-c-8cc
endif
ifneq ($(PLATFORM),freebsd)
-core-deps-build-c-imagejs: build clean-core-deps-build-c-imagejs
+core-deps-build-c-imagejs: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -448,7 +456,7 @@ core-deps-build-c-imagejs: build clean-core-deps-build-c-imagejs
halt()"
endif
-core-deps-build-erl: build clean-core-deps-build-erl
+core-deps-build-erl: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -471,7 +479,7 @@ core-deps-build-erl: build clean-core-deps-build-erl
false = lists:member(cowlib, Deps), \
halt()"
-core-deps-build-js: build clean-core-deps-build-js
+core-deps-build-js: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -494,7 +502,7 @@ core-deps-build-js: build clean-core-deps-build-js
false = lists:member(jquery, Deps), \
halt()"
-core-deps-dep-commit: build clean-core-deps-dep-commit
+core-deps-dep-commit: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -525,7 +533,7 @@ endif
{ok, \"1.0.0\"} = application:get_key(cowboy, vsn), \
halt()"
-core-deps-dir: build clean-core-deps-dir
+core-deps-dir: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -555,7 +563,7 @@ endif
true = lists:member(cowboy, Deps), \
halt()"
-core-deps-doc: build clean-core-deps-doc
+core-deps-doc: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -583,7 +591,7 @@ core-deps-doc: build clean-core-deps-doc
halt()"
$i "Build the application documentation"
- $t $(MAKE) -C $(APP) docs $v
+ $t $(MAKE) -C $(APP) edoc $v
$i "Check that documentation dependencies were fetched"
$t test -d $(APP)/deps/edown
@@ -592,7 +600,7 @@ core-deps-doc: build clean-core-deps-doc
$t test -f $(APP)/doc/boy.md
$t test -f $(APP)/doc/girl.md
-core-deps-fetch-cp: build clean-core-deps-fetch-cp
+core-deps-fetch-cp: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -625,7 +633,7 @@ endif
true = lists:member(my_dep, Deps), \
halt()"
-core-deps-fetch-custom: build clean-core-deps-fetch-custom
+core-deps-fetch-custom: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -653,7 +661,7 @@ endif
true = lists:member(boop, Deps), \
halt()"
-core-deps-fetch-fail-bad: build clean-core-deps-fetch-fail-bad
+core-deps-fetch-fail-bad: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -666,7 +674,7 @@ core-deps-fetch-fail-bad: build clean-core-deps-fetch-fail-bad
$i "Check that building the application fails"
$t ! $(MAKE) -C $(APP) $v
-core-deps-fetch-fail-unknown: build clean-core-deps-fetch-fail-unknown
+core-deps-fetch-fail-unknown: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -679,7 +687,7 @@ core-deps-fetch-fail-unknown: build clean-core-deps-fetch-fail-unknown
$i "Check that building the application fails"
$t ! $(MAKE) -C $(APP) $v
-core-deps-fetch-git: build clean-core-deps-fetch-git
+core-deps-fetch-git: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -710,7 +718,7 @@ endif
{ok, \"1.0.0\"} = application:get_key(cowboy, vsn), \
halt()"
-core-deps-fetch-git-submodule: build clean-core-deps-fetch-git-submodule
+core-deps-fetch-git-submodule: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -764,7 +772,7 @@ endif
true = lists:member(my_dep, Deps), \
halt()"
-core-deps-fetch-hex: build clean-core-deps-fetch-hex
+core-deps-fetch-hex: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -795,7 +803,7 @@ endif
{ok, \"1.0.0\"} = application:get_key(cowboy, vsn), \
halt()"
-core-deps-fetch-hg: build clean-core-deps-fetch-hg
+core-deps-fetch-hg: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -825,7 +833,7 @@ endif
halt()"
# Legacy must fail for the top-level application, but work for dependencies.
-core-deps-fetch-legacy: build clean-core-deps-fetch-legacy
+core-deps-fetch-legacy: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -841,7 +849,7 @@ core-deps-fetch-legacy: build clean-core-deps-fetch-legacy
$i "Check that building the application works with IS_DEP=1"
$t $(MAKE) -C $(APP) IS_DEP=1 $v
-core-deps-fetch-svn: build clean-core-deps-fetch-svn
+core-deps-fetch-svn: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -870,7 +878,7 @@ endif
{ok, \"1.0.0\"} = application:get_key(cowlib, vsn), \
halt()"
-core-deps-ignore: build clean-core-deps-ignore
+core-deps-ignore: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -899,7 +907,7 @@ endif
$i "Check that the correct dependencies were fetched"
$t test -d $(APP)/deps/ranch
-core-deps-mv: build clean-core-deps-mv clean-core-deps-mv-moved
+core-deps-mv: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -921,7 +929,7 @@ core-deps-mv: build clean-core-deps-mv clean-core-deps-mv-moved
$i "Build the application"
$t $(MAKE) -C $(APP)-moved $v
-core-deps-mv-rebar: build clean-core-deps-mv-rebar clean-core-deps-mv-rebar-moved
+core-deps-mv-rebar: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -946,7 +954,7 @@ core-deps-mv-rebar: build clean-core-deps-mv-rebar clean-core-deps-mv-rebar-move
# A lower-level dependency of the first dependency always
# wins over a lower-level dependency of the second dependency.
-core-deps-order-first: build clean-core-deps-order-first
+core-deps-order-first: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -987,7 +995,7 @@ endif
halt()"
# A higher-level dependency always wins.
-core-deps-order-top: build clean-core-deps-order-top
+core-deps-order-top: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -1018,7 +1026,7 @@ endif
{ok, \"1.0.0\"} = application:get_key(cowlib, vsn), \
halt()"
-core-deps-no-autopatch: build clean-core-deps-no-autopatch
+core-deps-no-autopatch: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -1039,7 +1047,7 @@ core-deps-no-autopatch: build clean-core-deps-no-autopatch
$i "Check that Cowlib was not autopatched"
$t grep -q Hoguin $(APP)/deps/cowlib/erlang.mk
-core-deps-no-autopatch-erlang-mk: build clean-core-deps-no-autopatch-erlang-mk
+core-deps-no-autopatch-erlang-mk: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -1058,7 +1066,7 @@ core-deps-no-autopatch-erlang-mk: build clean-core-deps-no-autopatch-erlang-mk
$i "Check that Erlang.mk was not autopatched"
$t grep -q Hoguin $(APP)/deps/cowlib/erlang.mk
-core-deps-no-autopatch-rebar: build clean-core-deps-no-autopatch-rebar
+core-deps-no-autopatch-rebar: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -1080,7 +1088,7 @@ core-deps-no-autopatch-rebar: build clean-core-deps-no-autopatch-rebar
$t if grep -q erlang\.mk $(APP)/deps/lager/Makefile; then false; fi
ifndef LEGACY
-core-deps-otp: build clean-core-deps-otp
+core-deps-otp: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -1104,7 +1112,7 @@ core-deps-otp: build clean-core-deps-otp
halt()"
endif
-core-deps-pkg: build clean-core-deps-pkg
+core-deps-pkg: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -1134,7 +1142,7 @@ endif
true = lists:member(cowboy, Deps), \
halt()"
-core-deps-rel: build clean-core-deps-rel
+core-deps-rel: build clean
$i "Bootstrap a new release-enabled OTP library named $(APP)"
$t mkdir $(APP)/
@@ -1195,7 +1203,7 @@ else
$t $(APP)/_rel/$(APP)_release/bin/$(APP)_release stop $v
endif
-core-deps-search: build clean-core-deps-search
+core-deps-search: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -1208,7 +1216,7 @@ core-deps-search: build clean-core-deps-search
$i "Run 'make search q=cowboy' and check that it prints packages"
$t test -n "`$(MAKE) -C $(APP) search q=cowboy`"
-core-deps-shell: build clean-core-deps-shell
+core-deps-shell: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -1247,7 +1255,7 @@ core-deps-shell: build clean-core-deps-shell
false = lists:member(tddreloader, Deps), \
halt()"
-core-deps-skip: build clean-core-deps-skip
+core-deps-skip: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -1284,7 +1292,7 @@ endif
$t test -d $(APP)/deps/cowboy
$t test -d $(APP)/deps/ranch
-core-deps-test: build clean-core-deps-test
+core-deps-test: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
diff --git a/test/core_plugins.mk b/test/core_plugins.mk
index 184c08f..6d10f2a 100644
--- a/test/core_plugins.mk
+++ b/test/core_plugins.mk
@@ -2,18 +2,12 @@
CORE_PLUGINS_CASES = all one
CORE_PLUGINS_TARGETS = $(addprefix core-plugins-,$(CORE_PLUGINS_CASES))
-CORE_PLUGINS_CLEAN_TARGETS = $(addprefix clean-,$(CORE_PLUGINS_TARGETS))
-.PHONY: core-plugins $(CORE_PLUGINS_TARGETS) clean-core-plugins $(CORE_PLUGINS_CLEAN_TARGETS)
-
-clean-core-plugins: $(CORE_PLUGINS_CLEAN_TARGETS)
-
-$(CORE_PLUGINS_CLEAN_TARGETS):
- $t rm -rf $(APP_TO_CLEAN)/
+.PHONY: core-plugins $(CORE_PLUGINS_TARGETS)
core-plugins: $(CORE_PLUGINS_TARGETS)
-core-plugins-all: build clean-core-plugins-all
+core-plugins-all: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -45,7 +39,7 @@ core-plugins-all: build clean-core-plugins-all
$i "Run 'make plugin2' and check that it prints plugin2"
$t test -n "`$(MAKE) -C $(APP) plugin2 | grep plugin2`"
-core-plugins-one: build clean-core-plugins-one
+core-plugins-one: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
diff --git a/test/core_upgrade.mk b/test/core_upgrade.mk
index c4a8725..64a8b5d 100644
--- a/test/core_upgrade.mk
+++ b/test/core_upgrade.mk
@@ -1,19 +1,42 @@
# Core: Erlang.mk upgrade.
-CORE_UPGRADE_CASES = custom-build-dir custom-config custom-repo no-config renamed-config
+CORE_UPGRADE_CASES = conflicting-configs custom-build-dir custom-config custom-repo no-config renamed-config
CORE_UPGRADE_TARGETS = $(addprefix core-upgrade-,$(CORE_UPGRADE_CASES))
-CORE_UPGRADE_CLEAN_TARGETS = $(addprefix clean-,$(CORE_UPGRADE_TARGETS))
-.PHONY: core-upgrade $(CORE_UPGRADE_TARGETS) clean-core-upgrade $(CORE_UPGRADE_CLEAN_TARGETS)
+.PHONY: core-upgrade $(CORE_UPGRADE_TARGETS)
-clean-core-upgrade: $(CORE_UPGRADE_CLEAN_TARGETS)
+core-upgrade: $(CORE_UPGRADE_TARGETS)
-$(CORE_UPGRADE_CLEAN_TARGETS):
- $t rm -rf $(APP_TO_CLEAN)/
+core-upgrade-conflicting-configs: build clean
-core-upgrade: $(CORE_UPGRADE_TARGETS)
+ $i "Bootstrap a new OTP library named $(APP)"
+ $t mkdir $(APP)/
+ $t cp ../erlang.mk $(APP)/
+ $t $(MAKE) -C $(APP) -f erlang.mk bootstrap-lib $v
+
+ $i "Fork erlang.mk locally and modify it"
+ $t git clone -q https://github.com/ninenines/erlang.mk $(APP)/alt-erlangmk-repo
+ $t echo core/core > $(APP)/alt-erlangmk-repo/build.config
+ $t (cd $(APP)/alt-erlangmk-repo && \
+ git checkout -q -b test-modified-build.config && \
+ git config user.email "[email protected]" && \
+ git config user.name "test suite" && \
+ git commit -q -a -m 'Modify build.config' && \
+ git checkout master)
+
+ $i "Point application to an alternate erlang.mk repository"
+ $t perl -ni.bak -e 'print;if ($$.==1) {print "ERLANG_MK_REPO = file://$(abspath $(APP)/alt-erlangmk-repo)\nERLANG_MK_COMMIT = test-modified-build.config\n"}' $(APP)/Makefile
+
+ $i "Create a custom build.config file without plugins"
+ $t echo "core/*" > $(APP)/build.config
+
+ $i "Upgrade Erlang.mk"
+ $t $(MAKE) -C $(APP) erlang-mk $v
+
+ $i "Check that the bootstrap plugin is gone"
+ $t ! $(MAKE) -C $(APP) list-templates $v
-core-upgrade-custom-build-dir: build clean-core-upgrade-custom-build-dir
+core-upgrade-custom-build-dir: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -39,7 +62,7 @@ core-upgrade-custom-build-dir: build clean-core-upgrade-custom-build-dir
$i "Check that the custom build directory is gone"
$t test ! -d $(APP)/custom/
-core-upgrade-custom-config: build clean-core-upgrade-custom-config
+core-upgrade-custom-config: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -55,7 +78,7 @@ core-upgrade-custom-config: build clean-core-upgrade-custom-config
$i "Check that the bootstrap plugin is gone"
$t ! $(MAKE) -C $(APP) list-templates $v
-core-upgrade-custom-repo: build clean-core-upgrade-custom-repo
+core-upgrade-custom-repo: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -69,7 +92,8 @@ core-upgrade-custom-repo: build clean-core-upgrade-custom-repo
git checkout -q -b test-copyright && \
git config user.email "[email protected]" && \
git config user.name "test suite" && \
- git commit -q -a -m 'Add Testsuite copyright')
+ git commit -q -a -m 'Add Testsuite copyright' && \
+ git checkout master)
$i "Point application to an alternate erlang.mk repository"
$t perl -ni.bak -e 'print;if ($$.==1) {print "ERLANG_MK_REPO = file://$(abspath $(APP)/alt-erlangmk-repo)\nERLANG_MK_COMMIT = test-copyright\n"}' $(APP)/Makefile
@@ -80,7 +104,7 @@ core-upgrade-custom-repo: build clean-core-upgrade-custom-repo
$i "Check our modification is there"
$t grep -q "# Copyright (c) erlang.mk Testsuite!" $(APP)/erlang.mk
-core-upgrade-no-config: build clean-core-upgrade-no-config
+core-upgrade-no-config: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -99,7 +123,7 @@ core-upgrade-no-config: build clean-core-upgrade-no-config
$i "Check that the rule is gone"
$t ! $(MAKE) -C $(APP) erlang_mk_upgrade_test_rule $v
-core-upgrade-renamed-config: build clean-core-upgrade-renamed-config
+core-upgrade-renamed-config: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
diff --git a/test/plugin_asciidoc.mk b/test/plugin_asciidoc.mk
new file mode 100644
index 0000000..a583585
--- /dev/null
+++ b/test/plugin_asciidoc.mk
@@ -0,0 +1,158 @@
+# AsciiDoc plugin.
+
+ASCIIDOC_CASES = build docs guide install manual
+ASCIIDOC_TARGETS = $(addprefix asciidoc-,$(ASCIIDOC_CASES))
+
+.PHONY: asciidoc $(ASCIIDOC_TARGETS)
+
+asciidoc: $(ASCIIDOC_TARGETS)
+
+asciidoc-build: build clean
+
+ $i "Bootstrap a new OTP application named $(APP)"
+ $t mkdir $(APP)/
+ $t cp ../erlang.mk $(APP)/
+ $t $(MAKE) -C $(APP) -f erlang.mk bootstrap $v
+
+ $i "Only enable man pages section 3"
+ $t perl -ni.bak -e 'print;if ($$.==1) {print "MAN_SECTIONS = 3\n"}' $(APP)/Makefile
+
+ $i "Run AsciiDoc"
+ $t $(MAKE) -C $(APP) asciidoc $v
+
+ $i "Check that no documentation was generated"
+ $t test ! -e $(APP)/doc/guide.pdf
+ $t test ! -e $(APP)/doc/html/
+ $t test ! -e $(APP)/doc/man3/
+
+ $i "Generate AsciiDoc documentation"
+ $t mkdir -p $(APP)/doc/src/guide/ $(APP)/doc/src/manual/
+ $t printf "%s\n" \
+ "= Erlang.mk tests" "" \
+ "Hello world!" > $(APP)/doc/src/guide/book.asciidoc
+ $t printf "%s\n" \
+ "= erlang_mk(3)" "" \
+ "== Name" "" \
+ "erlang_mk - Erlang.mk test" "" \
+ "== Description" "" \
+ "Hello world!" > $(APP)/doc/src/manual/erlang_mk.asciidoc
+
+ $i "Run AsciiDoc"
+ $t $(MAKE) -C $(APP) asciidoc $v
+
+ $i "Check that the documentation was generated"
+ $t test -f $(APP)/doc/guide.pdf
+ $t test -d $(APP)/doc/html/
+ $t test -f $(APP)/doc/man3/erlang_mk.3.gz
+
+ $i "Distclean the application"
+ $t $(MAKE) -C $(APP) distclean $v
+
+ $i "Check that the generated documentation was removed"
+ $t test ! -e $(APP)/doc/guide.pdf
+ $t test ! -e $(APP)/doc/html/
+ $t test ! -e $(APP)/doc/man3/
+
+ $i "Generate an invalid AsciiDoc file"
+ $t printf "%s\n" \
+ "= fail(3)" "" \
+ "This will fail because the Name section is missing." > $(APP)/doc/src/manual/fail.asciidoc
+
+ $i "Check that AsciiDoc errors out"
+ $t ! $(MAKE) -C $(APP) asciidoc $v
+
+asciidoc-docs: build clean
+
+ $i "Bootstrap a new OTP application named $(APP)"
+ $t mkdir $(APP)/
+ $t cp ../erlang.mk $(APP)/
+ $t $(MAKE) -C $(APP) -f erlang.mk bootstrap $v
+
+ $i "Generate AsciiDoc documentation"
+ $t mkdir -p $(APP)/doc/src/guide/
+ $t printf "%s\n" \
+ "= Erlang.mk tests" "" \
+ "Hello world!" > $(APP)/doc/src/guide/book.asciidoc
+
+ $i "Check that AsciiDoc runs on 'make docs'"
+ $t $(MAKE) -C $(APP) docs $v
+ $t test -f $(APP)/doc/guide.pdf
+ $t test -d $(APP)/doc/html/
+
+asciidoc-guide: build clean
+
+ $i "Bootstrap a new OTP application named $(APP)"
+ $t mkdir $(APP)/
+ $t cp ../erlang.mk $(APP)/
+ $t $(MAKE) -C $(APP) -f erlang.mk bootstrap $v
+
+ $i "Generate AsciiDoc documentation"
+ $t mkdir -p $(APP)/doc/src/guide/ $(APP)/doc/src/manual/
+ $t printf "%s\n" \
+ "= Erlang.mk tests" "" \
+ "Hello world!" > $(APP)/doc/src/guide/book.asciidoc
+ $t printf "%s\n" \
+ "= erlang_mk(3)" "" \
+ "== Name" "" \
+ "erlang_mk - Erlang.mk test" "" \
+ "== Description" "" \
+ "Hello world!" > $(APP)/doc/src/manual/erlang_mk.asciidoc
+
+ $i "Check that only the guide is generated on 'make asciidoc-guide'"
+ $t $(MAKE) -C $(APP) asciidoc-guide $v
+ $t test -f $(APP)/doc/guide.pdf
+ $t test -d $(APP)/doc/html/
+ $t test ! -e $(APP)/doc/man3/
+
+asciidoc-install: build clean
+
+ $i "Bootstrap a new OTP application named $(APP)"
+ $t mkdir $(APP)/
+ $t cp ../erlang.mk $(APP)/
+ $t $(MAKE) -C $(APP) -f erlang.mk bootstrap $v
+
+ $i "Only enable man pages section 3"
+ $t perl -ni.bak -e 'print;if ($$.==1) {print "MAN_SECTIONS = 3\n"}' $(APP)/Makefile
+
+ $i "Generate AsciiDoc documentation"
+ $t mkdir -p $(APP)/doc/src/manual/
+ $t printf "%s\n" \
+ "= erlang_mk(3)" "" \
+ "== Name" "" \
+ "erlang_mk - Erlang.mk test" "" \
+ "== Description" "" \
+ "Hello world!" > $(APP)/doc/src/manual/erlang_mk.asciidoc
+
+ $i "Build and install the man pages to $(APP)/installed/"
+ $t $(MAKE) -C $(APP) install-docs MAN_INSTALL_PATH=installed/share $v
+
+ $i "Check that the documentation was installed properly"
+ $t test -f $(APP)/installed/share/man3/erlang_mk.3.gz
+
+asciidoc-manual: build clean
+
+ $i "Bootstrap a new OTP application named $(APP)"
+ $t mkdir $(APP)/
+ $t cp ../erlang.mk $(APP)/
+ $t $(MAKE) -C $(APP) -f erlang.mk bootstrap $v
+
+ $i "Only enable man pages section 3"
+ $t perl -ni.bak -e 'print;if ($$.==1) {print "MAN_SECTIONS = 3\n"}' $(APP)/Makefile
+
+ $i "Generate AsciiDoc documentation"
+ $t mkdir -p $(APP)/doc/src/guide/ $(APP)/doc/src/manual/
+ $t printf "%s\n" \
+ "= Erlang.mk tests" "" \
+ "Hello world!" > $(APP)/doc/src/guide/book.asciidoc
+ $t printf "%s\n" \
+ "= erlang_mk(3)" "" \
+ "== Name" "" \
+ "erlang_mk - Erlang.mk test" "" \
+ "== Description" "" \
+ "Hello world!" > $(APP)/doc/src/manual/erlang_mk.asciidoc
+
+ $i "Check that only the manual is generated on 'make asciidoc-manual'"
+ $t $(MAKE) -C $(APP) asciidoc-manual $v
+ $t test ! -e $(APP)/doc/guide.pdf
+ $t test ! -e $(APP)/doc/html/
+ $t test -f $(APP)/doc/man3/erlang_mk.3.gz
diff --git a/test/plugin_bootstrap.mk b/test/plugin_bootstrap.mk
index 16bfb58..2b62b6f 100644
--- a/test/plugin_bootstrap.mk
+++ b/test/plugin_bootstrap.mk
@@ -1,19 +1,13 @@
# Bootstrap plugin.
-BOOTSTRAP_CASES = app lib rel templates
+BOOTSTRAP_CASES = app lib rel sp tab templates
BOOTSTRAP_TARGETS = $(addprefix bootstrap-,$(BOOTSTRAP_CASES))
-BOOTSTRAP_CLEAN_TARGETS = $(addprefix clean-,$(BOOTSTRAP_TARGETS))
-.PHONY: bootstrap $(BOOTSTRAP_TARGETS) clean-bootstrap $(BOOTSTRAP_CLEAN_TARGETS)
-
-clean-bootstrap: $(BOOTSTRAP_CLEAN_TARGETS)
-
-$(BOOTSTRAP_CLEAN_TARGETS):
- $t rm -rf $(APP_TO_CLEAN)/
+.PHONY: bootstrap $(BOOTSTRAP_TARGETS)
bootstrap: $(BOOTSTRAP_TARGETS)
-bootstrap-app: build clean-bootstrap-app
+bootstrap-app: build clean
$i "Bootstrap a new OTP application named $(APP)"
$t mkdir $(APP)/
@@ -44,7 +38,7 @@ endif
{module, $(APP)_sup} = code:load_file($(APP)_sup), \
halt()"
-bootstrap-lib: build clean-bootstrap-lib
+bootstrap-lib: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -69,7 +63,7 @@ endif
{ok, []} = application:get_key($(APP), modules), \
halt()"
-bootstrap-rel: build clean-bootstrap-rel
+bootstrap-rel: build clean
$i "Bootstrap a new release-enabled OTP application named $(APP)"
$t mkdir $(APP)/
@@ -116,7 +110,68 @@ endif
$i "Check that there's no erl_crash.dump file"
$t test ! -f $(APP)/_rel/$(APP)_release/erl_crash.dump
-bootstrap-templates: build clean-bootstrap-templates
+bootstrap-sp: build clean
+
+ $i "Bootstrap a new OTP application named $(APP)"
+ $t mkdir $(APP)/
+ $t cp ../erlang.mk $(APP)/
+ $t $(MAKE) -C $(APP) -f erlang.mk bootstrap SP=2 $v
+
+ $i "Check that all bootstrapped files exist"
+ $t test -f $(APP)/Makefile
+ifdef LEGACY
+ $t test -f $(APP)/src/$(APP).app.src
+endif
+ $t test -f $(APP)/src/$(APP)_app.erl
+ $t test -f $(APP)/src/$(APP)_sup.erl
+
+ $i "Check that bootstrapped files have no tabs"
+ifdef LEGACY
+ $t test -z "`awk -F "\t" 'NF > 1' $(APP)/src/$(APP).app.src`"
+endif
+ $t test -z "`awk -F "\t" 'NF > 1' $(APP)/src/$(APP)_app.erl`"
+ $t test -z "`awk -F "\t" 'NF > 1' $(APP)/src/$(APP)_sup.erl`"
+
+# Everything looks OK, but let's compile the application to make sure.
+ $i "Build the application"
+ $t $(MAKE) -C $(APP) $v
+
+ $i "Check that all compiled files exist"
+ $t test -f $(APP)/ebin/$(APP).app
+ $t test -f $(APP)/ebin/$(APP)_app.beam
+ $t test -f $(APP)/ebin/$(APP)_sup.beam
+
+ $i "Check that the application was compiled correctly"
+ $t $(ERL) -pa $(APP)/ebin/ -eval " \
+ ok = application:start($(APP)), \
+ {ok, [$(APP)_app, $(APP)_sup]} = application:get_key($(APP), modules), \
+ {module, $(APP)_app} = code:load_file($(APP)_app), \
+ {module, $(APP)_sup} = code:load_file($(APP)_sup), \
+ halt()"
+
+bootstrap-tab: build clean
+
+ $i "Bootstrap a new OTP application named $(APP)"
+ $t mkdir $(APP)/
+ $t cp ../erlang.mk $(APP)/
+ $t $(MAKE) -C $(APP) -f erlang.mk bootstrap $v
+
+ $i "Check that all bootstrapped files exist"
+ $t test -f $(APP)/Makefile
+ifdef LEGACY
+ $t test -f $(APP)/src/$(APP).app.src
+endif
+ $t test -f $(APP)/src/$(APP)_app.erl
+ $t test -f $(APP)/src/$(APP)_sup.erl
+
+ $i "Check that bootstrapped files have tabs"
+ifdef LEGACY
+ $t test "`awk -F "\t" 'NF > 1' $(APP)/src/$(APP).app.src`"
+endif
+ $t test "`awk -F "\t" 'NF > 1' $(APP)/src/$(APP)_app.erl`"
+ $t test "`awk -F "\t" 'NF > 1' $(APP)/src/$(APP)_sup.erl`"
+
+bootstrap-templates: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -135,6 +190,7 @@ bootstrap-templates: build clean-bootstrap-templates
$t $(MAKE) -C $(APP) --no-print-directory new t=cowboy_rest n=my_rest
$t $(MAKE) -C $(APP) --no-print-directory new t=cowboy_ws n=my_ws
$t $(MAKE) -C $(APP) --no-print-directory new t=ranch_protocol n=my_protocol
+ $t $(MAKE) -C $(APP) --no-print-directory new t=module n=my_module
# Here we disable warnings because templates contain missing behaviors.
$i "Build the application"
@@ -145,11 +201,12 @@ bootstrap-templates: build clean-bootstrap-templates
$t test -f $(APP)/ebin/my_fsm.beam
$t test -f $(APP)/ebin/my_server.beam
$t test -f $(APP)/ebin/my_sup.beam
+ $t test -f $(APP)/ebin/my_module.beam
$i "Check that all the modules can be loaded"
$t $(ERL) -pa $(APP)/ebin/ -eval " \
ok = application:start($(APP)), \
- {ok, Mods = [my_fsm, my_http, my_loop, my_protocol, my_rest, my_server, my_sup, my_ws]} \
+ {ok, Mods = [my_fsm, my_http, my_loop, my_module, my_protocol, my_rest, my_server, my_sup, my_ws]} \
= application:get_key($(APP), modules), \
[{module, M} = code:load_file(M) || M <- Mods], \
halt()"
diff --git a/test/plugin_c_src.mk b/test/plugin_c_src.mk
new file mode 100644
index 0000000..5e4e7fe
--- /dev/null
+++ b/test/plugin_c_src.mk
@@ -0,0 +1,89 @@
+# C source plugin.
+
+C_SRC_CASES = cpp custom dir env nif port
+C_SRC_TARGETS = $(addprefix c-src-,$(C_SRC_CASES))
+
+.PHONY: c-src $(C_SRC_TARGETS)
+
+c-src: $(C_SRC_TARGETS)
+c_src: c-src
+
+c-src-nif: build clean
+
+ $i "Bootstrap a new OTP library named $(APP)"
+ $t mkdir $(APP)/
+ $t cp ../erlang.mk $(APP)/
+ $t $(MAKE) -C $(APP) -f erlang.mk bootstrap-lib $v
+
+ $i "Generate a NIF from templates"
+ $t $(MAKE) -C $(APP) new-nif n=$(APP) $v
+
+ $i "Build the application"
+ $t $(MAKE) -C $(APP) $v
+
+ $i "Check that all compiled files exist"
+ $t test -f $(APP)/$(APP).d
+ $t test -f $(APP)/c_src/$(APP).o
+ $t test -f $(APP)/c_src/env.mk
+ $t test -f $(APP)/ebin/$(APP).app
+ $t test -f $(APP)/ebin/$(APP).beam
+ifeq ($(PLATFORM),msys2)
+ $t test -f $(APP)/priv/$(APP).dll
+else
+ $t test -f $(APP)/priv/$(APP).so
+endif
+
+ $i "Check that the application was compiled correctly"
+ $t $(ERL) -pa $(APP)/ebin/ -eval " \
+ ok = application:start($(APP)), \
+ {ok, [$(APP)]} = application:get_key($(APP), modules), \
+ {module, $(APP)} = code:load_file($(APP)), \
+ {hello, joe} = $(APP):hello(joe), \
+ {hello, mike} = $(APP):hello(mike), \
+ {hello, robert} = $(APP):hello(robert), \
+ halt()"
+
+ $i "Re-build the application"
+ $t $(MAKE) -C $(APP) $v
+
+ $i "Check that all compiled files exist"
+ $t test -f $(APP)/$(APP).d
+ $t test -f $(APP)/c_src/$(APP).o
+ $t test -f $(APP)/c_src/env.mk
+ $t test -f $(APP)/ebin/$(APP).app
+ $t test -f $(APP)/ebin/$(APP).beam
+ifeq ($(PLATFORM),msys2)
+ $t test -f $(APP)/priv/$(APP).dll
+else
+ $t test -f $(APP)/priv/$(APP).so
+endif
+
+ $i "Check that the application was compiled correctly"
+ $t $(ERL) -pa $(APP)/ebin/ -eval " \
+ ok = application:start($(APP)), \
+ {ok, [$(APP)]} = application:get_key($(APP), modules), \
+ {module, $(APP)} = code:load_file($(APP)), \
+ {hello, joe} = $(APP):hello(joe), \
+ {hello, mike} = $(APP):hello(mike), \
+ {hello, robert} = $(APP):hello(robert), \
+ halt()"
+
+ $i "Clean the application"
+ $t $(MAKE) -C $(APP) clean $v
+
+ $i "Check that all intermediate files were removed"
+ $t test ! -e $(APP)/$(APP).d
+ $t test ! -e $(APP)/c_src/$(APP).o
+ $t test ! -e $(APP)/ebin/$(APP).app
+ $t test ! -e $(APP)/ebin/$(APP).beam
+ifeq ($(PLATFORM),msys2)
+ $t test ! -e $(APP)/priv/$(APP).dll
+else
+ $t test ! -e $(APP)/priv/$(APP).so
+endif
+
+ $i "Distclean the application"
+ $t $(MAKE) -C $(APP) distclean $v
+
+ $i "Check that all files were removed"
+ $t test ! -e $(APP)/c_src/env.mk
diff --git a/test/plugin_ct.mk b/test/plugin_ct.mk
new file mode 100644
index 0000000..c32fa36
--- /dev/null
+++ b/test/plugin_ct.mk
@@ -0,0 +1,226 @@
+# Common Test plugin.
+
+CT_CASES = all apps-only case check group opts suite tests
+CT_TARGETS = $(addprefix ct-,$(CT_CASES))
+
+.PHONY: ct $(CT_TARGETS)
+
+ct: $(CT_TARGETS)
+
+ct-all: build clean
+
+ $i "Bootstrap a new OTP application named $(APP)"
+ $t mkdir $(APP)/
+ $t cp ../erlang.mk $(APP)/
+ $t $(MAKE) -C $(APP) -f erlang.mk bootstrap $v
+
+ $i "Check that Common Test detects no tests"
+ $t $(MAKE) -C $(APP) ct | grep -q "Nothing to be done for 'ct'."
+
+ $i "Generate a Common Test suite"
+ $t mkdir $(APP)/test
+ $t printf "%s\n" \
+ "-module($(APP)_SUITE)." \
+ "-export([all/0, ok/1])." \
+ "all() -> [ok]." \
+ "ok(_) -> ok." > $(APP)/test/$(APP)_SUITE.erl
+
+ $i "Check that Common Test runs tests"
+# We can't pipe CT's output without it crashing, so let's check that
+# the command succeeds and log files are created instead.
+ $t test ! -e $(APP)/logs/index.html
+ $t $(MAKE) -C $(APP) ct $v
+ $t test -f $(APP)/logs/index.html
+
+ $i "Generate a Common Test suite with a failing test case"
+ $t printf "%s\n" \
+ "-module($(APP)_fail_SUITE)." \
+ "-export([all/0, fail/1])." \
+ "all() -> [fail]." \
+ "fail(_) -> throw(fail)." > $(APP)/test/$(APP)_fail_SUITE.erl
+
+ $i "Check that Common Test errors out"
+ $t ! $(MAKE) -C $(APP) ct $v
+
+ $i "Check that logs are kept on clean"
+ $t $(MAKE) -C $(APP) clean $v
+ $t test -f $(APP)/logs/index.html
+
+ $i "Check that logs are deleted on distclean"
+ $t $(MAKE) -C $(APP) distclean $v
+ $t test ! -e $(APP)/logs/index.html
+
+ct-apps-only: build clean
+
+ $i "Create a multi application repository with no root application"
+ $t mkdir $(APP)/
+ $t cp ../erlang.mk $(APP)/
+ $t echo "include erlang.mk" > $(APP)/Makefile
+
+ $i "Create a new application named my_app"
+ $t $(MAKE) -C $(APP) new-app in=my_app $v
+
+ $i "Create a new library named my_lib"
+ $t $(MAKE) -C $(APP) new-lib in=my_lib $v
+
+ $i "Populate my_lib"
+ $t printf "%s\n" \
+ "-module(my_lib)." \
+ "-export([random_int/0])." \
+ "random_int() -> 4." > $(APP)/apps/my_lib/src/my_lib.erl
+
+ $i "Check that Common Test detects no tests"
+ $t $(MAKE) -C $(APP) ct | grep -q "Nothing to be done for 'ct'."
+
+ $i "Generate a Common Test suite in my_app"
+ $t mkdir $(APP)/apps/my_app/test
+ $t printf "%s\n" \
+ "-module(my_app_SUITE)." \
+ "-export([all/0, ok/1, call_my_lib/1])." \
+ "all() -> [ok, call_my_lib]." \
+ "ok(_) -> ok." \
+ "call_my_lib(_) -> 4 = my_lib:random_int()." > $(APP)/apps/my_app/test/my_app_SUITE.erl
+
+ $i "Generate a Common Test suite in my_lib"
+ $t mkdir $(APP)/apps/my_lib/test
+ $t printf "%s\n" \
+ "-module(my_lib_SUITE)." \
+ "-export([all/0, ok/1])." \
+ "all() -> [ok]." \
+ "ok(_) -> ok." > $(APP)/apps/my_lib/test/my_lib_SUITE.erl
+
+ $i "Check that Common Test runs tests"
+# We can't pipe CT's output without it crashing, so let's check that
+# the command succeeds and log files are created instead.
+ $t test ! -e $(APP)/apps/my_app/logs/index.html
+ $t test ! -e $(APP)/apps/my_lib/logs/index.html
+ $t $(MAKE) -C $(APP) ct $v
+ $t test -f $(APP)/apps/my_app/logs/index.html
+ $t test -f $(APP)/apps/my_lib/logs/index.html
+
+ct-case: build clean
+
+ $i "Bootstrap a new OTP application named $(APP)"
+ $t mkdir $(APP)/
+ $t cp ../erlang.mk $(APP)/
+ $t $(MAKE) -C $(APP) -f erlang.mk bootstrap $v
+
+ $i "Generate a Common Test suite with two cases"
+ $t mkdir $(APP)/test
+ $t printf "%s\n" \
+ "-module($(APP)_SUITE)." \
+ "-export([all/0, groups/0, ok/1, bad/1])." \
+ "all() -> [{group, mygroup}]." \
+ "groups() -> [{mygroup, [ok, bad]}]." \
+ "ok(_) -> ok." \
+ "bad(_) -> throw(fail)." > $(APP)/test/$(APP)_SUITE.erl
+
+ $i "Check that we can run Common Test on a specific test case"
+ $t $(MAKE) -C $(APP) ct-$(APP) t=mygroup:ok $v
+
+ct-check: build clean
+
+ $i "Bootstrap a new OTP application named $(APP)"
+ $t mkdir $(APP)/
+ $t cp ../erlang.mk $(APP)/
+ $t $(MAKE) -C $(APP) -f erlang.mk bootstrap $v
+
+ $i "Generate a Common Test suite"
+ $t mkdir $(APP)/test
+ $t printf "%s\n" \
+ "-module($(APP)_SUITE)." \
+ "-export([all/0, ok/1])." \
+ "all() -> [ok]." \
+ "ok(_) -> ok." > $(APP)/test/$(APP)_SUITE.erl
+
+ $i "Check that Common Test runs on 'make check'"
+ $t test ! -e $(APP)/logs/index.html
+ $t $(MAKE) -C $(APP) check $v
+ $t test -f $(APP)/logs/index.html
+
+ct-group: build clean
+
+ $i "Bootstrap a new OTP application named $(APP)"
+ $t mkdir $(APP)/
+ $t cp ../erlang.mk $(APP)/
+ $t $(MAKE) -C $(APP) -f erlang.mk bootstrap $v
+
+ $i "Generate a Common Test suite with two groups"
+ $t mkdir $(APP)/test
+ $t printf "%s\n" \
+ "-module($(APP)_SUITE)." \
+ "-export([all/0, groups/0, ok/1, bad/1])." \
+ "all() -> [{group, okgroup}, {group, badgroup}]." \
+ "groups() -> [{okgroup, [ok]}, {badgroup, [bad]}]." \
+ "ok(_) -> ok." \
+ "bad(_) -> throw(fail)." > $(APP)/test/$(APP)_SUITE.erl
+
+ $i "Check that we can run Common Test on a specific group"
+ $t $(MAKE) -C $(APP) ct-$(APP) t=okgroup $v
+
+ct-opts: build clean
+
+ $i "Bootstrap a new OTP application named $(APP)"
+ $t mkdir $(APP)/
+ $t cp ../erlang.mk $(APP)/
+ $t $(MAKE) -C $(APP) -f erlang.mk bootstrap $v
+
+ $i "Set CT_OPTS in the Makefile"
+ $t perl -ni.bak -e 'print;if ($$.==1) {print "CT_OPTS = -label hello_ct_opts\n"}' $(APP)/Makefile
+
+ $i "Generate a Common Test suite"
+ $t mkdir $(APP)/test
+ $t printf "%s\n" \
+ "-module($(APP)_SUITE)." \
+ "-export([all/0, ok/1])." \
+ "all() -> [ok]." \
+ "ok(_) -> ok." > $(APP)/test/$(APP)_SUITE.erl
+
+ $i "Run Common Test"
+ $t $(MAKE) -C $(APP) ct $v
+
+ $i "Check that Common Test uses options from CT_OPTS"
+ $t grep -q hello_ct_opts $(APP)/logs/index.html
+
+ct-suite: build clean
+
+ $i "Bootstrap a new OTP application named $(APP)"
+ $t mkdir $(APP)/
+ $t cp ../erlang.mk $(APP)/
+ $t $(MAKE) -C $(APP) -f erlang.mk bootstrap $v
+
+ $i "Generate two Common Test suites"
+ $t mkdir $(APP)/test
+ $t printf "%s\n" \
+ "-module($(APP)_ok_SUITE)." \
+ "-export([all/0, ok/1])." \
+ "all() -> [ok]." \
+ "ok(_) -> ok." > $(APP)/test/$(APP)_ok_SUITE.erl
+ $t printf "%s\n" \
+ "-module($(APP)_fail_SUITE)." \
+ "-export([all/0, bad/1])." \
+ "all() -> [bad]." \
+ "bad(_) -> throw(fail)." > $(APP)/test/$(APP)_fail_SUITE.erl
+
+ $i "Check that we can run Common Test on a specific test suite"
+ $t $(MAKE) -C $(APP) ct-$(APP)_ok $v
+
+ct-tests: build clean
+
+ $i "Bootstrap a new OTP application named $(APP)"
+ $t mkdir $(APP)/
+ $t cp ../erlang.mk $(APP)/
+ $t $(MAKE) -C $(APP) -f erlang.mk bootstrap $v
+
+ $i "Generate a Common Test suite"
+ $t mkdir $(APP)/test
+ $t printf "%s\n" \
+ "-module($(APP)_SUITE)." \
+ "-export([all/0, ok/1])." \
+ "all() -> [ok]." \
+ "ok(_) -> ok." > $(APP)/test/$(APP)_SUITE.erl
+
+ $i "Check that Common Test runs on 'make tests'"
+ $t test ! -e $(APP)/logs/index.html
+ $t $(MAKE) -C $(APP) tests $v
+ $t test -f $(APP)/logs/index.html
diff --git a/test/plugin_dialyzer.mk b/test/plugin_dialyzer.mk
new file mode 100644
index 0000000..3143319
--- /dev/null
+++ b/test/plugin_dialyzer.mk
@@ -0,0 +1,240 @@
+# Dialyzer plugin.
+
+DIALYZER_CASES = app apps-only apps-with-local-deps check custom-plt deps erlc-opts local-deps opts plt-apps
+DIALYZER_TARGETS = $(addprefix dialyzer-,$(DIALYZER_CASES))
+
+ifneq ($(shell which sem 2>/dev/null),)
+ DIALYZER_MUTEX = sem --fg --id dialyzer
+endif
+
+.PHONY: dialyzer $(C_SRC_TARGETS)
+
+dialyzer: $(DIALYZER_TARGETS)
+
+dialyzer-app: build clean
+
+ $i "Bootstrap a new OTP application named $(APP)"
+ $t mkdir $(APP)/
+ $t cp ../erlang.mk $(APP)/
+ $t $(MAKE) -C $(APP) -f erlang.mk bootstrap $v
+
+ $i "Run Dialyzer"
+ $t $(DIALYZER_MUTEX) $(MAKE) -C $(APP) dialyze $v
+
+ $i "Check that the PLT file was created"
+ $t test -f $(APP)/.$(APP).plt
+
+ $i "Create a module with a function that has no local return"
+ $t printf "%s\n" \
+ "-module(warn_me)." \
+ "doit() -> 1 = 2, ok." > $(APP)/src/warn_me.erl
+
+ $i "Confirm that Dialyzer errors out"
+ $t ! $(DIALYZER_MUTEX) $(MAKE) -C $(APP) dialyze $v
+
+ $i "Distclean the application"
+ $t $(MAKE) -C $(APP) distclean $v
+
+ $i "Check that the PLT file was removed"
+ $t test ! -e $(APP)/.$(APP).plt
+
+dialyzer-apps-only: build clean
+
+ $i "Create a multi application repository with no root application"
+ $t mkdir $(APP)/
+ $t cp ../erlang.mk $(APP)/
+ $t echo "include erlang.mk" > $(APP)/Makefile
+
+ $i "Create a new application my_app"
+ $t $(MAKE) -C $(APP) new-app in=my_app $v
+
+ $i "Create a module my_server from gen_server template in my_app"
+ $t $(MAKE) -C $(APP) new t=gen_server n=my_server in=my_app $v
+
+ $i "Add Cowlib to the list of dependencies"
+ $t perl -ni.bak -e 'print;if ($$.==1) {print "DEPS = cowlib\n"}' $(APP)/apps/my_app/Makefile
+
+ $i "Run Dialyzer"
+ $t $(DIALYZER_MUTEX) $(MAKE) -C $(APP) dialyze $v
+
+ $i "Check that the PLT file was created automatically"
+ $t test -f $(APP)/.$(APP).plt
+
+ $i "Confirm that Cowlib was included in the PLT"
+ $t dialyzer --plt_info --plt $(APP)/.$(APP).plt | grep -q cowlib
+
+ $i "Create a module with a function that has no local return"
+ $t printf "%s\n" \
+ "-module(warn_me)." \
+ "doit() -> 1 = 2, ok." > $(APP)/apps/my_app/src/warn_me.erl
+
+ $i "Confirm that Dialyzer errors out"
+ $t ! $(DIALYZER_MUTEX) $(MAKE) -C $(APP) dialyze $v
+
+dialyzer-apps-with-local-deps: build clean
+
+ $i "Create a multi application repository with no root application"
+ $t mkdir $(APP)/
+ $t cp ../erlang.mk $(APP)/
+ $t echo "include erlang.mk" > $(APP)/Makefile
+
+ $i "Create a new application my_app"
+ $t $(MAKE) -C $(APP) new-app in=my_app $v
+
+ $i "Create a new application my_core_app"
+ $t $(MAKE) -C $(APP) new-app in=my_core_app $v
+
+ $i "Add my_core_app to the list of local dependencies for my_app"
+ $t perl -ni.bak -e 'print;if ($$.==1) {print "LOCAL_DEPS = my_core_app\n"}' $(APP)/apps/my_app/Makefile
+
+ $i "Run Dialyzer"
+ $t $(DIALYZER_MUTEX) $(MAKE) -C $(APP) dialyze $v
+
+ $i "Check that the PLT file was created automatically"
+ $t test -f $(APP)/.$(APP).plt
+
+ $i "Confirm that my_core_app was NOT included in the PLT"
+ $t ! dialyzer --plt_info --plt $(APP)/.$(APP).plt | grep -q my_core_app
+
+dialyzer-check: build clean
+
+ $i "Bootstrap a new OTP application named $(APP)"
+ $t mkdir $(APP)/
+ $t cp ../erlang.mk $(APP)/
+ $t $(MAKE) -C $(APP) -f erlang.mk bootstrap $v
+
+ $i "Run 'make check'"
+ $t $(DIALYZER_MUTEX) $(MAKE) -C $(APP) check $v
+
+ $i "Check that the PLT file was created"
+ $t test -f $(APP)/.$(APP).plt
+
+ $i "Create a module with a function that has no local return"
+ $t printf "%s\n" \
+ "-module(warn_me)." \
+ "doit() -> 1 = 2, ok." > $(APP)/src/warn_me.erl
+
+ $i "Confirm that Dialyzer errors out on 'make check'"
+ $t ! $(DIALYZER_MUTEX) $(MAKE) -C $(APP) check $v
+
+dialyzer-custom-plt: build clean
+
+ $i "Bootstrap a new OTP application named $(APP)"
+ $t mkdir $(APP)/
+ $t cp ../erlang.mk $(APP)/
+ $t $(MAKE) -C $(APP) -f erlang.mk bootstrap $v
+
+ $i "Set a custom DIALYZER_PLT location"
+ $t perl -ni.bak -e 'print;if ($$.==1) {print "DIALYZER_PLT = custom.plt\n"}' $(APP)/Makefile
+
+ $i "Run Dialyzer"
+ $t $(DIALYZER_MUTEX) $(MAKE) -C $(APP) dialyze $v
+
+ $i "Check that the PLT file was created"
+ $t test -f $(APP)/custom.plt
+
+ $i "Distclean the application"
+ $t $(MAKE) -C $(APP) distclean $v
+
+ $i "Check that the PLT file was removed"
+ $t test ! -e $(APP)/custom.plt
+
+dialyzer-deps: build clean
+
+ $i "Bootstrap a new OTP application named $(APP)"
+ $t mkdir $(APP)/
+ $t cp ../erlang.mk $(APP)/
+ $t $(MAKE) -C $(APP) -f erlang.mk bootstrap $v
+
+ $i "Add Cowlib to the list of dependencies"
+ $t perl -ni.bak -e 'print;if ($$.==1) {print "DEPS = cowlib\n"}' $(APP)/Makefile
+
+ $i "Run Dialyzer"
+ $t $(DIALYZER_MUTEX) $(MAKE) -C $(APP) dialyze $v
+
+ $i "Check that the PLT file was created"
+ $t test -f $(APP)/.$(APP).plt
+
+ $i "Confirm that Cowlib was included in the PLT"
+ $t dialyzer --plt_info --plt $(APP)/.$(APP).plt | grep -q cowlib
+
+dialyzer-erlc-opts: build clean
+
+ $i "Bootstrap a new OTP application named $(APP)"
+ $t mkdir $(APP)/
+ $t cp ../erlang.mk $(APP)/
+ $t $(MAKE) -C $(APP) -f erlang.mk bootstrap $v
+
+ $i "Create a header file in a non-standard directory"
+ $t mkdir $(APP)/exotic/
+ $t touch $(APP)/exotic/dialyze.hrl
+
+ $i "Create a module that includes this header"
+ $t printf "%s\n" \
+ "-module(no_warn)." \
+ "-export([doit/0])." \
+ "-include(\"dialyze.hrl\")." \
+ "doit() -> ok." > $(APP)/src/no_warn.erl
+
+ $i "Point ERLC_OPTS to the non-standard include directory"
+ $t perl -ni.bak -e 'print;if ($$.==1) {print "ERLC_OPTS += -I exotic\n"}' $(APP)/Makefile
+
+ $i "Run Dialyzer"
+ $t $(DIALYZER_MUTEX) $(MAKE) -C $(APP) dialyze $v
+
+dialyzer-local-deps: build clean
+
+ $i "Bootstrap a new OTP application named $(APP)"
+ $t mkdir $(APP)/
+ $t cp ../erlang.mk $(APP)/
+ $t $(MAKE) -C $(APP) -f erlang.mk bootstrap $v
+
+ $i "Add runtime_tools to the list of local dependencies"
+ $t perl -ni.bak -e 'print;if ($$.==1) {print "LOCAL_DEPS = runtime_tools\n"}' $(APP)/Makefile
+
+ $i "Build the PLT"
+ $t $(DIALYZER_MUTEX) $(MAKE) -C $(APP) plt $v
+
+ $i "Confirm that runtime_tools was included in the PLT"
+ $t dialyzer --plt_info --plt $(APP)/.$(APP).plt | grep -q runtime_tools
+
+dialyzer-opts: build clean
+
+ $i "Bootstrap a new OTP application named $(APP)"
+ $t mkdir $(APP)/
+ $t cp ../erlang.mk $(APP)/
+ $t $(MAKE) -C $(APP) -f erlang.mk bootstrap $v
+
+ $i "Make Dialyzer save output to a file"
+ $t perl -ni.bak -e 'print;if ($$.==1) {print "DIALYZER_OPTS = -o output.txt\n"}' $(APP)/Makefile
+
+ $i "Create a module with a function that has no local return"
+ $t printf "%s\n" \
+ "-module(warn_me)." \
+ "-export([doit/0])." \
+ "doit() -> gen_tcp:connect(a, b, c), ok." > $(APP)/src/warn_me.erl
+
+ $i "Run Dialyzer"
+ $t ! $(DIALYZER_MUTEX) $(MAKE) -C $(APP) dialyze $v
+
+ $i "Check that the PLT file was created"
+ $t test -f $(APP)/.$(APP).plt
+
+ $i "Check that the output file was created"
+ $t test -f $(APP)/output.txt
+
+dialyzer-plt-apps: build clean
+
+ $i "Bootstrap a new OTP application named $(APP)"
+ $t mkdir $(APP)/
+ $t cp ../erlang.mk $(APP)/
+ $t $(MAKE) -C $(APP) -f erlang.mk bootstrap $v
+
+ $i "Add runtime_tools to PLT_APPS"
+ $t perl -ni.bak -e 'print;if ($$.==1) {print "PLT_APPS = runtime_tools\n"}' $(APP)/Makefile
+
+ $i "Build the PLT"
+ $t $(DIALYZER_MUTEX) $(MAKE) -C $(APP) plt $v
+
+ $i "Confirm that runtime_tools was included in the PLT"
+ $t dialyzer --plt_info --plt $(APP)/.$(APP).plt | grep -q runtime_tools
diff --git a/test/plugin_edoc.mk b/test/plugin_edoc.mk
new file mode 100644
index 0000000..33f3d0f
--- /dev/null
+++ b/test/plugin_edoc.mk
@@ -0,0 +1,112 @@
+# EDoc plugin.
+
+EDOC_CASES = build docs no-overview opts
+EDOC_TARGETS = $(addprefix edoc-,$(EDOC_CASES))
+
+.PHONY: edoc $(EDOC_TARGETS)
+
+edoc: $(EDOC_TARGETS)
+
+edoc-build: build clean
+
+ $i "Bootstrap a new OTP application named $(APP)"
+ $t mkdir $(APP)/
+ $t cp ../erlang.mk $(APP)/
+ $t $(MAKE) -C $(APP) -f erlang.mk bootstrap $v
+
+ $i "Run EDoc"
+ $t $(MAKE) -C $(APP) edoc $v
+
+ $i "Check that documentation was generated"
+ $t test -f $(APP)/doc/index.html
+ $t test -f $(APP)/doc/$(APP)_app.html
+ $t test -f $(APP)/doc/$(APP)_sup.html
+
+ $i "Distclean the application"
+ $t $(MAKE) -C $(APP) distclean $v
+
+ $i "Check that the generated documentation was removed"
+ $t test ! -e $(APP)/doc/index.html
+ $t test ! -e $(APP)/doc/$(APP)_app.html
+ $t test ! -e $(APP)/doc/$(APP)_sup.html
+
+ $i "Generate a module with EDoc comments"
+ $t printf "%s\n" \
+ "%% @doc erlang-mk-edoc-module" \
+ "-module($(APP))." \
+ "-export([ok/0])." \
+ "" \
+ "%% @doc erlang-mk-edoc-function" \
+ "ok() -> ok." > $(APP)/src/$(APP).erl
+
+ $i "Run EDoc"
+ $t $(MAKE) -C $(APP) edoc $v
+
+ $i "Check that the new module's documentation was generated"
+ $t test -f $(APP)/doc/$(APP).html
+
+ $i "Check that the EDoc comments are in the generated documentation"
+ $t grep -q erlang-mk-edoc-module $(APP)/doc/$(APP).html
+ $t grep -q erlang-mk-edoc-function $(APP)/doc/$(APP).html
+
+ $i "Generate a module with an invalid EDoc comment"
+ $t printf "%s\n" \
+ "-module($(APP)_fail)." \
+ "-export([fail/0])." \
+ "%% @spec lol" \
+ "fail() -> fail." > $(APP)/src/$(APP)_fail.erl
+
+ $i "Check that EDoc errors out"
+ $t ! $(MAKE) -C $(APP) edoc $v
+
+edoc-docs: build clean
+
+ $i "Bootstrap a new OTP application named $(APP)"
+ $t mkdir $(APP)/
+ $t cp ../erlang.mk $(APP)/
+ $t $(MAKE) -C $(APP) -f erlang.mk bootstrap $v
+
+ $i "Generate a doc/overview.edoc file"
+ $t mkdir $(APP)/doc
+ $t printf "%s\n" \
+ "@author R. J. Hacker <[email protected]>" \
+ "@copyright 2007 R. J. Hacker" \
+ "@version 1.0.0" \
+ "@title Welcome to the 'frob' application!" \
+ "@doc 'frob' is a highly advanced frobnicator with low latency," > $(APP)/doc/overview.edoc
+
+ $i "Check that EDoc runs on 'make docs'"
+ $t $(MAKE) -C $(APP) docs $v
+ $t test -f $(APP)/doc/index.html
+
+ $i "Check that the overview.edoc file was used"
+ $t grep -q frobnicator $(APP)/doc/overview-summary.html
+
+edoc-no-overview: build clean
+
+ $i "Bootstrap a new OTP application named $(APP)"
+ $t mkdir $(APP)/
+ $t cp ../erlang.mk $(APP)/
+ $t $(MAKE) -C $(APP) -f erlang.mk bootstrap $v
+
+ $i "Check that EDoc doesn't run on 'make docs'"
+ $t $(MAKE) -C $(APP) docs $v
+ $t test ! -e $(APP)/doc/index.html
+
+edoc-opts: build clean
+
+ $i "Bootstrap a new OTP application named $(APP)"
+ $t mkdir $(APP)/
+ $t cp ../erlang.mk $(APP)/
+ $t $(MAKE) -C $(APP) -f erlang.mk bootstrap $v
+
+ $i "Add edown doclet for EDoc"
+ $t perl -ni.bak -e 'print;if ($$.==1) {print "DOC_DEPS = edown\nEDOC_OPTS = {doclet, edown_doclet}\n"}' $(APP)/Makefile
+
+ $i "Run EDoc"
+ $t $(MAKE) -C $(APP) edoc $v
+
+ $i "Check that the Markdown documentation was generated"
+ $t test -f $(APP)/doc/README.md
+ $t test -f $(APP)/doc/$(APP)_app.md
+ $t test -f $(APP)/doc/$(APP)_sup.md
diff --git a/test/plugin_erlydtl.mk b/test/plugin_erlydtl.mk
index acfd74c..b96596d 100644
--- a/test/plugin_erlydtl.mk
+++ b/test/plugin_erlydtl.mk
@@ -2,18 +2,12 @@
ERLYDTL_CASES = compile full-path
ERLYDTL_TARGETS = $(addprefix erlydtl-,$(ERLYDTL_CASES))
-ERLYDTL_CLEAN_TARGETS = $(addprefix clean-,$(ERLYDTL_TARGETS))
-.PHONY: erlydtl $(ERLYDTL_TARGETS) clean-erlydtl $(ERLYDTL_CLEAN_TARGETS)
-
-clean-erlydtl: $(ERLYDTL_CLEAN_TARGETS)
-
-$(ERLYDTL_CLEAN_TARGETS):
- $t rm -rf $(APP_TO_CLEAN)/
+.PHONY: erlydtl $(ERLYDTL_TARGETS)
erlydtl: $(ERLYDTL_TARGETS)
-erlydtl-compile: build clean-erlydtl-compile
+erlydtl-compile: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -41,7 +35,7 @@ erlydtl-compile: build clean-erlydtl-compile
{ok, [$(APP_)_one_dtl, $(APP)_two_dtl]} = application:get_key($(APP), modules), \
halt()"
-erlydtl-full-path: build clean-erlydtl-full-path
+erlydtl-full-path: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
diff --git a/test/plugin_eunit.mk b/test/plugin_eunit.mk
new file mode 100644
index 0000000..c25484b
--- /dev/null
+++ b/test/plugin_eunit.mk
@@ -0,0 +1,210 @@
+# EUnit plugin.
+
+EUNIT_CASES = all apps-only check erl-opts fun mod test-dir tests
+EUNIT_TARGETS = $(addprefix eunit-,$(EUNIT_CASES))
+
+.PHONY: eunit $(EUNIT_TARGETS)
+
+eunit: $(EUNIT_TARGETS)
+
+eunit-all: build clean
+
+ $i "Bootstrap a new OTP application named $(APP)"
+ $t mkdir $(APP)/
+ $t cp ../erlang.mk $(APP)/
+ $t $(MAKE) -C $(APP) -f erlang.mk bootstrap $v
+
+ $i "Check that EUnit detects no tests"
+ $t $(MAKE) -C $(APP) eunit | grep -q "There were no tests to run."
+
+ $i "Generate a module containing EUnit tests"
+ $t printf "%s\n" \
+ "-module($(APP))." \
+ "-ifdef(TEST)." \
+ "-include_lib(\"eunit/include/eunit.hrl\")." \
+ "ok_test() -> ok." \
+ "-endif." > $(APP)/src/$(APP).erl
+
+ $i "Build the project cleanly"
+ $t $(MAKE) -C $(APP) clean $v
+ $t $(MAKE) -C $(APP) $v
+
+ $i "Check that no EUnit test cases were exported"
+ $t $(ERL) -pa $(APP)/ebin -eval 'code:load_file($(APP)), false = erlang:function_exported($(APP), ok_test, 0), halt()'
+
+ $i "Check that EUnit runs tests"
+ $t $(MAKE) -C $(APP) eunit | grep -q "Test passed."
+
+ $i "Add a failing test to the module"
+ $t printf "%s\n" \
+ "-ifdef(TEST)." \
+ "bad_test() -> throw(fail)." \
+ "-endif." >> $(APP)/src/$(APP).erl
+
+ $i "Check that EUnit errors out"
+ $t ! $(MAKE) -C $(APP) eunit $v
+
+eunit-apps-only: build clean
+
+ $i "Create a multi application repository with no root application"
+ $t mkdir $(APP)/
+ $t cp ../erlang.mk $(APP)/
+ $t echo "include erlang.mk" > $(APP)/Makefile
+
+ $i "Create a new application named my_app"
+ $t $(MAKE) -C $(APP) new-app in=my_app $v
+
+ $i "Create a new library named my_lib"
+ $t $(MAKE) -C $(APP) new-lib in=my_lib $v
+
+ $i "Check that EUnit detects no tests"
+ $t $(MAKE) -C $(APP) eunit | grep -q "There were no tests to run."
+
+ $i "Generate a module containing EUnit tests in my_app"
+ $t printf "%s\n" \
+ "-module(my_app)." \
+ "-ifdef(TEST)." \
+ "-include_lib(\"eunit/include/eunit.hrl\")." \
+ "ok_test() -> ok." \
+ "-endif." > $(APP)/apps/my_app/src/my_app.erl
+
+ $i "Generate a module containing EUnit tests in my_lib"
+ $t printf "%s\n" \
+ "-module(my_lib)." \
+ "-ifdef(TEST)." \
+ "-include_lib(\"eunit/include/eunit.hrl\")." \
+ "ok_test() -> ok." \
+ "-endif." > $(APP)/apps/my_lib/src/my_lib.erl
+
+ $i "Check that EUnit runs tests"
+ $t $(MAKE) -C $(APP) eunit | grep -q "Test passed."
+
+eunit-check: build clean
+
+ $i "Bootstrap a new OTP application named $(APP)"
+ $t mkdir $(APP)/
+ $t cp ../erlang.mk $(APP)/
+ $t $(MAKE) -C $(APP) -f erlang.mk bootstrap $v
+
+ $i "Generate a module containing EUnit tests"
+ $t printf "%s\n" \
+ "-module($(APP))." \
+ "-ifdef(TEST)." \
+ "-include_lib(\"eunit/include/eunit.hrl\")." \
+ "ok_test() -> ok." \
+ "-endif." > $(APP)/src/$(APP).erl
+
+ $i "Check that EUnit runs on 'make check'"
+ $t $(MAKE) -C $(APP) check | grep -q "Test passed."
+
+eunit-erl-opts: build clean
+
+ $i "Bootstrap a new OTP application named $(APP)"
+ $t mkdir $(APP)/
+ $t cp ../erlang.mk $(APP)/
+ $t $(MAKE) -C $(APP) -f erlang.mk bootstrap $v
+
+ $i "Set EUNIT_ERL_OPTS in the Makefile"
+ $t perl -ni.bak -e 'print;if ($$.==1) {print "EUNIT_ERL_OPTS = -eval \"erlang:display(hello).\" \n"}' $(APP)/Makefile
+
+ $i "Generate a module containing EUnit tests"
+ $t printf "%s\n" \
+ "-module($(APP))." \
+ "-ifdef(TEST)." \
+ "-include_lib(\"eunit/include/eunit.hrl\")." \
+ "ok_test() -> ok." \
+ "-endif." > $(APP)/src/$(APP).erl
+
+ $i "Check that EUnit uses EUNIT_ERL_OPTS"
+ $t $(MAKE) -C $(APP) eunit | grep -q "hello"
+
+eunit-fun: build clean
+
+ $i "Bootstrap a new OTP application named $(APP)"
+ $t mkdir $(APP)/
+ $t cp ../erlang.mk $(APP)/
+ $t $(MAKE) -C $(APP) -f erlang.mk bootstrap $v
+
+ $i "Generate a module containing EUnit tests"
+ $t printf "%s\n" \
+ "-module($(APP))." \
+ "-ifdef(TEST)." \
+ "-include_lib(\"eunit/include/eunit.hrl\")." \
+ "ok_test() -> ok." \
+ "bad_test() -> throw(fail)." \
+ "-endif." > $(APP)/src/$(APP).erl
+
+ $i "Check that we can run EUnit on a specific test"
+ $t $(MAKE) -C $(APP) eunit t=$(APP):ok_test $v
+
+eunit-mod: build clean
+
+ $i "Bootstrap a new OTP application named $(APP)"
+ $t mkdir $(APP)/
+ $t cp ../erlang.mk $(APP)/
+ $t $(MAKE) -C $(APP) -f erlang.mk bootstrap $v
+
+ $i "Generate a module containing EUnit tests"
+ $t printf "%s\n" \
+ "-module($(APP))." \
+ "-ifdef(TEST)." \
+ "-include_lib(\"eunit/include/eunit.hrl\")." \
+ "ok_test() -> ok." \
+ "-endif." > $(APP)/src/$(APP).erl
+
+ $i "Generate a module containing failing EUnit tests"
+ $t printf "%s\n" \
+ "-module($(APP)_fail)." \
+ "-ifdef(TEST)." \
+ "-include_lib(\"eunit/include/eunit.hrl\")." \
+ "bad_test() -> throw(fail)." \
+ "-endif." > $(APP)/src/$(APP)_fail.erl
+
+ $i "Check that we can run EUnit on a specific module"
+ $t $(MAKE) -C $(APP) eunit t=$(APP) $v
+
+eunit-test-dir: build clean
+
+ $i "Bootstrap a new OTP application named $(APP)"
+ $t mkdir $(APP)/
+ $t cp ../erlang.mk $(APP)/
+ $t $(MAKE) -C $(APP) -f erlang.mk bootstrap $v
+
+ $i "Generate a module containing EUnit tests"
+ $t printf "%s\n" \
+ "-module($(APP))." \
+ "-ifdef(TEST)." \
+ "-include_lib(\"eunit/include/eunit.hrl\")." \
+ "log_test() -> os:cmd(\"echo $(APP) >> eunit.log\")." \
+ "-endif." > $(APP)/src/$(APP).erl
+
+ $i "Generate a module containing EUnit tests in TEST_DIR"
+ $t mkdir $(APP)/test
+ $t printf "%s\n" \
+ "-module($(APP)_tests)." \
+ "-include_lib(\"eunit/include/eunit.hrl\")." \
+ "log_test() -> os:cmd(\"echo $(APP)_tests >> eunit.log\")." > $(APP)/test/$(APP)_tests.erl
+
+ $i "Check that EUnit runs both tests"
+ $t $(MAKE) -C $(APP) eunit | grep -q "2 tests passed."
+
+ $i "Check that tests were both run only once"
+ $t printf "%s\n" $(APP) $(APP)_tests | cmp $(APP)/eunit.log -
+
+eunit-tests: build clean
+
+ $i "Bootstrap a new OTP application named $(APP)"
+ $t mkdir $(APP)/
+ $t cp ../erlang.mk $(APP)/
+ $t $(MAKE) -C $(APP) -f erlang.mk bootstrap $v
+
+ $i "Generate a module containing EUnit tests"
+ $t printf "%s\n" \
+ "-module($(APP))." \
+ "-ifdef(TEST)." \
+ "-include_lib(\"eunit/include/eunit.hrl\")." \
+ "ok_test() -> ok." \
+ "-endif." > $(APP)/src/$(APP).erl
+
+ $i "Check that EUnit runs on 'make tests'"
+ $t $(MAKE) -C $(APP) tests | grep -q "Test passed."
diff --git a/test/plugin_shell.mk b/test/plugin_shell.mk
index 474ef92..3db7bba 100644
--- a/test/plugin_shell.mk
+++ b/test/plugin_shell.mk
@@ -2,18 +2,12 @@
SHELL_CASES = default kjell
SHELL_TARGETS = $(addprefix shell-,$(SHELL_CASES))
-SHELL_CLEAN_TARGETS = $(addprefix clean-,$(SHELL_TARGETS))
-.PHONY: shell $(C_SRC_TARGETS) clean-shell $(SHELL_CLEAN_TARGETS)
-
-clean-shell: $(SHELL_CLEAN_TARGETS)
-
-$(SHELL_CLEAN_TARGETS):
- $t rm -rf $(APP_TO_CLEAN)/
+.PHONY: shell $(C_SRC_TARGETS)
shell: $(SHELL_TARGETS)
-shell-default: build clean-shell-default
+shell-default: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/
@@ -23,7 +17,7 @@ shell-default: build clean-shell-default
$i "Run the shell"
$t $(MAKE) -C $(APP) shell SHELL_OPTS="-eval 'halt()'" $v
-shell-kjell: build clean-shell-kjell
+shell-kjell: build clean
$i "Bootstrap a new OTP library named $(APP)"
$t mkdir $(APP)/