------------
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.
- 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)
(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
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, &TARGES of course refers to a make variable called
+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'
(<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.
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'
--------------------------------------------------------------------
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
+&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:
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 a & preceded by lwsp,
+ This processing continues until & preceded by lwsp,
or until EOL (the end of the line), or \ then EOL.
&:<directive> <args>....
&: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 unrecognise & 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
- is discarded.
+ 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 back before using &:include.
Notably
- STUFFSTUFF => STUFF
+ STUFFSTUFF => STUFFSTUFF
\STUFF => STUFF
STUFF!& set escape back to &
&TARGETS_things
- Handled specially. If mentioned, declares that
- this subdirectory ought to have a target `things'.
- (`all' if not specified). The rule will be
+ 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,
&TARGETS_check += & test-passed.stamp
It is important to mention &TARGETS_things at least once in
- the context of each applicable directory, because it arranges
- that the *parent* will also have a `things' target which
- recursively implies this directory's `things'.
+ 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, does not work. But mentioning it in a #-comment
- *does* work because the & filter does not care about comments.
+ 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.
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
-----------------