Migrated build system to erlang.mk.
authorStanislaw Klekot <dozzie@jarowit.net>
Tue, 9 May 2017 19:59:57 +0000 (21:59 +0200)
committerStanislaw Klekot <dozzie@jarowit.net>
Tue, 9 May 2017 19:59:57 +0000 (21:59 +0200)
.gitattributes
.gitignore
Makefile
_install/app_version [deleted file]
_install/lib_dir [deleted file]
build.config [new file with mode: 0644]
erlang.install.mk [new file with mode: 0644]
erlang.mk [new file with mode: 0644]
src/statip.app.src

index ddf4eec..fca2660 100644 (file)
@@ -1,6 +1,3 @@
-_versions       export-ignore
+/_versions      export-ignore
 .gitattributes  export-ignore
 .gitignore      export-ignore
-doc/.gitignore  export-ignore
-tests/data/.gitignore         export-ignore
-tests/data/replay/.gitignore  export-ignore
index d58f15c..06057ec 100644 (file)
@@ -4,4 +4,6 @@
 /ebin/*.app
 /build
 /pylib/*.egg-info
+/.erlang.mk
+/statip.d
 *.pyc
index 90a427e..efd6aba 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -12,34 +12,26 @@ DIALYZER_OPTS = --no_check_plt $(if $(DIALYZER_PLT),--plts $(DIALYZER_PLT))
 DIAGRAMS = $(basename $(notdir $(wildcard diagrams/*.diag)))
 DIAGRAMS_SVG = $(foreach D,$(DIAGRAMS),doc/images/$D.svg)
 
-ERL_APP_FILE = $(wildcard ebin/*.app)
-ERL_APP_NAME = $(patsubst ebin/%.app,%,$(ERL_APP_FILE))
-ERL_APP_VER = $(shell _install/app_version $(ERL_APP_FILE))
-ERL_INSTALL_PATH = $(shell _install/lib_dir)
-ESCRIPT_ARGS_FILE = /etc/statetip/erlang.args
-
 #-----------------------------------------------------------------------------
 
-.PHONY: all clean
+PROJECT = statip
+APP_VERSION = $(call app-version,ebin/$(PROJECT).app)
+ERL_INSTALL_LIB_DIR = $(ERL_LIB_DIR)/$(PROJECT)-$(APP_VERSION)
+DOCDIR = /usr/share/doc/statetip
+MANDIR = /usr/share/man
+CONFDIR = /etc/statetip
+ESCRIPT_ARGS_FILE = $(CONFDIR)/erlang.args
 
-all: compile edoc
+ERLC_OPTS = +debug_info
+EDOC_OPTS = {overview, "src/overview.edoc"}, {dir, "doc/edoc"}, \
+            {source_path, ["src", "examples"]}, todo
 
-clean:
-       rebar clean
-       python setup.py clean --all
-       rm -rf pylib/*.egg-info
-       ${MAKE} -C doc clean
-       rm -rf doc/edoc
+include erlang.mk
+include erlang.install.mk
 
 #-----------------------------------------------------------------------------
 
-.PHONY: compile build dialyzer
-
-build: compile
-
-compile:
-       rebar $@
-
+.PHONY: dialyzer
 YECC_ERL_FILES = $(subst .yrl,.erl,$(subst .xrl,.erl,$(wildcard src/*.[xy]rl)))
 ERL_SOURCE_FILES = $(filter-out $(YECC_ERL_FILES),$(wildcard src/*.erl))
 dialyzer:
@@ -48,47 +40,48 @@ dialyzer:
 
 #-----------------------------------------------------------------------------
 
-.PHONY: doc edoc diagrams
-
+.PHONY: doc
 doc: diagrams edoc
        ${MAKE} -C doc all
 
-edoc:
-       rebar doc
-
+.PHONY: diagrams
 diagrams: $(DIAGRAMS_SVG)
 
 doc/images/%.svg: diagrams/%.diag
        blockdiag -o $@ -T svg $<
 
+distclean:: clean-doc
+
+.PHONY: clean-doc
+clean-doc:
+       ${MAKE} -C doc clean
+       rm -rf doc/edoc
+
 #-----------------------------------------------------------------------------
 
-.PHONY: install install-doc install-erlang install-python
+.PHONY: install install-erlang install-python install-doc
 
 install: install-erlang install-python
 
-install-doc:
-       mkdir -p $(DESTDIR)/usr/share/doc/statetip
-       mkdir -p $(DESTDIR)/usr/share/doc/statetip/html
-       mkdir -p $(DESTDIR)/usr/share/doc/statetip/erlang-api
-       cp -R doc/html/* $(DESTDIR)/usr/share/doc/statetip/html
-       cp doc/edoc/*.html doc/edoc/*.png doc/edoc/*.css $(DESTDIR)/usr/share/doc/statetip/erlang-api
-       install -m 644 -D doc/man/statetipd.8 $(DESTDIR)/usr/share/man/man8/statetipd.8
-       install -m 644 -D doc/man/statetip.1 $(DESTDIR)/usr/share/man/man1/statetip.1
-       install -m 644 -D doc/man/statetip-protocol.7 $(DESTDIR)/usr/share/man/man7/statetip-protocol.7
-
-install-erlang:
-       mkdir -p $(DESTDIR)/etc/statetip
-       mkdir -p $(DESTDIR)/usr/sbin
-       mkdir -p $(DESTDIR)$(ERL_INSTALL_PATH)/$(ERL_APP_NAME)-$(ERL_APP_VER)/ebin
-       install -m 644 ebin/*.app ebin/*.beam $(DESTDIR)$(ERL_INSTALL_PATH)/$(ERL_APP_NAME)-$(ERL_APP_VER)/ebin
-       sed 's:^%%!.*:%%! -noinput -kernel error_logger silent -args_file $(ESCRIPT_ARGS_FILE):' bin/statetipd > $(DESTDIR)/usr/sbin/statetipd
-       chmod 755 $(DESTDIR)/usr/sbin/statetipd
+install-erlang: app
+       $(call install-wildcard,644,ebin/*,$(DESTDIR)$(ERL_INSTALL_LIB_DIR)/ebin)
+       $(call install-escript,bin/statetipd,$(DESTDIR)/usr/sbin/statetipd,-noinput -kernel error_logger silent -args_file $(ESCRIPT_ARGS_FILE))
+       mkdir -p $(DESTDIR)$(CONFDIR)
        touch $(DESTDIR)$(ESCRIPT_ARGS_FILE)
-       install -m 644 examples/statetip.toml $(DESTDIR)/etc/statetip/statetip.toml.example
+       install -m 644 examples/statetip.toml $(DESTDIR)$(CONFDIR)/statetip.toml.example
 
 install-python:
        python setup.py install --prefix=/usr --exec-prefix=/usr$(if $(DESTDIR), --root=$(DESTDIR))
 
+install-doc: doc
+       mkdir -p $(DESTDIR)$(DOCDIR)
+       mkdir -p $(DESTDIR)$(DOCDIR)/html
+       mkdir -p $(DESTDIR)$(DOCDIR)/erlang-api
+       cp -R doc/html/* $(DESTDIR)$(DOCDIR)/html
+       $(call install-wildcard,644,doc/edoc/*.html doc/edoc/*.png doc/edoc/*.css,$(DESTDIR)$(DOCDIR)/erlang-api)
+       $(call install,644,doc/man/statetipd.8,$(DESTDIR)$(MANDIR)/man8)
+       $(call install,644,doc/man/statetip.1,$(DESTDIR)$(MANDIR)/man1)
+       $(call install,644,doc/man/statetip-protocol.7,$(DESTDIR)$(MANDIR)/man7)
+
 #-----------------------------------------------------------------------------
 # vim:ft=make
diff --git a/_install/app_version b/_install/app_version
deleted file mode 100755 (executable)
index 4cf0897..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/usr/bin/escript
-
-main([AppFile]) ->
-  {ok, [{application, _, KeyList}]} = file:consult(AppFile),
-  io:put_chars([proplists:get_value(vsn, KeyList), "\n"]).
-
-%% vim:ft=erlang
diff --git a/_install/lib_dir b/_install/lib_dir
deleted file mode 100755 (executable)
index ce8db32..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-#!/usr/bin/escript
-
-main([]) ->
-  io:put_chars([code:lib_dir(), "\n"]);
-
-main([AppFile]) ->
-  {ok, [{application, AppName, KeyList}]} = file:consult(AppFile),
-  Version = proplists:get_value(vsn, KeyList),
-  AppDirName = iolist_to_binary(io_lib:format("~s-~s", [AppName, Version])),
-  io:put_chars([filename:join(code:lib_dir(), AppDirName), "\n"]).
-
-%% vim:ft=erlang
diff --git a/build.config b/build.config
new file mode 100644 (file)
index 0000000..5c0403e
--- /dev/null
@@ -0,0 +1,11 @@
+# erlang.mk bootstrap configuration
+
+# Core modules.
+core/core
+core/erlc
+core/docs   # target for plugins/edoc
+core/compat # rebar.config
+
+#plugins/c_src
+#plugins/dialyzer
+plugins/edoc
diff --git a/erlang.install.mk b/erlang.install.mk
new file mode 100644 (file)
index 0000000..b6345f8
--- /dev/null
@@ -0,0 +1,59 @@
+#!/usr/bin/make -f
+#
+# Installation helper for Erlang projects.
+# Intended to be used along with erlang.mk.
+#
+#-----------------------------------------------------------------------------
+# variables to be used in main makefile or to be set for functions in next
+# sections
+
+ERL_LIB_DIR = $(shell $(ERL) -noinput -eval ' \
+       io:put_chars([code:lib_dir(), "\n"]), \
+       halt(). \
+')
+ESCRIPT_PATH = /usr/bin/escript
+
+#-----------------------------------------------------------------------------
+# information reading helpers
+
+# APP_VERSION = $(call app-version,ebin/$(PROJECT).app)
+define app-version
+$(shell $(ERL) -eval ' \
+       {ok, AppFile} = init:get_argument(app_file), \
+       {ok, [{application,_,KeyList}]} = file:consult(AppFile), \
+       io:put_chars([proplists:get_value(vsn, KeyList), "\n"]), \
+       halt(). \
+' -app_file $1)
+endef
+
+#-----------------------------------------------------------------------------
+# build rule helpers
+
+# $(call install-wildcard,$(MODE),$(WILDCARD),$(DESTDIR))
+define install-wildcard
+$(foreach F,$(wildcard $2),$(call install,$1,$F,$3))
+endef
+
+# $(call install,$(MODE),$(FILE),$(DESTDIR))
+#
+# Note that this function preserves the filename. If you need to install the
+# file under a different name (e.g. "*.example"), use /usr/bin/install
+# directly.
+define install
+install -D -m $1 $2 $3/$(notdir $2)
+
+endef
+
+# $(call install-escript,$(FILE),$(DESTFILE),$(BEAM_OPTS))
+#
+# Remember to set in $(BEAM_OPTS) at least "-args_file ...", so the VM args
+# can be overriden.
+define install-escript
+mkdir -p $(dir $2)
+printf '#!%s\n%%%%! %s\n' '$(ESCRIPT_PATH)' '$3' > $2
+sed -e '1,3{/^#!/d; /^%*!/d}' $1 >> $2
+chmod 755 $2
+endef
+
+#-----------------------------------------------------------------------------
+# vim:ft=make
diff --git a/erlang.mk b/erlang.mk
new file mode 100644 (file)
index 0000000..d2d0111
--- /dev/null
+++ b/erlang.mk
@@ -0,0 +1,552 @@
+# Copyright (c) 2013-2016, Loïc Hoguin <essen@ninenines.eu>
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+.PHONY: all app apps deps search rel relup docs install-docs check tests clean distclean help erlang-mk
+
+ERLANG_MK_FILENAME := $(realpath $(lastword $(MAKEFILE_LIST)))
+
+ERLANG_MK_VERSION = 2016.01.12-1-ge0ebd0a
+
+# Core configuration.
+
+PROJECT ?= $(notdir $(CURDIR))
+PROJECT := $(strip $(PROJECT))
+
+PROJECT_VERSION ?= rolling
+PROJECT_MOD ?= $(PROJECT)_app
+PROJECT_ENV ?= []
+
+# Verbosity.
+
+V ?= 0
+
+verbose_0 = @
+verbose_2 = set -x;
+verbose = $(verbose_$(V))
+
+gen_verbose_0 = @echo " GEN   " $@;
+gen_verbose_2 = set -x;
+gen_verbose = $(gen_verbose_$(V))
+
+# Temporary files directory.
+
+ERLANG_MK_TMP ?= $(CURDIR)/.erlang.mk
+export ERLANG_MK_TMP
+
+# "erl" command.
+
+ERL = erl +A0 -noinput -boot start_clean
+
+# Platform detection.
+
+ifeq ($(PLATFORM),)
+UNAME_S := $(shell uname -s)
+
+ifeq ($(UNAME_S),Linux)
+PLATFORM = linux
+else ifeq ($(UNAME_S),Darwin)
+PLATFORM = darwin
+else ifeq ($(UNAME_S),SunOS)
+PLATFORM = solaris
+else ifeq ($(UNAME_S),GNU)
+PLATFORM = gnu
+else ifeq ($(UNAME_S),FreeBSD)
+PLATFORM = freebsd
+else ifeq ($(UNAME_S),NetBSD)
+PLATFORM = netbsd
+else ifeq ($(UNAME_S),OpenBSD)
+PLATFORM = openbsd
+else ifeq ($(UNAME_S),DragonFly)
+PLATFORM = dragonfly
+else ifeq ($(shell uname -o),Msys)
+PLATFORM = msys2
+else
+$(error Unable to detect platform. Please open a ticket with the output of uname -a.)
+endif
+
+export PLATFORM
+endif
+
+# Core targets.
+
+all:: deps app rel
+
+# Noop to avoid a Make warning when there's nothing to do.
+rel::
+       $(verbose) :
+
+relup:: deps app
+
+check:: tests
+
+clean:: clean-crashdump
+
+clean-crashdump:
+ifneq ($(wildcard erl_crash.dump),)
+       $(gen_verbose) rm -f erl_crash.dump
+endif
+
+distclean:: clean distclean-tmp
+
+distclean-tmp:
+       $(gen_verbose) rm -rf $(ERLANG_MK_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 <essen@ninenines.eu>" \
+               "" \
+               "Usage: [V=1] $(MAKE) [target]..." \
+               "" \
+               "Core targets:" \
+               "  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" \
+               "  install-docs  Install the man pages for this project" \
+               "  check         Compile and run all tests and analysis for this project" \
+               "  tests         Run the tests for this project" \
+               "  clean         Delete temporary and output files from most targets" \
+               "  distclean     Delete all temporary and output files" \
+               "  help          Display this help and exit" \
+               "  erlang-mk     Update erlang.mk to the latest version"
+
+# Core functions.
+
+empty :=
+space := $(empty) $(empty)
+tab := $(empty)        $(empty)
+comma := ,
+
+define newline
+
+
+endef
+
+define comma_list
+$(subst $(space),$(comma),$(strip $(1)))
+endef
+
+# Adding erlang.mk to make Erlang scripts who call init:get_plain_arguments() happy.
+define erlang
+$(ERL) $(2) -pz $(ERLANG_MK_TMP)/rebar/ebin -eval "$(subst $(newline),,$(subst ",\",$(1)))" -- erlang.mk
+endef
+
+ifeq ($(PLATFORM),msys2)
+core_native_path = $(subst \,\\\\,$(shell cygpath -w $1))
+else
+core_native_path = $1
+endif
+
+core_http_get = curl -Lf$(if $(filter-out 0,$(V)),,s)o $(call core_native_path,$1) $2
+
+core_eq = $(and $(findstring $(1),$(2)),$(findstring $(2),$(1)))
+
+core_find = $(if $(wildcard $1),$(shell find $(1:%/=%) -type f -name $(subst *,\*,$2)))
+
+core_lc = $(subst A,a,$(subst B,b,$(subst C,c,$(subst D,d,$(subst E,e,$(subst F,f,$(subst G,g,$(subst H,h,$(subst I,i,$(subst J,j,$(subst K,k,$(subst L,l,$(subst M,m,$(subst N,n,$(subst O,o,$(subst P,p,$(subst Q,q,$(subst R,r,$(subst S,s,$(subst T,t,$(subst U,u,$(subst V,v,$(subst W,w,$(subst X,x,$(subst Y,y,$(subst Z,z,$(1)))))))))))))))))))))))))))
+
+core_ls = $(filter-out $(1),$(shell echo $(1)))
+
+# @todo Use a solution that does not require using perl.
+core_relpath = $(shell perl -e 'use File::Spec; print File::Spec->abs2rel(@ARGV) . "\n"' $1 $2)
+
+# Automated update.
+
+ERLANG_MK_REPO ?= https://github.com/ninenines/erlang.mk
+ERLANG_MK_COMMIT ?=
+ERLANG_MK_BUILD_CONFIG ?= build.config
+ERLANG_MK_BUILD_DIR ?= .erlang.mk.build
+
+erlang-mk:
+       git clone $(ERLANG_MK_REPO) $(ERLANG_MK_BUILD_DIR)
+ifdef ERLANG_MK_COMMIT
+       cd $(ERLANG_MK_BUILD_DIR) && git checkout $(ERLANG_MK_COMMIT)
+endif
+       if [ -f $(ERLANG_MK_BUILD_CONFIG) ]; then cp $(ERLANG_MK_BUILD_CONFIG) $(ERLANG_MK_BUILD_DIR)/build.config; fi
+       $(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) 2013-2016, Loïc Hoguin <essen@ninenines.eu>
+# This file is part of erlang.mk and subject to the terms of the ISC License.
+
+.PHONY: clean-app
+
+# Configuration.
+
+ERLC_OPTS ?= -Werror +debug_info +warn_export_vars +warn_shadow_vars \
+       +warn_obsolete_guard # +bin_opt_info +warn_export_all +warn_missing_spec
+COMPILE_FIRST ?=
+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)))
+
+# Verbosity.
+
+app_verbose_0 = @echo " APP   " $(PROJECT);
+app_verbose_2 = set -x;
+app_verbose = $(app_verbose_$(V))
+
+appsrc_verbose_0 = @echo " APP   " $(PROJECT).app.src;
+appsrc_verbose_2 = set -x;
+appsrc_verbose = $(appsrc_verbose_$(V))
+
+makedep_verbose_0 = @echo " DEPEND" $(PROJECT).d;
+makedep_verbose_2 = set -x;
+makedep_verbose = $(makedep_verbose_$(V))
+
+erlc_verbose_0 = @echo " ERLC  " $(filter-out $(patsubst %,%.erl,$(ERLC_EXCLUDE)),\
+       $(filter %.erl %.core,$(?F)));
+erlc_verbose_2 = set -x;
+erlc_verbose = $(erlc_verbose_$(V))
+
+xyrl_verbose_0 = @echo " XYRL  " $(filter %.xrl %.yrl,$(?F));
+xyrl_verbose_2 = set -x;
+xyrl_verbose = $(xyrl_verbose_$(V))
+
+asn1_verbose_0 = @echo " ASN1  " $(filter %.asn1,$(?F));
+asn1_verbose_2 = set -x;
+asn1_verbose = $(asn1_verbose_$(V))
+
+mib_verbose_0 = @echo " MIB   " $(filter %.bin %.mib,$(?F));
+mib_verbose_2 = set -x;
+mib_verbose = $(mib_verbose_$(V))
+
+ifneq ($(wildcard src/),)
+
+# Targets.
+
+ifeq ($(wildcard ebin/test),)
+app:: deps $(PROJECT).d
+       $(verbose) $(MAKE) --no-print-directory app-build
+else
+app:: clean deps $(PROJECT).d
+       $(verbose) $(MAKE) --no-print-directory app-build
+endif
+
+ifeq ($(wildcard src/$(PROJECT_MOD).erl),)
+define app_file
+{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) $(DEPS))]},
+       {env, $(subst \,\\,$(PROJECT_ENV))}$(if $(findstring {,$(PROJECT_APP_EXTRA_KEYS)),$(comma)$(newline)$(tab)$(subst \,\\,$(PROJECT_APP_EXTRA_KEYS)),)
+]}.
+endef
+else
+define app_file
+{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) $(DEPS))]},
+       {mod, {$(PROJECT_MOD), []}},
+       {env, $(subst \,\\,$(PROJECT_ENV))}$(if $(findstring {,$(PROJECT_APP_EXTRA_KEYS)),$(comma)$(newline)$(tab)$(subst \,\\,$(PROJECT_APP_EXTRA_KEYS)),)
+]}.
+endef
+endif
+
+app-build: ebin/$(PROJECT).app
+       $(verbose) :
+
+# Source files.
+
+ALL_SRC_FILES := $(sort $(call core_find,src/,*))
+
+ERL_FILES := $(filter %.erl,$(ALL_SRC_FILES))
+CORE_FILES := $(filter %.core,$(ALL_SRC_FILES))
+
+# ASN.1 files.
+
+ifneq ($(wildcard asn1/),)
+ASN1_FILES = $(sort $(call core_find,asn1/,*.asn1))
+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)
+       $(verbose) mv asn1/*.erl src/
+       $(verbose) mv asn1/*.hrl include/
+       $(verbose) mv asn1/*.asn1db include/
+endef
+
+$(PROJECT).d:: $(ASN1_FILES)
+       $(if $(strip $?),$(call compile_asn1,$?))
+endif
+
+# SNMP MIB files.
+
+ifneq ($(wildcard mibs/),)
+MIB_FILES = $(sort $(call core_find,mibs/,*.mib))
+
+$(PROJECT).d:: $(COMPILE_MIB_FIRST_PATHS) $(MIB_FILES)
+       $(verbose) mkdir -p include/ priv/mibs/
+       $(mib_verbose) erlc -v $(ERLC_MIB_OPTS) -o priv/mibs/ -I priv/mibs/ $?
+       $(mib_verbose) erlc -o include/ -- $(addprefix priv/mibs/,$(patsubst %.mib,%.bin,$(notdir $?)))
+endif
+
+# Leex and Yecc files.
+
+XRL_FILES := $(filter %.xrl,$(ALL_SRC_FILES))
+XRL_ERL_FILES = $(addprefix src/,$(patsubst %.xrl,%.erl,$(notdir $(XRL_FILES))))
+ERL_FILES += $(XRL_ERL_FILES)
+
+YRL_FILES := $(filter %.yrl,$(ALL_SRC_FILES))
+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) $?)
+
+# Erlang and Core Erlang files.
+
+define makedep.erl
+       E = ets:new(makedep, [bag]),
+       G = digraph:new([acyclic]),
+       ErlFiles = lists:usort(string:tokens("$(ERL_FILES)", " ")),
+       Modules = [{list_to_atom(filename:basename(F, ".erl")), F} || F <- ErlFiles],
+       Add = fun (Mod, Dep) ->
+               case lists:keyfind(Dep, 1, Modules) of
+                       false -> ok;
+                       {_, DepFile} ->
+                               {_, ModFile} = lists:keyfind(Mod, 1, Modules),
+                               ets:insert(E, {ModFile, DepFile}),
+                               digraph:add_vertex(G, Mod),
+                               digraph:add_vertex(G, Dep),
+                               digraph:add_edge(G, Mod, Dep)
+               end
+       end,
+       AddHd = fun (F, Mod, DepFile) ->
+               case file:open(DepFile, [read]) of
+                       {error, enoent} -> ok;
+                       {ok, Fd} ->
+                               F(F, Fd, Mod),
+                               {_, ModFile} = lists:keyfind(Mod, 1, Modules),
+                               ets:insert(E, {ModFile, DepFile})
+               end
+       end,
+       Attr = fun
+               (F, Mod, behavior, Dep) -> Add(Mod, Dep);
+               (F, Mod, behaviour, Dep) -> Add(Mod, Dep);
+               (F, Mod, compile, {parse_transform, Dep}) -> Add(Mod, Dep);
+               (F, Mod, compile, Opts) when is_list(Opts) ->
+                       case proplists:get_value(parse_transform, Opts) of
+                               undefined -> ok;
+                               Dep -> Add(Mod, Dep)
+                       end;
+               (F, Mod, include, Hrl) ->
+                       case filelib:is_file("include/" ++ Hrl) of
+                               true -> AddHd(F, Mod, "include/" ++ Hrl);
+                               false ->
+                                       case filelib:is_file("src/" ++ Hrl) of
+                                               true -> AddHd(F, Mod, "src/" ++ Hrl);
+                                               false -> false
+                                       end
+                       end;
+               (F, Mod, include_lib, "$1/include/" ++ Hrl) -> AddHd(F, Mod, "include/" ++ Hrl);
+               (F, Mod, include_lib, Hrl) -> AddHd(F, Mod, "include/" ++ Hrl);
+               (F, Mod, import, {Imp, _}) ->
+                       case filelib:is_file("src/" ++ atom_to_list(Imp) ++ ".erl") of
+                               false -> ok;
+                               true -> Add(Mod, Imp)
+                       end;
+               (_, _, _, _) -> ok
+       end,
+       MakeDepend = fun(F, Fd, Mod) ->
+               case io:parse_erl_form(Fd, undefined) of
+                       {ok, {attribute, _, Key, Value}, _} ->
+                               Attr(F, Mod, Key, Value),
+                               F(F, Fd, Mod);
+                       {eof, _} ->
+                               file:close(Fd);
+                       _ ->
+                               F(F, Fd, Mod)
+               end
+       end,
+       [begin
+               Mod = list_to_atom(filename:basename(F, ".erl")),
+               {ok, Fd} = file:open(F, [read]),
+               MakeDepend(MakeDepend, Fd, Mod)
+       end || F <- ErlFiles],
+       Depend = sofs:to_external(sofs:relation_to_family(sofs:relation(ets:tab2list(E)))),
+       CompileFirst = [X || X <- lists:reverse(digraph_utils:topsort(G)), [] =/= digraph:in_neighbours(G, X)],
+       ok = file:write_file("$(1)", [
+               [[F, "::", [[" ", D] || D <- Deps], "; @touch \$$@\n"] || {F, Deps} <- Depend],
+               "\nCOMPILE_FIRST +=", [[" ", atom_to_list(CF)] || CF <- CompileFirst], "\n"
+       ]),
+       halt()
+endef
+
+ifeq ($(if $(NO_MAKEDEP),$(wildcard $(PROJECT).d),),)
+$(PROJECT).d:: $(ERL_FILES) $(call core_find,include/,*.hrl) $(MAKEFILE_LIST)
+       $(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):: $(ERLANG_MK_TMP)/last-makefile-change
+ebin/$(PROJECT).app:: $(ERLANG_MK_TMP)/last-makefile-change
+endif
+
+-include $(PROJECT).d
+
+ebin/$(PROJECT).app:: ebin/
+
+ebin/:
+       $(verbose) mkdir -p ebin/
+
+define compile_erl
+       $(erlc_verbose) erlc -v $(if $(IS_DEP),$(filter-out -Werror,$(ERLC_OPTS)),$(ERLC_OPTS)) -o ebin/ \
+               -pa ebin/ -I include/ $(filter-out $(ERLC_EXCLUDE_PATHS),$(COMPILE_FIRST_PATHS) $(1))
+endef
+
+ebin/$(PROJECT).app:: $(ERL_FILES) $(CORE_FILES) $(wildcard src/$(PROJECT).app.src)
+       $(eval FILES_TO_COMPILE := $(filter-out src/$(PROJECT).app.src,$?))
+       $(if $(strip $(FILES_TO_COMPILE)),$(call compile_erl,$(FILES_TO_COMPILE)))
+       $(eval GITDESCRIBE := $(shell git describe --dirty --abbrev=7 --tags --always --first-parent 2>/dev/null || true))
+       $(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)))))' \
+               > ebin/$(PROJECT).app
+else
+       $(verbose) if [ -z "$$(grep -e '^[^%]*{\s*modules\s*,' src/$(PROJECT).app.src)" ]; then \
+               echo "Empty modules entry not found in $(PROJECT).app.src. Please consult the erlang.mk README for instructions." >&2; \
+               exit 1; \
+       fi
+       $(appsrc_verbose) cat src/$(PROJECT).app.src \
+               | sed "s/{[[:space:]]*modules[[:space:]]*,[[:space:]]*\[\]}/{modules, \[$(call comma_list,$(MODULES))\]}/" \
+               | sed "s/{id,[[:space:]]*\"git\"}/{id, \"$(subst /,\/,$(GITDESCRIBE))\"}/" \
+               > ebin/$(PROJECT).app
+endif
+
+clean:: clean-app
+
+clean-app:
+       $(gen_verbose) rm -rf $(PROJECT).d ebin/ priv/mibs/ $(XRL_ERL_FILES) $(YRL_ERL_FILES) \
+               $(addprefix include/,$(patsubst %.mib,%.hrl,$(notdir $(MIB_FILES)))) \
+               $(addprefix include/,$(patsubst %.asn1,%.hrl,$(notdir $(ASN1_FILES)))) \
+               $(addprefix include/,$(patsubst %.asn1,%.asn1db,$(notdir $(ASN1_FILES)))) \
+               $(addprefix src/,$(patsubst %.asn1,%.erl,$(notdir $(ASN1_FILES))))
+
+endif
+
+# Copyright (c) 2016, Loïc Hoguin <essen@ninenines.eu>
+# Copyright (c) 2015, Viktor Söderqvist <viktor@zuiderkwast.se>
+# This file is part of erlang.mk and subject to the terms of the ISC License.
+
+.PHONY: docs-deps
+
+# Configuration.
+
+ALL_DOC_DEPS_DIRS = $(addprefix $(DEPS_DIR)/,$(DOC_DEPS))
+
+# Targets.
+
+$(foreach dep,$(DOC_DEPS),$(eval $(call dep_target,$(dep))))
+
+ifneq ($(SKIP_DEPS),)
+doc-deps:
+else
+doc-deps: $(ALL_DOC_DEPS_DIRS)
+       $(verbose) for dep in $(ALL_DOC_DEPS_DIRS) ; do $(MAKE) -C $$dep; done
+endif
+
+# Copyright (c) 2015-2016, Loïc Hoguin <essen@ninenines.eu>
+# This file is part of erlang.mk and subject to the terms of the ISC License.
+
+.PHONY: rebar.config
+
+# We strip out -Werror because we don't want to fail due to
+# warnings when used as a dependency.
+
+compat_prepare_erlc_opts = $(shell echo "$1" | sed 's/, */,/g')
+
+define compat_convert_erlc_opts
+$(if $(filter-out -Werror,$1),\
+       $(if $(findstring +,$1),\
+               $(shell echo $1 | cut -b 2-)))
+endef
+
+define compat_erlc_opts_to_list
+[$(call comma_list,$(foreach o,$(call compat_prepare_erlc_opts,$1),$(call compat_convert_erlc_opts,$o)))]
+endef
+
+define compat_rebar_config
+{deps, [
+$(call comma_list,$(foreach d,$(DEPS),\
+       $(if $(filter hex,$(call dep_fetch,$d)),\
+               {$(call dep_name,$d)$(comma)"$(call dep_repo,$d)"},\
+               {$(call dep_name,$d)$(comma)".*"$(comma){git,"$(call dep_repo,$d)"$(comma)"$(call dep_commit,$d)"}})))
+]}.
+{erl_opts, $(call compat_erlc_opts_to_list,$(ERLC_OPTS))}.
+endef
+
+$(eval _compat_rebar_config = $$(compat_rebar_config))
+$(eval export _compat_rebar_config)
+
+rebar.config:
+       $(gen_verbose) echo "$${_compat_rebar_config}" > rebar.config
+
+# Copyright (c) 2013-2016, Loïc Hoguin <essen@ninenines.eu>
+# This file is part of erlang.mk and subject to the terms of the ISC License.
+
+.PHONY: distclean-edoc edoc
+
+# Configuration.
+
+EDOC_OPTS ?=
+
+# Core targets.
+
+ifneq ($(wildcard doc/overview.edoc),)
+docs:: edoc
+endif
+
+distclean:: distclean-edoc
+
+# Plugin-specific targets.
+
+edoc: distclean-edoc doc-deps
+       $(gen_verbose) $(ERL) -eval 'edoc:application($(PROJECT), ".", [$(EDOC_OPTS)]), halt().'
+
+distclean-edoc:
+       $(gen_verbose) rm -f doc/*.css doc/*.html doc/*.png doc/edoc-info
index 6b566c9..2225e57 100644 (file)
@@ -1,6 +1,7 @@
 {application, statip, [
   {description, "StateTip event stream registry"},
   {vsn, "0.1.1"},
+  {modules, []},
   {registered, [
     statip_sup,
     statip_log,