summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md283
-rw-r--r--build-aux/Makefile.each.head/00-dist.mk20
-rw-r--r--build-aux/Makefile.each.tail/10-std.mk53
-rw-r--r--build-aux/Makefile.each.tail/11-gnustuff.mk60
-rw-r--r--build-aux/Makefile.once.head/00-dist.mk44
-rw-r--r--build-aux/Makefile.once.head/00-gnuconf.mk160
-rw-r--r--build-aux/Makefile.once.head/00-write-ifchanged.mk1
-rw-r--r--build-aux/Makefile.once.head/10-std.mk39
-rw-r--r--build-aux/Makefile.once.head/11-gnustuff.mk34
-rw-r--r--build-aux/Makefile.once.tail/00-dist.mk27
-rw-r--r--build-aux/Makefile.once.tail/11-gnustuff.mk17
-rwxr-xr-xbuild-aux/write-ifchanged25
-rw-r--r--config.mk.in114
13 files changed, 877 insertions, 0 deletions
diff --git a/README.md b/README.md
new file mode 100644
index 0000000000..e7606eb817
--- /dev/null
+++ b/README.md
@@ -0,0 +1,283 @@
+Autothing
+=========
+
+Autothing is a set of Makefile fragments that you can `include` in
+your GNU Makefiles to provide two core things:
+
+ 1. Make it _easy_ to write non-recursive Makefiles. (search for the
+ paper "Recursive Make Considered Harmful")
+ 2. Provide boilerplate for standard features people expect to be
+ implemented in Makefiles.
+
+Between these two, it should largely obviate GNU Automake in your
+projects.
+
+The recommended including Autothing into your project is to add the
+autothing repository as a `git` remote, and merge the `core` branch,
+and whichever `mod-*` module branches you want into your project's
+branch.
+
+| module name | dependencies | description |
+|-------------+--------------+--------------------------------------------------------------------------------------------------|
+| at | | The core of Autothing |
+|-------------+--------------+--------------------------------------------------------------------------------------------------|
+| std | at | Provide .PHONY targets: all/build/install/uninstall/mostlyclean/clean/distclean/maintainer-clean |
+| dist | std | Provide .PHONY target: dist |
+| gnuconf | dist | Provide default values for user-variables from the GNU Coding Standards' Makefile Conventions |
+| gnustuff | gnuconf | Provide remaining stuff from the GNU Coding Standards' Makefile Conventions |
+
+Core (psuedo-module: at)
+------------------------
+
+As harmful as recursive make is, it's historically been difficult to
+to write non-recursive Makefiles. The goal of the core of Autothing
+is to make it easy.
+
+In each source directory, you write a `Makefile`, very similarly to if
+you were writing for plain GNU Make, with the form:
+
+ topoutdir ?= ...
+ topsrcdir ?= ...
+ include $(topsrcdir)/build-aux/Makefile.head.mk
+
+ # your makefile
+
+ include $(topsrcdir)/build-aux/Makefile.tail.mk
+
+| at.path | Use $(call at.path,FILENAME1 FILENAME2...) sanitize filenames that are not in the current Makefile's directory or its children |
+| at.nl | A newline, for convenience, since it is difficult to type a newline in GNU Make expressions |
+
+| at.dirlocal | Which variables to apply the namespacing mechanism to |
+| at.phony | Which targets to mark as .PHONY, and have automatic recursive dependencies |
+| at.subdirs | Which directories to consider as children of this one |
+| at.depdirs | Which directories are't subdirs, but may contain dependencies of targets in this directory |
+
+outdir
+srcdir
+
+Module: std
+-----------
+
+| Variable | Create Command | Delete Command | Description | Relative to |
+|---------------+----------------+-----------------------------+-----------------------------------+-------------|
+| std.src_files | emacs | rm -rf . | Files that the developer writes | srcdir |
+| std.gen_files | ??? | make maintainer-clean | Files the developer compiles | srcdir |
+| std.cfg_files | ./configure | make distclean | Users' compile-time configuration | outdir |
+| std.out_files | make all | make mostlyclean/make clean | Files the user compiles | outdir |
+| std.sys_files | make install | make uninstall | Files the user installs | DESTDIR |
+
+In addition, there are two more variables that control not how files
+are created, but how they are deleted:
+
+| Variable | Affected command | Description | Relative to |
+|-----------------+------------------+------------------------------------------------+-------------|
+| std.clean_files | make clean | A list of things to `rm` in addition to the | outdir |
+| | | files in `$(std.out_files)`. (Example: `*.o`) | |
+|-----------------+------------------+------------------------------------------------+-------------|
+| std.slow_files | make mostlyclean | A list of things that (as an exception) should | outdir |
+| | | _not_ be deleted. (otherwise, `mostlyclean` | |
+| | | is the same as `clean`) | |
+
+| Variable | Default | Description |
+|----------+----------+-------------|
+| DESTDIR | | |
+|----------+----------+-------------|
+| RM | rm -f | |
+| RMDIR_P | rmdir -p | |
+| TRUE | true | |
+
+Module: dist
+------------
+
+The `dist` module produces distribution tarballs
+
+| Variable | Default | Description |
+|--------------+------------+-------------|
+| dist.exts | .tar.gz | |
+| dist.pkgname | $(PACKAGE) | |
+| dist.version | $(VERSION) | |
+
+| Variable | Default | Description |
+|-----------+-------------+----------------------------------------------------|
+| CP | cp | |
+| GZIP | gzip | |
+| MKDIR | mkdir | |
+| MKDIR_P | mkdir -p | |
+| MV | mv | |
+| RM | rm -f | |
+| TAR | tar | |
+|-----------+-------------+----------------------------------------------------|
+| GZIPFLAGS | $(GZIP_ENV) | |
+| GZIP_ENV | --best | Because of GNU Automake, users expect this to work |
+
+Module: gnuconf
+---------------
+
+The `gnuconf` module provides default values for user-facing toggles
+required by the GNU Coding Standards.
+
+There is only one developer configuration option:
+
+| Variable | Default | Description |
+|-----------------+------------+-----------------------------------------------|
+| gnuconf.pkgname | $(PACKAGE) | The package name to use in the default docdir |
+
+There is an extensive list of user configuration options:
+
+| Variable | Default | Description |
+|-----------------+---------------------------------------+-------------------------------------------|
+| AWK | awk | |
+| CAT | cat | |
+| CMP | cmp | |
+| CP | cp | |
+| DIFF | diff | |
+| ECHO | echo | |
+| EGREP | egrep | |
+| EXPR | expr | |
+| FALSE | false | |
+| GREP | grep | |
+| INSTALL_INFO | install-info | |
+| LN | ln | |
+| LS | ls | |
+| MKDIR | mkdir | |
+| MV | mv | |
+| PRINTF | printf | |
+| PWD | pwd | |
+| RM | rm | |
+| RMDIR | rmdir | |
+| SED | sed | |
+| SLEEP | sleep | |
+| SORT | sort | |
+| TAR | tar | |
+| TEST | test | |
+| TOUCH | touch | |
+| TR | tr | |
+| TRUE | true | |
+|-----------------+---------------------------------------+-------------------------------------------|
+| AR | ar | |
+| ARFLAGS | | |
+| BISON | bison | |
+| BISONFLAGS | | |
+| CC | cc | |
+| CCFLAGS | $(CFLAGS) | |
+| FLEX | flex | |
+| FLEXFLAGS | | |
+| INSTALL | install | |
+| INSTALLFLAGS | | |
+| LD | ld | |
+| LDFLAGS | | |
+| LDCONFIG | ldconfig | TODO: detect absence, fall back to `true` |
+| LDCONFIGFLAGS | | |
+| LEX | lex | |
+| LEXFLAGS | $(LFLAGS) | |
+| MAKEINFO | makeinfo | |
+| MAKEINFOFLAGS | | |
+| RANLIB | ranlib | TODO: detect absence, fall back to `true` |
+| RANLIBFLAGS | | |
+| TEXI2DVI | texi2dvi | |
+| TEXI2DVIFLAGS | | |
+| YACC | yacc | |
+| YACCFLAGS | $(YFLAGS) | |
+|-----------------+---------------------------------------+-------------------------------------------|
+| CFLAGS | | |
+| LFLAGS | | |
+| YFLAGS | | |
+|-----------------+---------------------------------------+-------------------------------------------|
+| LN_S | ln -s | TODO: detect when to fall back to `cp` |
+|-----------------+---------------------------------------+-------------------------------------------|
+| CHGRP | chgrp | |
+| CHMOD | chmod | |
+| CHOWN | chown | |
+| MKNOD | mknod | |
+|-----------------+---------------------------------------+-------------------------------------------|
+| INSTALL_PROGRAM | $(INSTALL) | |
+| INSTALL_DATA | ${INSTALL} -m 644 | |
+|-----------------+---------------------------------------+-------------------------------------------|
+| prefix | /usr/local | |
+| exec_prefix | $(prefix) | |
+|-----------------+---------------------------------------+-------------------------------------------|
+| bindir | $(exec_prefix)/bin | |
+| sbindir | $(exec_prefix)/sbin | |
+| libexecdir | $(exec_prefix)/libexec | |
+|-----------------+---------------------------------------+-------------------------------------------|
+| datadir | $(datarootdir) | |
+| sysconfdir | $(prefix)/etc | |
+| sharedstatedir | $(prefix)/com | |
+| localstatedir | $(prefix)/var | |
+| runstatedir | $(localstatedir)/run | |
+|-----------------+---------------------------------------+-------------------------------------------|
+| includedir | $(prefix)/include | |
+| oldincludedir | /usr/include | |
+| docdir | $(datarootdir)/doc/$(gnuconf.pkgname) | |
+| infodir | $(datarootdir)/info | |
+| htmldir | $(docdir) | |
+| dvidir | $(docdir) | |
+| pdfdir | $(docdir) | |
+| psdir | $(docdir) | |
+| libdir | $(exec_prefix)/lib | |
+| lispdir | $(datarootdir)/emacs/site-lisp | |
+| localedir | $(datarootdir)/locale | |
+|-----------------+---------------------------------------+-------------------------------------------|
+| mandir | $(datarootdir)/man | |
+| man1dir | $(mandir)/man1 | |
+| man2dir | $(mandir)/man2 | |
+| man3dir | $(mandir)/man3 | |
+| man4dir | $(mandir)/man4 | |
+| man5dir | $(mandir)/man5 | |
+| man6dir | $(mandir)/man6 | |
+| man7dir | $(mandir)/man7 | |
+| man8dir | $(mandir)/man8 | |
+|-----------------+---------------------------------------+-------------------------------------------|
+| manext | .1 | |
+| man1ext | .1 | |
+| man2ext | .2 | |
+| man3ext | .3 | |
+| man4ext | .4 | |
+| man5ext | .5 | |
+| man6ext | .6 | |
+| man7ext | .7 | |
+| man8ext | .8 | |
+
+Module: gnustuff
+----------------
+
+This is a poorly-thought-out module implementing remaining things from
+the GNU Coding Standards.
+
+This is poorly thought out and poorly tested because it's basically
+the part of the GNU Coding Standards that I don't use.
+
+Developer configuration options:
+
+| Variable | Default | Description |
+|-----------------------+-----------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------|
+| gnustuff.info_docs | | The list of texinfo documents in the current directory, without the `.texi` suffix. |
+| gnustuff.program_dirs | $(bindir) $(sbindir) $(libexecdir) | Directories to use $(INSTALL_PROGRAM) for inserting files into. |
+| gnustuff.data_dirs | <every variable from gnuconf ending in `dir` that isn't bindir, sbindir, or libexecdir> | Directories to use $(INSTALL_DATA) for inserting files into. |
+| gnustuff.dirs | $(gnustuff.program_dirs) $(gnustuff.data_dirs) | Directories to create |
+
+User configuration options:
+
+| Variable | Default | Description |
+|-----------+-----------------+-------------|
+| STRIP | strip | |
+| TEXI2HTML | makeinfo --html | |
+| TEXI2PDF | texi2pdf | |
+| TEXI2PS | texi2dvi --ps | |
+| MKDIR_P | mkdir -p | |
+
+It provides several `.phony` targets:
+ - install-{html,dvi,pdf,ps}
+ - install-strip
+ - {info,html,dvi,pdf,ps}
+ - TAGS
+ - check
+ - installcheck
+
+It also augments the `std` `install` rule to run $(INSTALL_INFO) as
+necessary.
+
+And several real rules:
+ - How to install files into any of the $(gnustuff.program_dirs) or
+ $(gnustuff.data_dirs).
+ - How to generate info, dvi, html, pdf, and ps files from texi files.
diff --git a/build-aux/Makefile.each.head/00-dist.mk b/build-aux/Makefile.each.head/00-dist.mk
new file mode 100644
index 0000000000..a0943059ba
--- /dev/null
+++ b/build-aux/Makefile.each.head/00-dist.mk
@@ -0,0 +1,20 @@
+# Copyright (C) 2015-2016 Luke Shumaker
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+ifeq ($(outdir),$(topoutdir))
+std.clean_files += $(addprefix $(dist.pkgname)-*,$(dist.exts) .tar /)
+endif
+
+$(outdir)/dist: $(addprefix $(topoutdir)/$(dist.pkgname)-$(dist.version),$(dist.exts))
diff --git a/build-aux/Makefile.each.tail/10-std.mk b/build-aux/Makefile.each.tail/10-std.mk
new file mode 100644
index 0000000000..693f39da90
--- /dev/null
+++ b/build-aux/Makefile.each.tail/10-std.mk
@@ -0,0 +1,53 @@
+# Copyright (C) 2015-2016 Luke Shumaker
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# Add some more defaults to the *_files variables
+std.clean_files += $(std.gen_files) $(std.cfg_files) $(std.out_files)
+
+# Fix each variable at its current value to avoid any weirdness
+$(foreach c,src gen cfg out sys clean slow,$(eval std.$c_files := $$(std.$c_files)))
+
+# Make each of the standard variables relative to the correct directory
+std.src_files := $(patsubst ./%,%,$(addprefix $(srcdir)/,$(std.src_files)))
+std.gen_files := $(patsubst ./%,%,$(addprefix $(srcdir)/,$(std.gen_files)))
+std.cfg_files := $(patsubst ./%,%,$(addprefix $(outdir)/,$(std.cfg_files)))
+std.out_files := $(patsubst ./%,%,$(addprefix $(outdir)/,$(std.out_files)))
+std.sys_files := $(addprefix $(DESTDIR),$(std.sys_files))
+std.clean_files := $(patsubst ./%,%,$(addprefix $(outdir)/,$(std.clean_files)))
+std.slow_files := $(patsubst ./%,%,$(addprefix $(outdir)/,$(std.slow_files)))
+
+# Creative targets
+$(outdir)/build : $(std.out_files)
+$(outdir)/install : $(std.sys_files)
+$(outdir)/installdirs: $(sort $(dir $(std.sys_files)))
+
+# Destructive targets
+_std.uninstall/$(outdir) := $(std.sys_files)
+_std.mostlyclean/$(outdir) := $(filter-out $(std.slow_files) $(std.cfg_files) $(std.gen_files) $(std.src_files),$(std.clean_files))
+_std.clean/$(outdir) := $(filter-out $(std.cfg_files) $(std.gen_files) $(std.src_files),$(std.clean_files))
+_std.distclean/$(outdir) := $(filter-out $(std.gen_files) $(std.src_files),$(std.clean_files))
+_std.maintainer-clean/$(outdir) := $(filter-out $(std.src_files),$(std.clean_files))
+$(addprefix $(outdir)/,mostlyclean clean distclean maintainer-clean): %: %-hook
+ $(RM) -- $(sort $(filter-out %/,$(_std.$(@F)/$(@D))))
+ $(RM) -r -- $(sort $(filter %/,$(_std.$(@F)/$(@D))))
+ $(RMDIR_P) $(sort $(dir $(_std.$(@F)/$(@D)))) 2>/dev/null || $(TRUE)
+# separate uninstall to support GNU Coding Standards' NORMAL_UNINSTALL
+$(addprefix $(outdir)/,uninstall): %: %-hook
+ $(NORMAL_UNINSTALL)
+ $(RM) -- $(sort $(filter-out %/,$(_std.$(@F)/$(@D))))
+ $(RM) -r -- $(sort $(filter %/,$(_std.$(@F)/$(@D))))
+ $(RMDIR_P) $(sort $(dir $(_std.$(@F)/$(@D)))) 2>/dev/null || $(TRUE)
+$(foreach t,uninstall mostlyclean clean distclean maintainer-clean, $(outdir)/$t-hook)::
+.PHONY: $(foreach t,uninstall mostlyclean clean distclean maintainer-clean, $(outdir)/$t-hook)
diff --git a/build-aux/Makefile.each.tail/11-gnustuff.mk b/build-aux/Makefile.each.tail/11-gnustuff.mk
new file mode 100644
index 0000000000..790efad0fa
--- /dev/null
+++ b/build-aux/Makefile.each.tail/11-gnustuff.mk
@@ -0,0 +1,60 @@
+# Copyright (C) 2016 Luke Shumaker
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# 7.2.6: Standard Targets for Users
+# ---------------------------------
+
+std.gen_files += $(foreach f,$(gnustuff.info_docs), $f.info )
+std.sys_files += $(foreach f,$(gnustuff.info_docs), $(infodir)/$f.info )
+
+$(foreach d,$(gnustuff.program_dirs),$(eval $(call _gnustuff.install_program,$d)))
+$(foreach d,$(gnustuff.data_dirs) ,$(eval $(call _gnustuff.install_data,$d)))
+
+#all: std
+install:
+ $(foreach f,$(gnustuff.info_docs),$(INSTALL_INFO) $(DESTDIR)$(infodir)/$f.info $(DESTDIR)$(infodir)/dir$(at.nl))
+$(outdir)/install-html: $(foreach f,$(gnustuff.info_docs), $(DESTDIR)$(htmldir)/$f.html )
+$(outdir)/install-dvi : $(foreach f,$(gnustuff.info_docs), $(DESTDIR)$(dvidir)/$f.dvi )
+$(outdir)/install-pdf : $(foreach f,$(gnustuff.info_docs), $(DESTDIR)$(pdfdir)/$f.pdf )
+$(outdir)/install-ps : $(foreach f,$(gnustuff.info_docs), $(DESTDIR)$(psdir)/$f.ps )
+#uninstall: std
+$(outdir)/install-strip: install
+ $(STRIP) $(filter $(addsuffix /%,$(gnustuff.program_dirs)),$(std.sys_files/$(@D)))
+#clean: std
+#distclean: std
+#mostlyclean: std
+#maintainer-clean: std
+TAGS: TODO
+$(outdir)/info: $(addsuffix .info,$(gnustuff.info_docs))
+$(outdir)/dvi : $(addsuffix .dvi ,$(gnustuff.info_docs))
+$(outdir)/html: $(addsuffix .html,$(gnustuff.info_docs))
+$(outdir)/pdf : $(addsuffix .pdf ,$(gnustuff.info_docs))
+$(outdir)/ps : $(addsuffix .ps ,$(gnustuff.info_docs))
+#dist:dist
+check: TODO
+installcheck: TODO
+#installdirs: std
+
+$(outdir)/%.info: $(srcdir)/%.texi; $(MAKEINFO) -o $(@D) $<
+$(outdir)/%.info: $(outdir)/%.texi; $(MAKEINFO) -o $(@D) $<
+$(outdir)/%.dvi : $(srcdir)/%.texi; $(TEXI2DVI) -o $(@D) $<
+$(outdir)/%.dvi : $(outdir)/%.texi; $(TEXI2DVI) -o $(@D) $<
+$(outdir)/%.html: $(srcdir)/%.texi; $(TEXI2HTML) -o $(@D) $<
+$(outdir)/%.html: $(outdir)/%.texi; $(TEXI2HTML) -o $(@D) $<
+$(outdir)/%.pdf : $(srcdir)/%.texi; $(TEXI2PDF) -o $(@D) $<
+$(outdir)/%.pdf : $(outdir)/%.texi; $(TEXI2PDF) -o $(@D) $<
+$(outdir)/%.ps : $(srcdir)/%.texi; $(TEXI2PS) -o $(@D) $<
+$(outdir)/%.ps : $(outdir)/%.texi; $(TEXI2PS) -o $(@D) $<
+#installdirs: std
diff --git a/build-aux/Makefile.once.head/00-dist.mk b/build-aux/Makefile.once.head/00-dist.mk
new file mode 100644
index 0000000000..d5bfcd3d2f
--- /dev/null
+++ b/build-aux/Makefile.once.head/00-dist.mk
@@ -0,0 +1,44 @@
+# Copyright (C) 2015-2016 Luke Shumaker
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# Developer configuration
+
+dist.exts ?= .tar.gz
+dist.pkgname ?= $(PACKAGE)
+dist.version ?= $(VERSION)
+
+ifeq ($(dist.pkgname),)
+$(error dist.pkgname must be set)
+endif
+ifeq ($(dist.version),)
+$(error dist.version must be set)
+endif
+
+# User configuration
+
+CP ?= cp
+GZIP ?= gzip
+MKDIR ?= mkdir
+MKDIR_P ?= mkdir -p
+MV ?= mv
+RM ?= rm -f
+TAR ?= tar
+
+GZIPFLAGS ?= $(GZIP_ENV)
+GZIP_ENV ?= --best
+
+# Implementation
+
+at.phony += dist
diff --git a/build-aux/Makefile.once.head/00-gnuconf.mk b/build-aux/Makefile.once.head/00-gnuconf.mk
new file mode 100644
index 0000000000..83cb110c59
--- /dev/null
+++ b/build-aux/Makefile.once.head/00-gnuconf.mk
@@ -0,0 +1,160 @@
+# Copyright (C) 2016 Luke Shumaker
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# This file is based on §7.2 "Makefile Conventions" of the release of
+# the GNU Coding Standards dated April 13, 2016.
+
+gnuconf.pkgname ?= $(firstword $(PACKAGE_TARNAME) $(PACKAGE) $(PACKAGE_NAME))
+ifeq ($(gnuconf.pkgname),)
+$(error gnuconf.pkgname must be set)
+endif
+
+# 7.2.2: Utilities in Makefiles
+# -----------------------------
+
+# It's ok to hard-code these commands in rules, but who wants to
+# memorize the list of what's ok?
+AWK ?= awk
+CAT ?= cat
+CMP ?= cmp
+CP ?= cp
+DIFF ?= diff
+ECHO ?= echo
+EGREP ?= egrep
+EXPR ?= expr
+FALSE ?= false
+GREP ?= grep
+INSTALL_INFO ?= install-info
+LN ?= ln
+LS ?= ls
+MKDIR ?= mkdir
+MV ?= mv
+PRINTF ?= printf
+PWD ?= pwd
+RM ?= rm
+RMDIR ?= rmdir
+SED ?= sed
+SLEEP ?= sleep
+SORT ?= sort
+TAR ?= tar
+TEST ?= test
+TOUCH ?= touch
+TR ?= tr
+TRUE ?= true
+
+# These must be user-configurable
+AR ?= ar
+ARFLAGS ?=
+BISON ?= bison
+BISONFLAGS ?=
+CC ?= cc
+CCFLAGS ?= $(CFLAGS)
+FLEX ?= flex
+FLEXFLAGS ?=
+INSTALL ?= install
+#INSTALLFLAGS ?=
+LD ?= ld
+LDFLAGS ?=
+LDCONFIG ?= ldconfig #TODO
+LDCONFIGFLAGS ?=
+LEX ?= lex
+LEXFLAGS ?= $(LFLAGS)
+#MAKE
+MAKEINFO ?= makeinfo
+MAKEINFOFLAGS ?=
+RANLIB ?= ranlib #TODO
+RANLIBFLAGS ?=
+TEXI2DVI ?= texi2dvi
+TEXI2DVIFLAGS ?=
+YACC ?= yacc
+YACCFLAGS ?= $(YFLAGS)
+
+CFLAGS ?=
+LFLAGS ?=
+YFLAGS ?=
+
+LN_S ?= ln -s #TODO
+
+CHGRP ?= chgrp
+CHMOD ?= chmod
+CHOWN ?= chown
+MKNOD ?= mknod
+
+# 7.2.3: Variables for Specifying Commands
+# ----------------------------------------
+
+INSTALL_PROGRAM ?= $(INSTALL)
+INSTALL_DATA ?= ${INSTALL} -m 644
+
+# 7.2.5: Variables for Installation Directories
+# ---------------------------------------------
+
+# Root for the installation
+prefix ?= /usr/local
+exec_prefix ?= $(prefix)
+# Executable programs
+bindir ?= $(exec_prefix)/bin
+sbindir ?= $(exec_prefix)/sbin
+libexecdir ?= $(exec_prefix)/libexec
+# Data files
+datarootdir ?= $(prefix)/share
+datadir ?= $(datarootdir)
+sysconfdir ?= $(prefix)/etc
+sharedstatedir ?= $(prefix)/com
+localstatedir ?= $(prefix)/var
+runstatedir ?= $(localstatedir)/run
+# Specific types of files
+includedir ?= $(prefix)/include
+oldincludedir ?= /usr/include
+docdir ?= $(datarootdir)/doc/$(gnuconf.pkgname)
+infodir ?= $(datarootdir)/info
+htmldir ?= $(docdir)
+dvidir ?= $(docdir)
+pdfdir ?= $(docdir)
+psdir ?= $(docdir)
+libdir ?= $(exec_prefix)/lib
+lispdir ?= $(datarootdir)/emacs/site-lisp
+localedir ?= $(datarootdir)/locale
+
+mandir ?= $(datarootdir)/man
+man1dir ?= $(mandir)/man1
+man2dir ?= $(mandir)/man2
+man3dir ?= $(mandir)/man3
+man4dir ?= $(mandir)/man4
+man5dir ?= $(mandir)/man5
+man6dir ?= $(mandir)/man6
+man7dir ?= $(mandir)/man7
+man8dir ?= $(mandir)/man8
+
+manext ?= .1
+man1ext ?= .1
+man2ext ?= .2
+man3ext ?= .3
+man4ext ?= .4
+man5ext ?= .5
+man6ext ?= .6
+man7ext ?= .7
+man8ext ?= .8
+
+# 7.2.7: Install Command Categories
+# ---------------------------------
+
+PRE_INSTALL ?=
+POST_INSTALL ?=
+NORMAL_INSTALL ?=
+
+PRE_UNINSTALL ?=
+POST_UNINSTALL ?=
+NORMAL_UNINSTALL ?=
diff --git a/build-aux/Makefile.once.head/00-write-ifchanged.mk b/build-aux/Makefile.once.head/00-write-ifchanged.mk
new file mode 100644
index 0000000000..79ef1c419c
--- /dev/null
+++ b/build-aux/Makefile.once.head/00-write-ifchanged.mk
@@ -0,0 +1 @@
+WRITE_IFCHANGED = $(topsrcdir)/build-aux/write-ifchanged
diff --git a/build-aux/Makefile.once.head/10-std.mk b/build-aux/Makefile.once.head/10-std.mk
new file mode 100644
index 0000000000..3e058eca57
--- /dev/null
+++ b/build-aux/Makefile.once.head/10-std.mk
@@ -0,0 +1,39 @@
+# Copyright (C) 2015-2016 Luke Shumaker
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# Declare the default target
+all: build
+.PHONY: all noop
+
+# Standard creative PHONY targets
+at.phony += build install installdirs
+# Standard destructive PHONY targets
+at.phony += uninstall mostlyclean clean distclean maintainer-clean
+
+at.dirlocal += std.src_files
+at.dirlocal += std.gen_files
+at.dirlocal += std.cfg_files
+at.dirlocal += std.out_files
+at.dirlocal += std.sys_files
+at.dirlocal += std.clean_files
+at.dirlocal += std.slow_files
+
+# User configuration
+
+DESTDIR ?=
+
+RM ?= rm -f
+RMDIR_P ?= rmdir -p
+TRUE ?= true
diff --git a/build-aux/Makefile.once.head/11-gnustuff.mk b/build-aux/Makefile.once.head/11-gnustuff.mk
new file mode 100644
index 0000000000..800f6d271c
--- /dev/null
+++ b/build-aux/Makefile.once.head/11-gnustuff.mk
@@ -0,0 +1,34 @@
+# Copyright (C) 2016 Luke Shumaker
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+STRIP ?= strip
+TEXI2HTML ?= makeinfo --html
+TEXI2PDF ?= texi2pdf
+TEXI2PS ?= texi2dvi --ps
+MKDIR_P ?= mkdir -p
+
+gnustuff.program_dirs += $(bindir) $(sbindir) $(libexecdir)
+gnustuff.data_dirs += $(datarootdir) $(datadir) $(sysconfdir) $(sharedstatedir) $(localstatedir) $(runstatedir)
+gnustuff.data_dirs += $(includedir) $(oldincludedir) $(docdir) $(infodir) $(htmldir) $(dvidir) $(pdfdir) $(psdir) $(libdir) $(lispdir) $(localedir)
+gnustuff.data_dirs += $(mandir) $(man1dir) $(man2dir) $(man3dir) $(man4dir) $(man5dir) $(man6dir) $(man7dir) $(man8dir)
+
+gnustuff.info_docs ?=
+std.dirlocal += gnustuff.info_docs
+
+gnustuff.dirs += $(gnu.program_dirs) $(gnu.data_dirs)
+
+at.phony += install-html install-dvi install-pdf install-ps
+at.phony += info html dvi pdf ps
+at.phony += install-strip
diff --git a/build-aux/Makefile.once.tail/00-dist.mk b/build-aux/Makefile.once.tail/00-dist.mk
new file mode 100644
index 0000000000..b8b7733319
--- /dev/null
+++ b/build-aux/Makefile.once.tail/00-dist.mk
@@ -0,0 +1,27 @@
+# Copyright (C) 2015-2016 Luke Shumaker
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+_dist.copyfile = $(MKDIR_P) $(dir $2) && $(CP) -T $1 $2
+_dist.addfile = $(call _dist.copyfile,$3,$2/$(call at.relto,$1,$3))
+$(topoutdir)/$(dist.pkgname)-$(dist.version): $(foreach v,$(filter std.src_files/% std.gen_files/%,$(.VARIABLES)),$($v))
+ $(RM) -r $@ $(@D)/tmp.$(@F)
+ $(MKDIR) $(@D)/tmp.$(@F)
+ $(foreach f,$^,$(call _dist.addfile,$(topsrcdir),$(@D)/tmp.$(@F),$f)$(at.nl))
+ $(MV) $(@D)/tmp.$(@F) $@ || $(RM) -r $(@D)/tmp.$(@F)
+
+$(topoutdir)/$(dist.pkgname)-$(dist.version).tar: $(topoutdir)/$(dist.pkgname)-$(dist.version)
+ $(TAR) cf $@ -C $(<D) $(<F)
+$(topoutdir)/$(dist.pkgname)-$(dist.version).tar.gz: $(topoutdir)/$(dist.pkgname)-$(dist.version).tar
+ $(GZIP) $(GZIPFLAGS) < $< > $@
diff --git a/build-aux/Makefile.once.tail/11-gnustuff.mk b/build-aux/Makefile.once.tail/11-gnustuff.mk
new file mode 100644
index 0000000000..df5f19258c
--- /dev/null
+++ b/build-aux/Makefile.once.tail/11-gnustuff.mk
@@ -0,0 +1,17 @@
+# Copyright (C) 2016 Luke Shumaker
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+$(gnu.dirs):
+ $(MKDIR_P) $@
diff --git a/build-aux/write-ifchanged b/build-aux/write-ifchanged
new file mode 100755
index 0000000000..185ceb0039
--- /dev/null
+++ b/build-aux/write-ifchanged
@@ -0,0 +1,25 @@
+#!/usr/bin/env bash
+# Copyright (C) 2015 Luke Shumaker
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+outfile=$1
+tmpfile="$(dirname "$outfile")/.tmp${outfile##*/}"
+
+cat > "$tmpfile" || exit $?
+if cmp -s "$tmpfile" "$outfile"; then
+ rm -f "$tmpfile" || :
+else
+ mv -f "$tmpfile" "$outfile"
+fi
diff --git a/config.mk.in b/config.mk.in
new file mode 100644
index 0000000000..ffe7c1ca97
--- /dev/null
+++ b/config.mk.in
@@ -0,0 +1,114 @@
+# This file is based on §7.2 "Makefile Conventions" of the release of
+# the GNU Coding Standards dated April 13, 2016.
+
+dist.pkgname = @PACKAGE_TARNAME@
+gnu.pkgname = @PACKAGE_NAME@
+
+# AC_PROG_{AWK,GREP,EGREP,FGREP,INSTALL,MKDIR_P,SED}
+# 7.2.2: Utilities in Makefiles
+# -----------------------------
+
+# It's ok to hard-code these commands in rules, but who wants to
+# memorize the list of what's ok?
+AWK = @AWK@
+CAT = cat
+CMP = cmp
+CP = cp
+DIFF = diff
+ECHO = echo
+EGREP = @EGREP@
+EXPR = expr
+FALSE = false
+GREP = @GREP@
+INSTALL_INFO = install-info
+LN = ln
+LS = ls
+MKDIR = mkdir
+MV = mv
+PRINTF = printf
+PWD = pwd
+RM = rm
+RMDIR = rmdir
+SED = @SED@
+SLEEP = sleep
+SORT = sort
+TAR = tar
+TEST = test
+TOUCH = touch
+TR = tr
+TRUE = true
+
+AR = @AR@
+BISON = bison
+CC = @CC@
+FLEX = flex
+INSTALL = @INSTALL@
+LD = ld
+LDCONFIG = ldconfig
+LEX = @LEX@
+MAKEINFO = makeinfo
+RANLIB = @RANLIB@
+TEXI2DVI = texi2dvi
+YACC = @YACC@
+
+# 7.2.3 Variables for Specifying Commands
+# ---------------------------------------
+
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+
+STRIP = strip
+TEXI2HTML = $(MAKEINFO) --html
+TEXI2PDF = $(TEXI2DVI) --pdf
+TEXI2PS = $(TEXI2DVI) --ps
+MKDIR_P = @MKDIR_P@
+
+# 7.2.5 Variables for Installation Directories
+# --------------------------------------------
+
+# Root for the installation
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+# Executable programs
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+# Data files (Autoconf won't support runstatedir until version 2.70)
+datarootdir = @datarootdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+runstatedir = $(localstatedir)/run
+# Specific types of files
+includedir = @includedir@
+oldincludedir = @oldincludedir@
+docdir = @docdir@
+infodir = @infodir@
+htmldir = @htmldir@
+dvidir = @dvidir@
+pdfdir = @pdfdir@
+psdir = @psdir@
+libdir = @libdir@
+lispdir = $(datarootdir)/emacs/site-lisp
+localedir = @localedir@
+
+mandir = @mandir@
+man1dir = $(mandir)/man1
+man2dir = $(mandir)/man2
+man3dir = $(mandir)/man3
+man4dir = $(mandir)/man4
+man5dir = $(mandir)/man5
+man6dir = $(mandir)/man6
+man7dir = $(mandir)/man7
+man8dir = $(mandir)/man8
+
+manext = .1
+man1ext = .1
+man2ext = .2
+man3ext = .3
+man4ext = .4
+man5ext = .5
+man6ext = .6
+man7ext = .7
+man8ext = .8