chiark / gitweb /
Add 'subdirmk/' from commit 'f1789a0ae66174a95c8d629738eae98d40c084ac'
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Wed, 13 Nov 2019 23:24:27 +0000 (23:24 +0000)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Wed, 13 Nov 2019 23:24:27 +0000 (23:24 +0000)
git-subtree-dir: subdirmk
git-subtree-mainline: d212a384b4ef631a876e1ddd3e52fd09e4b1f484
git-subtree-split: f1789a0ae66174a95c8d629738eae98d40c084ac

27 files changed:
1  2 
subdirmk/.gitignore
subdirmk/DEVELOPER-CERTIFICATE
subdirmk/LGPL-2
subdirmk/README
subdirmk/autogen.sh
subdirmk/cdeps.sd.mk
subdirmk/clean.sd.mk
subdirmk/example/.gitignore
subdirmk/example/DEVELOPER-CERTIFICATE
subdirmk/example/LGPL-2
subdirmk/example/Perdir.sd.mk
subdirmk/example/Subdir.sd.mk
subdirmk/example/autogen.sh
subdirmk/example/configure.ac
subdirmk/example/lib/Subdir.sd.mk
subdirmk/example/lib/t/Subdir.sd.mk
subdirmk/example/lib/t/toytest.c
subdirmk/example/lib/toylib.c
subdirmk/example/lib/toylib.h
subdirmk/example/src/Subdir.sd.mk
subdirmk/example/src/toy.c
subdirmk/example/subdirmk
subdirmk/generate
subdirmk/regen.mk.in
subdirmk/subdirmk.ac
subdirmk/tests/check
subdirmk/usual.mk.in

