From a8aeb5ac175188fcf58634cd64e0289705c66b03 Mon Sep 17 00:00:00 2001 From: Feng Lee Date: Tue, 27 Feb 2018 09:13:14 +0800 Subject: [PATCH] Rename the 'mqtt_route' record to 'route' --- erlang.mk | 1199 ++++++++++++++----------------------------- src/emqx_pubsub.erl | 4 +- src/emqx_router.erl | 2 +- 3 files changed, 384 insertions(+), 821 deletions(-) diff --git a/erlang.mk b/erlang.mk index adf9d98b8..e348d4493 100644 --- a/erlang.mk +++ b/erlang.mk @@ -1,4 +1,4 @@ -# Copyright (c) 2013-2016, Loïc Hoguin +# Copyright (c) 2013-2015, 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 @@ -12,23 +12,11 @@ # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -.PHONY: all app apps deps search rel relup docs install-docs check tests clean distclean help erlang-mk +.PHONY: all app apps deps search rel docs install-docs check tests clean distclean help erlang-mk ERLANG_MK_FILENAME := $(realpath $(lastword $(MAKEFILE_LIST))) -export ERLANG_MK_FILENAME -ERLANG_MK_VERSION = 2017.08.28-22-gf545564 -ERLANG_MK_WITHOUT = - -# Make 3.81 and 3.82 are deprecated. - -ifeq ($(MAKE_VERSION),3.81) -$(warning Please upgrade to GNU Make 4 or later: https://erlang.mk/guide/installation.html) -endif - -ifeq ($(MAKE_VERSION),3.82) -$(warning Please upgrade to GNU Make 4 or later: https://erlang.mk/guide/installation.html) -endif +ERLANG_MK_VERSION = 2.0.0-pre.2-130-gc6fe5ea # Core configuration. @@ -37,7 +25,6 @@ PROJECT := $(strip $(PROJECT)) PROJECT_VERSION ?= rolling PROJECT_MOD ?= $(PROJECT)_app -PROJECT_ENV ?= [] # Verbosity. @@ -98,8 +85,6 @@ all:: deps app rel rel:: $(verbose) : -relup:: deps app - check:: tests clean:: clean-crashdump @@ -117,7 +102,7 @@ distclean-tmp: help:: $(verbose) printf "%s\n" \ "erlang.mk (version $(ERLANG_MK_VERSION)) is distributed under the terms of the ISC License." \ - "Copyright (c) 2013-2016 Loïc Hoguin " \ + "Copyright (c) 2013-2015 Loïc Hoguin " \ "" \ "Usage: [V=1] $(MAKE) [target]..." \ "" \ @@ -125,8 +110,6 @@ help:: " all Run deps, app and rel targets in that order" \ " app Compile the project" \ " deps Fetch dependencies (if needed) and compile them" \ - " fetch-deps Fetch dependencies recursively (if needed) without compiling them" \ - " list-deps List dependencies recursively on stdout" \ " search q=... Search for a package in the built-in index" \ " rel Build a release for this project, if applicable" \ " docs Build the documentation for this project" \ @@ -165,7 +148,30 @@ else core_native_path = $1 endif -core_http_get = curl -Lf$(if $(filter-out 0,$(V)),,s)o $(call core_native_path,$1) $2 +ifeq ($(shell which wget 2>/dev/null | wc -l), 1) +define core_http_get + wget --no-check-certificate -O $(1) $(2)|| rm $(1) +endef +else +define core_http_get.erl + ssl:start(), + inets:start(), + case httpc:request(get, {"$(2)", []}, [{autoredirect, true}], []) of + {ok, {{_, 200, _}, _, Body}} -> + case file:write_file("$(1)", Body) of + ok -> ok; + {error, R1} -> halt(R1) + end; + {error, R2} -> + halt(R2) + end, + halt(0). +endef + +define core_http_get + $(call erlang,$(call core_http_get.erl,$(call core_native_path,$1),$2)) +endef +endif core_eq = $(and $(findstring $(1),$(2)),$(findstring $(2),$(1))) @@ -185,102 +191,17 @@ ERLANG_MK_COMMIT ?= ERLANG_MK_BUILD_CONFIG ?= build.config ERLANG_MK_BUILD_DIR ?= .erlang.mk.build -erlang-mk: WITHOUT ?= $(ERLANG_MK_WITHOUT) 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 - $(MAKE) -C $(ERLANG_MK_BUILD_DIR) WITHOUT='$(strip $(WITHOUT))' + $(MAKE) -C $(ERLANG_MK_BUILD_DIR) cp $(ERLANG_MK_BUILD_DIR)/erlang.mk ./erlang.mk rm -rf $(ERLANG_MK_BUILD_DIR) -# The erlang.mk package index is bundled in the default erlang.mk build. -# Search for the string "copyright" to skip to the rest of the code. - -# Copyright (c) 2015-2017, Loïc Hoguin -# This file is part of erlang.mk and subject to the terms of the ISC License. - -.PHONY: distclean-kerl - -KERL_INSTALL_DIR ?= $(HOME)/erlang - -ifeq ($(strip $(KERL)),) -KERL := $(ERLANG_MK_TMP)/kerl/kerl -endif - -export KERL - -KERL_GIT ?= https://github.com/kerl/kerl -KERL_COMMIT ?= master - -KERL_MAKEFLAGS ?= - -OTP_GIT ?= https://github.com/erlang/otp - -define kerl_otp_target -ifeq ($(wildcard $(KERL_INSTALL_DIR)/$(1)),) -$(KERL_INSTALL_DIR)/$(1): $(KERL) - MAKEFLAGS="$(KERL_MAKEFLAGS)" $(KERL) build git $(OTP_GIT) $(1) $(1) - $(KERL) install $(1) $(KERL_INSTALL_DIR)/$(1) -endif -endef - -define kerl_hipe_target -ifeq ($(wildcard $(KERL_INSTALL_DIR)/$1-native),) -$(KERL_INSTALL_DIR)/$1-native: $(KERL) - KERL_CONFIGURE_OPTIONS=--enable-native-libs \ - MAKEFLAGS="$(KERL_MAKEFLAGS)" $(KERL) build git $(OTP_GIT) $1 $1-native - $(KERL) install $1-native $(KERL_INSTALL_DIR)/$1-native -endif -endef - -$(KERL): - $(verbose) mkdir -p $(ERLANG_MK_TMP) - $(gen_verbose) git clone --depth 1 $(KERL_GIT) $(ERLANG_MK_TMP)/kerl - $(verbose) cd $(ERLANG_MK_TMP)/kerl && git checkout $(KERL_COMMIT) - $(verbose) chmod +x $(KERL) - -distclean:: distclean-kerl - -distclean-kerl: - $(gen_verbose) rm -rf $(KERL) - -# Allow users to select which version of Erlang/OTP to use for a project. - -ERLANG_OTP ?= -ERLANG_HIPE ?= - -# Use kerl to enforce a specific Erlang/OTP version for a project. -ifneq ($(strip $(ERLANG_OTP)),) -export PATH := $(KERL_INSTALL_DIR)/$(ERLANG_OTP)/bin:$(PATH) -SHELL := env PATH=$(PATH) $(SHELL) -$(eval $(call kerl_otp_target,$(ERLANG_OTP))) - -# Build Erlang/OTP only if it doesn't already exist. -ifeq ($(wildcard $(KERL_INSTALL_DIR)/$(ERLANG_OTP))$(BUILD_ERLANG_OTP),) -$(info Building Erlang/OTP $(ERLANG_OTP)... Please wait...) -$(shell $(MAKE) $(KERL_INSTALL_DIR)/$(ERLANG_OTP) ERLANG_OTP=$(ERLANG_OTP) BUILD_ERLANG_OTP=1 >&2) -endif - -else -# Same for a HiPE enabled VM. -ifneq ($(strip $(ERLANG_HIPE)),) -export PATH := $(KERL_INSTALL_DIR)/$(ERLANG_HIPE)-native/bin:$(PATH) -SHELL := env PATH=$(PATH) $(SHELL) -$(eval $(call kerl_hipe_target,$(ERLANG_HIPE))) - -# Build Erlang/OTP only if it doesn't already exist. -ifeq ($(wildcard $(KERL_INSTALL_DIR)/$(ERLANG_HIPE))$(BUILD_ERLANG_OTP),) -$(info Building HiPE-enabled Erlang/OTP $(ERLANG_OTP)... Please wait...) -$(shell $(MAKE) $(KERL_INSTALL_DIR)/$(ERLANG_HIPE) ERLANG_HIPE=$(ERLANG_HIPE) BUILD_ERLANG_OTP=1 >&2) -endif - -endif -endif - -# Copyright (c) 2015-2016, Loïc Hoguin +# Copyright (c) 2015, Loïc Hoguin # This file is part of erlang.mk and subject to the terms of the ISC License. .PHONY: search @@ -307,10 +228,10 @@ else $(foreach p,$(PACKAGES),$(call pkg_print,$(p))) endif -# Copyright (c) 2013-2016, Loïc Hoguin +# Copyright (c) 2013-2015, Loïc Hoguin # This file is part of erlang.mk and subject to the terms of the ISC License. -.PHONY: distclean-deps clean-tmp-deps.log +.PHONY: distclean-deps # Configuration. @@ -330,32 +251,11 @@ export DEPS_DIR REBAR_DEPS_DIR = $(DEPS_DIR) export REBAR_DEPS_DIR -# External "early" plugins (see core/plugins.mk for regular plugins). -# They both use the core_dep_plugin macro. - -define core_dep_plugin -ifeq ($(2),$(PROJECT)) --include $$(patsubst $(PROJECT)/%,%,$(1)) -else --include $(DEPS_DIR)/$(1) - -$(DEPS_DIR)/$(1): $(DEPS_DIR)/$(2) ; -endif -endef - -DEP_EARLY_PLUGINS ?= - -$(foreach p,$(DEP_EARLY_PLUGINS),\ - $(eval $(if $(findstring /,$p),\ - $(call core_dep_plugin,$p,$(firstword $(subst /, ,$p))),\ - $(call core_dep_plugin,$p/early-plugins.mk,$p)))) - dep_name = $(if $(dep_$(1)),$(1),$(if $(pkg_$(1)_name),$(pkg_$(1)_name),$(1))) dep_repo = $(patsubst git://github.com/%,https://github.com/%, \ $(if $(dep_$(1)),$(word 2,$(dep_$(1))),$(pkg_$(1)_repo))) dep_commit = $(if $(dep_$(1)_commit),$(dep_$(1)_commit),$(if $(dep_$(1)),$(word 3,$(dep_$(1))),$(pkg_$(1)_commit))) -LOCAL_DEPS_DIRS = $(foreach a,$(LOCAL_DEPS),$(if $(wildcard $(APPS_DIR)/$(a)),$(APPS_DIR)/$(a))) ALL_APPS_DIRS = $(if $(wildcard $(APPS_DIR)/),$(filter-out $(APPS_DIR),$(shell find $(APPS_DIR) -maxdepth 1 -type d))) ALL_DEPS_DIRS = $(addprefix $(DEPS_DIR)/,$(foreach dep,$(filter-out $(IGNORE_DEPS),$(BUILD_DEPS) $(DEPS)),$(call dep_name,$(dep)))) @@ -378,7 +278,10 @@ dep_verbose = $(dep_verbose_$(V)) # Core targets. -apps:: $(ALL_APPS_DIRS) clean-tmp-deps.log +ifdef IS_APP +apps:: +else +apps:: $(ALL_APPS_DIRS) ifeq ($(IS_APP)$(IS_DEP),) $(verbose) rm -f $(ERLANG_MK_TMP)/apps.log endif @@ -386,42 +289,36 @@ endif # Create ebin directory for all apps to make sure Erlang recognizes them # as proper OTP applications when using -include_lib. This is a temporary # fix, a proper fix would be to compile apps/* in the right order. -ifndef IS_APP - $(verbose) set -e; for dep in $(ALL_APPS_DIRS) ; do \ - mkdir -p $$dep/ebin; \ + $(verbose) for dep in $(ALL_APPS_DIRS) ; do \ + mkdir -p $$dep/ebin || exit $$?; \ done -endif -# at the toplevel: if LOCAL_DEPS is defined with at least one local app, only -# compile that list of apps. otherwise, compile everything. -# within an app: compile all LOCAL_DEPS that are (uncompiled) local apps - $(verbose) set -e; for dep in $(if $(LOCAL_DEPS_DIRS)$(IS_APP),$(LOCAL_DEPS_DIRS),$(ALL_APPS_DIRS)) ; do \ + $(verbose) for dep in $(ALL_APPS_DIRS) ; do \ if grep -qs ^$$dep$$ $(ERLANG_MK_TMP)/apps.log; then \ :; \ else \ echo $$dep >> $(ERLANG_MK_TMP)/apps.log; \ - $(MAKE) -C $$dep IS_APP=1; \ + $(MAKE) -C $$dep IS_APP=1 || exit $$?; \ fi \ done - -clean-tmp-deps.log: -ifeq ($(IS_APP)$(IS_DEP),) - $(verbose) rm -f $(ERLANG_MK_TMP)/deps.log endif ifneq ($(SKIP_DEPS),) deps:: else -deps:: $(ALL_DEPS_DIRS) apps clean-tmp-deps.log +deps:: $(ALL_DEPS_DIRS) apps +ifeq ($(IS_APP)$(IS_DEP),) + $(verbose) rm -f $(ERLANG_MK_TMP)/deps.log +endif $(verbose) mkdir -p $(ERLANG_MK_TMP) - $(verbose) set -e; for dep in $(ALL_DEPS_DIRS) ; do \ + $(verbose) for dep in $(ALL_DEPS_DIRS) ; do \ if grep -qs ^$$dep$$ $(ERLANG_MK_TMP)/deps.log; then \ :; \ else \ echo $$dep >> $(ERLANG_MK_TMP)/deps.log; \ if [ -f $$dep/GNUmakefile ] || [ -f $$dep/makefile ] || [ -f $$dep/Makefile ]; then \ - $(MAKE) -C $$dep IS_DEP=1; \ + $(MAKE) -C $$dep IS_DEP=1 || exit $$?; \ else \ - echo "Error: No Makefile to build dependency $$dep." >&2; \ + echo "Error: No Makefile to build dependency $$dep."; \ exit 2; \ fi \ fi \ @@ -435,18 +332,17 @@ endif # in practice only Makefile is needed so far. define dep_autopatch if [ -f $(DEPS_DIR)/$(1)/erlang.mk ]; then \ - rm -rf $(DEPS_DIR)/$1/ebin/; \ $(call erlang,$(call dep_autopatch_appsrc.erl,$(1))); \ $(call dep_autopatch_erlang_mk,$(1)); \ elif [ -f $(DEPS_DIR)/$(1)/Makefile ]; then \ - if [ -f $(DEPS_DIR)/$1/rebar.lock ]; then \ - $(call dep_autopatch2,$1); \ - elif [ 0 != `grep -c "include ../\w*\.mk" $(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 \ + elif [ 0 != `grep -ci rebar $(DEPS_DIR)/$(1)/Makefile` ]; then \ $(call dep_autopatch2,$(1)); \ - elif [ -n "`find $(DEPS_DIR)/$(1)/ -type f -name \*.mk -not -name erlang.mk -exec grep -i "^[^#].*rebar" '{}' \;`" ]; then \ + elif [ -n "`find $(DEPS_DIR)/$(1)/ -type f -name \*.mk -not -name erlang.mk -exec grep -i rebar '{}' \;`" ]; then \ $(call dep_autopatch2,$(1)); \ + else \ + $(call erlang,$(call dep_autopatch_app.erl,$(1))); \ fi \ else \ if [ ! -d $(DEPS_DIR)/$(1)/src/ ]; then \ @@ -458,14 +354,11 @@ define dep_autopatch endef define dep_autopatch2 - ! test -f $(DEPS_DIR)/$1/ebin/$1.app || \ - mv -n $(DEPS_DIR)/$1/ebin/$1.app $(DEPS_DIR)/$1/src/$1.app.src; \ - rm -f $(DEPS_DIR)/$1/ebin/$1.app; \ 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 -o -f $(DEPS_DIR)/$(1)/rebar.config -o -f $(DEPS_DIR)/$(1)/rebar.config.script -o -f $(DEPS_DIR)/$1/rebar.lock ]; 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 \ @@ -477,15 +370,11 @@ define dep_autopatch_noop printf "noop:\n" > $(DEPS_DIR)/$(1)/Makefile endef -# Replace "include erlang.mk" with a line that will load the parent Erlang.mk -# if given. Do it for all 3 possible Makefile file names. +# Overwrite erlang.mk with the current file by default. ifeq ($(NO_AUTOPATCH_ERLANG_MK),) define dep_autopatch_erlang_mk - for f in Makefile makefile GNUmakefile; do \ - if [ -f $(DEPS_DIR)/$1/$$f ]; then \ - sed -i.bak s/'include *erlang.mk'/'include $$(if $$(ERLANG_MK_FILENAME),$$(ERLANG_MK_FILENAME),erlang.mk)'/ $(DEPS_DIR)/$1/$$f; \ - fi \ - done + echo "include $(call core_relpath,$(dir $(ERLANG_MK_FILENAME)),$(DEPS_DIR)/app)/erlang.mk" \ + > $(DEPS_DIR)/$1/erlang.mk endef else define dep_autopatch_erlang_mk @@ -504,7 +393,7 @@ define dep_autopatch_fetch_rebar if [ ! -d $(ERLANG_MK_TMP)/rebar ]; then \ git clone -q -n -- https://github.com/rebar/rebar $(ERLANG_MK_TMP)/rebar; \ cd $(ERLANG_MK_TMP)/rebar; \ - git checkout -q 576e12171ab8d69b048b827b92aa65d067deea01; \ + git checkout -q 791db716b5a3a7671e0b351f95ddf24b848ee173; \ $(MAKE); \ cd -; \ fi @@ -521,7 +410,6 @@ endef define dep_autopatch_rebar.erl application:load(rebar), application:set_env(rebar, log_level, debug), - rmemo:start(), Conf1 = case file:consult("$(call core_native_path,$(DEPS_DIR)/$1/rebar.config)") of {ok, Conf0} -> Conf0; _ -> [] @@ -550,10 +438,6 @@ define dep_autopatch_rebar.erl Write("C_SRC_TYPE = rebar\n"), Write("DRV_CFLAGS = -fPIC\nexport DRV_CFLAGS\n"), Write(["ERLANG_ARCH = ", rebar_utils:wordsize(), "\nexport ERLANG_ARCH\n"]), - ToList = fun - (V) when is_atom(V) -> atom_to_list(V); - (V) when is_list(V) -> "'\\"" ++ V ++ "\\"'" - end, fun() -> Write("ERLC_OPTS = +debug_info\nexport ERLC_OPTS\n"), case lists:keyfind(erl_opts, 1, Conf) of @@ -561,18 +445,16 @@ define dep_autopatch_rebar.erl {_, ErlOpts} -> lists:foreach(fun ({d, D}) -> - Write("ERLC_OPTS += -D" ++ ToList(D) ++ "=1\n"); - ({d, DKey, DVal}) -> - Write("ERLC_OPTS += -D" ++ ToList(DKey) ++ "=" ++ ToList(DVal) ++ "\n"); + Write("ERLC_OPTS += -D" ++ atom_to_list(D) ++ "=1\n"); ({i, I}) -> Write(["ERLC_OPTS += -I ", I, "\n"]); ({platform_define, Regex, D}) -> case rebar_utils:is_arch(Regex) of - true -> Write("ERLC_OPTS += -D" ++ ToList(D) ++ "=1\n"); + true -> Write("ERLC_OPTS += -D" ++ atom_to_list(D) ++ "=1\n"); false -> ok end; ({parse_transform, PT}) -> - Write("ERLC_OPTS += +'{parse_transform, " ++ ToList(PT) ++ "}'\n"); + Write("ERLC_OPTS += +'{parse_transform, " ++ atom_to_list(PT) ++ "}'\n"); (_) -> ok end, ErlOpts) end, @@ -681,9 +563,9 @@ define dep_autopatch_rebar.erl [] -> 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", + 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) -> @@ -722,7 +604,7 @@ define dep_autopatch_rebar.erl "%.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, ": ", 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)", @@ -734,7 +616,7 @@ define dep_autopatch_rebar.erl end, [PortSpec(S) || S <- PortSpecs] end, - Write("\ninclude $$\(if $$\(ERLANG_MK_FILENAME),$$\(ERLANG_MK_FILENAME),erlang.mk)"), + Write("\ninclude $(call core_relpath,$(dir $(ERLANG_MK_FILENAME)),$(DEPS_DIR)/app)/erlang.mk"), RunPlugin = fun(Plugin, Step) -> case erlang:function_exported(Plugin, Step, 2) of false -> ok; @@ -782,14 +664,27 @@ define dep_autopatch_rebar.erl halt() endef +define dep_autopatch_app.erl + UpdateModules = fun(App) -> + case filelib:is_regular(App) of + false -> ok; + true -> + {ok, [{application, '$(1)', L0}]} = file:consult(App), + 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}])) + end + end, + UpdateModules("$(call core_native_path,$(DEPS_DIR)/$1/ebin/$1.app)"), + halt() +endef + define dep_autopatch_appsrc_script.erl AppSrc = "$(call core_native_path,$(DEPS_DIR)/$1/src/$1.app.src)", AppSrcScript = AppSrc ++ ".script", - {ok, Conf0} = file:consult(AppSrc), - Bindings0 = erl_eval:new_bindings(), - Bindings1 = erl_eval:add_binding('CONFIG', Conf0, Bindings0), - Bindings = erl_eval:add_binding('SCRIPT', AppSrcScript, Bindings1), - {ok, [Conf]} = file:script(AppSrcScript, Bindings), + Bindings = erl_eval:new_bindings(), + {ok, Conf} = file:script(AppSrcScript, Bindings), ok = file:write_file(AppSrc, io_lib:format("~p.~n", [Conf])), halt() endef @@ -802,11 +697,7 @@ define dep_autopatch_appsrc.erl true -> {ok, [{application, $(1), L0}]} = file:consult(AppSrcIn), L1 = lists:keystore(modules, 1, L0, {modules, []}), - L2 = case lists:keyfind(vsn, 1, L1) of - {_, git} -> lists:keyreplace(vsn, 1, L1, {vsn, "git"}); - {_, {cmd, _}} -> lists:keyreplace(vsn, 1, L1, {vsn, "cmd"}); - _ -> L1 - end, + L2 = case lists:keyfind(vsn, 1, L1) of {_, git} -> lists:keyreplace(vsn, 1, L1, {vsn, "git"}); _ -> L1 end, L3 = case lists:keyfind(registered, 1, L2) of false -> [{registered, []}|L2]; _ -> L2 end, ok = file:write_file(AppSrcOut, io_lib:format("~p.~n", [{application, $(1), L3}])), case AppSrcOut of AppSrcIn -> ok; _ -> ok = file:delete(AppSrcIn) end @@ -836,16 +727,21 @@ define dep_fetch_cp cp -R $(call dep_repo,$(1)) $(DEPS_DIR)/$(call dep_name,$(1)); endef -define dep_fetch_ln - ln -s $(call dep_repo,$(1)) $(DEPS_DIR)/$(call dep_name,$(1)); +define dep_fetch_hex.erl + ssl:start(), + inets:start(), + {ok, {{_, 200, _}, _, Body}} = httpc:request(get, + {"https://s3.amazonaws.com/s3.hex.pm/tarballs/$(1)-$(2).tar", []}, + [], [{body_format, binary}]), + {ok, Files} = erl_tar:extract({binary, Body}, [memory]), + {_, Source} = lists:keyfind("contents.tar.gz", 1, Files), + ok = erl_tar:extract({binary, Source}, [{cwd, "$(call core_native_path,$(DEPS_DIR)/$1)"}, compressed]), + halt() endef # Hex only has a package version. No need to look in the Erlang.mk packages. define dep_fetch_hex - mkdir -p $(ERLANG_MK_TMP)/hex $(DEPS_DIR)/$1; \ - $(call core_http_get,$(ERLANG_MK_TMP)/hex/$1.tar,\ - https://s3.amazonaws.com/s3.hex.pm/tarballs/$1-$(strip $(word 2,$(dep_$1))).tar); \ - tar -xOf $(ERLANG_MK_TMP)/hex/$1.tar contents.tar.gz | tar -C $(DEPS_DIR)/$1 -xzf -; + $(call erlang,$(call dep_fetch_hex.erl,$(1),$(strip $(word 2,$(dep_$(1)))))); endef define dep_fetch_fail @@ -875,7 +771,7 @@ $(DEPS_DIR)/$(call dep_name,$1): $(eval DEP_NAME := $(call dep_name,$1)) $(eval DEP_STR := $(if $(filter-out $1,$(DEP_NAME)),$1,"$1 ($(DEP_NAME))")) $(verbose) if test -d $(APPS_DIR)/$(DEP_NAME); then \ - echo "Error: Dependency" $(DEP_STR) "conflicts with application found in $(APPS_DIR)/$(DEP_NAME)." >&2; \ + echo "Error: Dependency" $(DEP_STR) "conflicts with application found in $(APPS_DIR)/$(DEP_NAME)."; \ exit 17; \ fi $(verbose) mkdir -p $(DEPS_DIR) @@ -917,15 +813,15 @@ ifndef IS_APP clean:: clean-apps clean-apps: - $(verbose) set -e; for dep in $(ALL_APPS_DIRS) ; do \ - $(MAKE) -C $$dep clean IS_APP=1; \ + $(verbose) for dep in $(ALL_APPS_DIRS) ; do \ + $(MAKE) -C $$dep clean IS_APP=1 || exit $$?; \ done distclean:: distclean-apps distclean-apps: - $(verbose) set -e; for dep in $(ALL_APPS_DIRS) ; do \ - $(MAKE) -C $$dep distclean IS_APP=1; \ + $(verbose) for dep in $(ALL_APPS_DIRS) ; do \ + $(MAKE) -C $$dep distclean IS_APP=1 || exit $$?; \ done endif @@ -936,16 +832,77 @@ distclean-deps: $(gen_verbose) rm -rf $(DEPS_DIR) endif -# Forward-declare variables used in core/deps-tools.mk. This is required -# in case plugins use them. +# External plugins. -ERLANG_MK_RECURSIVE_DEPS_LIST = $(ERLANG_MK_TMP)/recursive-deps-list.log -ERLANG_MK_RECURSIVE_DOC_DEPS_LIST = $(ERLANG_MK_TMP)/recursive-doc-deps-list.log -ERLANG_MK_RECURSIVE_REL_DEPS_LIST = $(ERLANG_MK_TMP)/recursive-rel-deps-list.log -ERLANG_MK_RECURSIVE_TEST_DEPS_LIST = $(ERLANG_MK_TMP)/recursive-test-deps-list.log -ERLANG_MK_RECURSIVE_SHELL_DEPS_LIST = $(ERLANG_MK_TMP)/recursive-shell-deps-list.log +DEP_PLUGINS ?= -# Copyright (c) 2015-2016, Loïc Hoguin +define core_dep_plugin +-include $(DEPS_DIR)/$(1) + +$(DEPS_DIR)/$(1): $(DEPS_DIR)/$(2) ; +endef + +$(foreach p,$(DEP_PLUGINS),\ + $(eval $(if $(findstring /,$p),\ + $(call core_dep_plugin,$p,$(firstword $(subst /, ,$p))),\ + $(call core_dep_plugin,$p/plugins.mk,$p)))) + +# Copyright (c) 2013-2015, Loïc Hoguin +# This file is part of erlang.mk and subject to the terms of the ISC License. + +# Configuration. + +DTL_FULL_PATH ?= +DTL_PATH ?= templates/ +DTL_SUFFIX ?= _dtl +DTL_OPTS ?= + +# Verbosity. + +dtl_verbose_0 = @echo " DTL " $(filter %.dtl,$(?F)); +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 + "" -> + filename:basename(F, ".dtl"); + _ -> + "$(DTL_PATH)" ++ F2 = filename:rootname(F, ".dtl"), + re:replace(F2, "/", "_", [{return, list}, global]) + end, + Module = list_to_atom(string:to_lower(Module0) ++ "$(DTL_SUFFIX)"), + case erlydtl:compile(F, Module, [$(DTL_OPTS)] ++ [{out_dir, "ebin/"}, return_errors, {doc_root, "templates"}]) of + ok -> ok; + {ok, _} -> ok + end + end || F <- string:tokens("$(1)", " ")], + halt(). +endef + +ebin/$(PROJECT).app:: $(DTL_FILES) | ebin/ + $(if $(strip $?),\ + $(dtl_verbose) $(call erlang,$(call erlydtl_compile.erl,$?),-pa ebin/ $(DEPS_DIR)/erlydtl/ebin/)) + +endif + +# Copyright (c) 2015, Loïc Hoguin # This file is part of erlang.mk and subject to the terms of the ISC License. # Verbosity. @@ -964,9 +921,10 @@ endef define compile_proto.erl [begin + Dir = filename:dirname(filename:dirname(F)), protobuffs_compile:generate_source(F, - [{output_include_dir, "./include"}, - {output_src_dir, "./ebin"}]) + [{output_include_dir, Dir ++ "/include"}, + {output_src_dir, Dir ++ "/ebin"}]) end || F <- string:tokens("$(1)", " ")], halt(). endef @@ -976,7 +934,7 @@ ebin/$(PROJECT).app:: $(sort $(call core_find,src/,*.proto)) $(if $(strip $?),$(call compile_proto,$?)) endif -# Copyright (c) 2013-2016, Loïc Hoguin +# Copyright (c) 2013-2015, Loïc Hoguin # This file is part of erlang.mk and subject to the terms of the ISC License. .PHONY: clean-app @@ -990,8 +948,6 @@ COMPILE_FIRST_PATHS = $(addprefix src/,$(addsuffix .erl,$(COMPILE_FIRST))) ERLC_EXCLUDE ?= ERLC_EXCLUDE_PATHS = $(addprefix src/,$(addsuffix .erl,$(ERLC_EXCLUDE))) -ERLC_ASN1_OPTS ?= - ERLC_MIB_OPTS ?= COMPILE_MIB_FIRST ?= COMPILE_MIB_FIRST_PATHS = $(addprefix mibs/,$(addsuffix .mib,$(COMPILE_MIB_FIRST))) @@ -1041,27 +997,25 @@ endif ifeq ($(wildcard src/$(PROJECT_MOD).erl),) define app_file -{application, '$(PROJECT)', [ +{application, $(PROJECT), [ {description, "$(PROJECT_DESCRIPTION)"}, {vsn, "$(PROJECT_VERSION)"},$(if $(IS_DEP), {id$(comma)$(space)"$(1)"}$(comma)) {modules, [$(call comma_list,$(2))]}, {registered, []}, - {applications, [$(call comma_list,kernel stdlib $(OTP_DEPS) $(LOCAL_DEPS) $(foreach dep,$(DEPS),$(call dep_name,$(dep))))]}, - {env, $(subst \,\\,$(PROJECT_ENV))}$(if $(findstring {,$(PROJECT_APP_EXTRA_KEYS)),$(comma)$(newline)$(tab)$(subst \,\\,$(PROJECT_APP_EXTRA_KEYS)),) + {applications, [$(call comma_list,kernel stdlib $(OTP_DEPS) $(LOCAL_DEPS) $(DEPS))]} ]}. endef else define app_file -{application, '$(PROJECT)', [ +{application, $(PROJECT), [ {description, "$(PROJECT_DESCRIPTION)"}, {vsn, "$(PROJECT_VERSION)"},$(if $(IS_DEP), {id$(comma)$(space)"$(1)"}$(comma)) {modules, [$(call comma_list,$(2))]}, {registered, [$(call comma_list,$(PROJECT)_sup $(PROJECT_REGISTERED))]}, - {applications, [$(call comma_list,kernel stdlib $(OTP_DEPS) $(LOCAL_DEPS) $(foreach dep,$(DEPS),$(call dep_name,$(dep))))]}, - {mod, {$(PROJECT_MOD), []}}, - {env, $(subst \,\\,$(PROJECT_ENV))}$(if $(findstring {,$(PROJECT_APP_EXTRA_KEYS)),$(comma)$(newline)$(tab)$(subst \,\\,$(PROJECT_APP_EXTRA_KEYS)),) + {applications, [$(call comma_list,kernel stdlib $(OTP_DEPS) $(LOCAL_DEPS) $(DEPS))]}, + {mod, {$(PROJECT_MOD), []}} ]}. endef endif @@ -1071,10 +1025,8 @@ app-build: ebin/$(PROJECT).app # Source files. -ALL_SRC_FILES := $(sort $(call core_find,src/,*)) - -ERL_FILES := $(filter %.erl,$(ALL_SRC_FILES)) -CORE_FILES := $(filter %.core,$(ALL_SRC_FILES)) +ERL_FILES = $(sort $(call core_find,src/,*.erl)) +CORE_FILES = $(sort $(call core_find,src/,*.core)) # ASN.1 files. @@ -1084,7 +1036,7 @@ ERL_FILES += $(addprefix src/,$(patsubst %.asn1,%.erl,$(notdir $(ASN1_FILES)))) define compile_asn1 $(verbose) mkdir -p include/ - $(asn1_verbose) erlc -v -I include/ -o asn1/ +noobj $(ERLC_ASN1_OPTS) $(1) + $(asn1_verbose) erlc -v -I include/ -o asn1/ +noobj $(1) $(verbose) mv asn1/*.erl src/ $(verbose) mv asn1/*.hrl include/ $(verbose) mv asn1/*.asn1db include/ @@ -1107,16 +1059,16 @@ endif # Leex and Yecc files. -XRL_FILES := $(filter %.xrl,$(ALL_SRC_FILES)) +XRL_FILES = $(sort $(call core_find,src/,*.xrl)) XRL_ERL_FILES = $(addprefix src/,$(patsubst %.xrl,%.erl,$(notdir $(XRL_FILES)))) ERL_FILES += $(XRL_ERL_FILES) -YRL_FILES := $(filter %.yrl,$(ALL_SRC_FILES)) +YRL_FILES = $(sort $(call core_find,src/,*.yrl)) YRL_ERL_FILES = $(addprefix src/,$(patsubst %.yrl,%.erl,$(notdir $(YRL_FILES)))) ERL_FILES += $(YRL_ERL_FILES) $(PROJECT).d:: $(XRL_FILES) $(YRL_FILES) - $(if $(strip $?),$(xyrl_verbose) erlc -v -o src/ $(YRL_ERLC_OPTS) $?) + $(if $(strip $?),$(xyrl_verbose) erlc -v -o src/ $?) # Erlang and Core Erlang files. @@ -1166,12 +1118,7 @@ define makedep.erl (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, _}) -> - IsFile = - case lists:keyfind(Imp, 1, Modules) of - false -> false; - {_, FilePath} -> filelib:is_file(FilePath) - end, - case IsFile of + case filelib:is_file("src/" ++ atom_to_list(Imp) ++ ".erl") of false -> ok; true -> Add(Mod, Imp) end; @@ -1195,41 +1142,23 @@ define makedep.erl end || F <- ErlFiles], 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)], - TargetPath = fun(Target) -> - case lists:keyfind(Target, 1, Modules) of - false -> ""; - {_, DepFile} -> - DirSubname = tl(string:tokens(filename:dirname(DepFile), "/")), - string:join(DirSubname ++ [atom_to_list(Target)], "/") - end - end, ok = file:write_file("$(1)", [ [[F, "::", [[" ", D] || D <- Deps], "; @touch \$$@\n"] || {F, Deps} <- Depend], - "\nCOMPILE_FIRST +=", [[" ", TargetPath(CF)] || CF <- CompileFirst], "\n" + "\nCOMPILE_FIRST +=", [[" ", atom_to_list(CF)] || CF <- CompileFirst], "\n" ]), halt() endef ifeq ($(if $(NO_MAKEDEP),$(wildcard $(PROJECT).d),),) -$(PROJECT).d:: $(ERL_FILES) $(call core_find,include/,*.hrl) $(MAKEFILE_LIST) +$(PROJECT).d:: $(ERL_FILES) $(call core_find,include/,*.hrl) $(makedep_verbose) $(call erlang,$(call makedep.erl,$@)) endif -ifneq ($(words $(ERL_FILES) $(CORE_FILES) $(ASN1_FILES) $(MIB_FILES) $(XRL_FILES) $(YRL_FILES)),0) # Rebuild everything when the Makefile changes. -$(ERLANG_MK_TMP)/last-makefile-change: $(MAKEFILE_LIST) - $(verbose) mkdir -p $(ERLANG_MK_TMP) - $(verbose) if test -f $@; then \ - touch $(ERL_FILES) $(CORE_FILES) $(ASN1_FILES) $(MIB_FILES) $(XRL_FILES) $(YRL_FILES); \ - touch -c $(PROJECT).d; \ - fi - $(verbose) touch $@ +$(ERL_FILES) $(CORE_FILES) $(ASN1_FILES) $(MIB_FILES) $(XRL_FILES) $(YRL_FILES):: $(MAKEFILE_LIST) + @touch $@ -$(ERL_FILES) $(CORE_FILES) $(ASN1_FILES) $(MIB_FILES) $(XRL_FILES) $(YRL_FILES):: $(ERLANG_MK_TMP)/last-makefile-change -ebin/$(PROJECT).app:: $(ERLANG_MK_TMP)/last-makefile-change -endif - -include $(wildcard $(PROJECT).d) +-include $(PROJECT).d ebin/$(PROJECT).app:: ebin/ @@ -1248,7 +1177,7 @@ ebin/$(PROJECT).app:: $(ERL_FILES) $(CORE_FILES) $(wildcard src/$(PROJECT).app.s $(eval MODULES := $(patsubst %,'%',$(sort $(notdir $(basename \ $(filter-out $(ERLC_EXCLUDE_PATHS),$(ERL_FILES) $(CORE_FILES) $(BEAM_FILES))))))) ifeq ($(wildcard src/$(PROJECT).app.src),) - $(app_verbose) printf '$(subst %,%%,$(subst $(newline),\n,$(subst ','\'',$(call app_file,$(GITDESCRIBE),$(MODULES)))))' \ + $(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 \ @@ -1272,7 +1201,6 @@ clean-app: endif -# Copyright (c) 2016, Loïc Hoguin # Copyright (c) 2015, Viktor Söderqvist # This file is part of erlang.mk and subject to the terms of the ISC License. @@ -1290,10 +1218,10 @@ ifneq ($(SKIP_DEPS),) doc-deps: else doc-deps: $(ALL_DOC_DEPS_DIRS) - $(verbose) set -e; for dep in $(ALL_DOC_DEPS_DIRS) ; do $(MAKE) -C $$dep; done + $(verbose) for dep in $(ALL_DOC_DEPS_DIRS) ; do $(MAKE) -C $$dep; done endif -# Copyright (c) 2015-2016, Loïc Hoguin +# Copyright (c) 2015, Loïc Hoguin # This file is part of erlang.mk and subject to the terms of the ISC License. .PHONY: rel-deps @@ -1310,10 +1238,10 @@ ifneq ($(SKIP_DEPS),) rel-deps: else rel-deps: $(ALL_REL_DEPS_DIRS) - $(verbose) set -e; for dep in $(ALL_REL_DEPS_DIRS) ; do $(MAKE) -C $$dep; done + $(verbose) for dep in $(ALL_REL_DEPS_DIRS) ; do $(MAKE) -C $$dep; done endif -# Copyright (c) 2015-2016, Loïc Hoguin +# Copyright (c) 2015, Loïc Hoguin # 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 @@ -1335,7 +1263,7 @@ ifneq ($(SKIP_DEPS),) test-deps: else test-deps: $(ALL_TEST_DEPS_DIRS) - $(verbose) set -e; for dep in $(ALL_TEST_DEPS_DIRS) ; do $(MAKE) -C $$dep IS_DEP=1; done + $(verbose) for dep in $(ALL_TEST_DEPS_DIRS) ; do $(MAKE) -C $$dep IS_DEP=1; done endif ifneq ($(wildcard $(TEST_DIR)),) @@ -1368,7 +1296,7 @@ ifneq ($(wildcard $(TEST_DIR)/*.beam),) endif endif -# Copyright (c) 2015-2016, Loïc Hoguin +# Copyright (c) 2015, Loïc Hoguin # This file is part of erlang.mk and subject to the terms of the ISC License. .PHONY: rebar.config @@ -1404,90 +1332,54 @@ $(eval export _compat_rebar_config) rebar.config: $(gen_verbose) echo "$${_compat_rebar_config}" > rebar.config -# Copyright (c) 2015-2016, Loïc Hoguin +# Copyright (c) 2015, Loïc Hoguin # This file is part of erlang.mk and subject to the terms of the ISC License. -ifeq ($(filter asciideck,$(DEPS) $(DOC_DEPS)),asciideck) +.PHONY: asciidoc asciidoc-guide asciidoc-manual install-asciidoc distclean-asciidoc -.PHONY: asciidoc asciidoc-guide asciidoc-manual install-asciidoc distclean-asciidoc-guide distclean-asciidoc-manual - -# Core targets. +MAN_INSTALL_PATH ?= /usr/local/share/man +MAN_SECTIONS ?= 3 7 docs:: asciidoc -distclean:: distclean-asciidoc-guide distclean-asciidoc-manual - -# Plugin-specific targets. - asciidoc: asciidoc-guide asciidoc-manual -# User guide. - ifeq ($(wildcard doc/src/guide/book.asciidoc),) asciidoc-guide: else -asciidoc-guide: distclean-asciidoc-guide doc-deps +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/ - -distclean-asciidoc-guide: - $(gen_verbose) rm -rf doc/html/ doc/guide.pdf endif -# Man pages. - -ASCIIDOC_MANUAL_FILES := $(wildcard doc/src/manual/*.asciidoc) - -ifeq ($(ASCIIDOC_MANUAL_FILES),) +ifeq ($(wildcard doc/src/manual/*.asciidoc),) asciidoc-manual: else - -# Configuration. - -MAN_INSTALL_PATH ?= /usr/local/share/man -MAN_SECTIONS ?= 3 7 -MAN_PROJECT ?= $(shell echo $(PROJECT) | sed 's/^./\U&\E/') -MAN_VERSION ?= $(PROJECT_VERSION) - -# Plugin-specific targets. - -define asciidoc2man.erl -try - [begin - io:format(" ADOC ~s~n", [F]), - ok = asciideck:to_manpage(asciideck:parse_file(F), #{ - compress => gzip, - outdir => filename:dirname(F), - extra2 => "$(MAN_PROJECT) $(MAN_VERSION)", - extra3 => "$(MAN_PROJECT) Function Reference" - }) - end || F <- [$(shell echo $(addprefix $(comma)\",$(addsuffix \",$1)) | sed 's/^.//')]], - halt(0) -catch C:E -> - io:format("Exception ~p:~p~nStacktrace: ~p~n", [C, E, erlang:get_stacktrace()]), - halt(1) -end. -endef - -asciidoc-manual:: doc-deps - -asciidoc-manual:: $(ASCIIDOC_MANUAL_FILES) - $(call erlang,$(call asciidoc2man.erl,$?)) - $(foreach s,$(MAN_SECTIONS),mkdir -p doc/man$s/ && mv doc/src/manual/*.$s.gz doc/man$s/;) +asciidoc-manual: distclean-asciidoc doc-deps + for f in doc/src/manual/*.asciidoc ; do \ + a2x -v -f manpage $$f ; \ + done + for s in $(MAN_SECTIONS); do \ + mkdir -p doc/man$$s/ ; \ + mv doc/src/manual/*.$$s doc/man$$s/ ; \ + gzip doc/man$$s/*.$$s ; \ + done install-docs:: install-asciidoc install-asciidoc: asciidoc-manual - $(foreach s,$(MAN_SECTIONS),\ - mkdir -p $(MAN_INSTALL_PATH)/man$s/ && \ - install -g `id -g` -o `id -u` -m 0644 doc/man$s/*.gz $(MAN_INSTALL_PATH)/man$s/;) - -distclean-asciidoc-manual: - $(gen_verbose) rm -rf $(addprefix doc/man,$(MAN_SECTIONS)) -endif + for s in $(MAN_SECTIONS); do \ + mkdir -p $(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 -# Copyright (c) 2014-2016, Loïc Hoguin +distclean:: distclean-asciidoc + +distclean-asciidoc: + $(gen_verbose) rm -rf doc/html/ doc/guide.pdf doc/man3/ doc/man7/ + +# Copyright (c) 2014-2015, Loïc Hoguin # This file is part of erlang.mk and subject to the terms of the ISC License. .PHONY: bootstrap bootstrap-lib bootstrap-rel new list-templates @@ -1544,7 +1436,7 @@ ifdef SP define bs_Makefile PROJECT = $p PROJECT_DESCRIPTION = New project -PROJECT_VERSION = 0.1.0 +PROJECT_VERSION = 0.0.1 # Whitespace to be used when creating files from templates. SP = $(SP) @@ -1554,7 +1446,7 @@ else define bs_Makefile PROJECT = $p PROJECT_DESCRIPTION = New project -PROJECT_VERSION = 0.1.0 +PROJECT_VERSION = 0.0.1 endef endif @@ -1562,7 +1454,7 @@ endif define bs_apps_Makefile PROJECT = $p PROJECT_DESCRIPTION = New project -PROJECT_VERSION = 0.1.0 +PROJECT_VERSION = 0.0.1 include $(call core_relpath,$(dir $(ERLANG_MK_FILENAME)),$(APPS_DIR)/app)/erlang.mk endef @@ -1582,7 +1474,7 @@ stop(_State) -> endef define bs_relx_config -{release, {$p_release, "1"}, [$p, sasl, runtime_tools]}. +{release, {$p_release, "1"}, [$p]}. {extended_start_script, true}. {sys_config, "rel/sys.config"}. {vm_args, "rel/vm.args"}. @@ -1933,6 +1825,9 @@ endif ifndef t $(error Usage: $(MAKE) new t=TEMPLATE n=NAME [in=APP]) endif +ifndef tpl_$(t) + $(error Unknown template) +endif ifndef n $(error Usage: $(MAKE) new t=TEMPLATE n=NAME [in=APP]) endif @@ -1945,7 +1840,7 @@ endif list-templates: $(verbose) echo Available templates: $(sort $(patsubst tpl_%,%,$(filter tpl_%,$(.VARIABLES)))) -# Copyright (c) 2014-2016, Loïc Hoguin +# Copyright (c) 2014-2015, Loïc Hoguin # This file is part of erlang.mk and subject to the terms of the ISC License. .PHONY: clean-c_src distclean-c_src-env @@ -2180,56 +2075,57 @@ else $(call render_template,bs_erl_nif,src/$n.erl) endif -# Copyright (c) 2015-2017, Loïc Hoguin +# Copyright (c) 2015, Loïc Hoguin # This file is part of erlang.mk and subject to the terms of the ISC License. -.PHONY: ci ci-prepare ci-setup +.PHONY: ci ci-setup distclean-kerl +KERL ?= $(CURDIR)/kerl +export KERL + +KERL_URL ?= https://raw.githubusercontent.com/yrashk/kerl/master/kerl + +OTP_GIT ?= https://github.com/erlang/otp + +CI_INSTALL_DIR ?= $(HOME)/erlang CI_OTP ?= -CI_HIPE ?= -CI_ERLLVM ?= -ifeq ($(CI_VM),native) -ERLC_OPTS += +native -TEST_ERLC_OPTS += +native -else ifeq ($(CI_VM),erllvm) -ERLC_OPTS += +native +'{hipe, [to_llvm]}' -TEST_ERLC_OPTS += +native +'{hipe, [to_llvm]}' -endif - -ifeq ($(strip $(CI_OTP) $(CI_HIPE) $(CI_ERLLVM)),) +ifeq ($(strip $(CI_OTP)),) ci:: else +ci:: $(addprefix ci-,$(CI_OTP)) -ci:: $(addprefix ci-,$(CI_OTP) $(addsuffix -native,$(CI_HIPE)) $(addsuffix -erllvm,$(CI_ERLLVM))) - -ci-prepare: $(addprefix $(KERL_INSTALL_DIR)/,$(CI_OTP) $(addsuffix -native,$(CI_HIPE))) +ci-prepare: $(addprefix $(CI_INSTALL_DIR)/,$(CI_OTP)) ci-setup:: -ci-extra:: - ci_verbose_0 = @echo " CI " $(1); ci_verbose = $(ci_verbose_$(V)) define ci_target -ci-$1: $(KERL_INSTALL_DIR)/$2 - $(verbose) $(MAKE) --no-print-directory clean +ci-$(1): $(CI_INSTALL_DIR)/$(1) $(ci_verbose) \ - PATH="$(KERL_INSTALL_DIR)/$2/bin:$(PATH)" \ - CI_OTP_RELEASE="$1" \ - CT_OPTS="-label $1" \ - CI_VM="$3" \ - $(MAKE) ci-setup tests - $(verbose) $(MAKE) --no-print-directory ci-extra + PATH="$(CI_INSTALL_DIR)/$(1)/bin:$(PATH)" \ + CI_OTP_RELEASE="$(1)" \ + CT_OPTS="-label $(1)" \ + $(MAKE) clean ci-setup tests endef -$(foreach otp,$(CI_OTP),$(eval $(call ci_target,$(otp),$(otp),otp))) -$(foreach otp,$(CI_HIPE),$(eval $(call ci_target,$(otp)-native,$(otp)-native,native))) -$(foreach otp,$(CI_ERLLVM),$(eval $(call ci_target,$(otp)-erllvm,$(otp)-native,erllvm))) +$(foreach otp,$(CI_OTP),$(eval $(call ci_target,$(otp)))) -$(foreach otp,$(CI_OTP),$(eval $(call kerl_otp_target,$(otp)))) -$(foreach otp,$(sort $(CI_HIPE) $(CI_ERLLLVM)),$(eval $(call kerl_hipe_target,$(otp)))) +define ci_otp_target +ifeq ($(wildcard $(CI_INSTALL_DIR)/$(1)),) +$(CI_INSTALL_DIR)/$(1): $(KERL) + $(KERL) build git $(OTP_GIT) $(1) $(1) + $(KERL) install $(1) $(CI_INSTALL_DIR)/$(1) +endif +endef + +$(foreach otp,$(CI_OTP),$(eval $(call ci_otp_target,$(otp)))) + +$(KERL): + $(gen_verbose) $(call core_http_get,$(KERL),$(KERL_URL)) + $(verbose) chmod +x $(KERL) help:: $(verbose) printf "%s\n" "" \ @@ -2239,9 +2135,13 @@ help:: "The CI_OTP variable must be defined with the Erlang versions" \ "that must be tested. For example: CI_OTP = OTP-17.3.4 OTP-17.5.3" +distclean:: distclean-kerl + +distclean-kerl: + $(gen_verbose) rm -rf $(KERL) endif -# Copyright (c) 2013-2016, Loïc Hoguin +# Copyright (c) 2013-2015, Loïc Hoguin # This file is part of erlang.mk and subject to the terms of the ISC License. .PHONY: ct apps-ct distclean-ct @@ -2249,14 +2149,11 @@ endif # Configuration. CT_OPTS ?= - ifneq ($(wildcard $(TEST_DIR)),) -ifndef CT_SUITES -CT_SUITES := $(sort $(subst _SUITE.erl,,$(notdir $(call core_find,$(TEST_DIR)/,*_SUITE.erl)))) + CT_SUITES ?= $(sort $(subst _SUITE.erl,,$(notdir $(call core_find,$(TEST_DIR)/,*_SUITE.erl)))) +else + CT_SUITES ?= endif -endif -CT_SUITES ?= -CT_LOGS_DIR ?= $(CURDIR)/logs # Core targets. @@ -2279,18 +2176,15 @@ CT_RUN = ct_run \ -noinput \ -pa $(CURDIR)/ebin $(DEPS_DIR)/*/ebin $(APPS_DIR)/*/ebin $(TEST_DIR) \ -dir $(TEST_DIR) \ - -logdir $(CT_LOGS_DIR) + -logdir $(CURDIR)/logs ifeq ($(CT_SUITES),) ct: $(if $(IS_APP),,apps-ct) else -# We do not run tests if we are in an apps/* with no test directory. -ifneq ($(IS_APP)$(wildcard $(TEST_DIR)),1) ct: test-build $(if $(IS_APP),,apps-ct) - $(verbose) mkdir -p $(CT_LOGS_DIR) + $(verbose) mkdir -p $(CURDIR)/logs/ $(gen_verbose) $(CT_RUN) -sname ct_$(PROJECT) -suite $(addsuffix _SUITE,$(CT_SUITES)) $(CT_OPTS) endif -endif ifneq ($(ALL_APPS_DIRS),) define ct_app_target @@ -2316,16 +2210,16 @@ endif define ct_suite_target ct-$(1): test-build - $(verbose) mkdir -p $(CT_LOGS_DIR) + $(verbose) mkdir -p $(CURDIR)/logs/ $(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)))) distclean-ct: - $(gen_verbose) rm -rf $(CT_LOGS_DIR) + $(gen_verbose) rm -rf $(CURDIR)/logs/ -# Copyright (c) 2013-2016, Loïc Hoguin +# Copyright (c) 2013-2015, Loïc Hoguin # This file is part of erlang.mk and subject to the terms of the ISC License. .PHONY: plt distclean-plt dialyze @@ -2354,25 +2248,19 @@ help:: # Plugin-specific targets. define filter_opts.erl - Opts = init:get_plain_arguments(), - {Filtered, _} = lists:foldl(fun - (O, {Os, true}) -> {[O|Os], false}; - (O = "-D", {Os, _}) -> {[O|Os], true}; - (O = [\\$$-, \\$$D, _ | _], {Os, _}) -> {[O|Os], false}; - (O = "-I", {Os, _}) -> {[O|Os], true}; - (O = [\\$$-, \\$$I, _ | _], {Os, _}) -> {[O|Os], false}; - (O = "-pa", {Os, _}) -> {[O|Os], true}; - (_, Acc) -> Acc - end, {[], false}, Opts), - io:format("~s~n", [string:join(lists:reverse(Filtered), " ")]), + 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 - $(eval DEPS_LOG := $(shell test -f $(ERLANG_MK_TMP)/deps.log && \ - while read p; do test -d $$p/ebin && echo $$p/ebin; done <$(ERLANG_MK_TMP)/deps.log)) - $(verbose) dialyzer --build_plt --apps erts kernel stdlib \ - $(PLT_APPS) $(OTP_DEPS) $(LOCAL_DEPS) $(DEPS_LOG) + $(verbose) dialyzer --build_plt --apps erts kernel stdlib $(PLT_APPS) $(OTP_DEPS) $(LOCAL_DEPS) $(DEPS) plt: $(DIALYZER_PLT) @@ -2384,9 +2272,9 @@ dialyze: else dialyze: $(DIALYZER_PLT) endif - $(verbose) dialyzer --no_native `$(ERL) -eval "$(subst $(newline),,$(subst ",\",$(call filter_opts.erl)))" -extra $(ERLC_OPTS)` $(DIALYZER_DIRS) $(DIALYZER_OPTS) + $(verbose) dialyzer --no_native `$(call erlang,$(call filter_opts.erl,$(ERLC_OPTS)))` $(DIALYZER_DIRS) $(DIALYZER_OPTS) -# Copyright (c) 2013-2016, Loïc Hoguin +# Copyright (c) 2013-2015, Loïc Hoguin # This file is part of erlang.mk and subject to the terms of the ISC License. .PHONY: distclean-edoc edoc @@ -2394,21 +2282,10 @@ endif # Configuration. EDOC_OPTS ?= -EDOC_SRC_DIRS ?= -EDOC_OUTPUT ?= doc - -define edoc.erl - SrcPaths = lists:foldl(fun(P, Acc) -> - filelib:wildcard(atom_to_list(P) ++ "/{src,c_src}") ++ Acc - end, [], [$(call comma_list,$(patsubst %,'%',$(EDOC_SRC_DIRS)))]), - DefaultOpts = [{dir, "$(EDOC_OUTPUT)"}, {source_path, SrcPaths}, {subpackages, false}], - edoc:application($(1), ".", [$(2)] ++ DefaultOpts), - halt(0). -endef # Core targets. -ifneq ($(strip $(EDOC_SRC_DIRS)$(wildcard doc/overview.edoc)),) +ifneq ($(wildcard doc/overview.edoc),) docs:: edoc endif @@ -2417,91 +2294,30 @@ distclean:: distclean-edoc # Plugin-specific targets. edoc: distclean-edoc doc-deps - $(gen_verbose) $(call erlang,$(call edoc.erl,$(PROJECT),$(EDOC_OPTS))) + $(gen_verbose) $(ERL) -eval 'edoc:application($(PROJECT), ".", [$(EDOC_OPTS)]), halt().' distclean-edoc: - $(gen_verbose) rm -f $(EDOC_OUTPUT)/*.css $(EDOC_OUTPUT)/*.html $(EDOC_OUTPUT)/*.png $(EDOC_OUTPUT)/edoc-info + $(gen_verbose) rm -f doc/*.css doc/*.html doc/*.png doc/edoc-info -# Copyright (c) 2013-2016, Loïc Hoguin +# Copyright (c) 2014 Dave Cottlehuber # This file is part of erlang.mk and subject to the terms of the ISC License. -# Configuration. - -DTL_FULL_PATH ?= -DTL_PATH ?= templates/ -DTL_SUFFIX ?= _dtl -DTL_OPTS ?= - -# Verbosity. - -dtl_verbose_0 = @echo " DTL " $(filter %.dtl,$(?F)); -dtl_verbose = $(dtl_verbose_$(V)) - -# Core targets. - -DTL_PATH := $(abspath $(DTL_PATH)) -DTL_FILES := $(sort $(call core_find,$(DTL_PATH),*.dtl)) - -ifneq ($(DTL_FILES),) - -DTL_NAMES = $(addsuffix $(DTL_SUFFIX),$(DTL_FILES:$(DTL_PATH)/%.dtl=%)) -DTL_MODULES = $(if $(DTL_FULL_PATH),$(subst /,_,$(DTL_NAMES)),$(notdir $(DTL_NAMES))) -BEAM_FILES += $(addsuffix .beam,$(addprefix ebin/,$(DTL_MODULES))) - -ifneq ($(words $(DTL_FILES)),0) -# Rebuild templates when the Makefile changes. -$(ERLANG_MK_TMP)/last-makefile-change-erlydtl: $(MAKEFILE_LIST) - @mkdir -p $(ERLANG_MK_TMP) - @if test -f $@; then \ - touch $(DTL_FILES); \ - fi - @touch $@ - -ebin/$(PROJECT).app:: $(ERLANG_MK_TMP)/last-makefile-change-erlydtl -endif - -define erlydtl_compile.erl - [begin - Module0 = case "$(strip $(DTL_FULL_PATH))" of - "" -> - filename:basename(F, ".dtl"); - _ -> - "$(DTL_PATH)/" ++ F2 = filename:rootname(F, ".dtl"), - re:replace(F2, "/", "_", [{return, list}, global]) - end, - Module = list_to_atom(string:to_lower(Module0) ++ "$(DTL_SUFFIX)"), - case erlydtl:compile(F, Module, [$(DTL_OPTS)] ++ [{out_dir, "ebin/"}, return_errors]) of - ok -> ok; - {ok, _} -> ok - end - end || F <- string:tokens("$(1)", " ")], - halt(). -endef - -ebin/$(PROJECT).app:: $(DTL_FILES) | ebin/ - $(if $(strip $?),\ - $(dtl_verbose) $(call erlang,$(call erlydtl_compile.erl,$(call core_native_path,$?)),\ - -pa ebin/ $(DEPS_DIR)/erlydtl/ebin/)) - -endif - -# Copyright (c) 2016, Loïc Hoguin -# Copyright (c) 2014, Dave Cottlehuber -# This file is part of erlang.mk and subject to the terms of the ISC License. - -.PHONY: distclean-escript escript escript-zip +.PHONY: distclean-escript escript # Configuration. ESCRIPT_NAME ?= $(PROJECT) ESCRIPT_FILE ?= $(ESCRIPT_NAME) -ESCRIPT_SHEBANG ?= /usr/bin/env escript ESCRIPT_COMMENT ?= This is an -*- erlang -*- file -ESCRIPT_EMU_ARGS ?= -escript main $(ESCRIPT_NAME) -ESCRIPT_ZIP ?= 7z a -tzip -mx=9 -mtc=off $(if $(filter-out 0,$(V)),,> /dev/null) -ESCRIPT_ZIP_FILE ?= $(ERLANG_MK_TMP)/escript.zip +ESCRIPT_BEAMS ?= "ebin/*", "deps/*/ebin/*" +ESCRIPT_SYS_CONFIG ?= "rel/sys.config" +ESCRIPT_EMU_ARGS ?= -pa . \ + -sasl errlog_type error \ + -escript main $(ESCRIPT_NAME) +ESCRIPT_SHEBANG ?= /usr/bin/env escript +ESCRIPT_STATIC ?= "deps/*/priv/**", "priv/**" # Core targets. @@ -2514,28 +2330,44 @@ help:: # Plugin-specific targets. -escript-zip:: deps app - $(verbose) mkdir -p $(dir $(ESCRIPT_ZIP)) - $(verbose) rm -f $(ESCRIPT_ZIP_FILE) - $(gen_verbose) cd .. && $(ESCRIPT_ZIP) $(ESCRIPT_ZIP_FILE) $(PROJECT)/ebin/* -ifneq ($(DEPS),) - $(verbose) cd $(DEPS_DIR) && $(ESCRIPT_ZIP) $(ESCRIPT_ZIP_FILE) \ - `cat $(ERLANG_MK_TMP)/deps.log | sed 's/^$(subst /,\/,$(DEPS_DIR))\///' | sed 's/$$/\/ebin\/\*/'` -endif +# Based on https://github.com/synrc/mad/blob/master/src/mad_bundle.erl +# Copyright (c) 2013 Maxim Sokhatsky, Synrc Research Center +# Modified MIT License, https://github.com/synrc/mad/blob/master/LICENSE : +# Software may only be used for the great good and the true happiness of all +# sentient beings. -escript:: escript-zip - $(gen_verbose) printf "%s\n" \ - "#!$(ESCRIPT_SHEBANG)" \ - "%% $(ESCRIPT_COMMENT)" \ - "%%! $(ESCRIPT_EMU_ARGS)" > $(ESCRIPT_FILE) - $(verbose) cat $(ESCRIPT_ZIP_FILE) >> $(ESCRIPT_FILE) - $(verbose) chmod +x $(ESCRIPT_FILE) +define ESCRIPT_RAW +'Read = fun(F) -> {ok, B} = file:read_file(filename:absname(F)), B end,'\ +'Files = fun(L) -> A = lists:concat([filelib:wildcard(X)||X<- L ]),'\ +' [F || F <- A, not filelib:is_dir(F) ] end,'\ +'Squash = fun(L) -> [{filename:basename(F), Read(F) } || F <- L ] end,'\ +'Zip = fun(A, L) -> {ok,{_,Z}} = zip:create(A, L, [{compress,all},memory]), Z end,'\ +'Ez = fun(Escript) ->'\ +' Static = Files([$(ESCRIPT_STATIC)]),'\ +' Beams = Squash(Files([$(ESCRIPT_BEAMS), $(ESCRIPT_SYS_CONFIG)])),'\ +' Archive = Beams ++ [{ "static.gz", Zip("static.gz", Static)}],'\ +' escript:create(Escript, [ $(ESCRIPT_OPTIONS)'\ +' {archive, Archive, [memory]},'\ +' {shebang, "$(ESCRIPT_SHEBANG)"},'\ +' {comment, "$(ESCRIPT_COMMENT)"},'\ +' {emu_args, " $(ESCRIPT_EMU_ARGS)"}'\ +' ]),'\ +' file:change_mode(Escript, 8#755)'\ +'end,'\ +'Ez("$(ESCRIPT_FILE)"),'\ +'halt().' +endef + +ESCRIPT_COMMAND = $(subst ' ',,$(ESCRIPT_RAW)) + +escript:: distclean-escript deps app + $(gen_verbose) $(ERL) -eval $(ESCRIPT_COMMAND) distclean-escript: - $(gen_verbose) rm -f $(ESCRIPT_FILE) + $(gen_verbose) rm -f $(ESCRIPT_NAME) -# Copyright (c) 2015-2016, Loïc Hoguin # Copyright (c) 2014, Enrique Fernandez +# Copyright (c) 2015, Loïc Hoguin # This file is contributed to erlang.mk and subject to the terms of the ISC License. .PHONY: eunit apps-eunit @@ -2572,7 +2404,7 @@ define eunit.erl case "$(COVER)" of "" -> ok; _ -> - cover:export("$(COVER_DATA_DIR)/eunit.coverdata") + cover:export("eunit.coverdata") end, halt() endef @@ -2581,10 +2413,10 @@ EUNIT_ERL_OPTS += -pa $(TEST_DIR) $(DEPS_DIR)/*/ebin $(APPS_DIR)/*/ebin $(CURDIR ifdef t ifeq (,$(findstring :,$(t))) -eunit: test-build cover-data-dir +eunit: test-build $(gen_verbose) $(call erlang,$(call eunit.erl,['$(t)']),$(EUNIT_ERL_OPTS)) else -eunit: test-build cover-data-dir +eunit: test-build $(gen_verbose) $(call erlang,$(call eunit.erl,fun $(t)/0),$(EUNIT_ERL_OPTS)) endif else @@ -2594,90 +2426,28 @@ 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) cover-data-dir +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) eunit_retcode=0 ; for app in $(ALL_APPS_DIRS); do $(MAKE) -C $$app eunit IS_APP=1; \ - [ $$? -ne 0 ] && eunit_retcode=1 ; done ; \ - exit $$eunit_retcode + $(verbose) for app in $(ALL_APPS_DIRS); do $(MAKE) -C $$app eunit IS_APP=1; done endif endif -# Copyright (c) 2015-2017, Loïc Hoguin +# Copyright (c) 2013-2015, Loïc Hoguin # This file is part of erlang.mk and subject to the terms of the ISC License. -ifeq ($(filter proper,$(DEPS) $(TEST_DEPS)),proper) -.PHONY: proper - -# Targets. - -tests:: proper - -define proper_check.erl - code:add_pathsa(["$(call core_native_path,$(CURDIR)/ebin)", "$(call core_native_path,$(DEPS_DIR)/*/ebin)"]), - Module = fun(M) -> - [true] =:= lists:usort([ - case atom_to_list(F) of - "prop_" ++ _ -> - io:format("Testing ~p:~p/0~n", [M, F]), - proper:quickcheck(M:F(), nocolors); - _ -> - true - end - || {F, 0} <- M:module_info(exports)]) - end, - try - case $(1) of - all -> [true] =:= lists:usort([Module(M) || M <- [$(call comma_list,$(3))]]); - module -> Module($(2)); - function -> proper:quickcheck($(2), nocolors) - end - of - true -> halt(0); - _ -> halt(1) - catch error:undef -> - io:format("Undefined property or module?~n~p~n", [erlang:get_stacktrace()]), - halt(0) - end. -endef - -ifdef t -ifeq (,$(findstring :,$(t))) -proper: test-build - $(verbose) $(call erlang,$(call proper_check.erl,module,$(t))) -else -proper: test-build - $(verbose) echo Testing $(t)/0 - $(verbose) $(call erlang,$(call proper_check.erl,function,$(t)())) -endif -else -proper: test-build - $(eval MODULES := $(patsubst %,'%',$(sort $(notdir $(basename $(wildcard ebin/*.beam)))))) - $(gen_verbose) $(call erlang,$(call proper_check.erl,all,undefined,$(MODULES))) -endif -endif - -# Copyright (c) 2013-2016, Loïc Hoguin -# This file is part of erlang.mk and subject to the terms of the ISC License. - -.PHONY: relx-rel relx-relup distclean-relx-rel run +.PHONY: relx-rel distclean-relx-rel distclean-relx run # Configuration. -RELX ?= $(ERLANG_MK_TMP)/relx +RELX ?= $(CURDIR)/relx RELX_CONFIG ?= $(CURDIR)/relx.config -RELX_URL ?= https://github.com/erlware/relx/releases/download/v3.23.0/relx +RELX_URL ?= https://github.com/erlware/relx/releases/download/v3.19.0/relx RELX_OPTS ?= RELX_OUTPUT_DIR ?= _rel -RELX_REL_EXT ?= -RELX_TAR ?= 1 - -ifdef SFX - RELX_TAR = 1 -endif ifeq ($(firstword $(RELX_OPTS)),-o) RELX_OUTPUT_DIR = $(word 2,$(RELX_OPTS)) @@ -2690,12 +2460,10 @@ endif ifeq ($(IS_DEP),) ifneq ($(wildcard $(RELX_CONFIG)),) rel:: relx-rel - -relup:: relx-relup endif endif -distclean:: distclean-relx-rel +distclean:: distclean-relx-rel distclean-relx # Plugin-specific targets. @@ -2704,43 +2472,31 @@ $(RELX): $(verbose) chmod +x $(RELX) relx-rel: $(RELX) rel-deps app - $(verbose) $(RELX) -c $(RELX_CONFIG) $(RELX_OPTS) release $(if $(filter 1,$(RELX_TAR)),tar) - -relx-relup: $(RELX) rel-deps app - $(verbose) $(RELX) -c $(RELX_CONFIG) $(RELX_OPTS) release relup $(if $(filter 1,$(RELX_TAR)),tar) + $(verbose) $(RELX) -c $(RELX_CONFIG) $(RELX_OPTS) distclean-relx-rel: $(gen_verbose) rm -rf $(RELX_OUTPUT_DIR) +distclean-relx: + $(gen_verbose) rm -rf $(RELX) + # Run target. ifeq ($(wildcard $(RELX_CONFIG)),) -run:: +run: else define get_relx_release.erl - {ok, Config} = file:consult("$(call core_native_path,$(RELX_CONFIG))"), - {release, {Name, Vsn0}, _} = lists:keyfind(release, 1, Config), - Vsn = case Vsn0 of - {cmd, Cmd} -> os:cmd(Cmd); - semver -> ""; - {semver, _} -> ""; - VsnStr -> Vsn0 - end, - io:format("~s ~s", [Name, Vsn]), + {ok, Config} = file:consult("$(RELX_CONFIG)"), + {release, {Name, _}, _} = lists:keyfind(release, 1, Config), + io:format("~s", [Name]), halt(0). endef -RELX_REL := $(shell $(call erlang,$(get_relx_release.erl))) -RELX_REL_NAME := $(word 1,$(RELX_REL)) -RELX_REL_VSN := $(word 2,$(RELX_REL)) +RELX_RELEASE = `$(call erlang,$(get_relx_release.erl))` -ifeq ($(PLATFORM),msys2) -RELX_REL_EXT := .cmd -endif - -run:: all - $(verbose) $(RELX_OUTPUT_DIR)/$(RELX_REL_NAME)/bin/$(RELX_REL_NAME)$(RELX_REL_EXT) console +run: all + $(verbose) $(RELX_OUTPUT_DIR)/$(RELX_RELEASE)/bin/$(RELX_RELEASE) console help:: $(verbose) printf "%s\n" "" \ @@ -2749,8 +2505,8 @@ help:: endif -# Copyright (c) 2015-2016, Loïc Hoguin # Copyright (c) 2014, M Robert Martin +# Copyright (c) 2015, Loïc Hoguin # This file is contributed to erlang.mk and subject to the terms of the ISC License. .PHONY: shell @@ -2775,26 +2531,12 @@ help:: $(foreach dep,$(SHELL_DEPS),$(eval $(call dep_target,$(dep)))) build-shell-deps: $(ALL_SHELL_DEPS_DIRS) - $(verbose) set -e; for dep in $(ALL_SHELL_DEPS_DIRS) ; do $(MAKE) -C $$dep ; done + $(verbose) for dep in $(ALL_SHELL_DEPS_DIRS) ; do $(MAKE) -C $$dep ; done shell: build-shell-deps $(gen_verbose) $(SHELL_ERL) -pa $(SHELL_PATHS) $(SHELL_OPTS) -# Copyright (c) 2017, Jean-Sébastien Pédron -# This file is contributed to erlang.mk and subject to the terms of the ISC License. - -.PHONY: show-ERL_LIBS show-ERLC_OPTS show-TEST_ERLC_OPTS - -show-ERL_LIBS: - @echo $(ERL_LIBS) - -show-ERLC_OPTS: - @$(foreach opt,$(ERLC_OPTS) -pa ebin -I include,echo "$(opt)";) - -show-TEST_ERLC_OPTS: - @$(foreach opt,$(TEST_ERLC_OPTS) -pa ebin -I include,echo "$(opt)";) - -# Copyright (c) 2015-2016, Loïc Hoguin +# Copyright (c) 2015, Loïc Hoguin # This file is part of erlang.mk and subject to the terms of the ISC License. ifeq ($(filter triq,$(DEPS) $(TEST_DEPS)),triq) @@ -2805,10 +2547,7 @@ ifeq ($(filter triq,$(DEPS) $(TEST_DEPS)),triq) tests:: triq define triq_check.erl - code:add_pathsa([ - "$(call core_native_path,$(CURDIR)/ebin)", - "$(call core_native_path,$(DEPS_DIR)/*/ebin)", - "$(call core_native_path,$(TEST_DIR))"]), + code:add_pathsa(["$(CURDIR)/ebin", "$(DEPS_DIR)/*/ebin"]), try case $(1) of all -> [true] =:= lists:usort([triq:check(M) || M <- [$(call comma_list,$(3))]]); @@ -2819,7 +2558,7 @@ define triq_check.erl true -> halt(0); _ -> halt(1) catch error:undef -> - io:format("Undefined property or module?~n~p~n", [erlang:get_stacktrace()]), + io:format("Undefined property or module~n"), halt(0) end. endef @@ -2835,13 +2574,11 @@ triq: test-build endif else triq: test-build - $(eval MODULES := $(patsubst %,'%',$(sort $(notdir $(basename \ - $(wildcard ebin/*.beam) $(call core_find,$(TEST_DIR)/,*.beam)))))) + $(eval MODULES := $(patsubst %,'%',$(sort $(notdir $(basename $(wildcard ebin/*.beam)))))) $(gen_verbose) $(call erlang,$(call triq_check.erl,all,undefined,$(MODULES))) endif endif -# Copyright (c) 2016, Loïc Hoguin # Copyright (c) 2015, Erlang Solutions Ltd. # This file is part of erlang.mk and subject to the terms of the ISC License. @@ -2850,22 +2587,22 @@ endif # Configuration. ifeq ($(XREF_CONFIG),) - XREFR_ARGS := + XREF_ARGS := else - XREFR_ARGS := -c $(XREF_CONFIG) + XREF_ARGS := -c $(XREF_CONFIG) endif XREFR ?= $(CURDIR)/xrefr export XREFR -XREFR_URL ?= https://github.com/inaka/xref_runner/releases/download/1.1.0/xrefr +XREFR_URL ?= https://github.com/inaka/xref_runner/releases/download/0.2.2/xrefr # Core targets. help:: - $(verbose) printf '%s\n' '' \ - 'Xref targets:' \ - ' xref Run Xrefr using $$XREF_CONFIG as config file if defined' + $(verbose) printf "%s\n" "" \ + "Xref targets:" \ + " xref Run Xrefr using $XREF_CONFIG as config file if defined" distclean:: distclean-xref @@ -2881,29 +2618,29 @@ xref: deps app $(XREFR) distclean-xref: $(gen_verbose) rm -rf $(XREFR) -# Copyright (c) 2016, Loïc Hoguin -# Copyright (c) 2015, Viktor Söderqvist +# Copyright 2015, Viktor Söderqvist # This file is part of erlang.mk and subject to the terms of the ISC License. -COVER_REPORT_DIR ?= cover -COVER_DATA_DIR ?= $(CURDIR) +COVER_REPORT_DIR = cover # Hook in coverage to ct ifdef COVER ifdef CT_RUN -ifneq ($(wildcard $(TEST_DIR)),) +# All modules in 'ebin' +COVER_MODS = $(notdir $(basename $(call core_ls,ebin/*.beam))) + test-build:: $(TEST_DIR)/ct.cover.spec -$(TEST_DIR)/ct.cover.spec: cover-data-dir +$(TEST_DIR)/ct.cover.spec: + $(verbose) echo Cover mods: $(COVER_MODS) $(gen_verbose) printf "%s\n" \ - "{incl_app, '$(PROJECT)', details}." \ - '{export,"$(abspath $(COVER_DATA_DIR))/ct.coverdata"}.' > $@ + '{incl_mods,[$(subst $(space),$(comma),$(COVER_MODS))]}.' \ + '{export,"$(CURDIR)/ct.coverdata"}.' > $@ CT_RUN += -cover $(TEST_DIR)/ct.cover.spec endif endif -endif # Core targets @@ -2912,13 +2649,6 @@ ifneq ($(COVER_REPORT_DIR),) tests:: $(verbose) $(MAKE) --no-print-directory cover-report endif - -cover-data-dir: | $(COVER_DATA_DIR) - -$(COVER_DATA_DIR): - $(verbose) mkdir -p $(COVER_DATA_DIR) -else -cover-data-dir: endif clean:: coverdata-clean @@ -2932,7 +2662,7 @@ help:: "Cover targets:" \ " cover-report Generate a HTML coverage report from previously collected" \ " cover data." \ - " all.coverdata Merge all coverdata files into all.coverdata." \ + " all.coverdata Merge {eunit,ct}.coverdata into one coverdata file." \ "" \ "If COVER=1 is set, coverage data is generated by the targets eunit and ct. The" \ "target tests additionally generates a HTML coverage report from the combined" \ @@ -2941,20 +2671,17 @@ help:: # Plugin specific targets -COVERDATA = $(filter-out $(COVER_DATA_DIR)/all.coverdata,$(wildcard $(COVER_DATA_DIR)/*.coverdata)) +COVERDATA = $(filter-out all.coverdata,$(wildcard *.coverdata)) .PHONY: coverdata-clean coverdata-clean: - $(gen_verbose) rm -f $(COVER_DATA_DIR)/*.coverdata $(TEST_DIR)/ct.cover.spec + $(gen_verbose) rm -f *.coverdata ct.cover.spec # Merge all coverdata files into one. -define cover_export.erl - $(foreach f,$(COVERDATA),cover:import("$(f)") == ok orelse halt(1),) - cover:export("$(COVER_DATA_DIR)/$@"), halt(0). -endef - -all.coverdata: $(COVERDATA) cover-data-dir - $(gen_verbose) $(call erlang,$(cover_export.erl)) +all.coverdata: $(COVERDATA) + $(gen_verbose) $(ERL) -eval ' \ + $(foreach f,$(COVERDATA),cover:import("$(f)") == ok orelse halt(1),) \ + cover:export("$@"), halt(0).' # These are only defined if COVER_REPORT_DIR is non-empty. Set COVER_REPORT_DIR to # empty if you want the coverdata files but not the HTML report. @@ -2964,7 +2691,6 @@ ifneq ($(COVER_REPORT_DIR),) cover-report-clean: $(gen_verbose) rm -rf $(COVER_REPORT_DIR) - $(if $(shell ls -A $(COVER_DATA_DIR)/),,$(verbose) rmdir $(COVER_DATA_DIR)) ifeq ($(COVERDATA),) cover-report: @@ -2973,7 +2699,7 @@ else # Modules which include eunit.hrl always contain one line without coverage # because eunit defines test/0 which is never called. We compensate for this. EUNIT_HRL_MODS = $(subst $(space),$(comma),$(shell \ - grep -H -e '^\s*-include.*include/eunit\.hrl"' src/*.erl \ + grep -e '^\s*-include.*include/eunit\.hrl"' src/*.erl \ | sed "s/^src\/\(.*\)\.erl:.*/'\1'/" | uniq)) define cover_report.erl @@ -3008,171 +2734,8 @@ define cover_report.erl endef cover-report: - $(verbose) mkdir -p $(COVER_REPORT_DIR) + $(gen_verbose) mkdir -p $(COVER_REPORT_DIR) $(gen_verbose) $(call erlang,$(cover_report.erl)) endif endif # ifneq ($(COVER_REPORT_DIR),) - -# Copyright (c) 2016, Loïc Hoguin -# This file is part of erlang.mk and subject to the terms of the ISC License. - -.PHONY: sfx - -ifdef RELX_REL -ifdef SFX - -# Configuration. - -SFX_ARCHIVE ?= $(RELX_OUTPUT_DIR)/$(RELX_REL_NAME)/$(RELX_REL_NAME)-$(RELX_REL_VSN).tar.gz -SFX_OUTPUT_FILE ?= $(RELX_OUTPUT_DIR)/$(RELX_REL_NAME).run - -# Core targets. - -rel:: sfx - -# Plugin-specific targets. - -define sfx_stub -#!/bin/sh - -TMPDIR=`mktemp -d` -ARCHIVE=`awk '/^__ARCHIVE_BELOW__$$/ {print NR + 1; exit 0;}' $$0` -FILENAME=$$(basename $$0) -REL=$${FILENAME%.*} - -tail -n+$$ARCHIVE $$0 | tar -xzf - -C $$TMPDIR - -$$TMPDIR/bin/$$REL console -RET=$$? - -rm -rf $$TMPDIR - -exit $$RET - -__ARCHIVE_BELOW__ -endef - -sfx: - $(call render_template,sfx_stub,$(SFX_OUTPUT_FILE)) - $(gen_verbose) cat $(SFX_ARCHIVE) >> $(SFX_OUTPUT_FILE) - $(verbose) chmod +x $(SFX_OUTPUT_FILE) - -endif -endif - -# Copyright (c) 2013-2017, Loïc Hoguin -# This file is part of erlang.mk and subject to the terms of the ISC License. - -# External plugins. - -DEP_PLUGINS ?= - -$(foreach p,$(DEP_PLUGINS),\ - $(eval $(if $(findstring /,$p),\ - $(call core_dep_plugin,$p,$(firstword $(subst /, ,$p))),\ - $(call core_dep_plugin,$p/plugins.mk,$p)))) - -# Copyright (c) 2013-2015, Loïc Hoguin -# Copyright (c) 2015-2016, Jean-Sébastien Pédron -# This file is part of erlang.mk and subject to the terms of the ISC License. - -# Fetch dependencies recursively (without building them). - -.PHONY: fetch-deps fetch-doc-deps fetch-rel-deps fetch-test-deps \ - fetch-shell-deps - -.PHONY: $(ERLANG_MK_RECURSIVE_DEPS_LIST) \ - $(ERLANG_MK_RECURSIVE_DOC_DEPS_LIST) \ - $(ERLANG_MK_RECURSIVE_REL_DEPS_LIST) \ - $(ERLANG_MK_RECURSIVE_TEST_DEPS_LIST) \ - $(ERLANG_MK_RECURSIVE_SHELL_DEPS_LIST) - -fetch-deps: $(ERLANG_MK_RECURSIVE_DEPS_LIST) -fetch-doc-deps: $(ERLANG_MK_RECURSIVE_DOC_DEPS_LIST) -fetch-rel-deps: $(ERLANG_MK_RECURSIVE_REL_DEPS_LIST) -fetch-test-deps: $(ERLANG_MK_RECURSIVE_TEST_DEPS_LIST) -fetch-shell-deps: $(ERLANG_MK_RECURSIVE_SHELL_DEPS_LIST) - -ifneq ($(SKIP_DEPS),) -$(ERLANG_MK_RECURSIVE_DEPS_LIST) \ -$(ERLANG_MK_RECURSIVE_DOC_DEPS_LIST) \ -$(ERLANG_MK_RECURSIVE_REL_DEPS_LIST) \ -$(ERLANG_MK_RECURSIVE_TEST_DEPS_LIST) \ -$(ERLANG_MK_RECURSIVE_SHELL_DEPS_LIST): - $(verbose) :> $@ -else -# By default, we fetch "normal" dependencies. They are also included no -# matter the type of requested dependencies. -# -# $(ALL_DEPS_DIRS) includes $(BUILD_DEPS). - -$(ERLANG_MK_RECURSIVE_DEPS_LIST): $(ALL_DEPS_DIRS) -$(ERLANG_MK_RECURSIVE_DOC_DEPS_LIST): $(ALL_DEPS_DIRS) $(ALL_DOC_DEPS_DIRS) -$(ERLANG_MK_RECURSIVE_REL_DEPS_LIST): $(ALL_DEPS_DIRS) $(ALL_REL_DEPS_DIRS) -$(ERLANG_MK_RECURSIVE_TEST_DEPS_LIST): $(ALL_DEPS_DIRS) $(ALL_TEST_DEPS_DIRS) -$(ERLANG_MK_RECURSIVE_SHELL_DEPS_LIST): $(ALL_DEPS_DIRS) $(ALL_SHELL_DEPS_DIRS) - -# Allow to use fetch-deps and $(DEP_TYPES) to fetch multiple types of -# dependencies with a single target. -ifneq ($(filter doc,$(DEP_TYPES)),) -$(ERLANG_MK_RECURSIVE_DEPS_LIST): $(ALL_DOC_DEPS_DIRS) -endif -ifneq ($(filter rel,$(DEP_TYPES)),) -$(ERLANG_MK_RECURSIVE_DEPS_LIST): $(ALL_REL_DEPS_DIRS) -endif -ifneq ($(filter test,$(DEP_TYPES)),) -$(ERLANG_MK_RECURSIVE_DEPS_LIST): $(ALL_TEST_DEPS_DIRS) -endif -ifneq ($(filter shell,$(DEP_TYPES)),) -$(ERLANG_MK_RECURSIVE_DEPS_LIST): $(ALL_SHELL_DEPS_DIRS) -endif - -ERLANG_MK_RECURSIVE_TMP_LIST := $(abspath $(ERLANG_MK_TMP)/recursive-tmp-deps.log) - -$(ERLANG_MK_RECURSIVE_DEPS_LIST) \ -$(ERLANG_MK_RECURSIVE_DOC_DEPS_LIST) \ -$(ERLANG_MK_RECURSIVE_REL_DEPS_LIST) \ -$(ERLANG_MK_RECURSIVE_TEST_DEPS_LIST) \ -$(ERLANG_MK_RECURSIVE_SHELL_DEPS_LIST): -ifeq ($(IS_APP)$(IS_DEP),) - $(verbose) mkdir -p $(ERLANG_MK_TMP) - $(verbose) rm -f $(ERLANG_MK_RECURSIVE_TMP_LIST) -endif -ifndef IS_APP - $(verbose) set -e; for dep in $(ALL_APPS_DIRS) ; do \ - $(MAKE) -C $$dep $@ \ - IS_APP=1 \ - ERLANG_MK_RECURSIVE_TMP_LIST=$(ERLANG_MK_RECURSIVE_TMP_LIST); \ - done -endif - $(verbose) set -e; for dep in $^ ; do \ - if ! grep -qs ^$$dep$$ $(ERLANG_MK_RECURSIVE_TMP_LIST); then \ - echo $$dep >> $(ERLANG_MK_RECURSIVE_TMP_LIST); \ - if grep -qs -E "^[[:blank:]]*include[[:blank:]]+(erlang\.mk|.*/erlang\.mk|.*ERLANG_MK_FILENAME.*)$$" \ - $$dep/GNUmakefile $$dep/makefile $$dep/Makefile; then \ - $(MAKE) -C $$dep fetch-deps \ - IS_DEP=1 \ - ERLANG_MK_RECURSIVE_TMP_LIST=$(ERLANG_MK_RECURSIVE_TMP_LIST); \ - fi \ - fi \ - done -ifeq ($(IS_APP)$(IS_DEP),) - $(verbose) sort < $(ERLANG_MK_RECURSIVE_TMP_LIST) | uniq > $@ - $(verbose) rm $(ERLANG_MK_RECURSIVE_TMP_LIST) -endif -endif # ifneq ($(SKIP_DEPS),) - -# List dependencies recursively. - -.PHONY: list-deps list-doc-deps list-rel-deps list-test-deps \ - list-shell-deps - -list-deps: $(ERLANG_MK_RECURSIVE_DEPS_LIST) -list-doc-deps: $(ERLANG_MK_RECURSIVE_DOC_DEPS_LIST) -list-rel-deps: $(ERLANG_MK_RECURSIVE_REL_DEPS_LIST) -list-test-deps: $(ERLANG_MK_RECURSIVE_TEST_DEPS_LIST) -list-shell-deps: $(ERLANG_MK_RECURSIVE_SHELL_DEPS_LIST) - -list-deps list-doc-deps list-rel-deps list-test-deps list-shell-deps: - $(verbose) cat $^ diff --git a/src/emqx_pubsub.erl b/src/emqx_pubsub.erl index 03647fa3c..b4ac146a8 100644 --- a/src/emqx_pubsub.erl +++ b/src/emqx_pubsub.erl @@ -73,12 +73,12 @@ route([], #mqtt_delivery{message = Msg}) -> dropped(Msg#mqtt_message.topic), ignore; %% Dispatch on the local node. -route([#mqtt_route{topic = To, node = Node}], +route([#route{topic = To, node = Node}], Delivery = #mqtt_delivery{flows = Flows}) when Node =:= node() -> dispatch(To, Delivery#mqtt_delivery{flows = [{route, Node, To} | Flows]}); %% Forward to other nodes -route([#mqtt_route{topic = To, node = Node}], Delivery = #mqtt_delivery{flows = Flows}) -> +route([#route{topic = To, node = Node}], Delivery = #mqtt_delivery{flows = Flows}) -> forward(Node, To, Delivery#mqtt_delivery{flows = [{route, Node, To}|Flows]}); route(Routes, Delivery) -> diff --git a/src/emqx_router.erl b/src/emqx_router.erl index c07d9759d..060786590 100644 --- a/src/emqx_router.erl +++ b/src/emqx_router.erl @@ -196,7 +196,7 @@ add_local_route(Topic) -> del_local_route(Topic) -> gen_server:call(?ROUTER, {del_local_route, Topic}). --spec(match_local(binary()) -> [mqtt_route()]). +-spec(match_local(binary()) -> [route()]). match_local(Name) -> case ets:info(local_route, size) of 0 -> [];