From 8a5ecbb4fcaf0d9864074666a45d9263b73f31b8 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Sun, 7 Aug 2016 21:03:44 -0400 Subject: (systemd) stuff --- build-aux/Makefile.once.head/10-dist.mk | 42 +++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 build-aux/Makefile.once.head/10-dist.mk (limited to 'build-aux/Makefile.once.head/10-dist.mk') diff --git a/build-aux/Makefile.once.head/10-dist.mk b/build-aux/Makefile.once.head/10-dist.mk new file mode 100644 index 0000000..0e13ea2 --- /dev/null +++ b/build-aux/Makefile.once.head/10-dist.mk @@ -0,0 +1,42 @@ +# 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 . + +mod.dist.description = Make distribution tarballs + +# Developer configuration + +dist.exts ?= .tar.gz +dist.pkgname ?= $(firstword $(PACKAGE_TARNAME) $(PACKAGE) $(PACKAGE_NAME)) +dist.version ?= $(firstword $(PACKAGE_VERSION) $(VERSION)) + +ifeq ($(dist.pkgname),) +$(error Autothing module: dist: dist.pkgname must be set) +endif +ifeq ($(dist.version),) +$(error Autothing module: dist: 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 -- cgit v1.2.3-54-g00ecf From 88d181c25d2f99f8b510afe2f2cc7e1ba1fa012c Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Wed, 10 Aug 2016 11:22:38 -0400 Subject: (systemd) fix build system --- build-aux/Makefile.each.head/00-files.mk | 13 ++++--- build-aux/Makefile.each.head/zz-mod.mk | 1 - build-aux/Makefile.each.tail/00-dist.mk | 1 + build-aux/Makefile.each.tail/00-mod.mk | 41 ++++++++++++++++++++++ build-aux/Makefile.each.tail/10-nested.mk | 3 +- build-aux/Makefile.head.mk | 14 ++++---- build-aux/Makefile.once.head/10-dist.mk | 4 ++- build-aux/Makefile.once.head/10-files.mk | 5 ++- build-aux/Makefile.once.head/10-lt.mk | 12 ------- build-aux/Makefile.once.head/10-write-ifchanged.mk | 3 +- build-aux/Makefile.once.head/zz-mod.mk | 32 ++++++++++++----- build-aux/Makefile.once.tail/00-dist.mk | 2 +- build-aux/Makefile.once.tail/00-mod.mk | 32 ----------------- build-aux/Makefile.once.tail/00-noop.mk | 2 -- build-aux/Makefile.tail.mk | 2 +- 15 files changed, 95 insertions(+), 72 deletions(-) delete mode 100644 build-aux/Makefile.each.head/zz-mod.mk create mode 100644 build-aux/Makefile.each.tail/00-dist.mk create mode 100644 build-aux/Makefile.each.tail/00-mod.mk delete mode 100644 build-aux/Makefile.once.head/10-lt.mk delete mode 100644 build-aux/Makefile.once.tail/00-mod.mk delete mode 100644 build-aux/Makefile.once.tail/00-noop.mk (limited to 'build-aux/Makefile.once.head/10-dist.mk') diff --git a/build-aux/Makefile.each.head/00-files.mk b/build-aux/Makefile.each.head/00-files.mk index c9a94e1..c4820cf 100644 --- a/build-aux/Makefile.each.head/00-files.mk +++ b/build-aux/Makefile.each.head/00-files.mk @@ -17,13 +17,16 @@ files.src.src ?= files.src.int ?= files.src.cfg ?= files.src.gen ?= -files.src = $(sort $(foreach _files.v,$(filter files.src.%,$(.VARIABLES)),$($(_files.v)))) files.out.slow ?= files.out.int ?= files.out.cfg ?= -$(eval $(foreach t,$(files.groups),files.out.$t ?=$(at.nl))) -files.out = $(sort $(foreach _files.v,$(filter files.out.%,$(.VARIABLES)),$($(_files.v)))) -$(eval $(foreach t,$(files.groups),files.sys.$t ?=$(at.nl))) -files.sys = $(sort $(foreach _files.v,$(filter files.sys.%,$(.VARIABLES)),$($(_files.v)))) +# define files.out.$(group) files.sys.$(group) for every files.group +$(eval $(foreach t,$(files.groups),files.out.$t ?=$(at.nl)files.sys.$t ?=$(at.nl))) + +# define files.src, files.out, and files.sys aggregates +$(eval \ + files.src = $$(sort $(foreach _files.v,$(filter files.src.%,$(.VARIABLES)),$$($(_files.v))))$(at.nl)\ + files.out = $$(sort $(foreach _files.v,$(filter files.out.%,$(.VARIABLES)),$$($(_files.v))))$(at.nl)\ + files.sys = $$(sort $(foreach _files.v,$(filter files.sys.%,$(.VARIABLES)),$$($(_files.v))))) diff --git a/build-aux/Makefile.each.head/zz-mod.mk b/build-aux/Makefile.each.head/zz-mod.mk deleted file mode 100644 index b83c223..0000000 --- a/build-aux/Makefile.each.head/zz-mod.mk +++ /dev/null @@ -1 +0,0 @@ -_mod.each := $(sort $(_mod.each) $(filter-out $(_mod.once),$(_mod.vars))) diff --git a/build-aux/Makefile.each.tail/00-dist.mk b/build-aux/Makefile.each.tail/00-dist.mk new file mode 100644 index 0000000..df363b5 --- /dev/null +++ b/build-aux/Makefile.each.tail/00-dist.mk @@ -0,0 +1 @@ +_dist.files := $(strip $(_dist.files) $(_files.src)) diff --git a/build-aux/Makefile.each.tail/00-mod.mk b/build-aux/Makefile.each.tail/00-mod.mk new file mode 100644 index 0000000..6346173 --- /dev/null +++ b/build-aux/Makefile.each.tail/00-mod.mk @@ -0,0 +1,41 @@ +# 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 . + +$(outdir)/at-variables $(outdir)/at-variables-local: _mod.VARIABLES := $(filter-out $(call _mod.quote-pattern,$(_at.VARIABLES)),$(.VARIABLES)) +$(outdir)/at-variables-global: + @printf '%s\n' $(call _mod.quote-shell-each,$(sort $(.VARIABLES))) +$(outdir)/at-variables-local: + @printf '%s\n' $(call _mod.quote-shell-each,$(sort $(_mod.VARIABLES))) +$(outdir)/at-variables $(outdir)/at-values: + @printf '%s\n' $(call _mod.quote-shell-each,$(sort $(.VARIABLES),$(_mod.VARIABLES))) +$(outdir)/at-variables/%: + @printf '%s\n' $(call _mod.quote-shell,$($*)) +$(outdir)/at-values/%: + @printf '%s\n' $(call _mod.quote-shell,$(value $*)) +.PHONY: $(addprefix $(outdir)/, at-variables-global at-variables-local at-variables at-values) +at.targets += $(addprefix $(outdir)/, at-variables-global at-variables-local at-variables at-values at-variables/% at-values/%) + +$(outdir)/at-modules: + @printf 'Autothing modules used in this project:\n' + @printf ' - %s\n' $(foreach _mod.tmp,$(_mod.modules),$(call _mod.quote-shell,$(_mod.tmp) $(mod.$(_mod.tmp).description)))|column -t -s $$'\t' +$(addprefix $(outdir)/at-modules/,$(_mod.modules)): $(outdir)/at-modules/%: + @printf 'Name : %s\n' $(call _mod.quote-shell,$*) + @printf 'Description : %s\n' $(call _mod.quote-shell,$(mod.$*.description)) + @echo 'Contains Files :' $(call _mod.quote-shell-each,$(call at.relto,$(topsrcdir),$(sort $(mod.$*.files) $(wildcard $(topsrcdir)/build-aux/Makefile.*/??-$*.mk)))) + @echo 'Depends on :' $(mod.$*.depends) + +$(outdir)/at-noop: +.PHONY: $(outdir)/at-noop +at.targets += $(outdir)/at-noop diff --git a/build-aux/Makefile.each.tail/10-nested.mk b/build-aux/Makefile.each.tail/10-nested.mk index e9d02ca..5e5a40b 100644 --- a/build-aux/Makefile.each.tail/10-nested.mk +++ b/build-aux/Makefile.each.tail/10-nested.mk @@ -13,7 +13,8 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . -$(addprefix $(outdir)/,$(nested.targets)): $(outdir)/%: $(addsuffix /%,$(call at.addprefix,$(outdir),$(nested.subdirs))) +$(eval $(foreach _tmp.nested,$(nested.targets),\ + $$(outdir)/$(_tmp.nested): $$(addsuffix /$(_tmp.nested),$$(call at.addprefix,$$(outdir),$$(nested.subdirs)))$(at.nl))) .PHONY: $(addprefix $(outdir)/,$(nested.targets)) at.subdirs += $(nested.subdirs) diff --git a/build-aux/Makefile.head.mk b/build-aux/Makefile.head.mk index 105432c..c2ce307 100644 --- a/build-aux/Makefile.head.mk +++ b/build-aux/Makefile.head.mk @@ -24,13 +24,13 @@ ifeq ($(origin _at.NO_ONCE),undefined) # These 4 functions are all $(call _at.func,parent,child) _at.is_strict_subdir = $(filter $(abspath $1)/%,$(abspath $2)) _at.is_subdir = $(filter $(abspath $1)/%,$(abspath $2)/.) -_at.relbase = $(strip \ - $(if $(call _at.is_subdir,$1,$2), \ - $(patsubst $(abspath $1)/%,%,$(abspath $2)/.), \ +_at.relbase = $(strip \ + $(if $(call _at.is_subdir,$1,$2), \ + $(patsubst %/.,$(patsubst $(abspath $1)/%,%,$(abspath $2)/.)), \ $(abspath $2))) -_at.relto = $(strip \ - $(if $(call _at.is_subdir,$1,$2), \ - $(patsubst $(abspath $1)/%,%,$(abspath $2)/.), \ +_at.relto = $(strip \ + $(if $(call _at.is_subdir,$1,$2), \ + $(patsubst %/.,%,$(patsubst $(abspath $1)/%,%,$(abspath $2)/.)), \ ../$(call _at.relto,$(dir $1),$2))) # These 3 functions only take one operand; we define public multi-operand @@ -51,6 +51,8 @@ _at.target_variable = $(_at.target_variable.$(flavor $2)) _at.target_variable.recursive = $1: private $2 = $(subst $(at.nl),$$(at.nl),$(value $2)) _at.target_variable.simple = $1: private $2 := $$($2) +_at.quote-pattern = $(subst %,\%,$(subst \,\\,$1)) + # Sanity checking ###################################################### ifeq ($(filter undefine,$(.FEATURES)),) $(error Autothing: We need a version of Make that supports 'undefine') diff --git a/build-aux/Makefile.once.head/10-dist.mk b/build-aux/Makefile.once.head/10-dist.mk index 0e13ea2..e139096 100644 --- a/build-aux/Makefile.once.head/10-dist.mk +++ b/build-aux/Makefile.once.head/10-dist.mk @@ -13,7 +13,7 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . -mod.dist.description = Make distribution tarballs +mod.dist.description = `dist` target for distribution tarballs # Developer configuration @@ -28,6 +28,8 @@ ifeq ($(dist.version),) $(error Autothing module: dist: dist.version must be set) endif +_dist.files = + # User configuration CP ?= cp diff --git a/build-aux/Makefile.once.head/10-files.mk b/build-aux/Makefile.once.head/10-files.mk index 2af7bf8..5441735 100644 --- a/build-aux/Makefile.once.head/10-files.mk +++ b/build-aux/Makefile.once.head/10-files.mk @@ -24,7 +24,10 @@ files.generate ?= files.generate .DEFAULT_GOAL = $(files.default) # Standard creative PHONY targets -nested.targets += $(foreach g,$(files.groups), $g install-$g install-$gdirs) +nested.targets += $(files.generate) +nested.targets += install installdirs +nested.targets += $(foreach g,$(files.groups),$g) +nested.targets += $(foreach g,$(filter-out $(files.default),$(files.groups)),install-$g install-$gdirs) # Standard destructive PHONY targets nested.targets += uninstall mostlyclean clean distclean maintainer-clean diff --git a/build-aux/Makefile.once.head/10-lt.mk b/build-aux/Makefile.once.head/10-lt.mk deleted file mode 100644 index c8410d4..0000000 --- a/build-aux/Makefile.once.head/10-lt.mk +++ /dev/null @@ -1,12 +0,0 @@ -mod.lt.description = Easy handling of libtool dependencies -mod.lt.deps += files - -_lt.dups = $(sort $(foreach l,$1,$(if $(filter-out 1,$(words $(filter $l,$1))),$l))) -_lt.patsubst-all = $(if $1,$(call _sd.patsubst-all,$(wordlist 2,$(words $1),$1),$2,$(patsubst $(firstword $1),$2,$3)),$3) -_lt.unLIBPATTERNS = $(foreach _lt.tmp,$1,$(if $(filter $(.LIBPATTERNS),$(_lt.tmp)),$(call _lt.patsubst-all,$(.LIBPATTERNS),-l%,$(_lt.tmp)),$(_lt.tmp))) - -# The semantics for the de-dup bit are a bit weird. My head hurts thinking -# about them. TODO: clarify/simplify/something -lt.rpath = $(dir $(patsubst $(DESTDIR)%,%,$(filter %/$(@F),$(files.sys)))) -_lt.link_files = $(filter %.o %.lo %.la -l%,$(call _lt.unLIBPATTERNS$,$^)) -lt.link_files = $(filter-out $(call _lt.dups,$(_lt.link_files)),$(_lt.link_files)) diff --git a/build-aux/Makefile.once.head/10-write-ifchanged.mk b/build-aux/Makefile.once.head/10-write-ifchanged.mk index 7917201..b0a5ac4 100644 --- a/build-aux/Makefile.once.head/10-write-ifchanged.mk +++ b/build-aux/Makefile.once.head/10-write-ifchanged.mk @@ -1,3 +1,4 @@ -mod.write-ifchanged.description = build-aux/write-ifchanged helper script +mod.write-ifchanged.description = `write-ifchanged` auxiliary build script +mod.write-ifchanged.files += $(topsrcdir)/build-aux/write-ifchanged WRITE_IFCHANGED ?= $(topsrcdir)/build-aux/write-ifchanged diff --git a/build-aux/Makefile.once.head/zz-mod.mk b/build-aux/Makefile.once.head/zz-mod.mk index 7e52606..438f01e 100644 --- a/build-aux/Makefile.once.head/zz-mod.mk +++ b/build-aux/Makefile.once.head/zz-mod.mk @@ -13,14 +13,30 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . -mod.mod.description = Print information about Autothing modules +mod.mod.description = Display information about Autothing modules -_mod.target = at-mod-info -_mod.modules := $(sort $(patsubst %.mk,%,$(filter %.mk,$(subst -, ,$(notdir $(wildcard $(topsrcdir)/build-aux/Makefile.*/??-*.mk)))))) -_mod.quote = '$(subst ','\'',$1)' +# The trickery that is _mod.empty/_mod.space is from §6.2 of the GNU Make +# manual, "The Two Flavors of Variables". +_mod.empty := +_mod.space := $(_mod.empty) # +undefine _mod.empty +# _mod.rest is equivalent to GMSL rest. +_mod.rest = $(wordlist 2,$(words $1),$1) -$(eval $(foreach _mod.tmp,$(_mod.modules),mod.$(_mod.tmp).description ?=$(at.nl)mod.$(_mod.tmp).depends ?=$(at.nl))) +_mod.file2mod = $(foreach _mod.tmp,$(patsubst %.mk,%,$(notdir $1)),$(subst $(_mod.space),-,$(call _mod.rest,$(subst -, ,$(_mod.tmp))))) -_mod.vars = $(filter $(addsuffix .%,$(_mod.modules)),$(.VARIABLES)) -_mod.once := $(_mod.vars) -_mod.each := +_mod.modules := $(sort $(call _mod.file2mod,$(wildcard $(topsrcdir)/build-aux/Makefile.*/??-*.mk))) +undefine _mod.rest +undefine _mod.file2mod + +$(eval $(foreach _mod.tmp,$(_mod.modules),\ + mod.$(_mod.tmp).description ?=$(at.nl)\ + mod.$(_mod.tmp).depends ?=$(at.nl)\ + mod.$(_mod.tmp).files ?=$(at.nl))) + +_mod.quote-pattern = $(subst %,\%,$(subst \,\\,$1)) +_mod.quote-shell-each = $(foreach _mod.tmp,$1,$(call _mod.quote-shell,$(_mod.tmp))) + +# I put this as the last line in the file because it confuses Emacs syntax +# highlighting and makes the remainder of the file difficult to edit. +_mod.quote-shell = $(subst $(at.nl),'$$'\n'','$(subst ','\'',$1)') diff --git a/build-aux/Makefile.once.tail/00-dist.mk b/build-aux/Makefile.once.tail/00-dist.mk index 6c6aaed..3fbe0c4 100644 --- a/build-aux/Makefile.once.tail/00-dist.mk +++ b/build-aux/Makefile.once.tail/00-dist.mk @@ -15,7 +15,7 @@ _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)) +$(topoutdir)/$(dist.pkgname)-$(dist.version): $(_dist.files) $(RM) -r $@ $(@D)/.tmp.$(@F) $(MKDIR) $(@D)/.tmp.$(@F) $(foreach f,$^,$(call _dist.addfile,$(topsrcdir),$(@D)/.tmp.$(@F),$f)$(at.nl)) diff --git a/build-aux/Makefile.once.tail/00-mod.mk b/build-aux/Makefile.once.tail/00-mod.mk deleted file mode 100644 index 68350f0..0000000 --- a/build-aux/Makefile.once.tail/00-mod.mk +++ /dev/null @@ -1,32 +0,0 @@ -# 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 . - -$(_mod.target): - @printf 'Autothing modules used in this project:\n' - @printf ' - %s\n' $(foreach _mod.tmp,$(_mod.modules),$(call _mod.quote,$(_mod.tmp))) -$(addprefix $(_mod.target)/,$(_mod.modules)): $(_mod.target)/%: - @printf 'Module : %s ' $(call _mod.quote,$*) - @$(if $(at.mod.$*.description),printf ' - %s' $(call _mod.quote,mod.$*.description)) - @echo - @echo Depends on : $(mod.$*.depends) - @echo User configuration: - @egrep '^\s*[^:#]+\s*\?=' $(topsrcdir)/build-aux/Makefile.once.head/??-$*.mk 2>/dev/null | sed 's|^\s*||;s|?=|:' | grep -v -e ^'_' -e ^'$*' | column -t -s: |sed 's|^| |' - @echo Developer global inputs: - @egrep '^\s*[^:#]+\s*\?=' $(topsrcdir)/build-aux/Makefile.once.head/??-$*.mk 2>/dev/null | sed 's|^\s*||;s|?=|:' | grep ^'$*\.' | column -t -s: |sed 's|^| |' - @echo Developer per-directory inputs: - @egrep '^\s*[^:#]+\s*\?=' $(topsrcdir)/build-aux/Makefile.each.head/??-$*.mk 2>/dev/null | sed 's|^\s*||;s|?=|:' | grep ^'$*\.' | column -t -s: |sed 's|^| |' - @echo Developer outputs: - @egrep '^\s*[^:#]+\s*(|:|::)=' $(topsrcdir)/build-aux/Makefile.once.head/??-$*.mk 2>/dev/null | sed 's|^\s*||;s|?=|:' | grep ^'$*\.' | column -t -s: |sed 's|^| |' -.PHONY: $(addprefix mod/,$(_mod.modules)) diff --git a/build-aux/Makefile.once.tail/00-noop.mk b/build-aux/Makefile.once.tail/00-noop.mk deleted file mode 100644 index bac2ec1..0000000 --- a/build-aux/Makefile.once.tail/00-noop.mk +++ /dev/null @@ -1,2 +0,0 @@ -noop: -.PHONY: noop diff --git a/build-aux/Makefile.tail.mk b/build-aux/Makefile.tail.mk index aeba2d1..2e4adc6 100644 --- a/build-aux/Makefile.tail.mk +++ b/build-aux/Makefile.tail.mk @@ -22,7 +22,7 @@ _at.tmp_subdirs := $(call at.addprefix,$(outdir),$(at.subdirs)) # Clean the environment $(eval \ - $(foreach _at.tmp_variable,$(filter-out _at.tmp_variable $(_at.VARIABLES),$(.VARIABLES)),\ + $(foreach _at.tmp_variable,$(filter-out $(call _at.quote-pattern,_at.tmp_variable $(_at.VARIABLES)),$(.VARIABLES)),\ $(call _at.target_variable,$(_at.tmp_targets),$(_at.tmp_variable))$(at.nl)\ undefine $(_at.tmp_variable)$(at.nl))) -- cgit v1.2.3-54-g00ecf From 95d18493a5d3399993053b94cb1fc4542699f884 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Fri, 28 Oct 2016 12:45:33 -0400 Subject: (systemd) Autothing documentation --- build-aux/Makefile.README.old.txt | 161 +++++++++++++ build-aux/Makefile.README.txt | 262 +++++++++------------ build-aux/Makefile.each.tail/00-dist.mk | 2 +- build-aux/Makefile.each.tail/00-mod.mk | 13 +- build-aux/Makefile.once.head/00-gitfiles.mk | 41 ++++ build-aux/Makefile.once.head/00-quote.mk | 23 +- build-aux/Makefile.once.head/00-var.mk | 14 ++ build-aux/Makefile.once.head/10-dist.mk | 34 +++ build-aux/Makefile.once.head/10-files.mk | 39 +++ build-aux/Makefile.once.head/10-gnuconf.mk | 17 +- build-aux/Makefile.once.head/10-nested.mk | 26 ++ build-aux/Makefile.once.head/10-write-atomic.mk | 18 ++ build-aux/Makefile.once.head/10-write-ifchanged.mk | 18 ++ build-aux/Makefile.once.head/zz-mod.mk | 22 ++ build-aux/Makefile.once.tail/00-dist.mk | 1 + 15 files changed, 523 insertions(+), 168 deletions(-) create mode 100644 build-aux/Makefile.README.old.txt (limited to 'build-aux/Makefile.once.head/10-dist.mk') diff --git a/build-aux/Makefile.README.old.txt b/build-aux/Makefile.README.old.txt new file mode 100644 index 0000000..b0a0965 --- /dev/null +++ b/build-aux/Makefile.README.old.txt @@ -0,0 +1,161 @@ +Obsolete +======== + +The following was written for previous versions of Autothing. I'm leaving it +here for now because I'll likely canibalize it for other bits of documentation, +either for Autothing itself, the `files` module, or the `dist` module. + +High-level overview +------------------- + +Now, what this does for you is: + + (search for the paper +"Recursive Make Considered Harmful") As harmful as recursive make is, +it's historically been difficult to to write non-recursive Makefiles. +This makes it easy. + +It also makes it easy to follow the GNU standards for your makefiles: +it takes care of this entire table of .PHONY targets for you: + +| this | and this | are aliases for this | +|------+------------------+--------------------------------------------------------| +| all | build | $(outdir)/build | +| | install | $(outdir)/install | +| | uninstall | $(outdir)/uninstall | +| | mostlyclean | $(outdir)/mostlyclean | +| | clean | $(outdir)/clean | +| | distclean | $(outdir)/distclean | +| | maintainer-clean | $(outdir)/maintainer-clean | +| | check | $(outdir)/check (not implemented for you) | +| | dist | $(topoutdir)/$(PACKAGE)-$(VERSION).tar.gz (not .PHONY) | + +(You are still responsible for implementing the `$(outdir)/check` +target in each of your Makefiles.) + +What you have to do is: + +In each source directory, you write a `Makefile`, very similarly to if +you were writing for plain GNU Make, with + + topoutdir ?= ... + topsrcdir ?= ... + include $(topsrcdir)/build-aux/Makefile.head.mk + + # your makefile + + include $(topsrcdir)/build-aux/Makefile.tail.mk + +And in the top-level source directory, Write your own helper makefiles +that get included: + - `common.once.head.mk`: before parsing any of your Makefiles + - `common.each.head.mk`: before parsing each of your Makefiles + - `common.each.tail.mk`: after parsing each of your Makefiles + - `common.each.tail.mk`: after parsing all of your Makefiles + +The `common.*.mk` makefiles are nice for including generic pattern +rules and variables that aren't specific to a directory. + +You're probably thinking that this sounds too good to be true! +Unfortunately, there are two major deviations from writing a plain +recursive Makefile: + + 1. all targets and prerequisites (including .PHONY targets!) need to + be prefixed with + `$(srcdir)`/`$(outdir)`/`$(topsrcdir)`/`$(topoutdir)`. + * sub-gotcha: this means that if a pattern rule has a + prerequisite that may be in srcdir or outdir, then it must be + specified twice, once for each case. + 2. if a prerequisite is in a directory "owned" by another Makefile, + you must filter the pathname through `am_path`: + `$(call am_path,YOUR_PATH)`. Further, that path must NOT contain + a `..` segment; if you need to refer to a sibling directory, do it + relative to `$(topoutdir)` or `$(topsrcdir)`. + +Telling automake about your program +----------------------------------- + +You tell automake what to do for you by setting some variables. They +are all prefixed with `am_`; this prefix may be changed by editing the +`_am` variable at the top of `automake.head.mk`. + +The exception to this is the `am_path` variable, which is a macro that +is used to make a list of filenames relative to the appropriate +directory, because unlike normal GNU (Auto)Make, `$(outdir)` isn't +nescessarily equal to `.`. See above. + +There are several commands that generate files; simply record the list +of files that each command generates as the following variable +variables: + +| Variable | Create Command | Delete Command | Description | Relative to | +|--------------+----------------+-----------------------------+-----------------------------------+-------------| +| am_src_files | emacs | rm -rf . | Files that the developer writes | srcdir | +| am_gen_files | ??? | make maintainer-clean | Files the developer compiles | srcdir | +| am_cfg_files | ./configure | make distclean | Users' compile-time configuration | outdir | +| am_out_files | make all | make mostlyclean/make clean | Files the user compiles | outdir | +| am_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 | +|----------------+------------------+------------------------------------------------+-------------| +| am_clean_files | make clean | A list of things to `rm` in addition to the | outdir | +| | | files in `$(am_out_files)`. (Example: `*.o`) | | +|----------------+------------------+------------------------------------------------+-------------| +| am_slow_files | make mostlyclean | A list of things that (as an exception) should | outdir | +| | | _not_ be deleted. (otherwise, `mostlyclean` | | +| | | is the same as `clean`) | | + +Finally, there are two variables that express the relationships +between directories: + +| Variable | Description | +|------------+---------------------------------------------------------| +| am_subdirs | A list of other directories (containing Makefiles) that | +| | may be considered "children" of this | +| | directory/Makefile; building a phony target in this | +| | directory should also build it in the subdirectory. | +| | They are not necesarily actually subdirectories of this | +| | directory in the filesystem. | +|------------+---------------------------------------------------------| +| am_depdirs | A list of other directories (containing Makefiles) that | +| | contain or generate files that are dependencies of | +| | targets in this directory. They are not necesarily | +| | actually subdirectories of this directory in the | +| | filesystem. Except for files that are dependencies of | +| | files in this directory, things in the dependency | +| | directory will not be built. | + +Tips, notes +----------- + +I like to have the first (non-comment) line in a Makefile be: + + include $(dir $(lastword $(MAKEFILE_LIST)))/../../config.mk + +(adjusting the number of `../` sequences as nescessary). Then, my +(user-editable) `config.mk` is of the form: + + ifeq ($(topsrcdir),) + topoutdir := $(patsubst %/,%,$(dir $(lastword $(MAKEFILE_LIST)))) + topsrcdir := $(topoutdir) + + # your configuration + + endif + +If the package has a `./configure` script, then I have it modifiy +topsrcdir as necessary, as well as modifying whatever other parts of +the configuration. All of the configuration lives in `config.mk`; +`./configure` doesn't modify any `Makefile`s, it just generates +`config.mk`, and copies (or (sym?)link?) every `$(srcdir)/Makefile` to +`$(outdir)/Makefile`. + +---- +Copyright (C) 2016 Luke Shumaker + +This documentation file is placed into the public domain. If that is +not possible in your legal system, I grant you permission to use it in +absolutely every way that I can legally grant to you. diff --git a/build-aux/Makefile.README.txt b/build-aux/Makefile.README.txt index e06ba52..3be7a9d 100644 --- a/build-aux/Makefile.README.txt +++ b/build-aux/Makefile.README.txt @@ -1,160 +1,108 @@ -Luke's AutoMake -=============== - -Yo, this document is incomplete. It describes the magical -automake.{head,tail}.mk Makefiles and how to use them, kinda. - -I wrote a "clone" of automake. I say clone, because it works -differently. Yeah, I need a new name for it. - -High-level overview -------------------- - -Now, what this does for you is: - -It makes it _easy_ to write non-recursive Makefiles--and ones that are -similar to plain recursive Makefiles, at that! (search for the paper -"Recursive Make Considered Harmful") As harmful as recursive make is, -it's historically been difficult to to write non-recursive Makefiles. -This makes it easy. - -It also makes it easy to follow the GNU standards for your makefiles: -it takes care of this entire table of .PHONY targets for you: - -| this | and this | are aliases for this | -|------+------------------+--------------------------------------------------------| -| all | build | $(outdir)/build | -| | install | $(outdir)/install | -| | uninstall | $(outdir)/uninstall | -| | mostlyclean | $(outdir)/mostlyclean | -| | clean | $(outdir)/clean | -| | distclean | $(outdir)/distclean | -| | maintainer-clean | $(outdir)/maintainer-clean | -| | check | $(outdir)/check (not implemented for you) | -| | dist | $(topoutdir)/$(PACKAGE)-$(VERSION).tar.gz (not .PHONY) | - -(You are still responsible for implementing the `$(outdir)/check` -target in each of your Makefiles.) - -What you have to do is: - -In each source directory, you write a `Makefile`, very similarly to if -you were writing for plain GNU Make, with - - topoutdir ?= ... - topsrcdir ?= ... - include $(topsrcdir)/build-aux/Makefile.head.mk - - # your makefile - - include $(topsrcdir)/build-aux/Makefile.tail.mk - -And in the top-level source directory, Write your own helper makefiles -that get included: - - `common.once.head.mk`: before parsing any of your Makefiles - - `common.each.head.mk`: before parsing each of your Makefiles - - `common.each.tail.mk`: after parsing each of your Makefiles - - `common.each.tail.mk`: after parsing all of your Makefiles - -The `common.*.mk` makefiles are nice for including generic pattern -rules and variables that aren't specific to a directory. - -You're probably thinking that this sounds too good to be true! -Unfortunately, there are two major deviations from writing a plain -recursive Makefile: - - 1. all targets and prerequisites (including .PHONY targets!) need to - be prefixed with - `$(srcdir)`/`$(outdir)`/`$(topsrcdir)`/`$(topoutdir)`. - * sub-gotcha: this means that if a pattern rule has a - prerequisite that may be in srcdir or outdir, then it must be - specified twice, once for each case. - 2. if a prerequisite is in a directory "owned" by another Makefile, - you must filter the pathname through `am_path`: - `$(call am_path,YOUR_PATH)`. Further, that path must NOT contain - a `..` segment; if you need to refer to a sibling directory, do it - relative to `$(topoutdir)` or `$(topsrcdir)`. - -Telling automake about your program ------------------------------------ - -You tell automake what to do for you by setting some variables. They -are all prefixed with `am_`; this prefix may be changed by editing the -`_am` variable at the top of `automake.head.mk`. - -The exception to this is the `am_path` variable, which is a macro that -is used to make a list of filenames relative to the appropriate -directory, because unlike normal GNU (Auto)Make, `$(outdir)` isn't -nescessarily equal to `.`. See above. - -There are several commands that generate files; simply record the list -of files that each command generates as the following variable -variables: - -| Variable | Create Command | Delete Command | Description | Relative to | -|--------------+----------------+-----------------------------+-----------------------------------+-------------| -| am_src_files | emacs | rm -rf . | Files that the developer writes | srcdir | -| am_gen_files | ??? | make maintainer-clean | Files the developer compiles | srcdir | -| am_cfg_files | ./configure | make distclean | Users' compile-time configuration | outdir | -| am_out_files | make all | make mostlyclean/make clean | Files the user compiles | outdir | -| am_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 | -|----------------+------------------+------------------------------------------------+-------------| -| am_clean_files | make clean | A list of things to `rm` in addition to the | outdir | -| | | files in `$(am_out_files)`. (Example: `*.o`) | | -|----------------+------------------+------------------------------------------------+-------------| -| am_slow_files | make mostlyclean | A list of things that (as an exception) should | outdir | -| | | _not_ be deleted. (otherwise, `mostlyclean` | | -| | | is the same as `clean`) | | - -Finally, there are two variables that express the relationships -between directories: - -| Variable | Description | -|------------+---------------------------------------------------------| -| am_subdirs | A list of other directories (containing Makefiles) that | -| | may be considered "children" of this | -| | directory/Makefile; building a phony target in this | -| | directory should also build it in the subdirectory. | -| | They are not necesarily actually subdirectories of this | -| | directory in the filesystem. | -|------------+---------------------------------------------------------| -| am_depdirs | A list of other directories (containing Makefiles) that | -| | contain or generate files that are dependencies of | -| | targets in this directory. They are not necesarily | -| | actually subdirectories of this directory in the | -| | filesystem. Except for files that are dependencies of | -| | files in this directory, things in the dependency | -| | directory will not be built. | - -Tips, notes ------------ - -I like to have the first (non-comment) line in a Makefile be: - - include $(dir $(lastword $(MAKEFILE_LIST)))/../../config.mk - -(adjusting the number of `../` sequences as nescessary). Then, my -(user-editable) `config.mk` is of the form: - - ifeq ($(topsrcdir),) - topoutdir := $(patsubst %/,%,$(dir $(lastword $(MAKEFILE_LIST)))) - topsrcdir := $(topoutdir) - - # your configuration - - endif - -If the package has a `./configure` script, then I have it modifiy -topsrcdir as necessary, as well as modifying whatever other parts of -the configuration. All of the configuration lives in `config.mk`; -`./configure` doesn't modify any `Makefile`s, it just generates -`config.mk`, and copies (or (sym?)link?) every `$(srcdir)/Makefile` to -`$(outdir)/Makefile`. +# -*- Mode: markdown -*- + +Autothing 3: The smart way to write GNU Makefiles +================================================= + +Autothing is a thing that does things automatically. + +Ok, more helpfully: Autothing is a pair of .mk Makefile fragments that +you can `include` from your Makefiles to make them easier to write; +specifically, it makes it _easy_ to write non-recursive Makefiles--and +ones that are similar to plain recursive Makefiles, at that! + +Synopsis +-------- + +Write your makefiles of the form: + + topsrcdir ?= ... + topoutdir ?= ... + at.Makefile ?= Makefile # Optional + include $(topsrcdir)/build-aux/Makefile.head.mk + + $(outdir)/%.o: $(srcdir)/%.c: + $(CC) -c -o $@ $< + + $(outdir)/hello: $(outdir)/hello.o + + at.subdirs = ... + at.targets = ... + + include $(topsrcdir)/build-aux/Makefile.tail.mk + +This is similar to, but not quite, the comfortable way that you probably +already write your Makefiles. + +Details +------- + +There are two fundamental things that Autothing provides: + + 1. Variable namespacing + 2. Tools for dealing with paths + +The first is important because globals are bad for composability. + +The second is important because GNU Make is too dumb to know that +`foo/bar/../baz` == `foo/baz`. + +Then, there's something that maybe doesn't belong, but I didn't have the heart +to cut it out: + + 3. A module (plugin) system. + +The module system is "important" because there are very often common bits that +you want to be included in every Makefile, and this gives some structure to +that. + +Requirements: + - A version of GNU Make that supports `undefine`. (TODO: check which version + of GNU Make introduced this feature) + +Inputs: + - In each `Makefile`: + - Before `Makefile.head.mk`: + - Variable (mandatory) : `topoutdir` + - Variable (mandatory) : `topsrcdir` (must not be a subdirectory of `$(topoutdir)`) + - Variable (optional) : `at.Makefile` (Default: `Makefile`) + - Between `Makefile.head.mk` and `Makefile.tail.mk`: + - Variable: `at.targets` (Default: empty) + - Variable: `at.subdirs` (Default: empty) + - Files: + - `${topsrcdir}/build-aux/Makefile.{each,once}.{head,tail}/*.mk` + +Outputs: + - Global: + - Variable (function): `$(call at.is_subdir, parent, child)` + - Variable (function): `$(call at.is_strict_subdir, parent, child)` + - Variable (function): `$(call at.relbase, parent, children...)` + - Variable (function): `$(call at.relto, parent, children...)` + - Variable (function): `$(call at.path, paths...)` + - Variable (function): `$(call at.out2src, paths...)` + - Variable (function): `$(call at.addprefix, prefix, paths...)` + - Per-directory: + - Variable: `$(outdir)` + - Variable: `$(srcdir)` + +TODO: actually explain things. + +Motivation/Exposition +--------------------- + +This section needs rewritten. Or really just written. + +Other projects like GNU Automake were created to plaster over differences +between make(1) implementations; however, this isn't all that Automake +provides, it also makes it easy to do complex things that users want, or the +GNU Coding Standards require. That's silly. + +Autothing does depend on GNU Make; other make(1) implementations will +not work. However, if you are open to adding GNU Make as a +dependency, then Autothing should obviate the need for GNU Automake, +while also making your Makefiles better. + + Peter Miller (1997) "Recursive Make Considered Harmful" + ---- Copyright (C) 2016 Luke Shumaker diff --git a/build-aux/Makefile.each.tail/00-dist.mk b/build-aux/Makefile.each.tail/00-dist.mk index df363b5..bc2a3d5 100644 --- a/build-aux/Makefile.each.tail/00-dist.mk +++ b/build-aux/Makefile.each.tail/00-dist.mk @@ -1 +1 @@ -_dist.files := $(strip $(_dist.files) $(_files.src)) +_dist.files := $(strip $(_dist.files) $(call at.addprefix,$(srcdir),$(files.src))) diff --git a/build-aux/Makefile.each.tail/00-mod.mk b/build-aux/Makefile.each.tail/00-mod.mk index dc1a2fe..5b77436 100644 --- a/build-aux/Makefile.each.tail/00-mod.mk +++ b/build-aux/Makefile.each.tail/00-mod.mk @@ -29,12 +29,15 @@ at.targets += $(addprefix $(outdir)/, at-variables-global at-variables-local at- $(outdir)/at-modules: @printf 'Autothing modules used in this project:\n' - @printf ' - %s\n' $(foreach _mod.tmp,$(_mod.modules),$(call quote.shell,$(_mod.tmp) $(mod.$(_mod.tmp).description)))|column -t -s $$'\t' + @printf ' - %s\n' $(foreach _mod.tmp,$(_mod.modules),$(call quote.shell,$(_mod.tmp) $(mod.$(_mod.tmp).description) $(if $(value mod.$(_mod.tmp).doc),(more))))|column -t -s $$'\t' $(addprefix $(outdir)/at-modules/,$(_mod.modules)): $(outdir)/at-modules/%: - @printf 'Name : %s\n' $(call quote.shell,$*) - @printf 'Description : %s\n' $(call quote.shell,$(mod.$*.description)) - @echo 'Contains Files :' $(call quote.shell-each,$(call at.relto,$(topsrcdir),$(sort $(mod.$*.files) $(wildcard $(topsrcdir)/build-aux/Makefile.*/??-$*.mk)))) - @echo 'Depends on :' $(mod.$*.depends) + @printf 'Name : %s\n' $(call quote.shell,$*) + @printf 'Description : %s\n' $(call quote.shell,$(mod.$*.description)) + @echo 'Depends on :' $(sort $(mod.$*.depends)) + @echo 'Files :' + @printf ' %s\n' $(call quote.shell-each,$(call at.relto,$(topsrcdir),$(sort $(mod.$*.files) $(wildcard $(topsrcdir)/build-aux/Makefile.*/??-$*.mk)))) + @echo 'Documentation :' + @printf '%s\n' $(call quote.shell,$(value mod.$*.doc)) | sed -e 's/^# / /' -e 's/^#//' $(outdir)/at-noop: .PHONY: $(outdir)/at-noop diff --git a/build-aux/Makefile.once.head/00-gitfiles.mk b/build-aux/Makefile.once.head/00-gitfiles.mk index b17b63a..faae91d 100644 --- a/build-aux/Makefile.once.head/00-gitfiles.mk +++ b/build-aux/Makefile.once.head/00-gitfiles.mk @@ -15,6 +15,47 @@ mod.gitfiles.description = Automatically populate files.src.src from git mod.gitfiles.depends += files nested write-ifchanged quote +mod.gitfiles.files += $(topsrcdir)/$(gitfiles.file) +define mod.gitfiles.doc +# Inputs: +# - Global variable : `gitfiles.file` (Default: gitfiles.mk) +# - Directory variable : `nested.subdirs` +# - External : git +# Outputs: +# - File : `$(topsrcdir)/$(gitfiles.file)` +# - Directory variable : `files.src.src` +# - Directory variable : `files.src.gen` (only in top dir) +# +# The `files` module has a variable (`files.src.src`) that you (the +# developer) set to list "pure" source files; the type of files that you +# would check into a version control system. Since you are a +# responsible developer, you use a version control system. Since the +# computer is already maintaining a list of these files *in the VCS*, +# why should you--a filthy human--need to also maintain the list? Enter +# gitfiles, which will talk to git to maintain `files.src.src`, but +# won't require that the git repository be distributed to +# installing-users. +# +# If `$(topsrcdir)/.git` exists, then it will generate +# `$(topsrcdir)/$(gitfiles.file)`. Otherwise, it will assume that +# `$(topsrcdir)/$(gitfiles.file)` already exists. +# +# It will use the information in `$(topsrcdir)/$(gitfiles.file)` to +# append to `files.src.src` in each directory +# +# Finally, since the generated `$(topsrcdir)/$(gitfiles.file)` must be +# distributed to users, it is added to $(topsrcdirs)'s `files.src.gen`. +# +# When setting `files.src.src`, it needs to know which files "belong" to +# the current directory directly, and which "belong" to a further +# subdirectory. To do this, it uses an expression involving +# `$(nested.subdirs)`. +# +# While gitfiles sets `files.src.src` very early +# in `each.head`, because `nested.subdirs` might not be set yet, it may +# or may not be safe to use the value of `$(files.src.src)` in your +# Makefile, depending on how you set `nested.subdirs`. +endef gitfiles.file ?= gitfiles.mk diff --git a/build-aux/Makefile.once.head/00-quote.mk b/build-aux/Makefile.once.head/00-quote.mk index 9fce401..4c954b1 100644 --- a/build-aux/Makefile.once.head/00-quote.mk +++ b/build-aux/Makefile.once.head/00-quote.mk @@ -14,6 +14,24 @@ # along with this program. If not, see . mod.quote.description = Macros to quote tricky strings +define mod.quote.doc +# Inputs: +# (none) +# Outputs: +# - Global variable: `quote.var` : GNU Make variables +# - Global variable: `quote.pattern` : GNU Make patterns +# - Global variable: `quote.ere` : POSIX Extended Regular Expressions +# - Global variable: `quote.bre` : POSIX Basic Regular Expressions +# - Global variable: `quote.shell` : POSIX sh(1) strings +# - Global variable: `quote.shell-each`: POSIX sh(1) strings +# +# Escaping/quoting things is hard! This module provides a number of +# functions to escape/quote strings for various contexts. +# +# `quote.shell-each` quotes each list-item separately (munging +# whitespace), while `quote.shell` keeps them as one string (preserving +# whitespace). +endef _quote.backslash = $(if $1,$(call _quote.backslash,$(wordlist 2,$(words $1),$1),$(subst $(firstword $1),\$(firstword $1),$2)),$2) @@ -24,6 +42,7 @@ quote.bre = $(call _quote.backslash, \ ^ . [ $$ * ,$1) quote.shell-each = $(foreach _quote.tmp,$1,$(call quote.shell,$(_quote.tmp))) -# I put this as the last line in the file because it confuses Emacs syntax -# highlighting and makes the remainder of the file difficult to edit. +# I put this as the last line in the file because it confuses Emacs +# syntax highlighting and makes the remainder of the file difficult to +# edit. quote.shell = $(subst $(at.nl),'$$'\n'','$(subst ','\'',$1)') diff --git a/build-aux/Makefile.once.head/00-var.mk b/build-aux/Makefile.once.head/00-var.mk index d1e537e..636bbb0 100644 --- a/build-aux/Makefile.once.head/00-var.mk +++ b/build-aux/Makefile.once.head/00-var.mk @@ -14,5 +14,19 @@ # along with this program. If not, see . mod.var.description = Depend on the values of variables +define mod.var.doc +# Inputs: +# (user-defined) +# Outputs: +# Target : `$(outdir)/.var.%` +# Directory variable: `at.targets` +# +# It's a well-known secret that many files generated by a Makefile vary with +# the values of particular variables, but that GNU Make can't track these +# dependencies. Well, with some cleverness, it actually can! +# +# With this module, to depend on the value of a variable, depend on +# `$(outdir)/.var.VARNAME`. +endef .PHONY: _var.FORCE diff --git a/build-aux/Makefile.once.head/10-dist.mk b/build-aux/Makefile.once.head/10-dist.mk index e139096..8c68d04 100644 --- a/build-aux/Makefile.once.head/10-dist.mk +++ b/build-aux/Makefile.once.head/10-dist.mk @@ -14,6 +14,40 @@ # along with this program. If not, see . mod.dist.description = `dist` target for distribution tarballs +define mod.dist.doc +# User variables: +# - `CP ?= cp` +# - `GZIP ?= gzip` +# - `MKDIR ?= mkdir` +# - `MKDIR_P ?= mkdir -p` +# - `MV ?= mv` +# - `RM ?= rm -f` +# - `TAR ?= tar` +# - `GZIPFLAGS ?= $(GZIP_ENV)` +# - `GZIP_ENV ?= --best` (only used via `GZIPFLAGS`, not directly) +# Inputs: +# - Global variable : `dist.exts` (Default: `.tar.gz`) +# - Global variable : `dist.pkgname` (Default: first of PACKAGE_TARNAME PACKAGE PACKAGE_NAME) +# - Global variable : `dist.version` (Default: first of PACKAGE_VERSION VERSION) +# - Directory variable : `files.src` +# Outputs: +# - Directory variable : `files.out.int` (only in top dir) +# - .PHONY Target : `$(outdir)/dist` +# - Target : `$(topoutdir)/$(dist.pkgname)-$(dist.version)` +# - Target : `$(topoutdir)/$(dist.pkgname)-$(dist.version).tar` +# - Target : `$(topoutdir)/$(dist.pkgname)-$(dist.version).tar.gz` +# +# Provide the standard `dist` .PHONY target, based on the `files` module +# information. +# +# You may change the default compression target easily via the +# `dist.exts` variable, but you must define the rule for it manually. +# +# Bugs: +# +# The tarball isn't reproducible. It uses file-system ordering of +# files, and includes timestamps. +endef # Developer configuration diff --git a/build-aux/Makefile.once.head/10-files.mk b/build-aux/Makefile.once.head/10-files.mk index 5441735..9d27ae9 100644 --- a/build-aux/Makefile.once.head/10-files.mk +++ b/build-aux/Makefile.once.head/10-files.mk @@ -15,6 +15,45 @@ mod.files.description = Keeping track of groups of files mod.files.depends += nested +define mod.files.doc +# User variables: +# - `DESTDIR ?=` +# - `RM ?= rm -f` +# - `RMDIR_P ?= rmdir -p --ignore-fail-on-non-empty` +# - `TRUE ?= true` +# Inputs: +# - Global variable : `files.groups ?= all` +# - Global variable : `files.default ?= all` +# - Global variable : `files.vcsclean ?= files.vcsclean` +# - Global variable : `files.generate ?= files.generate` +# - Directory variable : `files.src.src` +# - Directory variable : `files.src.int` +# - Directory variable : `files.src.cfg` +# - Directory variable : `files.src.gen` +# - Directory variable : `files.out.slow` +# - Directory variable : `files.out.int` +# - Directory variable : `files.out.cfg` +# - Directory variable : `files.out.$(files.groups)` (well, $(addprefix...)) +# - Directory variable : `files.sys.$(files.groups)` (well, $(addprefix...)) +# Outputs: +# - Global variable : `nested.targets` +# - Global variable : `at.targets` +# - Global variable : `.DEFAULT_GOAL = $(files.default)` +# - Creative .PHONY targets: +# - `$(outdir)/$(files.generate))` +# - `$(addprefix $(outdir)/,$(files.groups))` +# - `$(outdir)/installdirs` +# - `$(outdir)/install` +# - Destructive .PHONY targets: +# - `$(outdir)/uninstall` +# - `$(outdir)/mostlyclean` +# - `$(outdir)/clean` +# - `$(outdir)/distclean` +# - `$(outdir)/maintainer-clean` +# - `$(outdir)/$(files.vcsclean)` +# +# TODO: prose documentation +endef files.groups ?= all files.default ?= all diff --git a/build-aux/Makefile.once.head/10-gnuconf.mk b/build-aux/Makefile.once.head/10-gnuconf.mk index c07cfb5..6d641bb 100644 --- a/build-aux/Makefile.once.head/10-gnuconf.mk +++ b/build-aux/Makefile.once.head/10-gnuconf.mk @@ -13,10 +13,21 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . -# This file is based on §7.2 "Makefile Conventions" of the release of -# the GNU Coding Standards dated July 25, 2016. - mod.gnuconf.description = GNU standard configuration variables +define mod.gnuconf.doc +# Inputs: +# - Global variable: `gnuconf.pkgname` +# (Default: `$(firstword $(PACKAGE_TARNAME) $(PACKAGE) $(PACKAGE_NAME))`) +# Outputs: +# (see below) +# +# This module defines default values (using `?=`) a huge list of +# variables specified in the GNU Coding Standards that installing-users +# expect to be able to set. +# +# This is based on §7.2 "Makefile Conventions" of the July 25, 2016 +# release of the GNU Coding Standards. +endef gnuconf.pkgname ?= $(firstword $(PACKAGE_TARNAME) $(PACKAGE) $(PACKAGE_NAME)) ifeq ($(gnuconf.pkgname),) diff --git a/build-aux/Makefile.once.head/10-nested.mk b/build-aux/Makefile.once.head/10-nested.mk index af9fdf7..72e15ab 100644 --- a/build-aux/Makefile.once.head/10-nested.mk +++ b/build-aux/Makefile.once.head/10-nested.mk @@ -14,5 +14,31 @@ # along with this program. If not, see . mod.nested.description = Easy nested .PHONY targets +define mod.nested.doc +# Inputs: +# - Global variable : `nested.targets` +# - Directory variable : `nested.subdirs` +# Outputs: +# - .PHONY Targets : `$(addprefix $(outdir)/,$(nested.targets))` +# - Variable : `at.subdirs` +# +# The Autothing `at.subdirs` slates a subdirectory's Makefile for inclusion, +# but doesn't help with recursive targets like `all`, `install`, or `clean`, +# which one would expect to descend into subdirectories. Enter `nested`: +# Define a global list of targets that are recursive/nested, and then in each +# directory define a list of subdirectries that one would expect them to +# recurse into. +# +# Directories added to `nested.subdirs` are automatically added to `at.subdirs` +# during the each.tail phase. +# +# It may help to think of at.subdirs and nested.subdirs in terms of their +# Automake conterparts: +# +# | Autothing | GNU Automake | +# +----------------+--------------+ +# | at.subdirs | DIST_SUBDIRS | +# | nested.subdirs | SUBDIRS | +endef nested.targets ?= diff --git a/build-aux/Makefile.once.head/10-write-atomic.mk b/build-aux/Makefile.once.head/10-write-atomic.mk index f099ae2..ce6acd8 100644 --- a/build-aux/Makefile.once.head/10-write-atomic.mk +++ b/build-aux/Makefile.once.head/10-write-atomic.mk @@ -1,4 +1,22 @@ mod.write-atomic.description = `write-atomic` auxiliary build script mod.write-atomic.files += $(topsrcdir)/build-aux/write-atomic +define mod.write-atomic.doc +# User variables: +# - `WRITE_ATOMIC ?= $(topsrcdir)/build-aux/write-atomic` +# Inputs: +# (none) +# Outputs: +# (none) +# +# The $(WRITE_ATOMIC) program reads a file from stdin, and writes it to +# the file named in argv[1], but does so atomically. +# +# That is, the following lines are almost equivalient: +# +# ... > $@ +# ... | $(WRITE_ATOMIC) $@ +# +# The are only different in that one is atomic, while the other is not. +endef WRITE_ATOMIC ?= $(topsrcdir)/build-aux/write-atomic diff --git a/build-aux/Makefile.once.head/10-write-ifchanged.mk b/build-aux/Makefile.once.head/10-write-ifchanged.mk index b0a5ac4..5abb3ce 100644 --- a/build-aux/Makefile.once.head/10-write-ifchanged.mk +++ b/build-aux/Makefile.once.head/10-write-ifchanged.mk @@ -1,4 +1,22 @@ mod.write-ifchanged.description = `write-ifchanged` auxiliary build script mod.write-ifchanged.files += $(topsrcdir)/build-aux/write-ifchanged +define mod.write-ifchanged.doc +# User variables: +# - `WRITE_IFCHANGED ?= $(topsrcdir)/build-aux/write-ifchanged` +# Inputs: +# (none) +# Outputs: +# (none) +# +# The $(WRITE_IFCHANGED) program reads a file from stdin, and writes it to the +# file named in argv[1], but does so atomically, but more importantly, does so +# in a way that does not bump the file's ctime if the new content is the same +# as the old content. +# +# That is, the following lines are almost equivalient: +# +# ... > $@ +# ... | $(WRITE_ATOMIC) $@ +endef WRITE_IFCHANGED ?= $(topsrcdir)/build-aux/write-ifchanged diff --git a/build-aux/Makefile.once.head/zz-mod.mk b/build-aux/Makefile.once.head/zz-mod.mk index 732f1e1..1b12a2f 100644 --- a/build-aux/Makefile.once.head/zz-mod.mk +++ b/build-aux/Makefile.once.head/zz-mod.mk @@ -15,6 +15,28 @@ mod.mod.description = Display information about Autothing modules mod.mod.depends += quote +define mod.mod.doc +# Inputs: +# - Files : `$(topsrcdir)/build-aux/Makefile.*/??-*.mk` +# - Global variable : `mod.*.name` +# - Global variable : `mod.*.description` +# - Global variable : `mod.*.depends` +# - Global variable : `mod.*.files` +# - Global variable : `mod.*.doc` +# Outputs: +# - Directory variable : `at.targets` +# - .PHONY Target : `$(outdir)/at-variables-local` +# - .PHONY Target : `$(outdir)/at-variables-global` +# - .PHONY Target : `$(outdir)/at-variables` +# - .PHONY Target : `$(outdir)/at-variables/%` +# - .PHONY Target : `$(outdir)/at-values` +# - .PHONY Target : `$(outdir)/at-values/%` +# - .PHONY Target : `$(outdir)/at-modules` +# - .PHONY Target : `$(outdir)/at-modules/%` +# - .PHONY Target : `$(outdir)/at-noop` +# +# TODO: prose documentation +endef # The trickery that is _mod.empty/_mod.space is from §6.2 of the GNU Make # manual, "The Two Flavors of Variables". diff --git a/build-aux/Makefile.once.tail/00-dist.mk b/build-aux/Makefile.once.tail/00-dist.mk index 3fbe0c4..a890d9d 100644 --- a/build-aux/Makefile.once.tail/00-dist.mk +++ b/build-aux/Makefile.once.tail/00-dist.mk @@ -21,6 +21,7 @@ $(topoutdir)/$(dist.pkgname)-$(dist.version): $(_dist.files) $(foreach f,$^,$(call _dist.addfile,$(topsrcdir),$(@D)/.tmp.$(@F),$f)$(at.nl)) $(MV) $(@D)/.tmp.$(@F) $@ || $(RM) -r $(@D)/.tmp.$(@F) +# TODO: The tar rule isn't reproducible, it should be. $(topoutdir)/$(dist.pkgname)-$(dist.version).tar: %.tar: % $(TAR) cf $@ -C $( Date: Sun, 30 Oct 2016 19:27:23 -0400 Subject: (systemd) at: mod: don't call on .doc --- build-aux/Makefile.each.tail/00-mod.mk | 4 ++-- build-aux/Makefile.once.head/00-gitfiles.mk | 1 + build-aux/Makefile.once.head/00-quote.mk | 1 + build-aux/Makefile.once.head/00-var.mk | 1 + build-aux/Makefile.once.head/10-dist.mk | 1 + build-aux/Makefile.once.head/10-files.mk | 1 + build-aux/Makefile.once.head/10-gnuconf.mk | 1 + build-aux/Makefile.once.head/10-nested.mk | 1 + build-aux/Makefile.once.head/10-write-atomic.mk | 1 + build-aux/Makefile.once.head/10-write-ifchanged.mk | 1 + build-aux/Makefile.once.head/zz-mod.mk | 5 +++-- 11 files changed, 14 insertions(+), 4 deletions(-) (limited to 'build-aux/Makefile.once.head/10-dist.mk') diff --git a/build-aux/Makefile.each.tail/00-mod.mk b/build-aux/Makefile.each.tail/00-mod.mk index 5b77436..d6514dd 100644 --- a/build-aux/Makefile.each.tail/00-mod.mk +++ b/build-aux/Makefile.each.tail/00-mod.mk @@ -29,7 +29,7 @@ at.targets += $(addprefix $(outdir)/, at-variables-global at-variables-local at- $(outdir)/at-modules: @printf 'Autothing modules used in this project:\n' - @printf ' - %s\n' $(foreach _mod.tmp,$(_mod.modules),$(call quote.shell,$(_mod.tmp) $(mod.$(_mod.tmp).description) $(if $(value mod.$(_mod.tmp).doc),(more))))|column -t -s $$'\t' + @printf ' - %s\n' $(foreach _mod.tmp,$(_mod.modules),$(call quote.shell,$(_mod.tmp) $(mod.$(_mod.tmp).description) $(if $(mod.$(_mod.tmp).doc),(more))))|column -t -s $$'\t' $(addprefix $(outdir)/at-modules/,$(_mod.modules)): $(outdir)/at-modules/%: @printf 'Name : %s\n' $(call quote.shell,$*) @printf 'Description : %s\n' $(call quote.shell,$(mod.$*.description)) @@ -37,7 +37,7 @@ $(addprefix $(outdir)/at-modules/,$(_mod.modules)): $(outdir)/at-modules/%: @echo 'Files :' @printf ' %s\n' $(call quote.shell-each,$(call at.relto,$(topsrcdir),$(sort $(mod.$*.files) $(wildcard $(topsrcdir)/build-aux/Makefile.*/??-$*.mk)))) @echo 'Documentation :' - @printf '%s\n' $(call quote.shell,$(value mod.$*.doc)) | sed -e 's/^# / /' -e 's/^#//' + @printf '%s\n' $(call quote.shell,$(mod.$*.doc)) | sed -e 's/^# / /' -e 's/^#//' $(outdir)/at-noop: .PHONY: $(outdir)/at-noop diff --git a/build-aux/Makefile.once.head/00-gitfiles.mk b/build-aux/Makefile.once.head/00-gitfiles.mk index faae91d..1214e50 100644 --- a/build-aux/Makefile.once.head/00-gitfiles.mk +++ b/build-aux/Makefile.once.head/00-gitfiles.mk @@ -56,6 +56,7 @@ define mod.gitfiles.doc # or may not be safe to use the value of `$(files.src.src)` in your # Makefile, depending on how you set `nested.subdirs`. endef +mod.gitfiles.doc := $(value mod.gitfiles.doc) gitfiles.file ?= gitfiles.mk diff --git a/build-aux/Makefile.once.head/00-quote.mk b/build-aux/Makefile.once.head/00-quote.mk index 4c954b1..94bc943 100644 --- a/build-aux/Makefile.once.head/00-quote.mk +++ b/build-aux/Makefile.once.head/00-quote.mk @@ -32,6 +32,7 @@ define mod.quote.doc # whitespace), while `quote.shell` keeps them as one string (preserving # whitespace). endef +mod.quote.doc := $(value mod.quote.doc) _quote.backslash = $(if $1,$(call _quote.backslash,$(wordlist 2,$(words $1),$1),$(subst $(firstword $1),\$(firstword $1),$2)),$2) diff --git a/build-aux/Makefile.once.head/00-var.mk b/build-aux/Makefile.once.head/00-var.mk index 636bbb0..1f50f21 100644 --- a/build-aux/Makefile.once.head/00-var.mk +++ b/build-aux/Makefile.once.head/00-var.mk @@ -28,5 +28,6 @@ define mod.var.doc # With this module, to depend on the value of a variable, depend on # `$(outdir)/.var.VARNAME`. endef +mod.var.doc := $(value mod.var.doc) .PHONY: _var.FORCE diff --git a/build-aux/Makefile.once.head/10-dist.mk b/build-aux/Makefile.once.head/10-dist.mk index 8c68d04..831ca12 100644 --- a/build-aux/Makefile.once.head/10-dist.mk +++ b/build-aux/Makefile.once.head/10-dist.mk @@ -48,6 +48,7 @@ define mod.dist.doc # The tarball isn't reproducible. It uses file-system ordering of # files, and includes timestamps. endef +mod.dist.doc := $(value mod.dist.doc) # Developer configuration diff --git a/build-aux/Makefile.once.head/10-files.mk b/build-aux/Makefile.once.head/10-files.mk index 9d27ae9..e697a88 100644 --- a/build-aux/Makefile.once.head/10-files.mk +++ b/build-aux/Makefile.once.head/10-files.mk @@ -54,6 +54,7 @@ define mod.files.doc # # TODO: prose documentation endef +mod.files.doc := $(value mod.files.doc) files.groups ?= all files.default ?= all diff --git a/build-aux/Makefile.once.head/10-gnuconf.mk b/build-aux/Makefile.once.head/10-gnuconf.mk index 6d641bb..a4b7696 100644 --- a/build-aux/Makefile.once.head/10-gnuconf.mk +++ b/build-aux/Makefile.once.head/10-gnuconf.mk @@ -28,6 +28,7 @@ define mod.gnuconf.doc # This is based on §7.2 "Makefile Conventions" of the July 25, 2016 # release of the GNU Coding Standards. endef +mod.gnuconf.doc := $(value mod.gnuconf.doc) gnuconf.pkgname ?= $(firstword $(PACKAGE_TARNAME) $(PACKAGE) $(PACKAGE_NAME)) ifeq ($(gnuconf.pkgname),) diff --git a/build-aux/Makefile.once.head/10-nested.mk b/build-aux/Makefile.once.head/10-nested.mk index 72e15ab..4f181a9 100644 --- a/build-aux/Makefile.once.head/10-nested.mk +++ b/build-aux/Makefile.once.head/10-nested.mk @@ -40,5 +40,6 @@ define mod.nested.doc # | at.subdirs | DIST_SUBDIRS | # | nested.subdirs | SUBDIRS | endef +mod.nested.doc := $(value mod.nested.doc) nested.targets ?= diff --git a/build-aux/Makefile.once.head/10-write-atomic.mk b/build-aux/Makefile.once.head/10-write-atomic.mk index ce6acd8..c4aa808 100644 --- a/build-aux/Makefile.once.head/10-write-atomic.mk +++ b/build-aux/Makefile.once.head/10-write-atomic.mk @@ -18,5 +18,6 @@ define mod.write-atomic.doc # # The are only different in that one is atomic, while the other is not. endef +mod.write-atomic.doc := $(value mod.write-atomic.doc) WRITE_ATOMIC ?= $(topsrcdir)/build-aux/write-atomic diff --git a/build-aux/Makefile.once.head/10-write-ifchanged.mk b/build-aux/Makefile.once.head/10-write-ifchanged.mk index 5abb3ce..649aab9 100644 --- a/build-aux/Makefile.once.head/10-write-ifchanged.mk +++ b/build-aux/Makefile.once.head/10-write-ifchanged.mk @@ -18,5 +18,6 @@ define mod.write-ifchanged.doc # ... > $@ # ... | $(WRITE_ATOMIC) $@ endef +mod.write-ifchanged.doc := $(value mod.write-ifchanged.doc) WRITE_IFCHANGED ?= $(topsrcdir)/build-aux/write-ifchanged diff --git a/build-aux/Makefile.once.head/zz-mod.mk b/build-aux/Makefile.once.head/zz-mod.mk index 1b12a2f..95d251d 100644 --- a/build-aux/Makefile.once.head/zz-mod.mk +++ b/build-aux/Makefile.once.head/zz-mod.mk @@ -18,7 +18,6 @@ mod.mod.depends += quote define mod.mod.doc # Inputs: # - Files : `$(topsrcdir)/build-aux/Makefile.*/??-*.mk` -# - Global variable : `mod.*.name` # - Global variable : `mod.*.description` # - Global variable : `mod.*.depends` # - Global variable : `mod.*.files` @@ -37,6 +36,7 @@ define mod.mod.doc # # TODO: prose documentation endef +mod.mod.doc := $(value mod.mod.doc) # The trickery that is _mod.empty/_mod.space is from §6.2 of the GNU Make # manual, "The Two Flavors of Variables". @@ -55,4 +55,5 @@ undefine _mod.file2mod $(eval $(foreach _mod.tmp,$(_mod.modules),\ mod.$(_mod.tmp).description ?=$(at.nl)\ mod.$(_mod.tmp).depends ?=$(at.nl)\ - mod.$(_mod.tmp).files ?=$(at.nl))) + mod.$(_mod.tmp).files ?=$(at.nl)\ + mod.$(_mod.tmp).doc ?=$(at.nl))) -- cgit v1.2.3-54-g00ecf From 2d33bd2f34f011c4f025a073b50d536f6a66a4db Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Mon, 16 Jan 2017 19:27:20 -0500 Subject: Improve documentation. --- Makefile | 12 + README.md | 115 +--------- build-aux/Makefile.README.old.txt | 134 +---------- build-aux/Makefile.README.txt | 391 +++++++++++++++++++++++++++++--- build-aux/Makefile.once.head/10-dist.mk | 2 +- 5 files changed, 381 insertions(+), 273 deletions(-) mode change 100644 => 120000 README.md (limited to 'build-aux/Makefile.once.head/10-dist.mk') diff --git a/Makefile b/Makefile index cd5a79c..fe9010a 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,15 @@ +# This Makefile is a minimal stub that exists to allow the +# `at-modules` set of Make targets to print documentation for the +# present Autothing modules. +# +# This file is part of the documentation for Autothing. +# +# Copyright (C) 2017 Luke Shumaker +# +# This documentation file is placed into the public domain. If that +# is not possible in your legal system, I grant you permission to use +# it in absolutely every way that I can legally grant to you. + dist.pkgname = autothing dist.version = 1.0 gnuconf.pkgname = autothing diff --git a/README.md b/README.md deleted file mode 100644 index ac5ff61..0000000 --- a/README.md +++ /dev/null @@ -1,114 +0,0 @@ -Autothing 3: The smart way to write GNU Makefiles -================================================= - -Autothing is a thing that does things automatically. - -Ok, more helpfully: Autothing is a pair of .mk Makefile fragments that -you can `include` from your Makefiles to make them easier to write; -specifically, it makes it _easy_ to write non-recursive Makefiles--and -ones that are similar to plain recursive Makefiles, at that! - -Sample ------- - -Write your makefiles of the form: - - topsrcdir ?= ... - topoutdir ?= ... - at.Makefile ?= Makefile # Optional - include $(topsrcdir)/build-aux/Makefile.head.mk - - $(outdir)/%.o: $(srcdir)/%.c: - $(CC) -c -o $@ $< - - $(outdir)/hello: $(outdir)/hello.o - - at.subdirs = ... - at.targets = ... - - include $(topsrcdir)/build-aux/Makefile.tail.mk - -This is similar to, but not quite, the comfortable way that you probably -already write your Makefiles. - -What's where? -------------- - -There are three things that Autothing provides: - - 1. Variable namespacing - 2. Tools for dealing with paths - 3. A module (plugin) system. - -This repository contains both Autothing itself, and several modules. - -Autothing itself is described in `build-aux/Makefile.README.txt`. -That file is the core documentation. - -There is a "mod" module that adds self-documenting capabilities to the -module system; adding Make targets that print documentation about the -modules used in a project. For convenience, in the top level of this -repository, there is a Makefile allowing you to use these targets to -get documentation on the modules in this repository. - -Running `make at-modules` will produce a list of modules, and short -descriptions of them: - - $ make at-modules - Autothing modules used in this project: - - dist `dist` target for distribution tarballs (more) - - files Keeping track of groups of files (more) - - gitfiles Automatically populate files.src.src from git (more) - - gnuconf GNU standard configuration variables (more) - - mod Display information about Autothing modules (more) - - nested Easy nested .PHONY targets (more) - - quote Macros to quote tricky strings (more) - - texinfo The GNU documentation system (more) - - var Depend on the values of variables (more) - - write-atomic `write-atomic` auxiliary build script (more) - - write-ifchanged `write-ifchanged` auxiliary build script (more) - -The "(more)" at the end of a line indicates that there is further -documentation for that module, which can be produced by running the -command `make at-modules/MODULE_NAME`. - -Further development -------------------- - -The raison d'être of GNU Automake is that targeting multiple -implementations of Make is hard; the different dialects have diverged -significantly. - -But GNU's requirement of supporting multiple implementations of Make -is relaxing. With GNU Emacs 25, it GNU Make is explicitly required. -We can finally rise up from our Automake shackles! - -... But we soon discover that the GNU Coding Standards require many -things of our Makefiles, which Automake took care of for us. - -So, several of the modules in this repository combine to attempt to -provide the things that the GNU Coding Standards require. Between -`gnuconf`, `dist`, `files`, and `texinfo`; the GNU Coding Standards -for Makefiles are nearly entirely satisfied. However, there are a few -targets that are required, but aren't implemented by a module (yet!): - - - `install-strip` - - `TAGS` - - `check` - - `installcheck` (optional, but recommended) - -Further, none of the standard modules actually provide rules for -installing files; they merely define the standard install targets with -dependencies on the files they need to install. This is because -actual rules for installing them can be project-specific, but also -depend on classes of files that none of the modules are aware of; -binary executables might need a strip flag passed to INSTALL, but we -need to avoid that flag for scripts; some parts might need libtool -install commands, others not. - ----- -Copyright (C) 2016-2017 Luke Shumaker - -This documentation file is placed into the public domain. If that is -not possible in your legal system, I grant you permission to use it in -absolutely every way that I can legally grant to you. diff --git a/README.md b/README.md new file mode 120000 index 0000000..5e5ea4a --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +build-aux/Makefile.README.txt \ No newline at end of file diff --git a/build-aux/Makefile.README.old.txt b/build-aux/Makefile.README.old.txt index b0a0965..b4ea562 100644 --- a/build-aux/Makefile.README.old.txt +++ b/build-aux/Makefile.README.old.txt @@ -1,20 +1,14 @@ Obsolete ======== -The following was written for previous versions of Autothing. I'm leaving it -here for now because I'll likely canibalize it for other bits of documentation, -either for Autothing itself, the `files` module, or the `dist` module. +The following was written for previous versions of Autothing. I'm +leaving it here for now because I'll likely canibalize it for other +bits of documentation, either for Autothing itself, the `files` +module, or the `dist` module. High-level overview ------------------- -Now, what this does for you is: - - (search for the paper -"Recursive Make Considered Harmful") As harmful as recursive make is, -it's historically been difficult to to write non-recursive Makefiles. -This makes it easy. - It also makes it easy to follow the GNU standards for your makefiles: it takes care of this entire table of .PHONY targets for you: @@ -33,126 +27,6 @@ it takes care of this entire table of .PHONY targets for you: (You are still responsible for implementing the `$(outdir)/check` target in each of your Makefiles.) -What you have to do is: - -In each source directory, you write a `Makefile`, very similarly to if -you were writing for plain GNU Make, with - - topoutdir ?= ... - topsrcdir ?= ... - include $(topsrcdir)/build-aux/Makefile.head.mk - - # your makefile - - include $(topsrcdir)/build-aux/Makefile.tail.mk - -And in the top-level source directory, Write your own helper makefiles -that get included: - - `common.once.head.mk`: before parsing any of your Makefiles - - `common.each.head.mk`: before parsing each of your Makefiles - - `common.each.tail.mk`: after parsing each of your Makefiles - - `common.each.tail.mk`: after parsing all of your Makefiles - -The `common.*.mk` makefiles are nice for including generic pattern -rules and variables that aren't specific to a directory. - -You're probably thinking that this sounds too good to be true! -Unfortunately, there are two major deviations from writing a plain -recursive Makefile: - - 1. all targets and prerequisites (including .PHONY targets!) need to - be prefixed with - `$(srcdir)`/`$(outdir)`/`$(topsrcdir)`/`$(topoutdir)`. - * sub-gotcha: this means that if a pattern rule has a - prerequisite that may be in srcdir or outdir, then it must be - specified twice, once for each case. - 2. if a prerequisite is in a directory "owned" by another Makefile, - you must filter the pathname through `am_path`: - `$(call am_path,YOUR_PATH)`. Further, that path must NOT contain - a `..` segment; if you need to refer to a sibling directory, do it - relative to `$(topoutdir)` or `$(topsrcdir)`. - -Telling automake about your program ------------------------------------ - -You tell automake what to do for you by setting some variables. They -are all prefixed with `am_`; this prefix may be changed by editing the -`_am` variable at the top of `automake.head.mk`. - -The exception to this is the `am_path` variable, which is a macro that -is used to make a list of filenames relative to the appropriate -directory, because unlike normal GNU (Auto)Make, `$(outdir)` isn't -nescessarily equal to `.`. See above. - -There are several commands that generate files; simply record the list -of files that each command generates as the following variable -variables: - -| Variable | Create Command | Delete Command | Description | Relative to | -|--------------+----------------+-----------------------------+-----------------------------------+-------------| -| am_src_files | emacs | rm -rf . | Files that the developer writes | srcdir | -| am_gen_files | ??? | make maintainer-clean | Files the developer compiles | srcdir | -| am_cfg_files | ./configure | make distclean | Users' compile-time configuration | outdir | -| am_out_files | make all | make mostlyclean/make clean | Files the user compiles | outdir | -| am_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 | -|----------------+------------------+------------------------------------------------+-------------| -| am_clean_files | make clean | A list of things to `rm` in addition to the | outdir | -| | | files in `$(am_out_files)`. (Example: `*.o`) | | -|----------------+------------------+------------------------------------------------+-------------| -| am_slow_files | make mostlyclean | A list of things that (as an exception) should | outdir | -| | | _not_ be deleted. (otherwise, `mostlyclean` | | -| | | is the same as `clean`) | | - -Finally, there are two variables that express the relationships -between directories: - -| Variable | Description | -|------------+---------------------------------------------------------| -| am_subdirs | A list of other directories (containing Makefiles) that | -| | may be considered "children" of this | -| | directory/Makefile; building a phony target in this | -| | directory should also build it in the subdirectory. | -| | They are not necesarily actually subdirectories of this | -| | directory in the filesystem. | -|------------+---------------------------------------------------------| -| am_depdirs | A list of other directories (containing Makefiles) that | -| | contain or generate files that are dependencies of | -| | targets in this directory. They are not necesarily | -| | actually subdirectories of this directory in the | -| | filesystem. Except for files that are dependencies of | -| | files in this directory, things in the dependency | -| | directory will not be built. | - -Tips, notes ------------ - -I like to have the first (non-comment) line in a Makefile be: - - include $(dir $(lastword $(MAKEFILE_LIST)))/../../config.mk - -(adjusting the number of `../` sequences as nescessary). Then, my -(user-editable) `config.mk` is of the form: - - ifeq ($(topsrcdir),) - topoutdir := $(patsubst %/,%,$(dir $(lastword $(MAKEFILE_LIST)))) - topsrcdir := $(topoutdir) - - # your configuration - - endif - -If the package has a `./configure` script, then I have it modifiy -topsrcdir as necessary, as well as modifying whatever other parts of -the configuration. All of the configuration lives in `config.mk`; -`./configure` doesn't modify any `Makefile`s, it just generates -`config.mk`, and copies (or (sym?)link?) every `$(srcdir)/Makefile` to -`$(outdir)/Makefile`. - ---- Copyright (C) 2016 Luke Shumaker diff --git a/build-aux/Makefile.README.txt b/build-aux/Makefile.README.txt index c68870a..f67ede2 100644 --- a/build-aux/Makefile.README.txt +++ b/build-aux/Makefile.README.txt @@ -5,36 +5,110 @@ Autothing 3: The smart way to write GNU Makefiles Autothing is a thing that does things automatically. -Ok, more helpfully: Autothing is a pair of .mk Makefile fragments that -you can `include` from your Makefiles to make them easier to write; -specifically, it makes it _easy_ to write non-recursive Makefiles--and -ones that are similar to plain recursive Makefiles, at that! +Ok, more helpfully: Autothing is a pair of .mk Makefile fragments +(`Makefile.head.mk` and `Makefile.tail.mk`) that you can `include` +from your Makefiles to make them easier to write; specifically, it +makes it _easy_ to write non-recursive Makefiles--and ones that are +similar to plain recursive Makefiles, at that! -Synopsis --------- +To many people, talking about GNU Make directly is a non-starter +because it means giving up the many other features that things like +GNU Automake provide. Other projects like GNU Automake were created +to plaster over differences between make(1) implementations; however, +this isn't all that Automake provides, it also makes it easy to do +complex things that users want, or the GNU Coding Standards require. +That's silly; the implementation of these features should be +orthogonal to plastering over the differences between Make +implementations. So, in addition to the Automake core, Automake is +distributed with several "modules" that implement similar feature sets +to what Automake provides. -Write your makefiles of the form: +Autothing does depend on GNU Make; other make(1) implementations will +not work. However, if you are open to adding GNU Make as a +dependency, then Autothing should obviate the need for GNU Automake, +while also making your Makefiles better. + +Non-recursive? +-------------- + + (For those of you who aren't up on Makefile jargon) + +When you have a project that spans multiple directories, you'll +probably want to split up the Makefile, having the appropriate parts +in each sub-directory. There are a number of strategies you can use +to approach this. + +One of the more prevelant strategies (so much so that GNU make +includes special support for it) is to write "recursive Makefiles"; +that is, have Make rules that include commands like + + other-directory/libfoo.so: + $(MAKE) -C other-directory libfoo.so + +or + + other-directory/libfoo.so + cd other-directory && $(MAKE) libfoo.so +This approach is popular because it is both very easy to implement, +and is supported by a wide variety of Make implementations. But, it +also introduces a wide variety of issues; so much so that a rather +famous paper was written about it: "Recursive Make Considered Harmful" +(Miller, 1997). + +For all of the arguments against it, and all of the alternative +approaches, recusive Makefiles are hard to beat because they are just +so easy to write, and the alternatives... aren't. UNTIL NOW! + +Instead of having rules that spawn a separate Make process in another +directory for targets in that directory, Autothing lets you provide a +list of directories that include targets that targets in this +directory might depend on, and Autothing will automagically include +the Makefile in that other directory into *this* instance of the Make +program. + + Peter Miller (1997) "Recursive Make Considered Harmful" + + +An example Makefile / Introduction +---------------------------------- + +Write your Makefiles of the form: + + # Initialize basic information about how your project is structured. topsrcdir ?= ... topoutdir ?= ... - at.Makefile ?= Makefile # Optional + + # Include the Autothing entry point include $(topsrcdir)/build-aux/Makefile.head.mk + # Now write your Makefile very similarly to how you normally + # would. Just make sure that outputs are relative to $(outdir) + # and inputs relative to $(srcdir). $(outdir)/%.o: $(srcdir)/%.c: $(CC) -c -o $@ $< - $(outdir)/hello: $(outdir)/hello.o + # If any of the dependencies of files here are outputs of a + # Makefile in another directory, list those directories here. at.subdirs = ... - at.targets = ... + # This part is kind of a pain: define a list of ouput targets that + # this Makefile produces. + at.targets = $(outdir)/%.o $(outdir)/hello + + # Include the Autothing exit point include $(topsrcdir)/build-aux/Makefile.tail.mk This is similar to, but not quite, the comfortable way that you probably already write your Makefiles. -Details -------- +It is recommended that Autothing lives inside of the "build-aux" +directory in the top level of your project sources; "build-aux" is a +standard directory for auxiliary build programs and tools. + +What does Autothing do for me? +------------------------------ There are two fundamental things that Autothing provides: @@ -49,16 +123,179 @@ The second is important because GNU Make is too dumb to know that Then, there's something that maybe doesn't belong, but I didn't have the heart to cut it out: - 3. A module (plugin) system. + 3. A module (plugin) system, which allows for modules to provide + additional feature sets. The module system is "important" because there are very often common bits that you want to be included in every Makefile, and this gives some structure to that. -Requirements: +Let's step through each of those features. + +## Variable namespacing + +When you write a Makefile, you quite likely use (global) variables. +When you have a project that uses multiple Makefiles, each Makefile +might have the same variable names, but with different values +(especially if converting from recursive Make). + +You could be very disciplined and carefully name your variables so +that they don't conflict. This is difficult and error prone normally, +but becomes neigh-on-impossible if you are converting a large-ish +project from recursive Make. + +So, Autothing provides a solution. If you provide Autothing with a +list of targets defined in your Makefile (via the `at.targets` +variable), Autothing will make any variables you defined local to that +Makefile; they will be present when making targets listed in +`at.targets`, but will be hidden from other Makfiles that get +included. + +Any variables defined before `Makefile.head.mk` is included are +treated as truly global; all Makefiles included will have access to +them. + +## Tools for dealing with paths + +As stated above, GNU Make is too dumb to realize that `foo/bar/../baz` +== `foo/baz`; so one has to be reasonably careful about path +normalization. For dealing with path normalization problems that +arise because of the way Autothing inclusions work, several global +functions are provided for dealing with paths. + +`$(call at.is_subdir,a,b)` returns whether `b` is a sub-directory of +`a` (including `a` as a sub-directory of itself). +`at.is_strict_subdir` does the same, but does not treat `a` as a +sub-directory of itself. (These function names mimic the terms +"subset" and "strict subset" in mathematics.) These use an empty +string for "false" and a non-empty string for "true". + +`$(call at.path,files...)` is a generic path-normalization routine. +The outputs of the other `at.*` functions are already normalized, and +do not need to be passed through this. Files immediately inside of +`$(srcdir)` or `$(outdir)` (without another directory name after the +variable) are already normalized, and do not need to be passed through +this function either. However, it is always safe to pass a path +through this function, so if in doubt, call `at.path`. + +`$(call at.relbase,dir,files...)` and its cousin `at.relto` take a +directory and a list of files, and transform each of the filenames to +be relative to the directory, if the file is inside of the directory. +Where they differ is that if the file is not inside of the directory; +`at.relbase` transforms it into an absolute path, while `at.relto` +prepends as many `../` segments as necessary to make it relative to +the directory. (These function names mimic the `--relative-base` and +`--relative-to` flags of the `realpath` utility that is part of GNU +coreutils.) + +If `$(srcdir)` and `$(outdir)` are the same, then `$(call +at.out2src,files...)` is a no-op, but otherwise it takes a (possibly +relative) path in `$(outdir)`, and transforms it to the equivalent +filename in `$(srcdir)`. + +`$(call at.addprefix,dir,files...)` takes a directory and a list of +filenames, and looks at each filename; if it is an absolute path, it +passes it through (well, "only" normalizes it); if the filename is a +relative path, it is joined with the given base directory. + +## Modules to provide feature sets + +The module system serves two purposes + + 1. Allow your developers to share logic between Makefiles in multiple + directories. + 2. Allow your developers to import "standard" modules implementing + common feature sets, so they don't have to. + +Distributed along with autothing are some "standard" modules that +provide commonly desired functionality from Makefiles; tricky little +things that your developers shouldn't have to implement themselves for +every project; the things that GNU Automake would take care of if you +used Automake (a piece of software that Autothing hopes to replace). + +The module system is conceptually quite simple: have 4 directories for +`.mk` makefile snippets that get included at certain points: + + Makefile.once.head/*.mk + + Makefile.each.head/*.mk + a/Makefile + Makefile.each.tail/*.mk + + Makefile.each.head/*.mk + b/Makefile + Makefile.each.tail/*.mk + + Makefile.each.head/*.mk + c/Makefile + Makefile.each.tail/*.mk + + Makefile.once.tail/*.mk + +Deciding which of the 4 directories to put your snippets in... you'll +figure it out pretty quickly once you start playing with it. + +Beyond these 4 directories, Autothing itself imposes no structure, but +there are some conventions that are followed by the distributed along +with Autothing, and I recommend that your developers follow. + +Each of the `.mk` files is name `NN-MODULE.mk` where NN is a number +(to affect the order that the module files are evaluated in, in case +of dependencies between them), and MODULE is the module name. Each +module has "public" variables prefixed with `MODULE.`, and "private" +variables prefixed with `_MODULE.` (again, "MODULE" being the module +name). For example, the "groups" parameter of the "files" module is +configured via the `files.groups` variable. Within this convention, +Autothing presents itself as a pseudo-module named "at"; that is, +public Autothing variables are prefixed with `at.`. + +If you follow these conventions, then the "mod" module distributed +along with Autothing can display information about the modules that a +project uses, and documentation on each module. Running the command +`make at-modules` (implemented by the "mod" module) will produce a +list of the modules present in a project, and short descriptions of +them: + + $ make at-modules + Autothing modules used in this project: + - dist `dist` target for distribution tarballs (more) + - files Keeping track of groups of files (more) + - gitfiles Automatically populate files.src.src from git (more) + - gnuconf GNU standard configuration variables (more) + - mod Display information about Autothing modules (more) + - nested Easy nested .PHONY targets (more) + - quote Macros to quote tricky strings (more) + - texinfo The GNU documentation system (more) + - var Depend on the values of variables (more) + - write-atomic `write-atomic` auxiliary build script (more) + - write-ifchanged `write-ifchanged` auxiliary build script (more) + +The "(more)" at the end of a line indicates that there is further +documentation for that module, which can be produced by running the +command `make at-modules/MODULE_NAME`. See the output of `make +at-modules/mod` for instructions on how to produce this further +documentation for modules you develop. + +Besides the "mod" module, the set modules distributed along with +Autothing primarily exists to provide the bits of (sometimes somewhat +tricky) functionality required of Makefiles by the GNU Coding +Standards. Run the `at-modules` commands above for documentation on +each of them. + +Formal interface +---------------- + +System requirements: - A version of GNU Make that supports `undefine` (ie, version 3.82 and above). + If the user attempts to use your Autothing-using Makefile with an + older version of GNU Make, `Makefile.head.mk` will print an error + message and refuse to proceed: + + $ make-3.81 + build-aux/Makefile.head.mk:58: *** Autothing: We need a version of Make that supports 'undefine'. Stop. + Inputs: - In each `Makefile`: - Before `Makefile.head.mk`: @@ -71,6 +308,31 @@ Inputs: - Files: - `${topsrcdir}/build-aux/Makefile.{each,once}.{head,tail}/*.mk` + Unfortunately, a limitation of Autothing is that it does require a + designated "top" directory; it can't be used to have a sub-project + that can also be totally separate and built alone. In your + Makefiles, before you include `Makefile.head.mk`, you must tell + Autothing what the top directory is by setting `topoutdir` and + `topsrcdir`. + + If you wish for your per-directory Makefiles to have a name other + than `Makefile` (such as `GNUmakefile` or `makefile`, which GNU Make + also looks for by default; or another name for project-specific + reasons), Autothing supports this by setting the `at.Makefile` + variable. Unfortunately, Autothing does not support having a list + of filenames to try; so one must be consistent about the filename + throughout the project. + + In the body of each Makefile, you may set the `at.targets` variable + to list which targets should have access to the variables defined in + the body of that Makefile. + + In the body of each Makefile, you may set the `at.subdirs` variable + to list of directories which have their own Makefile which produces + targets that targets in this directory depend on. Directories + listed in `at.subdirs` may be relative or absolute; if relative, + they are interpreted as relative to `$(outdir)`. + Outputs: - Global: - Variable (function): `$(call at.is_subdir, parent, child)` @@ -80,29 +342,102 @@ Outputs: - Variable (function): `$(call at.path, paths...)` - Variable (function): `$(call at.out2src, paths...)` - Variable (function): `$(call at.addprefix, prefix, paths...)` + - Variable : `$(at.nl)` # a single newline - Per-directory: - Variable: `$(outdir)` - Variable: `$(srcdir)` -TODO: actually explain things. + For dealing with path normalization problems that arise because of + the way Autothing inclusions work, several global functions are + provided for dealing with paths; see the above "Tools for dealing + with paths" section for documentation on each of these functions. -Motivation/Exposition ---------------------- + For convenience, it also provides `$(at.nl)` which is a single + newline, as newlines are very difficult to type in Make variable + values. -This section needs rewritten. Or really just written. +Tips, notes +----------- -Other projects like GNU Automake were created to plaster over differences -between make(1) implementations; however, this isn't all that Automake -provides, it also makes it easy to do complex things that users want, or the -GNU Coding Standards require. That's silly. +If you use Autoconf (or similar), I recommend having a file at +`$(topsrcdir)/config.mk.in` of the form -Autothing does depend on GNU Make; other make(1) implementations will -not work. However, if you are open to adding GNU Make as a -dependency, then Autothing should obviate the need for GNU Automake, -while also making your Makefiles better. + ifeq ($(origin topsrcdir),undefined) + topoutdir := $(patsubst %/,%,$(dir $(lastword $(MAKEFILE_LIST)))) + topsrcdir := $(topoutdir)/@top_srcdir@ - Peter Miller (1997) "Recursive Make Considered Harmful" - + # Any other global variables you might want to set + + endif + +Then have `./configure` generate `$(topoutdir)/config.mk` from it by +placing `AC_CONFIG_FILES([config.mk])` in your `configure.ac`. I +recommend that you have `config.mk` be the _only_ Makefile edited by +`./configure`; which will require manual support to have `./configure` +link/copy the Makefiles unedited into `$(topoutdir)`; you can do this +by placing something like this in your `configure.ac`: + + AC_OUTPUT([], [], [ + if test "$srcdir" != .; then + find "$srcdir" -name Makefile -printf '%P\n' \ + | while read -r filename; do + mkdir -p "\$(dirname "\$filename")" + ln -srfT "$srcdir/\$filename" "\$filename" + done + fi + ]) + +This will allow you to write your Makefiles in the form: + + include $(dir $(lastword $(MAKEFILE_LIST)))/../../config.mk + include $(topsrcdir)/build-aux/Makefile.head.mk + + # your Makefile here + + include $(topsrcdir)/build-aux/Makefile.tail.mk + +Where you only need to adjust the number of `../` segments in the +first line based on how deep that directory is. + +Further development +------------------- + +Most of the modules distributed along with Autothing have the goal of +combining to provide the things that the GNU Coding Standards require. +Between `gnuconf`, `dist`, `files`, and `texinfo`; the GNU Coding +Standards for Makefiles are nearly entirely satisfied. However, there +are a few targets that are required, but aren't implemented by a +module (yet!): + + - `install-strip` + - `TAGS` + - `check` + - `installcheck` (optional, but recommended) + +TODO +---- + + - Write documentation on `srcdir`, `outdir`, and out-of-tree builds; + I don't think discussions involving the separate `srcdir` and + `outdir` make much sense without that context. + +Bugs/Limitations +---------------- + + - This documentation file is almost three times as long as the code + that it documents. + + - The "parse time" for projects with hundreds of sub-directories + (each having a Makefile) can be slow (ex: a project with 166 + directories has a parse time of around 12 seconds on my box). I + blame GNU Make's garbage collector; I don't think it was ever + designed to deal with as much "garbage" as Autothing's variable + namespacing throws at it. + + - Requires a designated "top" directory; see discussion above. + + - Does not support varying per-directory Makefile names; see + discussion above. ---- Copyright (C) 2016-2017 Luke Shumaker diff --git a/build-aux/Makefile.once.head/10-dist.mk b/build-aux/Makefile.once.head/10-dist.mk index 831ca12..27b39ec 100644 --- a/build-aux/Makefile.once.head/10-dist.mk +++ b/build-aux/Makefile.once.head/10-dist.mk @@ -13,7 +13,7 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . -mod.dist.description = `dist` target for distribution tarballs +mod.dist.description = `dist` target to create distribution tarballs define mod.dist.doc # User variables: # - `CP ?= cp` -- cgit v1.2.3-54-g00ecf From 16e8d3b92b5e35a5eaee40a7b7fc0279c342886a Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Mon, 30 Jan 2017 01:33:24 -0500 Subject: (libretools) Fix bugs in autothing. Some of these are that I hadn't originally designed autothing v3 to work with --warn-undefined-variables. Others are just straight-up bugs from inadequate testing. --- build-aux/Makefile.each.tail/00-var.mk | 6 +-- build-aux/Makefile.each.tail/10-files.mk | 21 +++----- build-aux/Makefile.each.tail/10-nested.mk | 3 +- build-aux/Makefile.each.tail/11-texinfo.mk | 4 -- build-aux/Makefile.head.mk | 22 ++++----- build-aux/Makefile.once.head/00-gitfiles.mk | 75 ----------------------------- build-aux/Makefile.once.head/00-var.mk | 7 ++- build-aux/Makefile.once.head/10-dist.mk | 8 ++- build-aux/Makefile.once.head/10-files.mk | 37 +++++++++----- build-aux/Makefile.once.head/10-gitfiles.mk | 75 +++++++++++++++++++++++++++++ build-aux/Makefile.once.head/10-gnuconf.mk | 3 ++ build-aux/Makefile.once.head/10-nested.mk | 3 +- build-aux/Makefile.once.head/10-texinfo.mk | 6 +-- 13 files changed, 142 insertions(+), 128 deletions(-) delete mode 100644 build-aux/Makefile.once.head/00-gitfiles.mk create mode 100644 build-aux/Makefile.once.head/10-gitfiles.mk (limited to 'build-aux/Makefile.once.head/10-dist.mk') diff --git a/build-aux/Makefile.each.tail/00-var.mk b/build-aux/Makefile.each.tail/00-var.mk index c2fd9d7..954defb 100644 --- a/build-aux/Makefile.each.tail/00-var.mk +++ b/build-aux/Makefile.each.tail/00-var.mk @@ -1,4 +1,4 @@ -# Copyright (C) 2016 Luke Shumaker +# Copyright (C) 2016-2017 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 @@ -13,10 +13,10 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . -mod.var.depends += quote write-ifchanged +mod.var.depends += files quote write-ifchanged $(outdir)/.var.%: _var.FORCE @printf '%s' $(call quote.shell,$($*)) | sed 's/^/#/' | $(WRITE_IFCHANGED) $@ -include $(wildcard $(outdir)/.var.*) -at.targets += $(addprefix $(outdir)/,.var.%) +files.out.int += .var.* diff --git a/build-aux/Makefile.each.tail/10-files.mk b/build-aux/Makefile.each.tail/10-files.mk index 3bb3bc2..787a3bd 100644 --- a/build-aux/Makefile.each.tail/10-files.mk +++ b/build-aux/Makefile.each.tail/10-files.mk @@ -1,4 +1,4 @@ -# Copyright (C) 2015-2016 Luke Shumaker +# Copyright (C) 2015-2017 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 @@ -41,17 +41,12 @@ _files.uninstall = $(_files.sys) _files.mostlyclean = $(filter-out $(_files.out.slow) $(_files.out.cfg),$(_files.out)) _files.clean = $(filter-out $(_files.out.cfg),$(_files.out)) _files.distclean = $(_files.out) -$(addprefix $(outdir)/,uninstall mostlyclean clean distclean): %: %-hook - $(RM) -- $(sort $(filter-out %/,$(_files.$(@F)))) - $(RM) -r -- $(sort $(filter %/,$(_files.$(@F)))) - $(RMDIR_P) -- $(sort $(dir $(_files.$(@F)))) -_files.maintainer-clean = $(filter-out $(_files.src.cfg) $(_files.src.src),$(_files.src)) -_files.$(files.vcsclean) = $(filter-out $(_files.src.src),$(_files.src)) -$(addprefix $(outdir)/,maintainer-clean $(files.vcsclean)): $(outdir)/%: $(outdir)/distclean $(outdir)/%-hook - @echo 'This command is intended for maintainers to use; it' - @echo 'deletes files that may need special tools to rebuild.' - $(RM) -- $(sort $(filter-out %/,$(_files.$(@F)))) - $(RM) -r -- $(sort $(filter %/,$(_files.$(@F)))) - $(RMDIR_P) -- $(sort $(dir $(_files.$(@F)))) +_files.maintainer-clean = $(_files.distclean) $(filter-out $(_files.src.cfg) $(_files.src.src),$(_files.src)) +_files.$(files.vcsclean) = $(_files.distclean) $(filter-out $(_files.src.src),$(_files.src)) +$(addprefix $(outdir)/,uninstall mostlyclean clean distclean maintainer-clean $(files.vcsclean)): %: %-hook + $(call _files.XARGS,$(RM) --, $(sort $(wildcard $(filter-out %/,$(_files.$(@F))))) ) + $(call _files.XARGS,$(RM) -r --, $(sort $(wildcard $(filter %/,$(_files.$(@F))))) ) + $(call _files.XARGS,$(RMDIR_P) --,$(filter-out ./,$(sort $(wildcard $(dir $(_files.$(@F))))))) +$(addprefix $(outdir)/,maintainer-clean $(files.vcsclean)): _files.maintainer-clean-warning $(foreach t,uninstall mostlyclean clean distclean maintainer-clean $(files.vcsclean), $(outdir)/$t-hook):: .PHONY: $(foreach t,uninstall mostlyclean clean distclean maintainer-clean $(files.vcsclean), $(outdir)/$t-hook) diff --git a/build-aux/Makefile.each.tail/10-nested.mk b/build-aux/Makefile.each.tail/10-nested.mk index 5e5a40b..667ec6f 100644 --- a/build-aux/Makefile.each.tail/10-nested.mk +++ b/build-aux/Makefile.each.tail/10-nested.mk @@ -1,4 +1,4 @@ -# Copyright (C) 2016 Luke Shumaker +# Copyright (C) 2016-2017 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 @@ -18,3 +18,4 @@ $(eval $(foreach _tmp.nested,$(nested.targets),\ .PHONY: $(addprefix $(outdir)/,$(nested.targets)) at.subdirs += $(nested.subdirs) +at.targets += $(addprefix $(outdir)/,$(nested.targets)) diff --git a/build-aux/Makefile.each.tail/11-texinfo.mk b/build-aux/Makefile.each.tail/11-texinfo.mk index 9491820..1ee5843 100644 --- a/build-aux/Makefile.each.tail/11-texinfo.mk +++ b/build-aux/Makefile.each.tail/11-texinfo.mk @@ -26,10 +26,6 @@ files.sys.html += $(foreach f,$(texinfo.docs), $(htmldir)/$f.html ) files.sys.pdf += $(foreach f,$(texinfo.docs), $(pdfdir)/$f.pdf ) files.sys.ps += $(foreach f,$(texinfo.docs), $(psdir)/$f.ps ) -$(outdir)/install: - $(POST_INSTALL) - $(foreach f,$(texinfo.docs),$(INSTALL_INFO) $(DESTDIR)$(infodir)/$f.info $(DESTDIR)$(infodir)/dir$(at.nl)) - $(outdir)/%.info: $(srcdir)/%.texi; $(MAKEINFO) -o $(@D) $< $(outdir)/%.info: $(outdir)/%.texi; $(MAKEINFO) -o $(@D) $< $(outdir)/%.dvi : $(srcdir)/%.texi; $(TEXI2DVI) -o $(@D) $< diff --git a/build-aux/Makefile.head.mk b/build-aux/Makefile.head.mk index f4eb51d..6ac3d49 100644 --- a/build-aux/Makefile.head.mk +++ b/build-aux/Makefile.head.mk @@ -32,17 +32,19 @@ _at.relbase = $(strip \ _at.relto = $(strip \ $(if $(call _at.is_subdir,$1,$2), \ $(patsubst %/.,%,$(patsubst $(abspath $1)/%,%,$(abspath $2)/.)), \ - ../$(call _at.relto,$(dir $1),$2))) + ../$(call _at.relto,$(dir $(abspath $1)),$2))) # These 3 functions only take one operand; we define public multi-operand # versions below. -_at.path = $(strip \ - $(if $(call _at.is_subdir,$(topoutdir),$1), \ - $(patsubst %/.,%,$(topoutdir)/$(call _at.relto,.,$1)), \ - $(if $(call _at.is_subdir,$(topsrcdir),$1), \ - $(patsubst %/.,%,$(topsrcdir)/$(call _at.relto,$(topsrcdir),$1)), \ - $(abspath $1)))) -_at.out2src = $(call _at.path,$(if $(call _at.is_subdir,$(topoutdir),$1),$(topsrcdir)/$(call _at.path,$1),$1)) +_at.path = $(strip $(or \ + $(if $(call _at.is_subdir, . ,$1), $(call _at.relto, . ,$1) ), \ + $(if $(call _at.is_subdir,$(topoutdir),$1),$(patsubst %/.,%,$(topoutdir)/$(call _at.relto,$(topoutdir),$1))), \ + $(if $(call _at.is_subdir,$(topsrcdir),$1),$(patsubst %/.,%,$(topsrcdir)/$(call _at.relto,$(topsrcdir),$1))), \ + $(abspath $1))) +_at.out2src = $(call _at.path,$(strip \ + $(if $(call _at.is_subdir,$(topoutdir),$1), \ + $(topsrcdir)/$(call _at.relto,$(topoutdir),$1), \ + $1))) _at.addprefix = $(call _at.path,$(if $(filter-out /%,$2),$1/$2,$2)) _at.rest = $(wordlist 2,$(words $1),$1) @@ -103,9 +105,7 @@ ifeq ($(call _at.is_subdir,$(topoutdir),$(outdir)),) $(error Autothing: not a subdirectory of topoutdir=$(topoutdir): $(outdir)) endif -# Don't use at.out2src because we *know* that $(outdir) is inside $(topoutdir), -# and has already had $(_at.path) called on it. -srcdir := $(call _at.path,$(topsrcdir)/$(outdir)) +srcdir := $(call _at.out2src,$(outdir)) ifeq ($(call _at.is_subdir,$(topsrcdir),$(srcdir)),) $(error Autothing: not a subdirectory of topsrcdir=$(topsrcdir): $(srcdir)) endif diff --git a/build-aux/Makefile.once.head/00-gitfiles.mk b/build-aux/Makefile.once.head/00-gitfiles.mk deleted file mode 100644 index 8566a7f..0000000 --- a/build-aux/Makefile.once.head/00-gitfiles.mk +++ /dev/null @@ -1,75 +0,0 @@ -# Copyright (C) 2016-2017 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 . - -mod.gitfiles.description = Automatically populate files.src.src from git -mod.gitfiles.depends += files nested write-ifchanged quote -mod.gitfiles.files += $(topsrcdir)/$(gitfiles.file) -define mod.gitfiles.doc -# Inputs: -# - Global variable : `gitfiles.file` (Default: gitfiles.mk) -# - Directory variable : `nested.subdirs` -# - External : git -# Outputs: -# - File : `$(topsrcdir)/$(gitfiles.file)` -# - Directory variable : `files.src.src` -# - Directory variable : `files.src.gen` (only in top dir) -# -# The `files` module has a variable (`files.src.src`) that you (the -# developer) set to list "pure" source files; the type of files that you -# would check into a version control system. Since you are a -# responsible developer, you use a version control system. Since the -# computer is already maintaining a list of these files *in the VCS*, -# why should you--a filthy human--need to also maintain the list? Enter -# gitfiles, which will talk to git to maintain `files.src.src`, but -# won't require that the git repository be distributed to -# installing-users. -# -# If `$(topsrcdir)/.git` exists, then it will generate -# `$(topsrcdir)/$(gitfiles.file)`. Otherwise, it will assume that -# `$(topsrcdir)/$(gitfiles.file)` already exists. -# -# It will use the information in `$(topsrcdir)/$(gitfiles.file)` to -# append to `files.src.src` in each directory -# -# Finally, since the generated `$(topsrcdir)/$(gitfiles.file)` must be -# distributed to users, it is added to $(topsrcdirs)'s `files.src.gen`. -# -# When setting `files.src.src`, it needs to know which files "belong" to -# the current directory directly, and which "belong" to a further -# subdirectory. To do this, it uses an expression involving -# `$(nested.subdirs)`. -# -# While gitfiles sets `files.src.src` very early in `each.head`, because -# `nested.subdirs` might not be set yet, it may or may not be safe to -# use the value of `$(files.src.src)` in your Makefile, depending on how -# you set `nested.subdirs`. -endef -mod.gitfiles.doc := $(value mod.gitfiles.doc) - -gitfiles.file ?= gitfiles.mk - -_gitfiles.all = --include $(topsrcdir)/$(gitfiles.file) - -ifneq ($(wildcard $(topsrcdir)/.git),) -$(topsrcdir)/$(gitfiles.file): _gitfiles.FORCE - @(cd $(@D) && git ls-files --recurse-submodules -z) | sed -z -e 's/\$$/\$$$$/g' -e 's/\n/$$(at.nl)/g' | xargs -r0 printf '_gitfiles.all+=%s\n' | $(WRITE_IFCHANGED) $@ -.PHONY: _gitfiles.FORCE -endif - -_gitfiles.dir = $(call at.relto,$(topsrcdir),$(srcdir)) -_gitfiles.pat = $(patsubst ./%,%,$(_gitfiles.dir)/%) -_gitfiles.dir.all = $(patsubst $(_gitfiles.pat),%,$(filter $(_gitfiles.pat),$(_gitfiles.all))) -_gitfiles.dir.src = $(filter-out $(addsuffix /%,$(nested.subdirs)),$(_gitfiles.dir.all)) diff --git a/build-aux/Makefile.once.head/00-var.mk b/build-aux/Makefile.once.head/00-var.mk index 1f50f21..7c9e6ff 100644 --- a/build-aux/Makefile.once.head/00-var.mk +++ b/build-aux/Makefile.once.head/00-var.mk @@ -1,4 +1,4 @@ -# Copyright (C) 2016 Luke Shumaker +# Copyright (C) 2016-2017 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 @@ -20,14 +20,17 @@ define mod.var.doc # Outputs: # Target : `$(outdir)/.var.%` # Directory variable: `at.targets` +# Directory variable: `var.` # # It's a well-known secret that many files generated by a Makefile vary with # the values of particular variables, but that GNU Make can't track these # dependencies. Well, with some cleverness, it actually can! # # With this module, to depend on the value of a variable, depend on -# `$(outdir)/.var.VARNAME`. +# `$(outdir)/.var.VARNAME`, or `$(var.)VARNAME` for short. endef mod.var.doc := $(value mod.var.doc) +var. = $(patsubst ./%,%,$(outdir)/.var.) + .PHONY: _var.FORCE diff --git a/build-aux/Makefile.once.head/10-dist.mk b/build-aux/Makefile.once.head/10-dist.mk index 27b39ec..3621195 100644 --- a/build-aux/Makefile.once.head/10-dist.mk +++ b/build-aux/Makefile.once.head/10-dist.mk @@ -1,4 +1,4 @@ -# Copyright (C) 2015-2016 Luke Shumaker +# Copyright (C) 2015-2017 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 @@ -50,6 +50,12 @@ define mod.dist.doc endef mod.dist.doc := $(value mod.dist.doc) +PACKAGE_TARNAME ?= +PACKAGE ?= +PACKAGE_NAME ?= +PACKAGE_VERSION ?= +VERSION ?= + # Developer configuration dist.exts ?= .tar.gz diff --git a/build-aux/Makefile.once.head/10-files.mk b/build-aux/Makefile.once.head/10-files.mk index f6fcf30..564f9d6 100644 --- a/build-aux/Makefile.once.head/10-files.mk +++ b/build-aux/Makefile.once.head/10-files.mk @@ -1,4 +1,4 @@ -# Copyright (C) 2015-2016 Luke Shumaker +# Copyright (C) 2015-2017 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 @@ -26,15 +26,15 @@ define mod.files.doc # - Global variable : `files.default ?= all` # - Global variable : `files.vcsclean ?= files.vcsclean` # - Global variable : `files.generate ?= files.generate` -# - Directory variable : `files.src.src` -# - Directory variable : `files.src.int` -# - Directory variable : `files.src.cfg` -# - Directory variable : `files.src.gen` -# - Directory variable : `files.out.slow` -# - Directory variable : `files.out.int` -# - Directory variable : `files.out.cfg` -# - Directory variable : `files.out.$(files.groups)` (well, $(addprefix...)) -# - Directory variable : `files.sys.$(files.groups)` (well, $(addprefix...)) +# - Directory variable : `files.src.src` # Sources +# - Directory variable : `files.src.int` # Intermediates; deletable +# - Directory variable : `files.src.cfg` # Outputs needed to run ./configure +# - Directory variable : `files.src.gen` # Other outputs +# - Directory variable : `files.out.slow` # Things to exclude from `make mostlyclean` +# - Directory variable : `files.out.int` # Intermediates +# - Directory variable : `files.out.cfg` # Outputs created by ./configure +# - Directory variable : `files.out.$(group)` for `group` in `$(files.groups)` +# - Directory variable : `files.sys.$(group)` for `group` in `$(files.groups)` # Outputs: # - Global variable : `nested.targets` # - Global variable : `at.targets` @@ -43,7 +43,7 @@ define mod.files.doc # - Directory variable : `files.out` # - Directory variable : `files.sys` # - Creative .PHONY targets: -# - `$(outdir)/$(files.generate))` +# - `$(outdir)/$(files.generate)` # - `$(outdir)/$(group)` for `group` in `$(files.groups)` # - `$(outdir)/install` # - `$(outdir)/install-$(group)` for `group` in `$(filter-out $(files.default),$(files.groups))` @@ -59,6 +59,10 @@ define mod.files.doc # Basic `*` wildcards are supported. Use `*`, not `%`; it will automatically # substitute `*`->`%` where appropriate. # +# Each of the destructive targets depends on `$(target)-hook`, which +# is defined to be a "double-colon rule" allowing you to add your own +# code. +# # TODO: prose documentation endef mod.files.doc := $(value mod.files.doc) @@ -76,7 +80,7 @@ nested.targets += install installdirs nested.targets += $(foreach g,$(files.groups),$g) nested.targets += $(foreach g,$(filter-out $(files.default),$(files.groups)),install-$g install-$gdirs) # Standard destructive PHONY targets -nested.targets += uninstall mostlyclean clean distclean maintainer-clean +nested.targets += uninstall mostlyclean clean distclean maintainer-clean $(files.vcsclean) # User configuration @@ -85,3 +89,12 @@ DESTDIR ?= RM ?= rm -f RMDIR_P ?= rmdir -p --ignore-fail-on-non-empty TRUE ?= true + +# Utility functions + +_files.XARGS = $(if $(strip $2),$1 $(strip $2)) + +_files.maintainer-clean-warning: + @echo 'This command is intended for maintainers to use; it' + @echo 'deletes files that may need special tools to rebuild.' +.PHONY: _files.maintainer-clean-warning diff --git a/build-aux/Makefile.once.head/10-gitfiles.mk b/build-aux/Makefile.once.head/10-gitfiles.mk new file mode 100644 index 0000000..8566a7f --- /dev/null +++ b/build-aux/Makefile.once.head/10-gitfiles.mk @@ -0,0 +1,75 @@ +# Copyright (C) 2016-2017 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 . + +mod.gitfiles.description = Automatically populate files.src.src from git +mod.gitfiles.depends += files nested write-ifchanged quote +mod.gitfiles.files += $(topsrcdir)/$(gitfiles.file) +define mod.gitfiles.doc +# Inputs: +# - Global variable : `gitfiles.file` (Default: gitfiles.mk) +# - Directory variable : `nested.subdirs` +# - External : git +# Outputs: +# - File : `$(topsrcdir)/$(gitfiles.file)` +# - Directory variable : `files.src.src` +# - Directory variable : `files.src.gen` (only in top dir) +# +# The `files` module has a variable (`files.src.src`) that you (the +# developer) set to list "pure" source files; the type of files that you +# would check into a version control system. Since you are a +# responsible developer, you use a version control system. Since the +# computer is already maintaining a list of these files *in the VCS*, +# why should you--a filthy human--need to also maintain the list? Enter +# gitfiles, which will talk to git to maintain `files.src.src`, but +# won't require that the git repository be distributed to +# installing-users. +# +# If `$(topsrcdir)/.git` exists, then it will generate +# `$(topsrcdir)/$(gitfiles.file)`. Otherwise, it will assume that +# `$(topsrcdir)/$(gitfiles.file)` already exists. +# +# It will use the information in `$(topsrcdir)/$(gitfiles.file)` to +# append to `files.src.src` in each directory +# +# Finally, since the generated `$(topsrcdir)/$(gitfiles.file)` must be +# distributed to users, it is added to $(topsrcdirs)'s `files.src.gen`. +# +# When setting `files.src.src`, it needs to know which files "belong" to +# the current directory directly, and which "belong" to a further +# subdirectory. To do this, it uses an expression involving +# `$(nested.subdirs)`. +# +# While gitfiles sets `files.src.src` very early in `each.head`, because +# `nested.subdirs` might not be set yet, it may or may not be safe to +# use the value of `$(files.src.src)` in your Makefile, depending on how +# you set `nested.subdirs`. +endef +mod.gitfiles.doc := $(value mod.gitfiles.doc) + +gitfiles.file ?= gitfiles.mk + +_gitfiles.all = +-include $(topsrcdir)/$(gitfiles.file) + +ifneq ($(wildcard $(topsrcdir)/.git),) +$(topsrcdir)/$(gitfiles.file): _gitfiles.FORCE + @(cd $(@D) && git ls-files --recurse-submodules -z) | sed -z -e 's/\$$/\$$$$/g' -e 's/\n/$$(at.nl)/g' | xargs -r0 printf '_gitfiles.all+=%s\n' | $(WRITE_IFCHANGED) $@ +.PHONY: _gitfiles.FORCE +endif + +_gitfiles.dir = $(call at.relto,$(topsrcdir),$(srcdir)) +_gitfiles.pat = $(patsubst ./%,%,$(_gitfiles.dir)/%) +_gitfiles.dir.all = $(patsubst $(_gitfiles.pat),%,$(filter $(_gitfiles.pat),$(_gitfiles.all))) +_gitfiles.dir.src = $(filter-out $(addsuffix /%,$(nested.subdirs)),$(_gitfiles.dir.all)) diff --git a/build-aux/Makefile.once.head/10-gnuconf.mk b/build-aux/Makefile.once.head/10-gnuconf.mk index e24dfa1..87baa14 100644 --- a/build-aux/Makefile.once.head/10-gnuconf.mk +++ b/build-aux/Makefile.once.head/10-gnuconf.mk @@ -30,6 +30,9 @@ define mod.gnuconf.doc endef mod.gnuconf.doc := $(value mod.gnuconf.doc) +PACKAGE_TARNAME ?= +PACKAGE ?= +PACKAGE_NAME ?= gnuconf.pkgname ?= $(firstword $(PACKAGE_TARNAME) $(PACKAGE) $(PACKAGE_NAME)) ifeq ($(gnuconf.pkgname),) $(error Autothing module: gnuconf: gnuconf.pkgname must be set) diff --git a/build-aux/Makefile.once.head/10-nested.mk b/build-aux/Makefile.once.head/10-nested.mk index 4f181a9..d903d53 100644 --- a/build-aux/Makefile.once.head/10-nested.mk +++ b/build-aux/Makefile.once.head/10-nested.mk @@ -1,4 +1,4 @@ -# Copyright (C) 2016 Luke Shumaker +# Copyright (C) 2016-2017 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 @@ -21,6 +21,7 @@ define mod.nested.doc # Outputs: # - .PHONY Targets : `$(addprefix $(outdir)/,$(nested.targets))` # - Variable : `at.subdirs` +# - Variable : `at.targets` # # The Autothing `at.subdirs` slates a subdirectory's Makefile for inclusion, # but doesn't help with recursive targets like `all`, `install`, or `clean`, diff --git a/build-aux/Makefile.once.head/10-texinfo.mk b/build-aux/Makefile.once.head/10-texinfo.mk index aac2c28..d24852d 100644 --- a/build-aux/Makefile.once.head/10-texinfo.mk +++ b/build-aux/Makefile.once.head/10-texinfo.mk @@ -29,17 +29,13 @@ define mod.texinfo.doc # - Directory variable : `files.out.{dvi,html,pdf,ps}` # - Directory variable : `files.sys.{dvi,html,pdf,ps,all}` # - .PHONY target : `$(outdir)/info` -# - .PHONY target : `$(outdir)/install` (see below) # - Target : `$(outdir)/%.info` # - Target : `$(outdir)/%.dvi` # - target : `$(outdir)/%.html` # - target : `$(outdir)/%.pdf` # - Target : `$(outdir)/%.ps` # -# The module counts on the `$(outdir)/install` target being defined by -# `files`, but not having a rule that executes once the dependencies -# have been taken care of; it adds a "post-install" rule to add the -# info files to the index. +# TODO: prose documentation endef mod.texinfo.doc := $(value mod.texinfo.doc) -- cgit v1.2.3-54-g00ecf