index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..a5b02c22134c75d5f045917c43ca36662c4b6a2b
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,8 @@@
++# subdirmk - subdirmk/.gitignore
++#  Copyright 2019 Mark Wooding
++#  Copyright 2019 Ian Jackson
++# SPDX-License-Identifier: LGPL-2.0-or-later
++
++#----- subdirmk-generated -----
++/regen.mk
++/usual.mk
index 0000000000000000000000000000000000000000,912d22ee9efecf5fb2a9cc972765a0efb23f82d3..912d22ee9efecf5fb2a9cc972765a0efb23f82d3
mode 000000,100644..100644
--- /dev/null
diff --cc subdirmk/LGPL-2
index 0000000000000000000000000000000000000000,5bc8fb2c8f757e34a0d8f4644f589d57609e213f..5bc8fb2c8f757e34a0d8f4644f589d57609e213f
mode 000000,100644..100644
--- /dev/null
--- 2/LGPL-2
diff --cc subdirmk/README
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..e5ef4b4f5c28a1291e1d4b9c4e981d1ffb4f4eb7
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,313 @@@
++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+.)
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..e28e80e0ce9a781dec49b395b83690ee2eef4344
new file mode 100755 (executable)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,7 @@@
++#!/bin/sh
++# subdirmk, autogen.sh (conventional autoconf invocation script)
++#  Copyright 2019 Ian Jackson
++# SPDX-License-Identifier: LGPL-2.0-or-later
++set -e
++cd ${0%/*}
++autoconf
index 0000000000000000000000000000000000000000,402e687c6aa63153951e95e704d02f488a77d547..402e687c6aa63153951e95e704d02f488a77d547
mode 000000,100644..100644
--- /dev/null
index 0000000000000000000000000000000000000000,08f8dcc61e5cd584618e97a8d81b696f0dfd50ca..08f8dcc61e5cd584618e97a8d81b696f0dfd50ca
mode 000000,100644..100644
--- /dev/null
index 0000000000000000000000000000000000000000,a97b4139b7dd13da6ec8ca4275dd43f9c2dc7765..a97b4139b7dd13da6ec8ca4275dd43f9c2dc7765
mode 000000,100644..100644
--- /dev/null
index 0000000000000000000000000000000000000000,d56384eea50f013b7ea783ea1e3537e6bde40fc9..d56384eea50f013b7ea783ea1e3537e6bde40fc9
mode 000000,120000..120000
--- /dev/null
index 0000000000000000000000000000000000000000,318395ddf447aa3b51e2e3e517456951b915b35a..318395ddf447aa3b51e2e3e517456951b915b35a
mode 000000,120000..120000
--- /dev/null
index 0000000000000000000000000000000000000000,65b863051db49bb3fe2bc1da96ea3275becd0605..65b863051db49bb3fe2bc1da96ea3275becd0605
mode 000000,100644..100644
--- /dev/null
index 0000000000000000000000000000000000000000,5c2040a1b8f65b8ce848380a3ee3c7fd7a688029..5c2040a1b8f65b8ce848380a3ee3c7fd7a688029
mode 000000,100644..100644
--- /dev/null
index 0000000000000000000000000000000000000000,589d83571b0fe6dd87282813af4c56da512956e7..589d83571b0fe6dd87282813af4c56da512956e7
mode 000000,120000..120000
--- /dev/null
index 0000000000000000000000000000000000000000,b7c07e7c60c2175905947d8e4851c13843c167ef..b7c07e7c60c2175905947d8e4851c13843c167ef
mode 000000,100644..100644
--- /dev/null
index 0000000000000000000000000000000000000000,c2939c54457ebe992e86b2a244e0550391d4aab4..c2939c54457ebe992e86b2a244e0550391d4aab4
mode 000000,100644..100644
--- /dev/null
index 0000000000000000000000000000000000000000,ae11cd053f19a584f8e492e303bb1029affc32c5..ae11cd053f19a584f8e492e303bb1029affc32c5
mode 000000,100644..100644
--- /dev/null
index 0000000000000000000000000000000000000000,aa03e1ec6baaee6d8774e3f5e16bdbb060b6c8d6..aa03e1ec6baaee6d8774e3f5e16bdbb060b6c8d6
mode 000000,100644..100644
--- /dev/null
index 0000000000000000000000000000000000000000,6e73f766b56e1cbe2dd751e6d4f8dfa4b34d7fc0..6e73f766b56e1cbe2dd751e6d4f8dfa4b34d7fc0
mode 000000,100644..100644
--- /dev/null
index 0000000000000000000000000000000000000000,04848d5ecf297f719dce1327aaaf962cdfec82df..04848d5ecf297f719dce1327aaaf962cdfec82df
mode 000000,100644..100644
--- /dev/null
index 0000000000000000000000000000000000000000,402116eebabd66740d2ba3bb284b1c190530ed86..402116eebabd66740d2ba3bb284b1c190530ed86
mode 000000,100644..100644
--- /dev/null
index 0000000000000000000000000000000000000000,a70f8616dd3d1ba921e1b42d2aa8c76862919b70..a70f8616dd3d1ba921e1b42d2aa8c76862919b70
mode 000000,100644..100644
--- /dev/null
index 0000000000000000000000000000000000000000,a96aa0ea9d8c443416d31c3a85dbe928f120cc23..a96aa0ea9d8c443416d31c3a85dbe928f120cc23
mode 000000,120000..120000
--- /dev/null
index 0000000000000000000000000000000000000000,486bdc54e1c888b7be9cee539918296651cc8010..486bdc54e1c888b7be9cee539918296651cc8010
mode 000000,100755..100755
--- /dev/null
index 0000000000000000000000000000000000000000,83952c9e648527eaf74b85b1c68317f13718ef50..83952c9e648527eaf74b85b1c68317f13718ef50
mode 000000,100644..100644
--- /dev/null
index 0000000000000000000000000000000000000000,bacd1cfa64dae69b4c5f9854b5fbea714bfa5795..bacd1cfa64dae69b4c5f9854b5fbea714bfa5795
mode 000000,100644..100644
--- /dev/null
index 0000000000000000000000000000000000000000,f0914dd597e456fd0a14287f1bb73d6834bcd44a..f0914dd597e456fd0a14287f1bb73d6834bcd44a
mode 000000,100755..100755
--- /dev/null
index 0000000000000000000000000000000000000000,66c71ebcde5ae968a04fa001accef3cd494800cb..66c71ebcde5ae968a04fa001accef3cd494800cb
mode 000000,100644..100644
--- /dev/null