From 7af3811df0e4d8707d8218361dd305f42df62be2 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Wed, 7 Sep 2016 01:20:54 -0400 Subject: (systemd) build-aux: add var and write-atomic modules --- build-aux/Makefile.once.head/00-var.mk | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 build-aux/Makefile.once.head/00-var.mk (limited to 'build-aux/Makefile.once.head/00-var.mk') diff --git a/build-aux/Makefile.once.head/00-var.mk b/build-aux/Makefile.once.head/00-var.mk new file mode 100644 index 0000000..d1e537e --- /dev/null +++ b/build-aux/Makefile.once.head/00-var.mk @@ -0,0 +1,18 @@ +# 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.var.description = Depend on the values of variables + +.PHONY: _var.FORCE -- 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/00-var.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/00-var.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 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/00-var.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