chiark / gitweb /
Introduce CDEPS_CFLAGS so without cdeps.sd.mk you don't get .*.d
[subdirmk.git] / subdirmk / README
index bebbf81709c844aa20d9198d84ac58dcdd02d796..cc309f6ae1ec796febb92b7b4fad8083f2d9669d 100644 (file)
@@ -5,7 +5,7 @@ Introduction
 ------------
 
 Peter Miller's 1997 essay _Recursive Make Considered Harmful_
 ------------
 
 Peter Miller's 1997 essay _Recursive Make Considered Harmful_
-persuasively argues that it is better to arrannge to have a single
+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.
 
 make invocation with the project's complete dependency tree, rather
 than the currently conventional `$(MAKE) -C subdirectory' approach.
 
@@ -14,7 +14,7 @@ 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)
   - 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 
+  - 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)
 
     and say `make all' and have something reasonable happen
     (to wit, build an appropriate subset)
 
@@ -25,8 +25,8 @@ builds well).
 Basic approach
 --------------
 
 Basic approach
 --------------
 
-The developer is expected to write a makefile fragment in each
-relevant subdirectory called `Subdir.mk.in'.
+The developer is expected to write a makefile fragment, in each
+relevant subdirectory, called `Subdir.sd.mk'.
 
 These fragments may contain ordinary make language.
 
 
 These fragments may contain ordinary make language.
 
@@ -34,23 +34,23 @@ However, the sigil & is treated specially.  By and large, it refers to
 `the current directory'.  There are a variety of convenient
 constructions.
 
 `the current directory'.  There are a variety of convenient
 constructions.
 
-The result is that to a large extent, the Subdir.mk.in has an easy way
+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.
 
 to namespace its "local" make variables, and an easy way to refer to
 its "local" filenames.
 
-The Subdir.mk.in's are filtered, fed through autoconf in the usual way
+The Subdir.sd.mk's are filtered, fed through autoconf in the usual way
 (for @..@-substitutions) and included by one autogenerated toplevel
 makefile.
 
 (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.
+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.
 
 
 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.mk.in
+Where there are dependencies between subdirectories, each Subdir.sd.mk
 can simply refer to files in other subdirectories directly.
 
 Invocation, "recursive" per-directory targets
 can simply refer to files in other subdirectories directly.
 
 Invocation, "recursive" per-directory targets
@@ -66,8 +66,9 @@ 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
 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.  (In src/Subdir.mk.in, this of course refers to a
-make variable called src_TARGETS.)
+&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
 
 The `all' target in a parent directory is taken to imply the `all'
 targets in all of its subdirectories, recursively.  And in the
@@ -76,105 +77,237 @@ 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
 (<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.
+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.
 
 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.  (&TARGETS is magic.)
+This will create a src/zonk target.
 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,
 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.mk.in (see below).
+mention its name in Perdir.sd.mk (see below).
 
 
-Perdir.mk.in, inclusion
+Perdir.sd.mk, inclusion
 -----------------------
 
 -----------------------
 
-The file Perdir.mk.in in the toplevel of fthe source is automatically
-processed after each individual directory's Subdir.mk.in, and the
+The file Perdir.sd.mk in the toplevel of fthe 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:
 &-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.mk.in
-  &:include subdirmk/clean.mk.in
-
-Note that you must use &:include, which is an include processed during
-the generation of the per-directory Subdir.mk files.  That ensures
-that the contents of these files is replicated, with appropriate
-per-directory substitutions, for each directory.
+  &:include subdirmk/cdeps.sd.mk
+  &:include subdirmk/clean.sd.mk
+For example you could put that in Perdir.sd.mk.
 
 Global definitions
 ------------------
 
 
 Global definitions
 ------------------
 
-If want to set global variables, such as CC
+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.
 
 
-  subdirmk/cdeps.mk.in
-  subdirmk/cdeps.mk.in
-  
+ 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.
 
 
-  (None of this prevents
+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:
 
 
-  https://web.archive.org/web/20150330111905/http://miller.emu.id.au/pmiller/books/rmch/
+&_             =>      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 &
 
 
-&CAPS          =>      subdir_CAPS                     or TOP_CAPS
-&lc            =>      subdir/lc                       or lc
+&:include filename             filename should usually be foo.sd.mk
+&:-include filename            tolerate nonexistent file
+       filenames are relative to $(top_srcdir)
 
 
-&_             =>      subdir_                         or TOP_
-&/             =>      subdir/                         or nothing
-&=_            =>      subdir                          or TOP
-&=/            =>      subdir                          or .
-&^             =>      $(top_srcdir)/subdir            or $(top_srcdir)
-&~             =>      $(abs_top_srcdir)/subdir        or $(abs_top_srcdir)
+&!<lwsp>       disables & until EOL (and then disappears)
 
 
-&&             =>      &&
-\&             =>      &
+&#     delete everything to end of line
+       (useful if the RHS contains unrecognise & constructions)
 
 
-& thing thing... &     =>      each thing prefixed by &/ &^/ &~/ resp
-& ^ thing thing... &           each thing is any non-ws
-& ~ thing thing... &           & may be omitted before EOL or before \EOL
-                               other &'s not recognised
+&!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.
 
 
-start of line (maybe after ws):
-&:<directive> <args>....
-args are processed for & first
-&:include filename             filename should usually be foo.mk.in
-&:-include filename
+       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
+-----------------
 
 
-CAPS is [A-Z][0-9_A-Z]*(?!\w)
-lc is [a-z][-+,0-9_a-z]*(?!\w)
+subdirmk is
+ Copyright 2019 Mark Wooding
+ Copyright 2019 Ian Jackson
 
 
-&!<spaces or tabs>     disables & *until* EOL (and disappears)
+    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.
 
 
-&!STUFF<lwsp>          STUFF is recognised instead of &
-                       the terminating lwsp is discarded too
-                       may also occur at eol
+    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.
 
 
-eg notably
- STUFF!&       now & is recognised instead (ie back to normal)
- STUFFSTUFF    STUFF
+    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/.
 
 
-eg
- &!@@@         @@@ is recognised instead of &
- @@@!&         go back to &
+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.
 
 
-&TARGETS[_things]              is handled specially
-                               must be spelled precisely this way
-                               if no _things, means _all
+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.
 
 
-Also, `all' is weird in that it is present even if not specified
+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+.)