diff options
-rw-r--r-- | README.md | 61 | ||||
-rw-r--r-- | build.config | 2 | ||||
-rw-r--r-- | core/core.mk | 16 | ||||
-rw-r--r-- | core/deps.mk | 47 | ||||
-rw-r--r-- | core/erlc.mk | 22 | ||||
-rw-r--r-- | core/test.mk | 44 | ||||
-rw-r--r-- | erlang.mk | 280 | ||||
-rw-r--r-- | plugins/ct.mk | 60 | ||||
-rw-r--r-- | plugins/elvis.mk | 10 | ||||
-rw-r--r-- | plugins/eunit.mk | 50 | ||||
-rw-r--r-- | plugins/triq.mk | 29 | ||||
-rw-r--r-- | test/Makefile | 20 |
12 files changed, 428 insertions, 213 deletions
@@ -138,6 +138,24 @@ dep_ct_helper = git https://github.com/extend/ct_helper.git master Please note that the test dependencies will only be compiled once when they are fetched, unlike the normal dependencies. +Autopatch +--------- + +The autopatch features allows you to automatically fix packages +that are not compatible with erlang.mk. It can also be used to +convert compatible packages to use erlang.mk itself for building +when used as dependency. + +The patching occurs only once, immediately after the package has +been fetched. + +erlang.mk defines a number of packages to be patched. You can add +more packages to the list by appending the `AUTOPATCH` variable. + +``` Makefile +AUTOPATCH += gproc +``` + Releases -------- @@ -215,12 +233,18 @@ 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 +MAKEFLAGS="-j32 -O" ``` Core package functionality @@ -252,6 +276,9 @@ You can change compilation options by setting the `ERLC_OPTS` variable. It takes the arguments that will then be passed to `erlc`. For more information, please see `erl -man erlc`. +Test target compilation options can be specified in `TEST_ERLC_OPTS`. +It will override `ERLC_OPTS`. + You can specify a list of modules to be compiled first using the `COMPILE_FIRST` variable. @@ -325,7 +352,10 @@ The defaults are system dependent. Common_test plugin ------------------ -This plugin is available by default. +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 @@ -438,9 +468,8 @@ EUnit plugin This plugin is available by default. It adds the following target: -`eunit` which runs all the EUnit tests found in `ebin` and -any of the additional EUnit directories specified in -`EUNIT_DIR`. +`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 @@ -487,6 +516,28 @@ 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 +``` + Contributing ------------ diff --git a/build.config b/build.config index 8b6e721..7e60d80 100644 --- a/build.config +++ b/build.config @@ -5,6 +5,7 @@ core/core core/deps core/erlc +core/test # Plugins. # @@ -20,3 +21,4 @@ plugins/escript plugins/eunit plugins/relx plugins/shell +plugins/triq diff --git a/core/core.mk b/core/core.mk index 95b4c57..8622be2 100644 --- a/core/core.mk +++ b/core/core.mk @@ -38,16 +38,20 @@ ifneq ($(words $(MAKECMDGOALS)),1) .NOTPARALLEL: endif -all:: - @$(MAKE) --no-print-directory deps +all:: deps @$(MAKE) --no-print-directory app -# @todo Plugin stuff creeping inside Core, not good. -ifneq ($(wildcard $(RELX_CONFIG)),) @$(MAKE) --no-print-directory rel -endif -clean:: +# Noop to avoid a Make warning when there's nothing to do. +rel:: + @echo -n + +clean:: clean-crashdump + +clean-crashdump: +ifneq ($(wildcard erl_crash.dump),) $(gen_verbose) rm -f erl_crash.dump +endif distclean:: clean diff --git a/core/deps.mk b/core/deps.mk index 7d4b974..35fefb5 100644 --- a/core/deps.mk +++ b/core/deps.mk @@ -5,6 +5,9 @@ # Configuration. +AUTOPATCH ?= edown gen_leader gproc +export AUTOPATCH + DEPS_DIR ?= $(CURDIR)/deps export DEPS_DIR @@ -42,6 +45,41 @@ distclean:: distclean-deps distclean-pkg # Deps related targets. +define dep_autopatch + $(ERL) -eval " \ +DepDir = \"$(DEPS_DIR)/$(1)/\", \ +fun() -> \ + {ok, Conf} = file:consult(DepDir ++ \"rebar.config\"), \ + File = case lists:keyfind(deps, 1, Conf) of false -> []; {_, Deps} -> \ + [begin {Method, Repo, Commit} = case Repos of \ + {git, R} -> {git, R, master}; \ + {M, R, {branch, C}} -> {M, R, C}; \ + {M, R, {tag, C}} -> {M, R, C}; \ + {M, R, C} -> {M, R, C} \ + end, \ + io_lib:format(\"DEPS += ~s\ndep_~s = ~s ~s ~s~n\", [Name, Name, Method, Repo, Commit]) \ + end || {Name, _, Repos} <- Deps] \ + end, \ + ok = file:write_file(\"$(DEPS_DIR)/$(1)/Makefile\", [\"ERLC_OPTS = +debug_info\n\n\", File, \"\ninclude erlang.mk\"]) \ +end(), \ +AppSrcOut = \"$(DEPS_DIR)/$(1)/src/$(1).app.src\", \ +AppSrcIn = case filelib:is_regular(AppSrcOut) of false -> \"$(DEPS_DIR)/$(1)/ebin/$(1).app\"; true -> AppSrcOut end, \ +fun() -> \ + {ok, [{application, $(1), L}]} = file:consult(AppSrcIn), \ + L2 = case lists:keyfind(modules, 1, L) of {_, _} -> L; false -> [{modules, []}|L] end, \ + L3 = case lists:keyfind(vsn, 1, L2) of {vsn, git} -> lists:keyreplace(vsn, 1, L2, {vsn, \"git\"}); _ -> L2 end, \ + ok = file:write_file(AppSrcOut, io_lib:format(\"~p.~n\", [{application, $(1), L3}])) \ +end(), \ +case AppSrcOut of AppSrcIn -> ok; _ -> ok = file:delete(AppSrcIn) end, \ +halt()." +endef + +ifeq ($(V),0) +define dep_autopatch_verbose + @echo " PATCH " $(1); +endef +endif + define dep_fetch if [ "$$$$VS" = "git" ]; then \ git clone -n -- $$$$REPO $(DEPS_DIR)/$(1); \ @@ -73,6 +111,15 @@ else COMMIT=$(word 3,$(dep_$(1))); \ $(call dep_fetch,$(1)) endif +ifneq ($(filter $(1),$(AUTOPATCH)),) + $(call dep_autopatch_verbose,$(1)) if [ -f $(DEPS_DIR)/$(1)/rebar.config ]; then \ + $(call dep_autopatch,$(1)); \ + cd $(DEPS_DIR)/$(1)/ && ln -s ../../erlang.mk; \ + elif [ ! -f $(DEPS_DIR)/$(1)/Makefile ]; then \ + echo "ERLC_OPTS = +debug_info\ninclude erlang.mk" > $(DEPS_DIR)/$(1)/Makefile; \ + cd $(DEPS_DIR)/$(1)/ && ln -s ../../erlang.mk; \ + fi +endif endef $(foreach dep,$(DEPS),$(eval $(call dep_target,$(dep)))) diff --git a/core/erlc.mk b/core/erlc.mk index 8d720aa..e391da8 100644 --- a/core/erlc.mk +++ b/core/erlc.mk @@ -31,9 +31,15 @@ xyrl_verbose = $(xyrl_verbose_$(V)) mib_verbose_0 = @echo " MIB " $(filter %.bin %.mib,$(?F)); mib_verbose = $(mib_verbose_$(V)) -# Core targets. +# Targets. -app:: erlc-include ebin/$(PROJECT).app +ifeq ($(wildcard ebin/test),) +app:: app-build +else +app:: clean app-build +endif + +app-build: erlc-include ebin/$(PROJECT).app $(eval MODULES := $(shell find ebin -type f -name \*.beam \ | sed "s/ebin\//'/;s/\.beam/',/" | sed '$$s/.$$//')) @if [ -z "$$(grep -E '^[^%]*{modules,' src/$(PROJECT).app.src)" ]; then \ @@ -46,6 +52,11 @@ app:: erlc-include ebin/$(PROJECT).app | sed "s/{id,[[:space:]]*\"git\"}/{id, \"$(GITDESCRIBE)\"}/" \ > ebin/$(PROJECT).app +erlc-include: + -@if [ -d ebin/ ]; then \ + find include/ src/ -type f -name \*.hrl -newer ebin -exec touch $(shell find src/ -type f -name "*.erl") \; 2>/dev/null || printf ''; \ + fi + define compile_erl $(erlc_verbose) erlc -v $(ERLC_OPTS) -o ebin/ \ -pa ebin/ -I include/ $(filter-out $(ERLC_EXCLUDE_PATHS),\ @@ -85,13 +96,6 @@ endif clean:: clean-app -# Extra targets. - -erlc-include: - -@if [ -d ebin/ ]; then \ - find include/ src/ -type f -name \*.hrl -newer ebin -exec touch $(shell find src/ -type f -name "*.erl") \; 2>/dev/null || printf ''; \ - fi - clean-app: $(gen_verbose) rm -rf ebin/ priv/mibs/ \ $(addprefix include/,$(addsuffix .hrl,$(notdir $(basename $(wildcard mibs/*.mib))))) diff --git a/core/test.mk b/core/test.mk new file mode 100644 index 0000000..d3f49c2 --- /dev/null +++ b/core/test.mk @@ -0,0 +1,44 @@ +# Copyright (c) 2015, Loïc Hoguin <[email protected]> +# This file is part of erlang.mk and subject to the terms of the ISC License. + +.PHONY: test-deps test-dir test-build clean-test-dir + +# Configuration. + +TEST_DIR ?= test + +ALL_TEST_DEPS_DIRS = $(addprefix $(DEPS_DIR)/,$(TEST_DEPS)) + +TEST_ERLC_OPTS ?= +debug_info +warn_export_vars +warn_shadow_vars +warn_obsolete_guard +TEST_ERLC_OPTS += -DTEST=1 + +# Targets. + +$(foreach dep,$(TEST_DEPS),$(eval $(call dep_target,$(dep)))) + +test-deps: $(ALL_TEST_DEPS_DIRS) + @for dep in $(ALL_TEST_DEPS_DIRS) ; do $(MAKE) -C $$dep; done + +ifneq ($(strip $(TEST_DIR)),) +test-dir: + $(gen_verbose) erlc -v $(TEST_ERLC_OPTS) -I include/ -o $(TEST_DIR) \ + $(wildcard $(TEST_DIR)/*.erl $(TEST_DIR)/*/*.erl) -pa ebin/ +endif + +ifeq ($(wildcard ebin/test),) +test-build: ERLC_OPTS=$(TEST_ERLC_OPTS) +test-build: clean deps test-deps + @$(MAKE) --no-print-directory app-build test-dir ERLC_OPTS="$(TEST_ERLC_OPTS)" + $(gen_verbose) touch ebin/test +else +test-build: ERLC_OPTS=$(TEST_ERLC_OPTS) +test-build: deps test-deps + @$(MAKE) --no-print-directory app-build test-dir ERLC_OPTS="$(TEST_ERLC_OPTS)" +endif + +clean:: clean-test-dir + +clean-test-dir: +ifneq ($(wildcard $(TEST_DIR)/*.beam),) + $(gen_verbose) rm -f $(TEST_DIR)/*.beam +endif @@ -38,16 +38,20 @@ ifneq ($(words $(MAKECMDGOALS)),1) .NOTPARALLEL: endif -all:: - @$(MAKE) --no-print-directory deps +all:: deps @$(MAKE) --no-print-directory app -# @todo Plugin stuff creeping inside Core, not good. -ifneq ($(wildcard $(RELX_CONFIG)),) @$(MAKE) --no-print-directory rel -endif -clean:: +# Noop to avoid a Make warning when there's nothing to do. +rel:: + @echo -n + +clean:: clean-crashdump + +clean-crashdump: +ifneq ($(wildcard erl_crash.dump),) $(gen_verbose) rm -f erl_crash.dump +endif distclean:: clean @@ -106,6 +110,9 @@ erlang-mk: # Configuration. +AUTOPATCH ?= edown gen_leader gproc +export AUTOPATCH + DEPS_DIR ?= $(CURDIR)/deps export DEPS_DIR @@ -143,6 +150,41 @@ distclean:: distclean-deps distclean-pkg # Deps related targets. +define dep_autopatch + $(ERL) -eval " \ +DepDir = \"$(DEPS_DIR)/$(1)/\", \ +fun() -> \ + {ok, Conf} = file:consult(DepDir ++ \"rebar.config\"), \ + File = case lists:keyfind(deps, 1, Conf) of false -> []; {_, Deps} -> \ + [begin {Method, Repo, Commit} = case Repos of \ + {git, R} -> {git, R, master}; \ + {M, R, {branch, C}} -> {M, R, C}; \ + {M, R, {tag, C}} -> {M, R, C}; \ + {M, R, C} -> {M, R, C} \ + end, \ + io_lib:format(\"DEPS += ~s\ndep_~s = ~s ~s ~s~n\", [Name, Name, Method, Repo, Commit]) \ + end || {Name, _, Repos} <- Deps] \ + end, \ + ok = file:write_file(\"$(DEPS_DIR)/$(1)/Makefile\", [\"ERLC_OPTS = +debug_info\n\n\", File, \"\ninclude erlang.mk\"]) \ +end(), \ +AppSrcOut = \"$(DEPS_DIR)/$(1)/src/$(1).app.src\", \ +AppSrcIn = case filelib:is_regular(AppSrcOut) of false -> \"$(DEPS_DIR)/$(1)/ebin/$(1).app\"; true -> AppSrcOut end, \ +fun() -> \ + {ok, [{application, $(1), L}]} = file:consult(AppSrcIn), \ + L2 = case lists:keyfind(modules, 1, L) of {_, _} -> L; false -> [{modules, []}|L] end, \ + L3 = case lists:keyfind(vsn, 1, L2) of {vsn, git} -> lists:keyreplace(vsn, 1, L2, {vsn, \"git\"}); _ -> L2 end, \ + ok = file:write_file(AppSrcOut, io_lib:format(\"~p.~n\", [{application, $(1), L3}])) \ +end(), \ +case AppSrcOut of AppSrcIn -> ok; _ -> ok = file:delete(AppSrcIn) end, \ +halt()." +endef + +ifeq ($(V),0) +define dep_autopatch_verbose + @echo " PATCH " $(1); +endef +endif + define dep_fetch if [ "$$$$VS" = "git" ]; then \ git clone -n -- $$$$REPO $(DEPS_DIR)/$(1); \ @@ -174,6 +216,15 @@ else COMMIT=$(word 3,$(dep_$(1))); \ $(call dep_fetch,$(1)) endif +ifneq ($(filter $(1),$(AUTOPATCH)),) + $(call dep_autopatch_verbose,$(1)) if [ -f $(DEPS_DIR)/$(1)/rebar.config ]; then \ + $(call dep_autopatch,$(1)); \ + cd $(DEPS_DIR)/$(1)/ && ln -s ../../erlang.mk; \ + elif [ ! -f $(DEPS_DIR)/$(1)/Makefile ]; then \ + echo "ERLC_OPTS = +debug_info\ninclude erlang.mk" > $(DEPS_DIR)/$(1)/Makefile; \ + cd $(DEPS_DIR)/$(1)/ && ln -s ../../erlang.mk; \ + fi +endif endef $(foreach dep,$(DEPS),$(eval $(call dep_target,$(dep)))) @@ -249,9 +300,15 @@ xyrl_verbose = $(xyrl_verbose_$(V)) mib_verbose_0 = @echo " MIB " $(filter %.bin %.mib,$(?F)); mib_verbose = $(mib_verbose_$(V)) -# Core targets. +# Targets. -app:: erlc-include ebin/$(PROJECT).app +ifeq ($(wildcard ebin/test),) +app:: app-build +else +app:: clean app-build +endif + +app-build: erlc-include ebin/$(PROJECT).app $(eval MODULES := $(shell find ebin -type f -name \*.beam \ | sed "s/ebin\//'/;s/\.beam/',/" | sed '$$s/.$$//')) @if [ -z "$$(grep -E '^[^%]*{modules,' src/$(PROJECT).app.src)" ]; then \ @@ -264,6 +321,11 @@ app:: erlc-include ebin/$(PROJECT).app | sed "s/{id,[[:space:]]*\"git\"}/{id, \"$(GITDESCRIBE)\"}/" \ > ebin/$(PROJECT).app +erlc-include: + -@if [ -d ebin/ ]; then \ + find include/ src/ -type f -name \*.hrl -newer ebin -exec touch $(shell find src/ -type f -name "*.erl") \; 2>/dev/null || printf ''; \ + fi + define compile_erl $(erlc_verbose) erlc -v $(ERLC_OPTS) -o ebin/ \ -pa ebin/ -I include/ $(filter-out $(ERLC_EXCLUDE_PATHS),\ @@ -303,17 +365,55 @@ endif clean:: clean-app -# Extra targets. - -erlc-include: - -@if [ -d ebin/ ]; then \ - find include/ src/ -type f -name \*.hrl -newer ebin -exec touch $(shell find src/ -type f -name "*.erl") \; 2>/dev/null || printf ''; \ - fi - clean-app: $(gen_verbose) rm -rf ebin/ priv/mibs/ \ $(addprefix include/,$(addsuffix .hrl,$(notdir $(basename $(wildcard mibs/*.mib))))) +# Copyright (c) 2015, Loïc Hoguin <[email protected]> +# This file is part of erlang.mk and subject to the terms of the ISC License. + +.PHONY: test-deps test-dir test-build clean-test-dir + +# Configuration. + +TEST_DIR ?= test + +ALL_TEST_DEPS_DIRS = $(addprefix $(DEPS_DIR)/,$(TEST_DEPS)) + +TEST_ERLC_OPTS ?= +debug_info +warn_export_vars +warn_shadow_vars +warn_obsolete_guard +TEST_ERLC_OPTS += -DTEST=1 + +# Targets. + +$(foreach dep,$(TEST_DEPS),$(eval $(call dep_target,$(dep)))) + +test-deps: $(ALL_TEST_DEPS_DIRS) + @for dep in $(ALL_TEST_DEPS_DIRS) ; do $(MAKE) -C $$dep; done + +ifneq ($(strip $(TEST_DIR)),) +test-dir: + $(gen_verbose) erlc -v $(TEST_ERLC_OPTS) -I include/ -o $(TEST_DIR) \ + $(wildcard $(TEST_DIR)/*.erl $(TEST_DIR)/*/*.erl) -pa ebin/ +endif + +ifeq ($(wildcard ebin/test),) +test-build: ERLC_OPTS=$(TEST_ERLC_OPTS) +test-build: clean deps test-deps + @$(MAKE) --no-print-directory app-build test-dir ERLC_OPTS="$(TEST_ERLC_OPTS)" + $(gen_verbose) touch ebin/test +else +test-build: ERLC_OPTS=$(TEST_ERLC_OPTS) +test-build: deps test-deps + @$(MAKE) --no-print-directory app-build test-dir ERLC_OPTS="$(TEST_ERLC_OPTS)" +endif + +clean:: clean-test-dir + +clean-test-dir: +ifneq ($(wildcard $(TEST_DIR)/*.beam),) + $(gen_verbose) rm -f $(TEST_DIR)/*.beam +endif + # Copyright (c) 2014, Loïc Hoguin <[email protected]> # This file is part of erlang.mk and subject to the terms of the ISC License. @@ -751,78 +851,56 @@ endif # Copyright (c) 2013-2014, Loïc Hoguin <[email protected]> # This file is part of erlang.mk and subject to the terms of the ISC License. -.PHONY: build-ct-deps build-ct-suites tests-ct clean-ct distclean-ct +.PHONY: ct distclean-ct # Configuration. CT_OPTS ?= -ifneq ($(wildcard test/),) - CT_SUITES ?= $(sort $(subst _SUITE.erl,,$(shell find test -type f -name \*_SUITE.erl -exec basename {} \;))) +ifneq ($(wildcard $(TEST_DIR)),) + CT_SUITES ?= $(sort $(subst _SUITE.erl,,$(shell find $(TEST_DIR) -type f -name \*_SUITE.erl -exec basename {} \;))) else CT_SUITES ?= endif -TEST_ERLC_OPTS ?= +debug_info +warn_export_vars +warn_shadow_vars +warn_obsolete_guard -TEST_ERLC_OPTS += -DTEST=1 -DEXTRA=1 +'{parse_transform, eunit_autoexport}' - # Core targets. -tests:: tests-ct - -clean:: clean-ct +tests:: ct distclean:: distclean-ct help:: @printf "%s\n" "" \ + "Common_test targets:" \ + " ct Run all the common_test suites for this project" \ + "" \ "All your common_test suites have their associated targets." \ "A suite named http_SUITE can be ran using the ct-http target." # Plugin-specific targets. -ALL_TEST_DEPS_DIRS = $(addprefix $(DEPS_DIR)/,$(TEST_DEPS)) - CT_RUN = ct_run \ -no_auto_compile \ -noinput \ - -pa $(realpath ebin) $(DEPS_DIR)/*/ebin \ - -dir test \ + -pa ebin $(DEPS_DIR)/*/ebin \ + -dir $(TEST_DIR) \ -logdir logs -$(foreach dep,$(TEST_DEPS),$(eval $(call dep_target,$(dep)))) - -build-ct-deps: $(ALL_TEST_DEPS_DIRS) - @for dep in $(ALL_TEST_DEPS_DIRS) ; do $(MAKE) -C $$dep; done - -build-ct-suites: build-ct-deps - $(gen_verbose) erlc -v $(TEST_ERLC_OPTS) -I include/ -o test/ \ - $(wildcard test/*.erl test/*/*.erl) -pa ebin/ - -tests-ct: ERLC_OPTS = $(TEST_ERLC_OPTS) -tests-ct: clean deps app build-ct-suites - @if [ -d "test" ] ; \ - then \ - mkdir -p logs/ ; \ - $(CT_RUN) -suite $(addsuffix _SUITE,$(CT_SUITES)) $(CT_OPTS) ; \ - fi - $(gen_verbose) rm -f test/*.beam +ifeq ($(CT_SUITES),) +ct: +else +ct: test-build + @mkdir -p logs/ + $(gen_verbose) $(CT_RUN) -suite $(addsuffix _SUITE,$(CT_SUITES)) $(CT_OPTS) +endif define ct_suite_target -ct-$(1): ERLC_OPTS = $(TEST_ERLC_OPTS) -ct-$(1): clean deps app build-ct-suites - @if [ -d "test" ] ; \ - then \ - mkdir -p logs/ ; \ - $(CT_RUN) -suite $(addsuffix _SUITE,$(1)) $(CT_OPTS) ; \ - fi - $(gen_verbose) rm -f test/*.beam +ct-$(1): test-build + @mkdir -p logs/ + $(gen_verbose) $(CT_RUN) -suite $(addsuffix _SUITE,$(1)) $(CT_OPTS) endef $(foreach test,$(CT_SUITES),$(eval $(call ct_suite_target,$(test)))) -clean-ct: - $(gen_verbose) rm -rf test/*.beam - distclean-ct: $(gen_verbose) rm -rf logs/ @@ -920,20 +998,18 @@ help:: "Elvis targets:" \ " elvis Run Elvis using the local elvis.config or download the default otherwise" -ifneq ($(wildcard $(ELVIS_CONFIG)),) -rel:: distclean-elvis -endif - distclean:: distclean-elvis # Plugin-specific targets. $(ELVIS): - @$(call core_http_get,$(ELVIS_CONFIG),$(ELVIS_CONFIG_URL)) @$(call core_http_get,$(ELVIS),$(ELVIS_URL)) @chmod +x $(ELVIS) -elvis: $(ELVIS) +$(ELVIS_CONFIG): + @$(call core_http_get,$(ELVIS_CONFIG),$(ELVIS_CONFIG_URL)) + +elvis: $(ELVIS) $(ELVIS_CONFIG) @$(ELVIS) rock -c $(ELVIS_CONFIG) $(ELVIS_OPTS) distclean-elvis: @@ -1039,25 +1115,20 @@ distclean-escript: # Copyright (c) 2014, Enrique Fernandez <[email protected]> # This file is contributed to erlang.mk and subject to the terms of the ISC License. -.PHONY: help-eunit build-eunit eunit distclean-eunit +.PHONY: eunit # Configuration -EUNIT_ERLC_OPTS ?= +debug_info +warn_export_vars +warn_shadow_vars +warn_obsolete_guard -DTEST=1 -DEXTRA=1 - -EUNIT_DIR ?= -EUNIT_DIRS = $(sort $(EUNIT_DIR) ebin) - -ifeq ($(strip $(EUNIT_DIR)),) +ifeq ($(strip $(TEST_DIR)),) TAGGED_EUNIT_TESTS = {dir,"ebin"} else -# All modules in EUNIT_DIR -EUNIT_DIR_MODS = $(notdir $(basename $(shell find $(EUNIT_DIR) -type f -name *.beam))) +# All modules in TEST_DIR +TEST_DIR_MODS = $(notdir $(basename $(shell find $(TEST_DIR) -type f -name *.beam))) # All modules in 'ebin' EUNIT_EBIN_MODS = $(notdir $(basename $(shell find ebin -type f -name *.beam))) -# Only those modules in EUNIT_DIR with no matching module in 'ebin'. +# Only those modules in TEST_DIR with no matching module in 'ebin'. # This is done to avoid some tests being executed twice. -EUNIT_MODS = $(filter-out $(patsubst %,%_tests,$(EUNIT_EBIN_MODS)),$(EUNIT_DIR_MODS)) +EUNIT_MODS = $(filter-out $(patsubst %,%_tests,$(EUNIT_EBIN_MODS)),$(TEST_DIR_MODS)) TAGGED_EUNIT_TESTS = {dir,"ebin"} $(foreach mod,$(EUNIT_MODS),$(shell echo $(mod) | sed -e 's/\(.*\)/{module,\1}/g')) endif @@ -1071,42 +1142,23 @@ endef # Core targets. -help:: help-eunit - tests:: eunit -clean:: clean-eunit +help:: + @printf "%s\n" "" \ + "EUnit targets:" \ + " eunit Run all the EUnit tests for this project" # Plugin-specific targets. EUNIT_RUN = $(ERL) \ - -no_auto_compile \ - -pa $(realpath $(EUNIT_DIR)) $(DEPS_DIR)/*/ebin \ - -pz $(realpath ebin) \ + -pa $(TEST_DIR) $(DEPS_DIR)/*/ebin \ + -pz ebin \ -eval 'case eunit:test([$(call str-join,$(TAGGED_EUNIT_TESTS))], [$(EUNIT_OPTS)]) of ok -> halt(0); error -> halt(1) end.' -help-eunit: - @printf "%s\n" "" \ - "EUnit targets:" \ - " eunit Run all the EUnit tests for this project" - -ifeq ($(strip $(EUNIT_DIR)),) -build-eunit: -else ifeq ($(strip $(EUNIT_DIR)),ebin) -build-eunit: -else -build-eunit: - $(gen_verbose) erlc -v $(EUNIT_ERLC_OPTS) -I include/ -o $(EUNIT_DIR) \ - $(wildcard $(EUNIT_DIR)/*.erl $(EUNIT_DIR)/*/*.erl) -pa ebin/ -endif - -eunit: ERLC_OPTS = $(EUNIT_ERLC_OPTS) -eunit: clean deps app build-eunit +eunit: test-build $(gen_verbose) $(EUNIT_RUN) -clean-eunit: - $(gen_verbose) $(foreach dir,$(EUNIT_DIRS),rm -rf $(dir)/*.beam) - # Copyright (c) 2013-2014, Loïc Hoguin <[email protected]> # This file is part of erlang.mk and subject to the terms of the ISC License. @@ -1184,3 +1236,33 @@ build-shell-deps: $(ALL_SHELL_DEPS_DIRS) shell: build-shell-deps $(gen_verbose) erl $(SHELL_PATH) $(SHELL_OPTS) + +# Copyright (c) 2015, Loïc Hoguin <[email protected]> +# This file is part of erlang.mk and subject to the terms of the ISC License. + +.PHONY: triq + +# Targets. + +tests:: triq + +define triq_run +$(ERL) -pa $(CURDIR)/ebin $(DEPS_DIR)/*/ebin \ + -eval "try $(1) of true -> halt(0); _ -> halt(1) catch error:undef -> io:format(\"Undefined property or module~n\"), halt() end." +endef + +ifdef t +ifeq (,$(findstring :,$(t))) +triq: test-build + @$(call triq_run,triq:check($(t))) +else +triq: test-build + @echo Testing $(t)/0 + @$(call triq_run,triq:check($(t)())) +endif +else +triq: test-build + $(eval MODULES := $(shell find ebin -type f -name \*.beam \ + | sed "s/ebin\//'/;s/\.beam/',/" | sed '$$s/.$$//')) + $(gen_verbose) $(call triq_run,[true] =:= lists:usort([triq:check(M) || M <- [$(MODULES)]])) +endif diff --git a/plugins/ct.mk b/plugins/ct.mk index 18d432a..b281842 100644 --- a/plugins/ct.mk +++ b/plugins/ct.mk @@ -1,77 +1,55 @@ # Copyright (c) 2013-2014, Loïc Hoguin <[email protected]> # This file is part of erlang.mk and subject to the terms of the ISC License. -.PHONY: build-ct-deps build-ct-suites tests-ct clean-ct distclean-ct +.PHONY: ct distclean-ct # Configuration. CT_OPTS ?= -ifneq ($(wildcard test/),) - CT_SUITES ?= $(sort $(subst _SUITE.erl,,$(shell find test -type f -name \*_SUITE.erl -exec basename {} \;))) +ifneq ($(wildcard $(TEST_DIR)),) + CT_SUITES ?= $(sort $(subst _SUITE.erl,,$(shell find $(TEST_DIR) -type f -name \*_SUITE.erl -exec basename {} \;))) else CT_SUITES ?= endif -TEST_ERLC_OPTS ?= +debug_info +warn_export_vars +warn_shadow_vars +warn_obsolete_guard -TEST_ERLC_OPTS += -DTEST=1 -DEXTRA=1 +'{parse_transform, eunit_autoexport}' - # Core targets. -tests:: tests-ct - -clean:: clean-ct +tests:: ct distclean:: distclean-ct help:: @printf "%s\n" "" \ + "Common_test targets:" \ + " ct Run all the common_test suites for this project" \ + "" \ "All your common_test suites have their associated targets." \ "A suite named http_SUITE can be ran using the ct-http target." # Plugin-specific targets. -ALL_TEST_DEPS_DIRS = $(addprefix $(DEPS_DIR)/,$(TEST_DEPS)) - CT_RUN = ct_run \ -no_auto_compile \ -noinput \ - -pa $(realpath ebin) $(DEPS_DIR)/*/ebin \ - -dir test \ + -pa ebin $(DEPS_DIR)/*/ebin \ + -dir $(TEST_DIR) \ -logdir logs -$(foreach dep,$(TEST_DEPS),$(eval $(call dep_target,$(dep)))) - -build-ct-deps: $(ALL_TEST_DEPS_DIRS) - @for dep in $(ALL_TEST_DEPS_DIRS) ; do $(MAKE) -C $$dep; done - -build-ct-suites: build-ct-deps - $(gen_verbose) erlc -v $(TEST_ERLC_OPTS) -I include/ -o test/ \ - $(wildcard test/*.erl test/*/*.erl) -pa ebin/ - -tests-ct: ERLC_OPTS = $(TEST_ERLC_OPTS) -tests-ct: clean deps app build-ct-suites - @if [ -d "test" ] ; \ - then \ - mkdir -p logs/ ; \ - $(CT_RUN) -suite $(addsuffix _SUITE,$(CT_SUITES)) $(CT_OPTS) ; \ - fi - $(gen_verbose) rm -f test/*.beam +ifeq ($(CT_SUITES),) +ct: +else +ct: test-build + @mkdir -p logs/ + $(gen_verbose) $(CT_RUN) -suite $(addsuffix _SUITE,$(CT_SUITES)) $(CT_OPTS) +endif define ct_suite_target -ct-$(1): ERLC_OPTS = $(TEST_ERLC_OPTS) -ct-$(1): clean deps app build-ct-suites - @if [ -d "test" ] ; \ - then \ - mkdir -p logs/ ; \ - $(CT_RUN) -suite $(addsuffix _SUITE,$(1)) $(CT_OPTS) ; \ - fi - $(gen_verbose) rm -f test/*.beam +ct-$(1): test-build + @mkdir -p logs/ + $(gen_verbose) $(CT_RUN) -suite $(addsuffix _SUITE,$(1)) $(CT_OPTS) endef $(foreach test,$(CT_SUITES),$(eval $(call ct_suite_target,$(test)))) -clean-ct: - $(gen_verbose) rm -rf test/*.beam - distclean-ct: $(gen_verbose) rm -rf logs/ diff --git a/plugins/elvis.mk b/plugins/elvis.mk index f3e75a8..580e2f5 100644 --- a/plugins/elvis.mk +++ b/plugins/elvis.mk @@ -21,20 +21,18 @@ help:: "Elvis targets:" \ " elvis Run Elvis using the local elvis.config or download the default otherwise" -ifneq ($(wildcard $(ELVIS_CONFIG)),) -rel:: distclean-elvis -endif - distclean:: distclean-elvis # Plugin-specific targets. $(ELVIS): - @$(call core_http_get,$(ELVIS_CONFIG),$(ELVIS_CONFIG_URL)) @$(call core_http_get,$(ELVIS),$(ELVIS_URL)) @chmod +x $(ELVIS) -elvis: $(ELVIS) +$(ELVIS_CONFIG): + @$(call core_http_get,$(ELVIS_CONFIG),$(ELVIS_CONFIG_URL)) + +elvis: $(ELVIS) $(ELVIS_CONFIG) @$(ELVIS) rock -c $(ELVIS_CONFIG) $(ELVIS_OPTS) distclean-elvis: diff --git a/plugins/eunit.mk b/plugins/eunit.mk index 1b83a0f..ae132ac 100644 --- a/plugins/eunit.mk +++ b/plugins/eunit.mk @@ -1,25 +1,20 @@ # Copyright (c) 2014, Enrique Fernandez <[email protected]> # This file is contributed to erlang.mk and subject to the terms of the ISC License. -.PHONY: help-eunit build-eunit eunit distclean-eunit +.PHONY: eunit # Configuration -EUNIT_ERLC_OPTS ?= +debug_info +warn_export_vars +warn_shadow_vars +warn_obsolete_guard -DTEST=1 -DEXTRA=1 - -EUNIT_DIR ?= -EUNIT_DIRS = $(sort $(EUNIT_DIR) ebin) - -ifeq ($(strip $(EUNIT_DIR)),) +ifeq ($(strip $(TEST_DIR)),) TAGGED_EUNIT_TESTS = {dir,"ebin"} else -# All modules in EUNIT_DIR -EUNIT_DIR_MODS = $(notdir $(basename $(shell find $(EUNIT_DIR) -type f -name *.beam))) +# All modules in TEST_DIR +TEST_DIR_MODS = $(notdir $(basename $(shell find $(TEST_DIR) -type f -name *.beam))) # All modules in 'ebin' EUNIT_EBIN_MODS = $(notdir $(basename $(shell find ebin -type f -name *.beam))) -# Only those modules in EUNIT_DIR with no matching module in 'ebin'. +# Only those modules in TEST_DIR with no matching module in 'ebin'. # This is done to avoid some tests being executed twice. -EUNIT_MODS = $(filter-out $(patsubst %,%_tests,$(EUNIT_EBIN_MODS)),$(EUNIT_DIR_MODS)) +EUNIT_MODS = $(filter-out $(patsubst %,%_tests,$(EUNIT_EBIN_MODS)),$(TEST_DIR_MODS)) TAGGED_EUNIT_TESTS = {dir,"ebin"} $(foreach mod,$(EUNIT_MODS),$(shell echo $(mod) | sed -e 's/\(.*\)/{module,\1}/g')) endif @@ -33,38 +28,19 @@ endef # Core targets. -help:: help-eunit - tests:: eunit -clean:: clean-eunit +help:: + @printf "%s\n" "" \ + "EUnit targets:" \ + " eunit Run all the EUnit tests for this project" # Plugin-specific targets. EUNIT_RUN = $(ERL) \ - -no_auto_compile \ - -pa $(realpath $(EUNIT_DIR)) $(DEPS_DIR)/*/ebin \ - -pz $(realpath ebin) \ + -pa $(TEST_DIR) $(DEPS_DIR)/*/ebin \ + -pz ebin \ -eval 'case eunit:test([$(call str-join,$(TAGGED_EUNIT_TESTS))], [$(EUNIT_OPTS)]) of ok -> halt(0); error -> halt(1) end.' -help-eunit: - @printf "%s\n" "" \ - "EUnit targets:" \ - " eunit Run all the EUnit tests for this project" - -ifeq ($(strip $(EUNIT_DIR)),) -build-eunit: -else ifeq ($(strip $(EUNIT_DIR)),ebin) -build-eunit: -else -build-eunit: - $(gen_verbose) erlc -v $(EUNIT_ERLC_OPTS) -I include/ -o $(EUNIT_DIR) \ - $(wildcard $(EUNIT_DIR)/*.erl $(EUNIT_DIR)/*/*.erl) -pa ebin/ -endif - -eunit: ERLC_OPTS = $(EUNIT_ERLC_OPTS) -eunit: clean deps app build-eunit +eunit: test-build $(gen_verbose) $(EUNIT_RUN) - -clean-eunit: - $(gen_verbose) $(foreach dir,$(EUNIT_DIRS),rm -rf $(dir)/*.beam) diff --git a/plugins/triq.mk b/plugins/triq.mk new file mode 100644 index 0000000..8a77c91 --- /dev/null +++ b/plugins/triq.mk @@ -0,0 +1,29 @@ +# Copyright (c) 2015, Loïc Hoguin <[email protected]> +# This file is part of erlang.mk and subject to the terms of the ISC License. + +.PHONY: triq + +# Targets. + +tests:: triq + +define triq_run +$(ERL) -pa $(CURDIR)/ebin $(DEPS_DIR)/*/ebin \ + -eval "try $(1) of true -> halt(0); _ -> halt(1) catch error:undef -> io:format(\"Undefined property or module~n\"), halt() end." +endef + +ifdef t +ifeq (,$(findstring :,$(t))) +triq: test-build + @$(call triq_run,triq:check($(t))) +else +triq: test-build + @echo Testing $(t)/0 + @$(call triq_run,triq:check($(t)())) +endif +else +triq: test-build + $(eval MODULES := $(shell find ebin -type f -name \*.beam \ + | sed "s/ebin\//'/;s/\.beam/',/" | sed '$$s/.$$//')) + $(gen_verbose) $(call triq_run,[true] =:= lists:usort([triq:check(M) || M <- [$(MODULES)]])) +endif diff --git a/test/Makefile b/test/Makefile index c387081..265c67c 100644 --- a/test/Makefile +++ b/test/Makefile @@ -62,7 +62,7 @@ app: app1 $i "Test 'app' passed." ct: app1 - $i "ct: Testing tests-ct and related targets." + $i "ct: Testing ct and related targets." $i "Setting up test suite." $t mkdir -p app1/test $t printf "%s\n" \ @@ -71,17 +71,17 @@ ct: app1 "all() -> [testcase1]." \ "testcase1(_) -> 2 = m:succ(1)." \ > app1/test/m_SUITE.erl - $t make -C app1 tests-ct $v - $i "Checking files created by 'make tests-ct'." - $t [ ! -e app1/test/m_SUITE.beam ] + $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-ct' does not delete logs." - $t make -C app1 clean-ct $v + $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 tests-ct' returns non-zero for a failing suite." + $i "Checking that 'make ct' returns non-zero for a failing suite." $t printf "%s\n" \ "-module(failing_SUITE)." \ "-export([all/0, testcase1/1])." \ @@ -89,7 +89,7 @@ ct: app1 "testcase1(_) -> 42 = m:succ(1)." \ > app1/test/failing_SUITE.erl $t if make -C app1 ct-failing $v ; then false ; fi - $i "Checking that 'make ct-distclean' deletes logs." + $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 ] @@ -131,7 +131,7 @@ eunit: app1 ' ?assertEqual(2, t:succ(1)),' \ ' os:cmd("echo x_tests >> test-eunit.log").' \ > app1/eunit/x_tests.erl - $t make -C app1 eunit EUNIT_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 @@ -143,7 +143,7 @@ eunit: app1 "succ_test() ->" \ " ?assertEqual(42, t:succ(1))." \ > app1/eunit/t_tests.erl - $t if make -C app1 eunit EUNIT_DIR=eunit $v ; then false ; fi + $t if make -C app1 eunit TEST_DIR=eunit $v ; then false ; fi $t rm -rf app1/eunit app1/src/t.erl app1/test-eunit.log $i "Test 'eunit' passed." |