--- /dev/null
--- /dev/null
++subdirmk - assistance for non-recursive use of make
++===================================================
++
++Introduction
++------------
++
++Peter Miller's 1997 essay _Recursive Make Considered Harmful_
++persuasively argues that it is better to arrange to have a single
++make invocation with the project's complete dependency tree, rather
++than the currently conventional `$(MAKE) -C subdirectory' approach.
++
++However, actually writing a project's build system in a non-recursive
++style is not very ergonomic. The main difficulties are:
++ - constantly having to write out long file and directory names
++ - the lack of a per-directory make variable namespace means
++ long make variables (or namespace clashes)
++ - it is difficult to arrange that one can cd to a subdirectory
++ and say `make all' and have something reasonable happen
++ (to wit, build an appropriate subset)
++
++`subdirmk' is an attempt to solve these problems (and it also slightly
++alleviates some of the boilerplate needed to support out-of-tree
++builds well).
++
++Basic approach
++--------------
++
++The developer is expected to write a makefile fragment, in each
++relevant subdirectory, called `Subdir.sd.mk'.
++
++These fragments may contain ordinary make language.
++
++However, the sigil & is treated specially. By and large, it refers to
++`the current directory'. There are a variety of convenient
++constructions.
++
++The result is that to a large extent, the Subdir.sd.mk has an easy way
++to namespace its "local" make variables, and an easy way to refer to
++its "local" filenames.
++
++The Subdir.sd.mk's are filtered, fed through autoconf in the usual way
++(for @..@-substitutions) and included by one autogenerated toplevel
++makefile.
++
++So all of the input is combined and passed to one make invocation.
++(A corollary is that there is no enforcement of the namespacing:
++discipline is required to prefix relevant variable names with &, etc.)
++
++Each subdirectory is also provided with an autogenerated `Makefile'
++which exists purely to capture ordinary make invocations and arrange
++for something suitable to happen.
++
++Where there are dependencies between subdirectories, each Subdir.sd.mk
++can simply refer to files in other subdirectories directly.
++
++Invocation, "recursive" per-directory targets
++---------------------------------------------
++
++Arrangements are made so that when you run `make foo' in a
++subdirectory, it is like running the whole toplevel makefile, from the
++toplevel, as `make subdir/foo'. If `subdir/foo' is a file that might
++be built, that builds it.
++
++But `foo' can also be a conventional target like `all'.
++
++Each subdirectory has its own `all' target. For example a
++subdirectory `src' has a target `src/all'. The rules for these are
++automatically generated from the settings of the per-directory
++&TARGETS variables. &TARGETS is magic in this way. (In
++src/Subdir.sd.mk, &TARGETS of course refers to a make variable called
++src_TARGETS.)
++
++The `all' target in a parent directory is taken to imply the `all'
++targets in all of its subdirectories, recursively. And in the
++autogenerated stub Makefiles, `all' is the default target. So if you
++just type `make' in the toplevel, you are asking for `&all'
++(<subdir>/all) for every directory in the project.
++
++In a parallel build, the rules for all these various subdirectory
++targets may be in run in parallel: there is only one `make' invocation
++at a time. There is no sequencing between subdirectories, only been
++individual targets (as specified according to their dependencies).
++
++You can define other per-directory recursive targets too: simply
++mention (usually, by setting) the variable &TARGETS_zonk, or whatever.
++This will create a src/zonk target (for appropriate value of src/).
++Unlike `all', these other targets only exist in areas of the project
++where at least something mentions them. So for example, if
++&TARGETS_zonk is mentioned in src but not lib, `make zonk' in
++lib will fail. If you want to make a target exist everywhere,
++mention its name in Perdir.sd.mk (see below).
++
++Perdir.sd.mk, inclusion
++-----------------------
++
++The file Perdir.sd.mk in the toplevel of the source is automatically
++processed after each individual directory's Subdir.sd.mk, and the
++&-substituted contents therefore appear once for each subdirectory.
++
++This lets you do per-directory boilerplate. Some useful boilerplate
++is already provided in subdirmk, for you to reference like this:
++ &:include subdirmk/cdeps.sd.mk
++ &:include subdirmk/clean.sd.mk
++For example you could put that in Perdir.sd.mk.
++
++Global definitions
++------------------
++
++If want to set global variables, such as CC, that should only be done
++once. You can put them in your top-level Subdir.sd.mk, or a separate
++file you `include' and declare using SUBDIRMK_MAKEFILES.
++
++If you need different settings of variables like CC for different
++subdirectories, you should probably do that with target-specific
++variable settings. See the info node `(make) Target-specific'.
++
++Subdirectory templates `.sd.mk' vs plain autoconf templates `.mk.in'
++--------------------------------------------------------------------
++
++There are two kinds of template files.
++
++ Filename .sd.mk .mk.in
++
++ Processed by &-substitution, autoconf only
++ then autoconf
++
++ Instantiated Usu. once per subdir Once only
++
++ Need to be mentioned No, but Subdir.sd.mk All not in subdirmk/
++ in configure.ac? via SUBDIRMK_SUBDIRS via SUBDIRMK_MAKEFILES
++
++ How to include `&:include foo.sd.mk' `include foo.mk'
++ in all relevant .sd.mk in only one
++ (but not needed for Subdir.sd.mk
++ Subdir and Perdir)
++
++If you `include subdirmk/regen.mk', dependency management and
++automatic regeneration for all of this template substitution, and for
++config.status etc. is done for you.
++
++Substitution syntax
++-------------------
++
++In general & expands to the subdirectory name when used for a
++filename, and to the subdirectory name with / replaced with _ for
++variable names.
++
++Note that & is processed *even in makefile comments*. The substitutor
++does not understand make syntax, or shell syntax, at all. However,
++the substitution rules are chosen to work well with constructs which
++are common in makefiles.
++
++In the notation below, we suppose that the substitution is being in
++done in a subdirectory sub/dir of the source tree. In the RH column
++we describe the expansion at the top level, which is often a special
++case (in general in variable names we call that TOP rather than the
++empty string).
++
++&CAPS => sub_dir_CAPS or TOP_CAPS
++&lc => sub/dir/lc or lc
++ Here CAPS is any ASCII letter A-Z and lc is a-z.
++ The assumption is that filenames are usually lowercase and
++ variables usually uppercase. Otherwise, use another syntax:
++
++&_ => sub_dir_ or TOP_
++&/ => sub/dir/ or nothing
++&=_ => sub_dir or TOP
++&=/ => sub/dir or .
++&^ => $(top_srcdir)/sub/dir or $(top_srcdir)
++&~ => $(abs_top_srcdir)/sub/dir or $(abs_top_srcdir)
++
++&& => && for convenience in shell runes
++\& => & general escaping mechanism
++
++& thing thing... &
++& ^ thing thing... &
++& ~ thing thing... &
++ Convenience syntax for prefixing multiple filenames.
++ Introduced by & followed by lwsp (space or tab).
++ Each lwsp-separated non-ws word is prefixed by &/ &^/ &~/
++ respectively. No other & escapes are recognised.
++ This processing continues until & preceded by lwsp,
++ or until EOL (the end of the line), or \ then EOL.
++
++&:<directive> <args>....
++ recognised at start of line only (possibly after lwsp)
++ args are processed for &
++
++&:include filename filename should usually be foo.sd.mk
++&:-include filename tolerate nonexistent file
++ filenames are relative to $(top_srcdir)
++
++&!<lwsp> disables & until EOL (and then disappears)
++
++&# delete everything to end of line
++ (useful if the RHS contains unrecognised & constructions)
++
++&!STUFF
++ changes the escape sequence from & to literally STUFF
++ STUFF may be any series of of non-whitespace characters,
++ and is terminated by EOL or lwsp. &!STUFF and the lwsp
++ are discarded.
++
++ After this, write STUFF instead of &, everywhere.
++ The effect is global and lasts until the next setting.
++ It takes effect on &:include'd files too, so maybe set
++ it back before using &:include.
++
++ Notably
++ STUFFSTUFF => STUFFSTUFF
++ \STUFF => STUFF
++ STUFF!& set escape back to &
++
++&TARGETS_things
++ Handled specially. If mentioned, declares that this
++ subdir ought to have a target `things'. The rule will be
++ &/things:: $(&TARGETS_things)
++
++ You may extend it by adding more :: rules for the target,
++ but the preferred style is to do things like this:
++ &TARGETS_check += & test-passed.stamp
++
++ It is important to mention &TARGETS_things at least once in
++ the context of each applicable directory, because doing so
++ arranges that the *parent* will also have a `things' target
++ which recursively implies this directory's `things'.
++
++ Must be spelled exactly &TARGETS_things. &_TARGETS_things,
++ for example, is not magic. But mentioning &TARGETS_things in
++ a #-comment *does* work because the & filter does not care
++ about comments.
++
++ `all' is extra special: every directory has an `all'
++ target, which corresponds to &TARGETS.
++
++Subdirectory and variable naming
++--------------------------------
++
++The simple variable decoration scheme does not enforce a strict
++namespace distinction between parts of variable names which come from
++subdirectory names, and parts that mean something else.
++
++So it is a good idea to be a bit careful with your directory naming.
++`TOP', names that contain `_', and names that are similar to parts of
++make variables (whether conventional ones, or ones used in your
++project) are best avoided.
++
++If you name your variables in ALL CAPS and your subdirectories in
++lower case with `-' rather than `_', there will be no confusion.
++
++Incorporating this into your project
++------------------------------------
++
++Use `git-subtree' to merge the subdirmk/ directory. You may find it
++useful to symlink the DEVELOPER-CERTIFICATE file (git can store
++symlinks as symlinks - just `git add' the link). And you probably
++want to mention the situation in your top-level COPYING.
++
++Symlink autogen.sh into your project toplevel.
++
++In your configure.ac, say
++
++ m4_include([subdirmk/subdirmk.ac])
++ SUBDIRMK_SUBDIRS([...list of subdirectories in relative syntax...])
++
++Write a Subdir.sd.mk in each directory. The toplevel one should
++probably contain:
++
++ include subdirmk/usual.mk
++ include subdirmk/regen.mk
++
++Write a Perdir.sd.mk in the toplevel, if you want. It should probably
++have:
++
++ &:include subdirmk/cdeps.sd.mk
++ &:include subdirmk/clean.sd.mk
++
++
++Legal information
++-----------------
++
++subdirmk is
++ Copyright 2019 Mark Wooding
++ Copyright 2019 Ian Jackson
++
++ subdirmk and its example is free software; you can redistribute it
++ and/or modify it under the terms of the GNU Library General Public
++ License as published by the Free Software Foundation; either
++ version 2 of the License, or (at your option) any later version.
++
++ This 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
++ Library General Public License for more details.
++
++ You should have received a copy of the GNU Library General Public
++ License along with this library as the file LGPL-2.
++ If not, see https://www.gnu.org/.
++
++Individual files generally contain the following tag in the copyright
++notice, instead of the full licence grant text:
++ SPDX-License-Identifier: LGPL-2.0-or-later
++As is conventional, this should be read as a licence grant.
++
++Contributions are accepted based on the git commit Signed-off-by
++convention, by which the contributors' certify their contributions
++according to the Developer Certificate of Origin version 1.1 - see
++the file DEVELOPER-CERTIFICATE.
++
++Where subdirmk is used by and incorporated into another project (eg
++via git subtree), the directory subdirmk/ is under GNU LGPL-2.0+, and
++the rest of the project are under that other project's licence(s).
++(The project's overall licence must be compatible with LGPL-2.0+.)