antimake: New build system.
authorMarko Kreen <markokr@gmail.com>
Tue, 29 Nov 2011 18:55:49 +0000 (20:55 +0200)
committerMarko Kreen <markokr@gmail.com>
Mon, 12 Dec 2011 11:50:51 +0000 (13:50 +0200)
Emulates Automake syntax on plain GNU Make.

m4/antimake.m4 [new file with mode: 0644]
mk/antimake.mk [new file with mode: 0755]
mk/antimake.txt [new file with mode: 0644]

diff --git a/m4/antimake.m4 b/m4/antimake.m4
new file mode 100644 (file)
index 0000000..792b5c8
--- /dev/null
@@ -0,0 +1,14 @@
+
+dnl
+dnl  AMK_INIT: Generate initial makefile
+dnl
+
+AC_DEFUN([AMK_INIT], [
+
+# if building separately from srcdir, write top-level makefile
+if test "$srcdir" != "."; then
+  echo "include $srcdir/Makefile" > Makefile
+fi
+
+])
+
diff --git a/mk/antimake.mk b/mk/antimake.mk
new file mode 100755 (executable)
index 0000000..7fefa86
--- /dev/null
@@ -0,0 +1,1443 @@
+#! /usr/bin/make -f
+
+#
+# antimake.mk - automake syntax with GNU Make
+#
+# Copyright (c) 2011  Marko Kreen
+#
+# 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.
+#
+
+# Goals:
+# - Clean user Makefiles, by using automake syntax
+# - Clean output during build
+# - Optional ties with `autoconf` and `libtool`
+# - Automatic dependency tracking
+# - Avoid separate build step for Makefiles
+# - No extra tools needed except GNU Make
+
+# Usage without autoconf:
+# - copy antimake.mk into source dir, then: include antimake.mk
+# - copy/link antimake.mk into PATH, then:  include $(shell antimake.mk)
+#
+# Usage with autoconf:
+# - Copy to antimake.mk.in at top dir, then process with autoconf
+#   to antimake.mk and include that one in Makefiles.
+#
+# - Have config.mak.in that also includes antimake.mk.
+#   Suggestion: the separate file should include antimake.mk
+#   using $(abs_top_srcdir) to support separate build dir.
+#
+# - Include config and antimake.mk separately in user Makefiles
+
+##
+## Startup hacks
+##
+
+# detect GNU make version, confuse others
+$(eval GNUMAKE380=1)
+GNUMAKE381=$(or ,1)
+define GNUMAKE382 =
+1
+endef
+
+# give error of too old
+ifeq ($(GNUMAKE381),)
+$(error GNU Make 3.81+ required)
+endif
+
+
+# extra targets if this file is executed directly
+ifeq ($(words $(MAKEFILE_LIST)), 1)
+
+.PHONY: show-location show-config
+
+# default: print location. For "include $(shell antimake.mk)"-style usage.
+show-location:
+       @echo $(MAKEFILE_LIST)
+
+# show autoconfigurable variables
+show-config:
+       @grep '@[^ ]*@$$' $(MAKEFILE_LIST)
+
+endif
+
+
+##
+## Allow this file to be processed through autoconf
+##
+
+#
+# to extract autoconfigurable values:
+#    $ grep '@[^ ]*@$' antimake.mk > config.mk.in
+#    $ antimake.mk show-config > config.mk.in
+#
+ifneq ($(filter-out @%,@PACKAGE_NAME@),)
+
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+
+PORTNAME = @PORTNAME@
+EXEEXT = @EXEEXT@
+HAVE_CC_DEPFLAG = @HAVE_CC_DEPFLAG@
+
+# C language
+CC = @CC@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CFLAGS = @CFLAGS@
+DEFS = @DEFS@
+WFLAGS = @WFLAGS@
+
+# C++ language
+CXX = @CXX@
+CXXFLAGS = @CXXFLAGS@
+
+# linking
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+
+# static and shared libs
+AR = @AR@
+ARFLAGS = @ARFLAGS@
+RANLIB = @RANLIB@
+LIBTOOL = @LIBTOOL@
+
+# other tools
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_DATA = @INSTALL_DATA@
+MKDIR_P = @MKDIR_P@
+SED = @SED@
+AWK = @AWK@
+GREP = @GREP@
+EGREP = @EGREP@
+STRIP = @STRIP@
+
+# install locations
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+bindir = @bindir@
+includedir = @includedir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datarootdir = @datarootdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+docdir = @docdir@
+mandir = @mandir@
+libdir = @libdir@
+localedir = @localedir@
+pkgdatadir = @pkgdatadir@
+pkgconfigdir = @pkgconfigdir@
+
+# autoconf values for top dir
+abs_top_srcdir ?= @abs_top_srcdir@
+abs_top_builddir ?= @abs_top_builddir@
+nosub_top_srcdir ?= @top_srcdir@
+nosub_top_builddir ?= @top_builddir@
+
+endif # end of @xx@ values
+
+##
+## In case of missing autoconf values, provide sane defaults
+##
+
+PACKAGE_NAME ?= package
+PACKAGE_TARNAME ?= $(PACKAGE_NAME)
+PACKAGE_VERSION ?= 0.0
+PACKAGE_STRING ?= $(PACKAGE_NAME) $(PACKAGE_VERSION)
+PACKAGE_URL ?= 
+PACKAGE_BUGREPORT ?= 
+
+PORTNAME ?= unix
+EXEEXT ?=
+HAVE_CC_DEPFLAG ?= yes
+
+# C language
+CC ?= cc
+CPP ?= cpp
+CPPFLAGS ?=
+CFLAGS ?= -O -g
+DEFS ?=
+WFLAGS ?= -Wall
+
+# C++ language
+CXX ?= c++
+CXXFLAGS ?= -O -g
+
+# linking
+LD ?= ld
+LDFLAGS ?=
+LIBS ?=
+
+# static and shared libs
+LIBTOOL ?= libtool
+AR ?= ar
+ARFLAGS ?= rcs
+ifeq ($(ARFLAGS),rv)
+ARFLAGS = rcs
+endif
+RANLIB ?= ranlib
+
+# other tools
+INSTALL ?= install
+INSTALL_PROGRAM ?= $(INSTALL)
+INSTALL_SCRIPT ?= $(INSTALL)
+INSTALL_DATA ?= $(INSTALL)
+MKDIR_P ?= mkdir -p
+SED ?= sed
+AWK ?= awk
+GREP ?= grep
+EGREP ?= grep -E
+STRIP ?= strip
+
+# install locations
+prefix ?= /usr/local
+exec_prefix ?= ${prefix}
+bindir ?= ${exec_prefix}/bin
+includedir ?= ${prefix}/include
+sbindir ?= ${exec_prefix}/sbin
+libexecdir ?= ${exec_prefix}/libexec
+datarootdir ?= ${prefix}/share
+datadir ?= ${datarootdir}
+sysconfdir ?= ${prefix}/etc
+docdir ?= ${datarootdir}/doc/${PACKAGE_TARNAME}
+mandir ?= ${datarootdir}/man
+libdir ?= ${exec_prefix}/lib
+localedir ?= ${datarootdir}/locale
+pkgdatadir ?= ${datarootdir}/${PACKAGE_TARNAME}
+pkgconfigdir ?= ${libdir}/pkgconfig
+
+# autoconf values for top dir
+abs_top_srcdir ?= $(CURDIR)
+abs_top_builddir ?= $(CURDIR)
+nosub_top_builddir ?= .
+nosub_top_srcdir ?= .
+
+##
+## Variables for user makefiles
+##
+
+# current subdirectory location from top dir (foo/bar)
+SUBLOC ?= .
+
+# subdirectories in current directory
+SUBDIRS ?=
+
+# extra files for clean targets
+CLEANFILES ?=
+DISTCLEANFILES ?=
+MAINTAINERCLEANFILES ?=
+
+# Additional flags for Makefile use, to avoid need
+# to touch flags coming from autoconf/cmdline
+AM_DEFS ?=
+AM_CPPFLAGS ?=
+AM_CFLAGS ?=
+AM_LDFLAGS ?=
+AM_LIBTOOLFLAGS ?=
+
+AM_MAKEFLAGS ?=
+AM_LIBS ?=
+
+# libusual sources, for embedded usage
+USUAL_DIR ?= .
+
+# V=1 -> verbose build
+V ?= 0
+
+# turn on function tracing
+AM_TRACE ?=
+
+# default formats for 'dist'
+AM_DIST_DEFAULT ?= gzip
+
+##
+## Non-user-serviceable area
+##
+
+# Hacking:
+#
+# - Uppercase names are simple (late) variables, lowercase names - targets,
+#   mixedcase - functions that need to be $(call)-ed.
+#
+# - Minimal amount of shell should be used here.
+#
+# - Minimal amount of := and $(eval)
+#
+# - It's useful to indent the expressions for easier understanding.
+#   Later the indendation needs to be removed, as whitespace is significant for Make.
+#   Several functions must not add any extra whitespace.
+#
+# GNU Make features in new versions:
+#
+#   3.80 - 2002-10-03: base version.  $(eval) $(value) $(MAKEFILE_LIST) $(.VARIABLES) $(call fixes)
+#   3.81 - 2006-04-01: $(or), $(and), $(lastword), $(abspath), $(realpath), $(info), $(flavor)
+#   3.82 - 2010-07-28: private, undefine, define var :=
+#
+# This file should use only features from 3.80
+
+##
+## command helpers
+##
+
+CCLD ?= $(CC)
+COMPILE ?= $(CC) $(AM_DEFS) $(DEFS) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LINK ?= $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+
+AM_AR ?= $(AR) $(ARFLAGS)
+
+LIBTOOLCMD ?= $(LIBTOOL) $(LIBTOOLQ) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS)
+
+RM = rm -f
+
+
+##
+## Internals
+##
+
+# varables that can be set per-target with target_VAR
+# they appear as AM_foo.  [Not supported: COMPILE]
+AM_TARGET_VARIABLES += CFLAGS CPPFLAGS LDFLAGS LIBTOOLFLAGS DEFS LIBS
+AM_TARGET_RELOC_VARIABLES += CFLAGS CPPFLAGS LDFLAGS
+
+# list of language (rather compiler) names
+AM_LANGUAGES += C CXX
+
+AM_BIG_PRIMARIES += LIBRARIES LTLIBRARIES PROGRAMS
+AM_SMALL_PRIMARIES += HEADERS SCRIPTS DATA MANS
+
+# list of destinations per primary
+AM_DESTINATIONS += bin lib libexec sbin \
+                  data doc include locale man sysconf \
+                  pkgdata pkgconfig \
+                  noinst EXTRA
+
+# primaries where 'dist' is default
+AM_DIST_PRIMARIES += HEADERS
+
+AM_PRIMARIES = $(AM_BIG_PRIMARIES) $(AM_SMALL_PRIMARIES)
+
+# distclean does rm -rf on that
+OBJDIR = .objs
+
+# non-configurable
+OBJEXT = o
+
+# files that need to be converted to objects
+AM_SRCEXTS = $(foreach lang,$(AM_LANGUAGES),$(AM_LANG_$(lang)_SRCEXTS))
+
+# target types - big/small: with/without objects
+# list of flags, 'noinst' is taken as dest, 'base' is always default
+AM_FLAGS = base nobase dist nodist
+
+## configure non-defult target params
+AM_PROGRAMS_InstFunc = ProgInstall
+AM_LTLIBRARIES_InstFunc = LTLibInstall
+AM_LTLIBRARIES_OBJEXT = .lo
+AM_SCRIPTS_InstFunc = ScriptInstall
+AM_MANS_InstFunc = ManInstall
+
+# files to distribute
+am_DISTFILES :=
+am_FINAL_DISTFILES = $(sort $(am_DISTFILES))
+AM_DIST_BASE = $(PACKAGE_TARNAME)-$(PACKAGE_VERSION)
+
+AM_ALL_TARGETS =
+
+##
+## Make dependencies work
+##
+
+HAVE_CC_DEPFLAG ?= yes
+ifeq ($(HAVE_CC_DEPFLAG),yes)
+OBJDEPS = -MD -MP -MT $@ -MF $@.d
+endif
+
+
+##
+## Quiet by default, 'make V=1' shows commands
+##
+
+CTX ?=
+ifeq ($(V), 0)
+E = @printf "%-4s %-8s %s\n" "$(CTX)"
+Q = @
+LIBTOOLQ = --silent
+MAKEFLAGS += --no-print-directory
+else
+E = @true
+Q =
+LIBTOOLQ = --silent
+endif
+
+
+##
+## libtool activation
+##
+
+# libtool activates when detects %.lo / %.la pattern
+LTCOMPILE = $(if $(filter %.lo,$@),$(LIBTOOLCMD) --mode=compile)
+LTLINK = $(if $(filter %.la %.lo,$^),$(LIBTOOLCMD) --mode=link)
+LTCLEAN = $(LIBTOOLCMD) --mode=clean
+
+
+##
+## Default setup for C
+##
+
+AM_LANG_C_SRCEXTS = .c
+define AM_LANG_C_COMPILE
+       $(E) "CC" $<
+       $(Q) $(LTCOMPILE) $(COMPILE) $(OBJDEPS) -c -o $@ $<
+endef
+define AM_LANG_C_LINK
+       $(E) "CCLD" $@
+       $(Q) $(LTLINK) $(LINK) $^ $(AM_LIBS) $(LIBS) $(AM_LT_RPATH)
+endef
+
+
+##
+## Default setup for C++
+##
+
+AM_TARGET_VARIABLES += CXXFLAGS
+
+CXXLD ?= $(CXX)
+CXXCOMPILE ?= $(CXX) $(AM_DEFS) $(DEFS) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLINK ?= $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+
+AM_LANG_CXX_SRCEXTS = .cc .cpp cxx
+define AM_LANG_CXX_COMPILE
+       $(E) "CXX" $<
+       $(Q) $(LTCOMPILE) $(CXXCOMPILE) $(OBJDEPS) -c -o $@ $<
+endef
+define AM_LANG_CXX_LINK
+       $(E) "CXXLD" $@
+       $(Q) $(LTLINK) $(CXXLINK) $^ $(AM_LIBS) $(LIBS) $(AM_LT_RPATH)
+endef
+
+
+##
+## Various other shortcuts
+##
+
+define ar_lib
+       @$(MKDIR_P) $(dir $@)
+       $(E) "AR" $@
+       $(Q) $(AM_AR) $@ $^
+       $(E) "RANLIB" $@
+       $(Q) $(RANLIB) $@
+endef
+
+# 1 - dir
+define ProgInstall
+       $(E) "INSTALL" "$< $(1)"
+       $(Q) $(MKDIR_P) $(1)
+       $(Q) $(INSTALL_PROGRAM) $< $(1)
+endef
+
+# 1 - dir
+define ScriptInstall
+       $(E) "INSTALL" "$< $(1)"
+       $(Q) $(MKDIR_P) $(1)
+       $(Q) $(INSTALL_SCRIPT) $< $(1)
+endef
+
+# 1 - dir
+define DataInstall
+       $(E) "INSTALL" "$< $(1)"
+       $(Q) $(MKDIR_P) $(1)
+       $(Q) $(INSTALL_DATA) $< $(1)
+endef
+
+# 1 - dir, add manX subdir
+ManInstall = $(call DataInstall,$(1)/man$(call LastWord,$(subst ., ,$<)))
+
+# 1 - dir
+define LTLibInstall
+       $(E) "INSTALL" "$< $(1)"
+       $(Q) $(MKDIR_P) $(1)
+       $(Q) $(LIBTOOLCMD) --mode=install $(INSTALL) $< $(1)
+endef
+
+
+##
+## Create .srcext -> .obj mapping for a language
+##
+
+# 1-tgt, 2-name, 3-srcext
+define LangObjTarget
+$(trace3)
+$$(OBJDIR)/$(1)/%.o $$(OBJDIR)/$(1)/%.lo: %$(3)
+       @$$(MKDIR_P) $$(dir $$@)
+       $$(AM_LANG_$(2)_COMPILE)
+endef
+
+# 1=tgt, 2=name
+define LangSetup
+$(trace2)
+$(foreach ext,$(AM_LANG_$(2)_SRCEXTS),$(call LangObjTarget,$(1),$(2),$(ext))$(NewLine))
+endef
+
+
+##
+## Utility functions
+##
+
+# for function debugging, put them at the start of body
+ifdef AM_TRACE
+trace1=$(warning $0('$1'))
+trace2=$(warning $0('$1','$2'))
+trace3=$(warning $0('$1','$2','$3'))
+trace4=$(warning $0('$1','$2','$3','$4'))
+trace5=$(warning $0('$1','$2','$3','$4','$5'))
+endif
+
+# for use inside $(eval)
+IFDEF = ifdef
+IFEQ = ifeq
+IFNEQ = ifneq
+ELSE = else
+ENDIF = endif
+
+# returns 'true' if $1==$2
+Eq = $(if $(1)$(2),$(if $(findstring $(1),$(2)),$(if $(findstring $(2),$(1)),true)),true)
+
+Not = $(if $(1),,true)
+Neq = $(call Not,$(call Eq,$(1),$(2)))
+
+# replace [-./] with '_'
+CleanName = $(subst /,_,$(subst -,_,$(subst .,_,$(1))))
+
+# return last word from word list
+LastWord = $(if $(1),$(word $(words $(1)),$(1)))
+
+Empty =
+Space = $(Empty) $(Empty)
+# twice to unconfuse syntax hiliters
+SQuote = '
+SQuote = '
+define NewLine
+
+
+endef
+
+# quote str for shell
+ShellQuote = '$(subst $(SQuote),'\$(SQuote)',$(1))'
+
+# replace extensions
+# 1-src ext list
+# 2-target ext
+# 3-source list
+ReplaceExts = $(foreach ext,$(1),$(patsubst %$(ext),%$(2),$(filter %$(ext),$(3))))
+
+# objs with objdir from source list (1-cleantgt, 2-src list)
+SourceObjs = $(trace1)$(call SourceObjsExt,$(1),.$(OBJEXT),$(2))
+
+# objs with objdir from source list
+# 1-cleantgt, 2-objext, 3-srcs list
+SourceObjsExt = $(addprefix $(call JoinPath,$(OBJDIR),$(1))/, $(call ReplaceExts,$(AM_SRCEXTS),$(2),$(3)))
+
+# dependency files from object files, must match OBJDEPS
+DepFiles = $(wildcard $(addsuffix .d,$(1)))
+
+# per-target var override, 1=target, 2=varname
+# if foo_VAR exists, expand to:
+#   build_foo install_foo clean_foo: AM_VAR = $(foo_VAR)
+#TgtVar = $(if $($(1)_$(2)),build_$(1): AM_$(2) = $($(1)_$(2)))
+TgtVar = $(if $($(1)_$(2)),$$($(1)_FINAL): AM_$(2) = $($(1)_$(2)))
+
+# loop TgtVar over AM_TARGET_VARIABLES, 1=target
+VarOverride = $(foreach var,$(AM_TARGET_VARIABLES),$(eval $(call TgtVar,$(1),$(var))))
+
+# check if actual target (.h, .exe) is nodist based on primary and flags
+# 1-prim 2-flags
+TargetNoDist = $(strip $(if $(filter nodist,$(2)), \
+                            true, \
+                           $(if $(filter dist,$(2)), \
+                                , \
+                                $(filter-out $(AM_DIST_PRIMARIES),$(1)))))
+
+# return sources that match language
+# 1-lang
+# 2-sources
+LangFiles = $(filter $(addprefix %,$(AM_LANG_$(1)_SRCEXTS)),$(2))
+
+# return list of langs that match sources.
+# 1-sources
+LangList = $(strip $(foreach lang,$(AM_LANGUAGES),$(if $(call LangFiles,$(lang),$(1)),$(lang))))
+
+# 1-sources
+LinkLangList = $(foreach lang,$(call LangList,$(1)),$(if $(AM_LANG_$(lang)_LINK),$(lang)))
+
+# pick linker variable based on sources, fallback to C
+# 1-sources
+DetectLinkVar = AM_LANG_$(call LastWord,C $(call LinkLangList,$(1)))_LINK
+
+# convert 'foo/bar' -> '../..'
+UpDirStep1 = $(subst /, ,$(1))
+UpDirStep2 = $(foreach dir,$(call UpDirStep1,$(1)),../)
+UpDirStep3 = $(subst / ,/,$(call UpDirStep2,$(1)))
+UpDirStep4 = $(patsubst %/,%,$(call UpDirStep3,$(1)))
+UpDir = $(if $(filter-out .,$(1)),$(call UpDirStep4,$(1)),.)
+
+# a,b -> a/b, skips component if '.'
+JoinPath2 = $(if $(filter-out .,$(1)),$(if $(filter-out .,$(2)),$(1)/$(2),$(1)),$(2))
+
+# a,b -> a/b, unless b is absolute
+JoinPath = $(if $(filter /%,$(2)),$(2),$(call JoinPath2,$(1),$(2)))
+
+
+
+##
+## Parse target list variables
+##
+
+## pick out components from name, call function
+# 1-varname, 2-words, 3-func, 4-func arg
+# func args: 1-var, 2-prim, 3-dest, 4-flags, 5-arg
+ParseName = $(call $(3),$(1),$(filter $(AM_PRIMARIES),$(2)),$(filter $(AM_DESTINATIONS),$(2)),$(filter $(AM_FLAGS),$(2)),$(4))
+
+ForEachList = $(foreach var,$(2),$(call ParseName,$(var),$(subst _, ,$(var)),$(1),$(3)))
+
+## try reconstruct name, if fails, its a random variable
+# 1-var, 2-prim,3-dest,4-flags
+CheckName = $(if $(call Eq,$(subst _, ,$(1)),$(strip $(4) $(call LastWord,$(3)) $(call LastWord,$(2)))),$(1))
+
+## also check if variable is filled
+# 1-var, 2-prim,3-dest,4-flags
+CheckNameFull = $(if $(call CheckName,$(1),$(2),$(3),$(4)),$(if $($(1)),$(1)))
+
+##
+## Loop over targets in list variables
+##
+
+## call function on parsed target
+# 1-var, 2-prim, 3-dest, 4-flags, 5-func
+# func args: 1-cleantgt, 2-tgt, 3-prim, 4-dest, 5-flags
+ForEachTarget2 = $(foreach tgt,$($(1)),$(call $(5),$(call CleanName,$(tgt)),$(tgt),$(2),$(3),$(4)))
+
+## ForEachTarget: call function on all targets in lists
+# 1-func, 2- var list
+# func args: 1-cleantgt, 2-tgt, 3-prim, 4-dest, 5-flags
+ForEachTarget = $(call ForEachList,ForEachTarget2,$(2),$(1))
+
+
+##
+## Utility functions for libusual link
+##
+
+# module names from sources (plus headers)
+UsualMods = $(trace1)$(shell $(USUAL_DIR)/find_modules.sh $(USUAL_DIR) $(wildcard $(addprefix $(srcdir)/,$(1))))
+
+# full-path sources based on module list
+UsualSrcsFull = $(wildcard $(addprefix $(USUAL_DIR)/usual/,$(addsuffix *.[ch],$(1))))
+
+# remove USUAL_DIR
+UsualStrip = $(subst $(USUAL_DIR)/,,$(1))
+
+# simple-path sources based on module list
+UsualSrcs = $(call UsualStrip,$(call UsualSrcsFull,$(1)))
+
+# objs with objdir from source file list (1-cleantgt, 2-src list)
+UsualObjs = $(call SourceObjs,$(1),$(call UsualSrcs,$(call UsualMods,$(2))))
+
+# usual sources from user source file list
+UsualSources = $(call UsualSrcsFull,$(call UsualMods,$(1)))
+
+
+## EMBED_SUBDIRS relocations
+
+## add subdir to files
+# 1-subdir, 2-file list
+RelocFiles = $(foreach f,$(2),$(call JoinPath,$(1),$(f)))
+
+
+# 1-dir, 2-pfx, 3-full
+RelocOneFlag2 = $(2)$(call JoinPath,$(1),$(patsubst $(2)%,%,$(3)))
+
+# 1-dir, 2-flag
+RelocOneFlag = $(if $(filter -L%,$(2)), \
+                    $(call RelocOneFlag2,$(1),-L,$(2)), \
+                   $(if $(filter -I%,$(2)), \
+                         $(call RelocOneFlag2,$(1),-I,$(2)), \
+                        $(if $(filter -%,$(2)), \
+                             $(2), \
+                             $(call JoinPath,$(1),$(2)))))
+
+## Relocate relative files, relative -I/-L, ignore -*
+# 1-dir, 2- flaglist
+RelocFlags = $(strip $(if $(filter-out .,$(1)), \
+                          $(foreach flg,$(2),$(call RelocOneFlag,$(1),$(flg))),$(2)))
+
+
+## Separate build dir relocation
+
+## non-local source dir: -Isrc/include -> -Isrc/include -I$(srcdir)/src/include
+# 1-srcdir, 2-flag list
+FixIncludes = $(strip $(if $(filter-out .,$(1)), \
+                          $(foreach flg,$(2),$(call FixIncludes2,$(1),$(flg))), \
+                          $(2)))
+# 1-dir, 2-flg
+FixIncludes2 = $(if $(filter -I%,$(2)), \
+                   $(call FixIncludes3,$(1),$(patsubst -I%,%,$(2))), \
+                   $(2))
+# 1-dir, 2-orig dir
+FixIncludes3 = -I$(2) -I$(call JoinPath,$(srcdir),$(2))
+
+
+##
+## Makefile fragments
+##
+
+### fill values
+# abs_top_srcdir, abs_top_builddir
+# nosub_top_builddir, nosub_top_srcdir
+# 1 - subdir
+define SetDirs
+abs_builddir := $$(call JoinPath,$$(abs_top_builddir),$(1))
+abs_srcdir := $$(call JoinPath,$$(abs_top_srcdir),$(1))
+top_builddir := $$(call UpDir,$(1))
+top_srcdir := $$(call JoinPath,$$(top_builddir),$$(nosub_top_srcdir))
+builddir := .
+$(IFEQ) ($$(nosub_top_srcdir),$$(nosub_top_builddir))
+srcdir := .
+$(ELSE)
+srcdir := $$(call JoinPath,$$(top_srcdir),$(1))
+$(ENDIF)
+endef
+
+
+##
+## Embedded subdirs
+##
+
+# func args: 1-cleantgt, 2-tgt, 3-prim, 4-dest, 5-flags
+define RelocBigTarget
+$(trace5)
+# move vars:
+$(foreach var,$(AM_TARGET_VARIABLES),$(NewLine)$$(am_PFX)_$(1)_$(var) := $$($(1)_$(var)))
+
+# move and relocate
+$$(am_PFX)_$(1)_SOURCES := $$(call RelocFiles,$$(am_DIR),$$($(1)_SOURCES))
+$$(am_PFX)_$(1)_LDADD := $$(call RelocFlags,$$(am_DIR),$$($(1)_LDADD))
+$$(am_PFX)_$(1)_LIBADD := $$(call RelocFlags,$$(am_DIR),$$($(1)_LIBADD))
+$$(am_PFX)_$(1)_CFLAGS := $$(call RelocFlags,$$(am_DIR),$$($(1)_CFLAGS))
+$$(am_PFX)_$(1)_CPPFLAGS := $$(call RelocFlags,$$(am_DIR),$$($(1)_CPPFLAGS))
+$$(am_PFX)_$(1)_LDFLAGS := $$(call RelocFlags,$$(am_DIR),$$($(1)_LDFLAGS))
+
+# clean vars
+$(1)_SOURCES =
+$(1)_LDADD =
+$(1)_LIBADD =
+$(foreach var,$(AM_TARGET_VARIABLES),$(NewLine)$(1)_$(var) = )
+endef
+
+
+## pick actual func
+# func args: 1-cleantgt, 2-tgt, 3-prim, 4-dest, 5-flags
+define RelocTarget
+$(trace5)
+$(if $(filter $(AM_BIG_PRIMARIES),$(3)),$(call RelocBigTarget,$(1),$(2),$(3),$(4),$(5)))
+endef
+
+
+## relocate target list
+# func args: 1-var, 2-prim, 3-dest, 4-flags, 5-arg
+define RelocTList
+$(trace5)
+
+# detect top and subdir target conflict - it's easier to detect
+# and error out than to work around the rare case
+$(IFNEQ) (,$$(filter $(2),$$(AM_BIG_PRIMARIES)))
+$(IFEQ) (.,$$(am_DIR))
+am_TOP_NAMES += $$(foreach tgt,$$($(1)),$$(call CleanName,$$(tgt)))
+$(ELSE)
+$(IFNEQ) (,$$(filter $$(am_TOP_NAMES),$$(foreach tgt,$$($(1)),$$(call CleanName,$$(tgt)))))
+$$(error $$(NewLine)$$(NewLine)\
+*** Target names used in top Makefile cannot be re-used in embedded Makefiles. $$(NewLine)\
+*** The target variables (eg. <tgt>_SOURCES) conflict is not handled yet)
+$(ENDIF)
+$(ENDIF)
+$(ENDIF)
+
+# move value under real_%
+$(IFEQ) ($(real_$(1)),)
+real_$(1) :=
+$(ENDIF)
+real_$(1) += $$(call RelocFiles,$$(am_DIR),$$($(1)))
+$(1) =
+
+# remember in proper list
+$(IFEQ) ($(3),EXTRA)
+am_EXTRA_TARGETLISTS += real_$(1)
+$(ELSE)
+am_TARGETLISTS += real_$(1)
+$(ENDIF)
+endef
+
+
+## process included values
+# 1-dir, 2-pfx, 3-tlist
+define EmbedProcess
+$(trace3)
+
+$(IFNEQ) ($$(filter $(1),$$(am_EMBED_DONE)),)
+$$(error Double entry in EMBED_SUBDIRS: $(1))
+$(ENDIF)
+
+# init local vars
+am_DIR := $(1)
+am_LOC := $$(call JoinPath,$$(SUBLOC),$(1))
+am_PFX := $(2)
+am_EMBED_DONE += $(1)
+
+# reloc & save vars
+am_DISTFILES += $$(call RelocFiles,$$(am_DIR),$$(EXTRA_DIST))
+am_CLEANFILES += $$(call RelocFiles,$$(am_DIR),$$(CLEANFILES))
+am_DISTCLEANFILES += $$(call RelocFiles,$$(am_DIR),$$(DISTCLEANFILES))
+am_MAINTAINERCLEANFILES += $$(call RelocFiles,$$(am_DIR),$$(MAINTAINERCLEANFILES))
+am_EMBED_TODO += $$(call RelocFiles,$$(am_DIR),$$(EMBED_SUBDIRS))
+am_SUBDIRS += $$(call RelocFiles,$$(am_DIR),$$(SUBDIRS))
+am_DIST_SUBDIRS += $$(call RelocFiles,$$(am_DIR),$$(DIST_SUBDIRS))
+# clean vars for new dir
+EXTRA_DIST =
+CLEANFILES =
+DISTCLEANFILES =
+MAINTAINERCLEANFILES =
+EMBED_SUBDIRS =
+SUBDIRS =
+DIST_SUBDIRS =
+
+$(call SetDirs,$(call JoinPath,$(SUBLOC),$(1)))
+$(call ForEachTarget,RelocTarget,$(3))
+$(call ForEachList,RelocTList,$(3))
+endef
+
+
+## read Makefile.am, process it
+# 1 - dir
+DoEmbed = $(trace1)$(strip \
+       $(if $(wildcard $(am_srcdir)/$(1)/Makefile.am), \
+               $(eval include $(am_srcdir)/$(1)/Makefile.am $(NewLine)) \
+              $(eval $(call EmbedProcess,$(1),$(call CleanName,$(1)),$(AM_ALL_TLISTS))), \
+            $(error $(SUBLOC)/Makefile failure: $(call JoinPath,$(SUBLOC),$(1)/Makefile.am) not found.)))
+
+##
+##  Fragments that build targets
+##
+
+# Note that variable initialization order is important here
+# as some of them will be used immediately.
+
+##
+## Install target object
+##
+
+# 1=cleantgt,2=rawtgt,3=prim,4=dest,5=flags
+define InstallTarget
+$(trace5)
+
+$(1)_DEST := $$(if $$($(4)dir),$$($(4)dir),$$(error '$(4)dir' empty))$(if $(filter nobase,$(5)),/$(dir $(2)))
+
+$(1)_InstFunc := $$(if $$(AM_$(3)_InstFunc),$$(AM_$(3)_InstFunc),DataInstall)
+
+# actual installation
+.PHONY: install_$(1)
+install: install_$(1)
+install_$(1): $(2)
+       $$(call $$($(1)_InstFunc),$$(DESTDIR)$$($(1)_DEST))
+
+# hack to pass -rpath to LTLIBRARIES on build time (1)
+$(2): AM_DEST = $$($(1)_DEST)
+
+endef
+
+# hack to pass -rpath to LTLIBRARIES on build time (2)
+%.la: AM_LT_RPATH = $(if $(AM_DEST),-rpath $(AM_DEST))
+
+
+##
+## Rules for big target
+##
+
+# 1=cleantgt,2=rawtgt,3=prim,4=dest,5=flags
+define BigTargetBuild
+$(trace5)
+AM_ALL_TARGETS += $(1)
+
+$(1)_ALLSRCS := $$($(1)_SOURCES) $$(EXTRA_$(1)_SOURCES) $$(nodist_$(1)_SOURCES) $$(nodist_EXTRA_$(1)_SOURCES)
+
+# calculate OBJS from SOURCES
+$(1)_OBJEXT := $$(if $$(AM_$(3)_OBJEXT),$$(AM_$(3)_OBJEXT),.$$(OBJEXT))
+$(1)_OBJS := $$(call SourceObjsExt,$(1),$$($(1)_OBJEXT), \
+                                  $$($(1)_SOURCES) $$(nodist_$(1)_SOURCES))
+
+# include additional objects, move flags to _LIBS
+$(IFEQ) ($(3),PROGRAMS)
+$(1)_OBJS += $$(filter-out -%,$$($(1)_LDADD))
+$(1)_LIBS += $$(filter -%,$$($(1)_LDADD))
+$(ELSE)
+$(1)_OBJS += $$(filter-out -%,$$($(1)_LIBADD))
+$(1)_LIBS += $$(filter -%,$$($(1)_LIBADD))
+$(ENDIF)
+
+# embed libusual objects directly
+$(IFEQ) ($$($(1)_EMBED_LIBUSUAL),1)
+$(1)_USUAL_SRCS = $$(call UsualSources,$$($(1)_ALLSRCS))
+$(1)_OBJS += $$(call UsualObjs,$(1),$$($(1)_SOURCES) $$(nodist_$(1)_SOURCES))
+$(1)_CPPFLAGS += -I$$(USUAL_DIR)
+$(IFEQ) ($$(filter $$(USUAL_DIR),$(VPATH)),)
+VPATH += $$(USUAL_DIR)
+$(ENDIF)
+$(ENDIF)
+
+# autodetect linker, unless given
+$(IFEQ) ($($(1)_LINK),)
+$(1)_LINKVAR := $$(call DetectLinkVar,$$($(1)_ALLSRCS))
+$(ELSE)
+$(1)_LINKVAR := $(1)_LINK
+$(ENDIF)
+
+# calculate target file name
+$(IFEQ) ($(3)$($(1)_EXT),PROGRAMS)
+$(1)_FINAL = $(2)$$(EXEEXT)
+$(ELSE)
+$(1)_FINAL = $(2)$$($(1)_EXT)
+$(ENDIF)
+
+# hook libtool into LTLIBRARIES cleanup
+$(IFEQ) ($(3),LTLIBRARIES)
+$(1)_RM = $$(LTCLEAN) $$(RM)
+$(ELSE)
+$(1)_RM = $$(RM)
+$(ENDIF)
+
+# fix includes in case of separate build dir
+$(1)_CPPFLAGS := $$(call FixIncludes,$$(srcdir),$$($(1)_CPPFLAGS))
+$(1)_CFLAGS := $$(call FixIncludes,$$(srcdir),$$($(1)_CFLAGS))
+
+# load dependencies
+-include .dummy. $$(call DepFiles, $$($(1)_OBJS))
+
+# actual build, clean & install targets
+.PHONY: build_$(1) clean_$(1)
+
+# allow target-specific variables
+$$(call VarOverride,$(1))
+
+# build by default, unless EXTRA_foo
+$(IFNEQ) ($(4),EXTRA)
+all: build_$(1)
+$(ENDIF)
+
+build_$(1): $$($(1)_SOURCES) $$(nodist_$(1)_SOURCES)
+build_$(1): $$($(1)_DEPENDENCIES)
+build_$(1): $$($(1)_FINAL)
+$$($(1)_FINAL): $$($(1)_OBJS)
+       @$$(MKDIR_P) $$(dir $$@)
+       $$($(if $(filter LIBRARIES,$(3)),ar_lib,$$($(1)_LINKVAR)))
+
+clean: clean_$(1)
+clean_$(1):
+       $$(E) "CLEAN" "$$($(1)_FINAL)"
+       $$(Q) $$($(1)_RM) -- $$($(1)_OBJS) $(if $(call TargetNoDist,$(3),$(5)),$$($(1)_FINAL))
+
+DISTCLEANFILES += $$(nodist_$(1)_SOURCES) $$(nodist_EXTRA_$(1)_SOURCES)
+
+$(foreach lang,$(AM_LANGUAGES),$(call LangSetup,$(1),$(lang)))
+
+endef
+
+# 1=cleantgt,2=rawtgt,3=prim,4=dest,5=flags
+define BigTargetDist
+am_DISTFILES += $$(filter-out $$(nodist_EXTRA_$(1)_SOURCES) $$(nodist_$(1)_SOURCES),$$($(1)_SOURCES) \
+            $$(EXTRA_$(1)_SOURCES)) $(if $(call TargetNoDist,$(3),$(5)),,$$($(1)_FINAL))
+endef
+
+# 1=cleantgt,2=rawtgt,3=prim,4=dest,5=flags
+define MakeBigTarget
+$(trace5)
+
+# build if first time
+$(IFEQ) ($(filter $(1),$(AM_ALL_TARGETS)),)
+$(call BigTargetBuild,$(1),$(2),$(3),$(4),$(5))
+$(call BigTargetDist,$(1),$(2),$(3),$(4),$(5))
+$(ELSE)
+# allow only EXTRA be double
+$(IFNEQ) ($(4),EXTRA)
+$$(error Target '$2' described listed several times)
+$(ENDIF)
+$(ENDIF)
+
+# call InstallTarget, for dest != (EXTRA, noinst)
+$(IFEQ) ($(filter EXTRA noinst,$(4)),)
+$(call InstallTarget,$(1),$$($(1)_FINAL),$(3),$(4),$(5))
+$(ENDIF)
+
+endef
+
+
+##
+## Rules for small target
+##
+
+# 1=cleantgt,2=rawtgt,3=prim,4=dest,5=flags
+define MakeSmallTarget
+$(trace5)
+AM_ALL_TARGETS += $(1)
+
+# should the target file be distributed or cleaned?
+$(IFEQ) ($(call TargetNoDist,$(3),$(5)),)
+am_DISTFILES += $(2)
+$(ELSE)
+CLEANFILES += $(2)
+$(ENDIF)
+
+# build if not EXTRA
+$(IFNEQ) ($(4),EXTRA)
+all: $(2)
+# install if not EXTRA or noinst
+$(IFNEQ) ($(4),noinst)
+$(call InstallTarget,$(1),$(2),$(3),$(4),$(5))
+$(ENDIF)
+$(ENDIF)
+
+endef
+
+
+##
+## Fill GNU-style vars for subdir
+##
+
+# preferred to top_srcdir/top_builddir
+topdir = $(top_builddir)
+
+ifneq ($(nosub_top_builddir),.)
+$(error Non-local builddir not supported)
+endif
+
+# initial locaton vars
+$(eval $(call SetDirs,$(SUBLOC)))
+
+ifneq ($(nosub_top_srcdir),$(nosub_top_builddir))
+# use VPATH to find non-local sources
+VPATH += $(srcdir)
+# fix includes
+AM_CPPFLAGS := $(call FixIncludes,$(srcdir),$(AM_CPPFLAGS))
+AM_CFLAGS := $(call FixIncludes,$(srcdir),$(AM_CFLAGS))
+endif
+
+
+##
+## Actual rules start
+##
+
+# if output is redirected, prepare target dir and launch submake
+
+ifneq ($(O),)
+
+ABS_DST := $(call JoinPath,$(CURDIR),$(O))
+.PHONY: $(MAKECMDGOALS)
+
+all $(filter-out all,$(MAKECMDGOALS)):
+       @test -d $(O) || { echo "Directory $(O) does not exist"; exit 1; }
+       @for mk in $(filter-out /%,$(MAKEFILE_LIST)); do \
+           if ! test -f $(O)/$${mk}; then \
+               printf '%s\n%s\n%s\n%s\n%s\n' \
+               'abs_top_srcdir = $(CURDIR)' \
+               'abs_top_builddir = $(ABS_DST)' \
+               'nosub_top_srcdir = $(call UpDir,$(O))' \
+               'nosub_top_builddir = .' \
+               'include $$(abs_top_srcdir)/'"$${mk}" \
+               > $(O)/$${mk}; \
+           fi; \
+       done
+       $(Q) $(MAKE) O= -C $(O) $(MAKECMDGOALS)
+
+# O=empty, this is main makefile
+else
+
+##
+## main targets, tie them with subdir and local targets
+##
+
+# disable random rules
+.SUFFIXES:
+
+all: sub-all all-local
+clean: sub-clean clean-local
+install: sub-install install-local
+distclean: sub-distclean distclean-local
+maintainer-clean: sub-maintainer-clean maintainer-clean-local
+.PHONY: all clean install dist distclean maintainer-clean
+
+# -local are empty targets by default
+.PHONY: all-local clean-local install-local distclean-local maintainer-clean-local
+all-local clean-local install-local distclean-local maintainer-clean-local:
+
+##
+## Actual embedding starts
+##
+
+AM_ALL_TLISTS2 = $(filter $(addprefix %,$(AM_PRIMARIES)),$(.VARIABLES))
+AM_ALL_TLISTS = $(call ForEachList,CheckName,$(AM_ALL_TLISTS2))
+
+am_srcdir := $(srcdir)
+am_DIR := .
+am_PFX :=
+am_TARGETLISTS :=
+am_EXTRA_TARGETLISTS :=
+am_TOP_NAMES :=
+
+# move top-level targets away
+$(eval $(call ForEachList,RelocTList,$(AM_ALL_TLISTS)))
+
+am_SUBDIRS := $(SUBDIRS)
+am_DIST_SUBDIRS := $(DIST_SUBDIRS)
+am_DISTFILES := $(EXTRA_DIST)
+am_CLEANFILES := $(CLEANFILES)
+am_DISTCLEANFILES := $(DISTCLEANFILES)
+am_MAINTAINERCLEANFILES := $(MAINTAINERCLEANFILES)
+am_EMBED_NOW := $(EMBED_SUBDIRS)
+am_EMBED_DONE :=
+am_EMBED_TODO :=
+EXTRA_DIST =
+CLEANFILES =
+DISTCLEANFILES =
+MAINTAINERCLEANFILES =
+SUBDIRS =
+DIST_SUBDIRS =
+EMBED_SUBDIRS =
+
+$(foreach dir,$(am_EMBED_NOW),$(call DoEmbed,$(dir)))
+am_EMBED_NOW := $(am_EMBED_TODO)
+am_EMBED_TODO :=
+
+$(foreach dir,$(am_EMBED_NOW),$(call DoEmbed,$(dir)))
+am_EMBED_NOW := $(am_EMBED_TODO)
+am_EMBED_TODO :=
+
+$(foreach dir,$(am_EMBED_NOW),$(call DoEmbed,$(dir)))
+am_EMBED_NOW := $(am_EMBED_TODO)
+am_EMBED_TODO :=
+$(if $(am_EMBED_NOW),$(error EMBED_SUBDIRS recursion limit reached...))
+
+# embedding done, move variables back
+
+$(eval $(call SetDirs,$(SUBLOC)))
+CLEANFILES := $(am_CLEANFILES)
+DISTCLEANFILES := $(am_DISTCLEANFILES)
+MAINTAINERCLEANFILES := $(am_MAINTAINERCLEANFILES)
+SUBDIRS := $(am_SUBDIRS)
+DIST_SUBDIRS := $(am_DIST_SUBDIRS)
+EMBED_SUBDIRS := $(am_EMBED_DONE)
+am_CLEANFILES =
+am_DISTCLEANFILES =
+am_MAINTAINERCLEANFILES =
+am_DIST_SUBDIRS =
+am_SUBDIRS =
+am_EMBED_DONE =
+
+am_TARGETLISTS := $(sort $(am_TARGETLISTS))
+am_EXTRA_TARGETLISTS := $(sort $(am_EXTRA_TARGETLISTS))
+
+# allow seeing moved lists
+AM_FLAGS += real
+
+## EMBED_SUBDIRS end
+
+##
+## clean targets
+##
+
+
+clean:
+ifdef CLEANFILES
+       $(E) "CLEAN" $@
+       $(Q) $(RM) -- $(CLEANFILES)
+endif
+
+distclean: clean
+       $(E) "DISTCLEAN" $@
+       $(Q) $(RM) -r -- $(OBJDIR)
+ifdef DISTCLEANFILES
+       $(Q) $(RM) -- $(DISTCLEANFILES)
+endif
+
+maintainer-clean: clean
+       $(E) "MAINTAINERCLEAN" $@
+       $(Q) $(RM) -r -- $(OBJDIR)
+ifdef DISTCLEANFILES
+       $(Q) $(RM) -- $(DISTCLEANFILES)
+endif
+ifdef MAINTAINERCLEANFILES
+       $(Q) $(RM) -- $(MAINTAINERCLEANFILES)
+endif
+
+
+##
+## actual subdir targets
+##
+
+# 1-dir
+define MakeSubDir
+       $(trace1)
+       $(E) "MKDIR" "Create $(call JoinPath,$(SUBLOC),$(1))"
+       $(Q) @$(MKDIR_P) $(1)
+       $(Q) @echo "include $(call UpDir,$(1))/$(srcdir)/$(1)/Makefile" > $(1)/Makefile
+endef
+
+# 1-dir, 2-tgt
+define SubTarget
+       $(trace2)
+       $(if $(wildcard $(1)/Makefile),,$(call MakeSubDir,$(1)))
+       $(E) "-->" "$(call JoinPath,$(SUBLOC),$(1))"
+       $(Q) $(MAKE) -C $(1) $(2)
+       $(E) "<--" "$(call JoinPath,$(SUBLOC),$(1))"
+endef
+
+sub-all sub-install sub-clean:
+       $(foreach dir,$(SUBDIRS),$(call SubTarget,$(dir),$(subst sub-,,$@))$(NewLine))
+
+# Avoid double dirs in DIST_SUBDIRS, without changing order
+am_DISTDIRS = $(SUBDIRS) $(foreach dir,$(DIST_SUBDIRS),$(if $(filter $(dir),$(SUBDIRS)),,$(dir)))
+
+sub-dist sub-distclean sub-maintainer-clean:
+       $(foreach dir,$(am_DISTDIRS),$(call SubTarget,$(dir),$(subst sub-,,$@))$(NewLine))
+.PHONY: sub-all sub-clean sub-install sub-dist sub-distclean sub-maintainer-clean
+
+
+##
+## actual dist targets
+##
+
+DistTarget = $(foreach fmt,$(1),dist-$(fmt))
+
+AM_DIST_ALL ?= gzip bzip2 xz zip
+
+AM_DIST_ALL_TGTS = $(call DistTarget,$(AM_DIST_ALL))
+AM_DIST_DEF_TGTS = $(call DistTarget,$(AM_DIST_DEFAULT))
+
+AM_FORMAT_gzip_EXT = tar.gz
+AM_FORMAT_gzip_CMD = tar chof - $(AM_DIST_BASE) | gzip > $(AM_DIST_BASE).$(AM_FORMAT_gzip_EXT)
+AM_FORMAT_bzip2_EXT = tar.bz2
+AM_FORMAT_bzip2_CMD = tar chof - $(AM_DIST_BASE) | bzip2 > $(AM_DIST_BASE).$(AM_FORMAT_bzip2_EXT)
+AM_FORMAT_xz_EXT = tar.xz
+AM_FORMAT_xz_CMD = tar chof - $(AM_DIST_BASE) | xz > $(AM_DIST_BASE).$(AM_FORMAT_xz_EXT)
+AM_FORMAT_zip_EXT = zip
+AM_FORMAT_zip_CMD = zip -rq $(AM_DIST_BASE).$(AM_FORMAT_zip_EXT) $(AM_DIST_BASE)
+
+# 1-name
+define MakeDist
+       $(E) "CHECK" $@
+       $(Q) $(MAKE) -s am-check-distfiles
+       $(E) "MKDIR" $(AM_DIST_BASE)
+       $(Q) $(RM) -r -- $(AM_DIST_BASE) $(AM_DIST_BASE).$(AM_DIST_$(1)_EXT)
+       $(Q) $(MKDIR_P) $(AM_DIST_BASE)
+       $(E) "COPY" $(AM_DIST_BASE)
+       $(Q) $(MAKE) -s am-show-distfiles | cpio -pmdL --quiet $(AM_DIST_BASE)
+       $(E) "PACK" $(AM_DIST_BASE).$(AM_FORMAT_$(1)_EXT)
+       $(Q) $(AM_FORMAT_$(1)_CMD)
+       $(Q) $(RM) -r -- $(AM_DIST_BASE)
+endef
+
+.PHONY: dist $(AM_DIST_ALL_TGTS)
+dist: $(AM_DIST_DEF_TGTS)
+dist-all: $(AM_DIST_ALL_TGTS)
+$(AM_DIST_ALL_TGTS):
+       $(call MakeDist,$(subst dist-,,$@))
+
+# show list of files that need to be in final archive
+.PHONY: am-show-distfiles
+am-show-distfiles:
+       $(foreach dir,$(am_DISTDIRS),@$(MAKE) $(AM_MAKEFLAGS) --no-print-directory -C $(dir) $@ $(NewLine))
+       $(foreach file,$(am_FINAL_DISTFILES),@echo "$(call JoinPath,$(SUBLOC),$(file))" $(NewLine))
+
+# do dependencies as separate step, in case building outputs anything
+.PHONY: am-check-distfiles
+am-make-distfiles: $(am_FINAL_DISTFILES)
+       $(foreach dir,$(am_DISTDIRS),@$(MAKE) $(AM_MAKEFLAGS) -C $(dir) $@ $(NewLine))
+
+##
+## Now generate the rules
+##
+
+## check which target func to call
+# 1=cleantgt,2=rawtgt,3=prim,4=dest,5=flags
+MakeTarget = $(call $(if $(filter $(AM_BIG_PRIMARIES),$(3)),MakeBigTarget,MakeSmallTarget),$(1),$(2),$(3),$(4),$(5))
+
+## process all targets in one list
+# 1-list, 2-prim,3-dest,4-flags
+MakeTargetList = $(foreach tgt,$($(1)),$(call MakeTarget,$(call CleanName,$(tgt)),$(tgt),$(2),$(3),$(4)))
+
+## process all target lists
+# 1=list names
+ProcessTargets = $(call ForEachTarget,MakeTarget,$(1))
+
+# process non-EXTRA targets
+$(eval $(call ProcessTargets,$(am_TARGETLISTS)))
+
+# process EXTRA_* last, they may already have been processed
+$(eval $(call ProcessTargets,$(am_EXTRA_TARGETLISTS)))
+
+##
+## debug target
+##
+
+# 1=var
+define AmDebugShow
+$(if $($(1)),@echo '$(1) = $($(1))')
+$(NewLine)
+endef
+
+# 1=cleantgt,2=rawtgt,3=prim,4=dest,5=flags
+define AmDebugTarget
+$(trace5)
+$(foreach var,$(AM_DEBUG_TARGET_VARS),$(call AmDebugShow,$(1)_$(var)))
+@echo ""
+endef
+
+# func args: 1-var, 2-prim, 3-dest, 4-flags
+CollectDests = $(filter-out noinst EXTRA,$(3))
+AM_USED_DESTS = $(sort $(call ForEachList,CollectDests,$(am_TARGETLISTS)))
+
+AM_DEBUG_VARS = GNUMAKE380 GNUMAKE381 GNUMAKE382 MAKEFILE_LIST \
+               AM_LANGUAGES AM_FLAGS AM_DESTINATIONS \
+               AM_ALL_TARGETS EXEEXT am_FINAL_DISTFILES \
+               nosub_top_builddir nosub_top_srcdir \
+               abs_top_srcdir abs_top_builddir \
+               srcdir builddir top_srcdir top_builddir \
+               SUBDIRS EMBED_SUBDIRS DIST_SUBDIRS \
+               DISTFILES CLEANFILES DISTCLEANFILES MAINTAINERCLEANFILES
+AM_DEBUG_TARGET_VARS = SOURCES OBJS LINKVAR DEST USUAL_OBJS USUAL_SRCS EXT FINAL \
+                      $(AM_TARGET_VARIABLES)
+AM_DEBUG_LANG_VARS = SRCEXTS
+am-debug:
+       @echo ""; echo "==== Global Variables ===="
+       $(foreach var,$(AM_DEBUG_VARS),$(call AmDebugShow,$(var)))
+       @echo ""; echo "==== Per-language Variables ===="
+       $(foreach lg,$(AM_LANGUAGES),$(foreach var,$(AM_DEBUG_LANG_VARS),$(call AmDebugShow,AM_LANG_$(lg)_$(var))))
+       @echo ""; echo "==== Per-target Variables ===="
+       $(call ForEachTarget,AmDebugTarget,$(am_TARGETLISTS) $(am_EXTRA_TARGETLISTS))
+       @echo ""; echo "==== Active install directories ===="
+       $(foreach dst,$(AM_USED_DESTS),@echo '  $(dst)dir = $($(dst)dir)'$(NewLine))
+
+
+##
+## regtests for basic tools
+##
+
+AM_TESTS = 1 2 3 4 5 6 7 8 9 10 11 12 13 14
+AM_TEST_1 = $(call Eq,a b c,a b c),$(call Eq,,),$(call Eq,a,aa),$(call Eq,a,a a)
+AM_TEST_1_RES = true,true,,
+AM_TEST_2 = $(call Neq,a,aa),$(call Neq,a,a)
+AM_TEST_2_RES = true,
+AM_TEST_3 = $(call CleanName,obj/foo-baz.x)
+AM_TEST_3_RES = obj_foo_baz_x
+AM_TEST_4 = $(call LastWord,a),$(call LastWord,a b c),$(call LastWord,)
+AM_TEST_4_RES = a,c,
+AM_TEST_5 = $(call ReplaceExts,.c .cpp X.foo,.o,s1.c s2.cpp s3X.foo s4.h)
+AM_TEST_5_RES = s1.o s2.o s3.o
+AM_TEST_5 = $(call LangList,foo.c c.foo),$(call LangList,foo.c c.foo f.cpp)
+AM_TEST_5_RES = C,C CXX
+AM_TEST_6 = $(call DetectLinkVar,foo.c c.foo),$(call DetectLinkVar,foo.c c.foo x.cpp),$(call DetectLinkVar,foo),$(call DetectLinkVar,)
+AM_TEST_6_RES = AM_LANG_C_LINK,AM_LANG_CXX_LINK,AM_LANG_C_LINK,AM_LANG_C_LINK
+AM_TEST_7 = $(call UpDir,foo)|$(call UpDir,)|$(call UpDir,.)|$(call UpDir,foo/bar)|$(call UpDir,a/b/c)|
+AM_TEST_7_RES = ..|.|.|../..|../../..|
+AM_TEST_8 = $(call JoinPath,.,.)|$(call JoinPath,,)|$(call JoinPath,a,.)|$(call JoinPath,.,b)|$(call JoinPath,a,b)
+AM_TEST_8_RES = .||a|b|a/b
+define AM_TEST_9_EVAL
+$(IFEQ) ($$(AM_TEST_9_RES),OK)
+AM_TEST_9 = OK
+$(ELSE)
+AM_TEST_9 = fail
+$(ENDIF)
+endef
+AM_TEST_9_RES = OK
+$(eval $(AM_TEST_9_EVAL))
+AM_TEST_10 = $(call CheckName,nobase_bin_PROGRAMS,PROGRAMS,bin,nobase)|$(call CheckName,a,a,,)|$(call CheckName,bin_bin_DATA,,bin bin,DATA)
+AM_TEST_10_RES = nobase_bin_PROGRAMS|a|
+AM_TEST_11_Show = $(4)-$(3)-$(2)
+AM_TEST_11 = $(call ForEachList,AM_TEST_11_Show,bin_PROGRAMS foo_DATA baz_foo base_nobase_dist_nodist_DATA_PROGRAMS)
+AM_TEST_11_RES = -bin-PROGRAMS --DATA -- base nobase dist nodist--DATA PROGRAMS
+AM_TEST_12 = $(call RelocFlags,sub/dir,-I. -I./foo -Lfoo/bar -I/inc -L/lib -lfoo obj.o ../mod.a /lib/c.a)
+AM_TEST_12_RES = -Isub/dir -Isub/dir/./foo -Lsub/dir/foo/bar -I/inc -L/lib -lfoo sub/dir/obj.o sub/dir/../mod.a /lib/c.a
+AM_TEST_13 = $(call TargetNoDist,HEADERS,)|$(call TargetNoDist,HEADERS,nodist)|$(call TargetNoDist,PROGRAMS,)|$(call TargetNoDist,PROGRAMS,dist)
+AM_TEST_13_RES = |true|PROGRAMS|
+AM_TEST_14 = $(call ShellQuote,foo'bar\')|$(call ShellQuote,as!d' \\ $$foo)
+AM_TEST_14_RES = 'foo'\''bar\'\'''|'as!d'\'' \\ $$foo'
+
+AmTest = $(if $(call Eq,$($(1)),$($(2))),@echo '$(1): OK',@echo '$(1): FAIL: $($(1)) != $($(2))')$(NewLine)
+am-test:
+       $(Q) test "$(call Eq,a b c,a b c),$(call Eq,,),$(call Eq,a,aa),$(call Eq,a,a a)" = "true,true,,"
+       $(foreach nr,$(AM_TESTS),$(call AmTest,AM_TEST_$(nr),AM_TEST_$(nr)_RES))
+
+##
+## help target
+##
+
+AmHelpNames = targets standalone internal config dests
+.PHONY: help $(foreach n,$(AmHelpNames),help-$(n) help-$(n)-local)
+$(foreach n,$(AmHelpNames),help-$(n)-local):
+help: $(foreach n,$(AmHelpNames),help-$(n) help-$(n)-local)
+
+# 1-var, 2-desc
+AmConf = @printf '  %-27s  %s=%s\n' $(call ShellQuote,$(2)) $(call ShellQuote,$(1)) $(call ShellQuote,$($(1)))
+
+help-targets:
+       @echo ""
+       @echo "Main targets:"
+       @echo "  all                Build all targets (default)"
+       @echo "  install            Install files"
+       @echo "  dist               Create source archive"
+       @echo "  clean              Clean built files"
+       @echo "  distclean          Clean configured files"
+       @echo "  maintainer-clean   Delete anything that can be generated"
+
+help-standalone:
+       @echo ""
+       @echo "Standalone targets:   (make -f antimake.mk)"
+       @echo "  show-location      Prints full path to antimake.mk (default)"
+       @echo "  show-config        Prints template config.mak.in"
+
+help-internal:
+       @echo ""
+       @echo "Internal targets:"
+       @echo "  am-show-distfiles  Shows files that go into source archive"
+       @echo "  am-debug           Shows variables that affect the build"
+       @echo "  am-test            Regtest for internal functions"
+
+help-config:
+       @echo ""
+       @echo "Config variables and their current values:"
+       $(call AmConf,CC,C compiler)
+       $(call AmConf,CFLAGS,C compiler flags)
+       $(call AmConf,CPPFLAGS,C pre-processor flags)
+       $(call AmConf,LDFLAGS,Linker flags)
+
+help-dests:
+       @echo ""
+       @echo "Destinations for install [ prefix=$(prefix) ]:"
+       $(foreach dst,$(AM_USED_DESTS),@echo '  $(dst)dir = $($(dst)dir)'$(NewLine))
+
+endif # O=empty
+
diff --git a/mk/antimake.txt b/mk/antimake.txt
new file mode 100644 (file)
index 0000000..d161975
--- /dev/null
@@ -0,0 +1,458 @@
+= antimake.mk(5) =
+
+== NAME ==
+
+antimake - Minimal Automake syntax on plain GNU Make
+
+== DESCRIPTION ==
+
+Antimake makes possible to use GNU Automake conventions
+to describe builds in ordinary Makefiles for GNU Make.
+
+It's main abstractions are target lists and target variables.
+Target list describes target type and where to install.
+Target variables give source files and additional flags for build.
+
+== EXAMPLE ==
+
+-------------------
+# target list
+bin_PROGRAMS = prog
+
+# target variables for 'prog'
+prog_SOURCES = prog.c prog.h
+prog_LDADD = libutil.a
+
+# target list
+noinst_LIBRARIES = libutil.a
+
+# target variables for 'libutil.a'
+libutil_a_SOURCES = util.c util.h
+
+# load Antimake
+include antimake.mk
+-------------------
+
+== Terminology ==
+
+Primary::
+  target type, describes how to build and install particular type of targets.
+
+Target::
+  a file that needs to be built and/or installed.
+
+Distribute::
+  Include file in source .tar.gz.  Non-distributed files are skipped
+  when building .tar.gz and are cleaned during `make distclean`.
+
+Source::
+  Source files are files that appear in `..._SOURCES` per-target variable.
+  They are distributed by default.  They may or may not result in object files.
+  It's fine to put both `.h` and `.c` files into _SOURCES.
+
+== TARGET LISTS ==
+
+Target lists are variables that contain file names that need to be
+built and installed.  They are specially named so that the name also describes how they
+are built, how and where they will be installed.
+
+The target list name contains 3 parts, separated with underscore, in following order:
+
+1. Optional flags.  Flags are: `nodist`, `dist`, `nobase`, `base`.  (Default: `base`, `nodist`)
+2. Destination directory name.  Destination directory called *bin* actual
+   location is stored in Make variable `$(bindir)`.  Some common values:
+   `bin`, `lib`, `include`.   There are more and the list can be extended.
+   Special name `noinst` means the target file should not be installed.
+3. Target type, also called "primary".   This will describe how the target
+   needs to be built.  Common values: `PROGRAMS`, `LIBRARIES`, `DATA`
+
+For details, what the various values mean, see next sections.
+
+.Examples:
+----------------
+bin_PROGRAMS = prog1 prog2
+# flags: base, nodist
+# dest: $(bindir)
+# type: PROGRAMS
+
+noinst_LIBRARIES = lib1.a lib2.a
+# flags: base, nodist
+# dest: noinst
+# type: LIBRARIES
+
+nobase_dist_doc_DATA = docs/README
+# flags: dist, nobase
+# dest: $(docdir)/docs
+# type: DATA
+----------------
+
+=== Primaries ===
+
+`PROGRAMS`::
+  executable programs, linked together from objects built from source files
+
+`LIBARIES`::
+  static libraries, linked together from objects built from source files
+
+`LTLIBRARIES`::
+  dynamic or static libraries, linked together from objects built from source files
+
+`HEADERS`::
+  header files, no default build method, the target files have `dist` flag by default.
+
+`MANS`::
+  man pages, no default build method, installed into manX subdir.
+
+`SCRIPTS`::
+  scripts, executable file, no default build method
+
+`DATA`::
+  data, non-executable file, no default build method
+
+=== Target list flags ===
+
+`dist`::
+  The target should be distributed with other sources.
+  Default for `HEADERS` type, others have `nodist` by default.
+
+`nodist`::
+  Target is not distributed and should be cleaned with distclean.
+  Default for all primaries, except `HEADERS`.
+
+`base`::
+  On install relative path is ignored, all files
+  end up in destination directory.  Always default.
+
+`nobase`::
+  On install relative path is kept.  Eg: if `includedir=/usr/include`
+  then `nobase_include_HEADERS=mylib/common.h`
+  is installed to `/usr/include/mylib/common.h`.
+
+`noinst`::
+  Target is built as part of build process, but is not installed.
+
+`EXTRA`::
+  Targets in such list are not built, nor installed.
+  Useful to make sure that sources for dynamically configured targets
+  will end up in source tarball.  Unlike other target list ariables,
+  `EXTRA_<primary>` may contain targets already defined in other
+  target lists, they will be filtered out from this list then.
+
+== Target variables ==
+
+Only big targets take additional variables: `PROGRAMS`/`LIBRARIES`/`LTLIBRARIES`.
+
+`<tgt>_SOURCES`::
+    All source files, *.c *.h *.cpp *.hpp.
+
+`nodist_<tgt>_SOURCES`::
+    Source files that should not be distributed.
+
+`EXTRA_<tgt>_SOURCES`::
+    In case tgt_SOURCES is dynamic, here is non-dynamic
+    list of sources for distribution.  Only dynamic sources
+    need to be listed here.
+
+`<tgt>_DEPENDENCIES`::
+    Add dependencies that need to be build before target build will start.
+
+`<tgt>_CFLAGS`, `<tgt>_CPPFLAGS`, `<tgt>_LDFLAGS`, `<tgt>_LIBTOOLFLAGS`::
+    Override corresponging AM_xx variable
+
+`<tgt>_LDADD`::
+    Add dependencies that are used during linking.
+    For PROGRAMS only.
+    They will be added to linker command line.
+
+`<tgt>_LIBADD`::
+    Add dependencies that are used during linking.
+    For LIBRARIES/LTLIBRARIES only.
+    They will be added to linker command line.
+
+`<tgt>_AR`::
+    Overrides $(AR) $(ARFLAGS).
+    For LIBRARIES only.
+
+.Example:
+-------------------
+bin_PROGRAMS = prog
+prog_SOURCE = main.c util.c util.h
+prog_CFLAGS = $(GTK_CFLAGS)
+prog_LDADD = $(GTK_LIBS)
+-------------------
+
+
+== Global variables ==
+
+They can be set before `antimake.mk` inclusion to change
+build behaviour.
+
+EXTRA_DIST::
+       Additional files to include in source archive.
+
+CLEANFILES::
+       Additional files to `make clean`.
+
+DISTCLEANFILES::
+       Additional files to `make distclean`.
+
+MAINTAINERCLEANFILES::
+       Additional files to `make maintainer-clean`.
+
+SUBDIRS::
+       Subdirectories of current directory where Make
+       needs to be recursively launched.  If subdirectory
+       `Makefile` is Antimake-base, it should set `SUBLOC`.
+
+SUBLOC::
+       Current diretory location in overall source tree.
+       This can stay unset in top directory.  Needed for
+       subdirectiories entered with `SUBDIRS` to find
+       its position in source tree.
+
+DIST_SUBDIRS::
+       Subdirs that only `make dist`, `make distclean` and `make maintainer-clean`
+       will enter.
+
+EMBED_SUBDIRS::
+       Subdirectories that are built non-recursively: they need to contain `Makefile.am`
+       that contains makefile-fragment with Antimake syntax
+       that describes local targets using relative filenames.
+       The fragment is included in main makefile and file
+       and variable names are converted and merged with top-level targets.
+
+USUAL_DIR::
+       Location of libusual tree, used for embedding libusual
+       sources.
+
+=== More details on EMBED_SUBDIRS ===
+
+It acts like `include $(dir)/Makefile.am` for each directory, except it converts
+file and variable names.  Example:
+
+---------------------
+Makefile:
+  EMBED_SUBDIRS = src
+
+src/Makefile.am:
+  bin_PROGRAMS = hello
+  hello_SOURCES = main.c
+  hello_CPPFLAGS = -I./include
+---------------------
+
+Conversion results as if top-level `Makefile` had contained following rows:
+
+----------------------
+bin_PROGRAMS += src/hello
+src_hello_SOURCES = src/main.c
+src_hello_CPPFLAGS = -I./src/include
+----------------------
+
+
+=== Global variables for current location ===
+
+* srcdir, builddir - relative path to source dir and build dir.
+* top_srcdir, top_builddir - relative path to top-level source and build dir.
+* abs_srcdir, abs_builddir - absolute path to source and build dir
+* abs_top_srcdir, abs_top_builddir - absolute path to top-level source and build dir
+* nosub_top_srcdir, nosub_top_builddir - relative path from top of builddir to srcdir and builddir.
+
+=== Global variables that target can override ===
+
+- AM_CPPFLAGS
+- AM_CFLAGS
+- AM_LDFLAGS
+- AM_LIBTOOLFLAGS
+- AM_DEFS
+- AM_MAKEFLAGS
+
+=== Global variables from autoconf ===
+
+These variables come usually from autoconf,
+but also have reasonable defaults:
+
+  CC, DEFS, CPPFLAGS, CFLAGS, LDFLAGS, LIBS,
+  LIBTOOL, LIBTOOLFLAGS, AR, ARFLAGS, RANLIB,
+  CXX, CXXFLAGS, INSTALL, MKDIR_P, LN_S
+
+=== Global variables for extending Antimake ===
+
+AM_DIST_DEFAULT::
+       Default format(s) for `make dist` target.  One or more of:
+       `gzip`, `bzip2`, `xz`, `zip`.  Default: `gzip`.
+
+
+AM_DESTINATIONS::
+       Additional directory names to consider as valid
+       destinations.  Expects corresponding `dir`-variable to be set.
+
+AM_SMALL_PRIMARIES::
+       Additional single-file primaries.  (Builtin: HEADERS, SCRIPTS, DATA, MANS)
+
+AM_BIG_PRIMARIES::
+       Additional primaries built from objects.  (Builtin: PROGRAMS, LIBRARIES, LTLIBRARIES)
+
+AM_LANGUAGES::
+       Additional language names.  Antimake expects variables
+       `AM_LANG_$(name)_SRCEXTS`, `AM_LANG_$(name)_COMPILE` and
+       `AM_LANG_$(name)_LINK` to be set.
+
+
+=== Variables for command-line usage ===
+
+DESTDIR::
+       Relocate installation root.
+
+AM_TRACE::
+       Turns on function-call debug info.  Can be set from command-line.
+
+=== Hacking variables ===
+
+GNUMAKE380, GNUMAKE381, GNUMAKE382::
+       If we have at least that version of GNU Make.  GNUMAKE380 is always
+       set, others may not be.  If Makefile uses features from newer GNU Make
+       it would be good idea to use those flags and error out with clear
+       error message, instead having mysterious failures.
+
+=== Libtool flags ===
+
+Useful http://www.gnu.org/software/libtool/manual/html_node/Link-mode.html[Libtool]
+flags that can be put int tgt_LDFLAGS for a LTLIBRARY:
+
+* -export-dynamic
+* -export-symbols symfile
+* -export-symbols-regex regex
+* -module
+
+See libtool http://www.gnu.org/software/libtool/manual/html_node/Versioning.html["Versioning"] chapter about those:
+
+* -avoid-version
+* -version-info  current[:revision[:age]]
+* -version-number major[:minor[:revision]]
+* -release major[:minor[:revision]]
+
+
+== Top-level pseudo-targets ==
+
+=== all ===
+
+The default target when no other target is given on command-line.  Builds all target files.
+
+==== Simple targets ====
+
+These are simple - either the file already exists,
+or the user needs to give build command.
+
+==== Object-based targets ====
+
+The targets in primaries PROGRAMS, LIBRARIES and LTLIBRARIES consist of multiple source
+files that need to be compiled into objects.  Then the objects need to be
+linked into final target.  The process is roughly following:
+
+. Dependencies are built (_LDADD, _LIBADD, _DEPENDENCIES).
+. Source list is filtered for extensions that can be compiled into object files,
+  object file list is created based on them.  The rest of files are used and
+  dependencies for target, but otherwise ignored.
+. Object files are built.
+. Linker is picked based on source files - as there can be files in multiple languages,
+  the most advanced language wins (the one that appears later in `AM_LANGUAGES`)
+. Final executable is linked.
+
+=== install ===
+
+Install all targets to their destination directories, which is mentioned
+in their target list variable name.  Eg.  `bin_PROGRAMS` will be installed
+to `$(bindir)`.   If destination is named `noinst`, it will not be installed.
+
+If the flag `nobase` is given, the relative filename is kept, otherwise
+basename is taken and it will appear directly under destination directory.
+
+.Example:
+------
+include_HEADERS = func1.h lib/func2.h
+# Files will end up in:
+#   $(includedir)/func1.h
+#   $(includedir)/func2.h
+
+nobase_include_HEADERS = func1.h lib/func2.h
+# Files will end up in:
+#   $(includedir)/func1.h
+#   $(includedir)/lib/func2.h
+------
+
+=== clean ===
+
+- Remove files in `$(CLEANFILES)`
+- Remove built objects.
+- Remove target files, unless they are marked as `dist`.
+  (Note: `HEADERS` primary is `dist` by default, all other are `nodist`)
+
+=== distclean ===
+
+- Remove files in `$(DISTCLEANFILES)`
+- Remove sources tagged with `nodist`.  All sources as `dist` by default.
+
+=== maintainer-clean ===
+
+- Remove files in `$(MAINTAINERCLEANFILES)`
+
+=== help ===
+
+Describe top-level targets.
+
+=== am-test ===
+
+Regression test for low-level Antimake functions.
+
+=== am-debug ===
+
+Show Antimake internal state.
+
+== FEATURES ==
+
+Done:
+
+- Big primaries: PROGRAMS, LIBRARIES, LTLIBRARIES
+- Small primaries: DATA, SCRIPTS, MANS, HEADERS
+- Flags: base nobase dist nodist noinst EXTRA
+- Target vars: SOURCES, CPPFLAGS, CFLAGS, LDFLAGS, LDADD/LIBADD
+- Separate build dir
+- Per-target objects
+- Languages: C, CXX
+- SUBDIRS, DIST_SUBDIRS
+- EMBED_SUBDIRS
+
+Todo:
+
+- Improve docs
+- Standardize and document how to extend
+- Deps with non-gcc?
+- Long if-s to support `O=` seems to break GNU Make 3.80.
+  Drop `O=` or drop 3.80?
+
+Probably out of scope:
+
+- `make uninstall`
+- `make distcheck`
+- `make dist` from separate build dir
+- `install-(exec|data)-hook` - based on dir not primary
+- Default file list for `EXTRA_DIST`.  (Problem: distclean / maintainer-clean)
+
+Definitely out of scope:
+
+- automake conditionals
+- automake extras (autoconf macros, ltdl)
+- automake nanny mode (gnu/gnits)
+
+== SEE ALSO ==
+
+GNU Make Reference: http://www.gnu.org/software/make/manual/make.html#Quick-Reference[]
+
+Recursive Make Considered Harmful: http://miller.emu.id.au/pmiller/books/rmch/[]
+
+Paul's Rules of Makefiles: http://make.mad-scientist.us/rules.html[]
+
+Small BSD-ish build system: https://webkeks.org/hg/buildsys/[]
+
+GNU Make Standard Library: http://sourceforge.net/projects/gmsl/[]
+