From ba27f059fb88fea41df52adafac670970a963c9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Hoguin?= Date: Wed, 1 May 2013 00:42:48 +0200 Subject: Initial commit --- LICENSE | 13 +++++++ README.md | 76 ++++++++++++++++++++++++++++++++++++ erlang.mk | 129 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 218 insertions(+) create mode 100644 LICENSE create mode 100644 README.md create mode 100644 erlang.mk diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..3e227ee --- /dev/null +++ b/LICENSE @@ -0,0 +1,13 @@ +Copyright (c) 2013, Loïc Hoguin + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..a8794a6 --- /dev/null +++ b/README.md @@ -0,0 +1,76 @@ +erlang.mk +========= + +Common Makefile rules for building and testing Erlang applications. + +Usage +----- + +Add the file `erlang.mk` to your project, then use the following base +Makefile: + +``` Makefile +PROJECT = my_project + +include erlang.mk +``` + +Dependencies +------------ + +Erlang projects often depend on other projects to run. Adding dependencies +to the Makefile is easy. You need to create the variable `DEPS` listing +the names of all the dependencies, along with one `dep_$(NAME)` variable +per dependency giving the git repository and commit to retrieve. + +These variables should be defined before the include line. + +``` Makefile +DEPS = cowboy bullet +dep_cowboy = https://github.com/extend/cowboy.git 0.8.4 +dep_bullet = https://github.com/extend/bullet.git 0.4.1 +``` + +They will always be compiled using the command `make`. + +Options +------- + +The following variables can be overriden: + +`V` defines the verbosity of the commands. You can set it +to an empty value to make commands verbose. + +`ERLC_OPTS` allows you to change the `erlc` compilation +options. You should always compile with at least the `+debug_info` set. + +`COMPILE_FIRST` is a list of modules (not filenames) that should be +compiled before all others. + +`DEPS_DIR` is the path to the directory where the dependencies are +downloaded to. It defaults to `deps`. It will be propagated into +all the subsequent make calls, allowing all dependencies to use +the same folder as expected. + +`CT_SUITES` is the list of common_test suites to run when you use +the `make tests` command. If your suite module is named `ponies_SUITE` +then you only need to put `ponies` in the list. + +`PLT_APPS` is the list of applications to include when building the +`.plt` file for Dialyzer. You do not need to put `erts`, `kernel` or +`stdlib` in there because they will always be included. The applications +the project depends on will also be included. + +`DIALYZER_OPTS` allows you to change the `dialyzer` options. + +Extra targets +------------- + +If you need more functionality out of your Makefile, you can add extra +targets after the include line. + +Support +------- + + * Official IRC Channel: #ninenines on irc.freenode.net + * [Mailing Lists](http://lists.ninenines.eu) diff --git a/erlang.mk b/erlang.mk new file mode 100644 index 0000000..50e2530 --- /dev/null +++ b/erlang.mk @@ -0,0 +1,129 @@ +# Copyright (c) 2013, Loïc Hoguin +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +# Verbosity and tweaks. + +V ?= 0 + +appsrc_verbose_0 = @echo " APP " $(PROJECT).app.src; +appsrc_verbose = $(appsrc_verbose_$(V)) + +erlc_verbose_0 = @echo " ERLC " $(?F); +erlc_verbose = $(erlc_verbose_$(V)) + +gen_verbose_0 = @echo " GEN " $@; +gen_verbose = $(gen_verbose_$(V)) + +.PHONY: all clean-all app clean deps clean-deps docs clean-docs \ + build-tests tests build-plt dialyze + +# Deps directory. + +DEPS_DIR ?= $(CURDIR)/deps +export DEPS_DIR + +ALL_DEPS_DIRS = $(addprefix $(DEPS_DIR)/,$(DEPS)) + +# Application. + +ERLC_OPTS ?= -Werror +debug_info +warn_export_all +warn_export_vars \ + +warn_shadow_vars +warn_obsolete_guard # +bin_opt_info +warn_missing_spec +COMPILE_FIRST ?= +COMPILE_FIRST_PATHS = $(addprefix src/,$(addsuffix .erl,$(COMPILE_FIRST))) + +all: deps app + +clean-all: clean clean-deps clean-docs + $(gen_verbose) rm -rf .$(PROJECT).plt $(DEPS_DIR) logs + +MODULES = $(shell ls src/*.erl | sed 's/src\///;s/\.erl/,/' | sed '$$s/.$$//') + +app: ebin/$(PROJECT).app + $(appsrc_verbose) cat src/$(PROJECT).app.src \ + | sed 's/{modules, \[\]}/{modules, \[$(MODULES)\]}/' \ + > ebin/$(PROJECT).app + +ebin/$(PROJECT).app: src/*.erl + @mkdir -p ebin/ + $(erlc_verbose) erlc -v $(ERLC_OPTS) -o ebin/ -pa ebin/ \ + $(COMPILE_FIRST_PATHS) $? + +clean: + $(gen_verbose) rm -rf ebin/ test/*.beam erl_crash.dump + +# Dependencies. + +define get_dep = + @mkdir -p $(DEPS_DIR) + git clone -n -- $(word 1,$(dep_$(1))) $(DEPS_DIR)/$(1) + cd $(DEPS_DIR)/$(1) ; git checkout -q $(word 2,$(dep_$(1))) +endef + +define dep_target = +$(DEPS_DIR)/$(1): + $(call get_dep,$(1)) +endef + +$(foreach dep,$(DEPS),$(eval $(call dep_target,$(dep)))) + +deps: $(ALL_DEPS_DIRS) + @for dep in $(ALL_DEPS_DIRS) ; do $(MAKE) -C $$dep; done + +clean-deps: + @for dep in $(ALL_DEPS_DIRS) ; do $(MAKE) -C $$dep clean; done + +# Documentation. + +docs: clean-docs + $(gen_verbose) erl -noshell \ + -eval 'edoc:application($(PROJECT), ".", []), init:stop().' + +clean-docs: + $(gen_verbose) rm -f doc/*.css doc/*.html doc/*.png doc/edoc-info + +# Tests. + +build-tests: + $(gen_verbose) erlc -v $(ERLC_OPTS) -o test/ \ + $(wildcard test/*.erl test/*/*.erl) -pa ebin/ + +CT_RUN = ct_run \ + -no_auto_compile \ + -noshell \ + -pa ebin $(DEPS_DIR)/*/ebin \ + -dir test \ + -logdir logs +# -cover test/cover.spec + +CT_SUITES ?= +CT_SUITES_FULL = $(addsuffix _SUITE,$(CT_SUITES)) + +tests: ERLC_OPTS += -DTEST=1 +'{parse_transform, eunit_autoexport}' +tests: clean clean-deps deps app build-tests + @mkdir -p logs/ + @$(CT_RUN) -suite $(CT_SUITES_FULL) + $(gen_verbose) rm -f test/*.beam + +# Dialyzer. + +PLT_APPS ?= +DIALYZER_OPTS ?= -Werror_handling -Wrace_conditions \ + -Wunmatched_returns # -Wunderspecs + +build-plt: deps app + @dialyzer --build_plt --output_plt .$(PROJECT).plt \ + --apps erts kernel stdlib $(PLT_APPS) $(ALL_DEPS_DIR) + +dialyze: + @dialyzer --src src --plt .$(PROJECT).plt --no_native $(DIALYZER_OPTS) -- cgit v1.2.3