1 subdirmk - assistance for non-recursive use of make
2 ===================================================
7 Peter Miller's 1997 essay _Recursive Make Considered Harmful_
8 persuasively argues that it is better to arrannge to have a single
9 make invocation with the project's complete dependency tree, rather
10 than the currently conventional `$(MAKE) -C subdirectory' approach.
12 However, actually writing a project's build system in a non-recursive
13 style is not very ergonomic. The main difficulties are:
14 - constantly having to write out long file and directory names
15 - the lack of a per-directory make variable namespace means
16 long make variables (or namespace clashes)
17 - it is difficult to arrange that one can cd to a subdirectory
18 and say `make all' and have something reasonable happen
19 (to wit, build an appropriate subset)
21 `subdirmk' is an attempt to solve these problems (and it also slightly
22 alleviates some of the boilerplate needed to support out-of-tree
28 The developer is expected to write a makefile fragment in each
29 relevant subdirectory called `Subdir.mk.in'.
31 These fragments may contain ordinary make language.
33 However, the sigil & is treated specially. By and large, it refers to
34 `the current directory'. There are a variety of convenient
37 The result is that to a large extent, the Subdir.mk.in has an easy way
38 to namespace its "local" make variables, and an easy way to refer to
39 its "local" filenames.
41 The Subdir.mk.in's are filtered, fed through autoconf in the usual way
42 (for @..@-substitutions) and included by one autogenerated toplevel
45 So all of the input is combined and passed to one make invocation. (A
46 corollary is that there is no enforcement of the namespacing:
47 discipline is required to prefix relevant variable names with &, etc.
49 Each subdirectory is also provided with an autogenerated `Makefile'
50 which exists purely to capture ordinary make invocations and arrange
51 for something suitable to happen.
53 Where there are dependencies between subdirectories, each Subdir.mk.in
54 can simply refer to files in other subdirectories directly.
56 Invocation, "recursive" per-directory targets
57 ---------------------------------------------
59 Arrangements are made so that when you run `make foo' in a
60 subdirectory, it is like running the whole toplevel makefile, from the
61 toplevel, as `make subdir/foo'. If `subdir/foo' is a file that might
62 be built, that builds it.
64 But `foo' can also be a conventional target like `all'.
66 Each subdirectory has its own `all' target. For example a
67 subdirectory `src' has a target `src/all'. The rules for these are
68 automatically generated from the settings of the per-directory
69 &TARGETS variables. (In src/Subdir.mk.in, this of course refers to a
70 make variable called src_TARGETS.)
72 The `all' target in a parent directory is taken to imply the `all'
73 targets in all of its subdirectories, recursively. And in the
74 autogenerated stub Makefiles, `all' is the default target. So if you
75 just type `make' in the toplevel, you are asking for `&all'
76 (<subdir>/all) for every directory in the project.
78 In a parallel build, the rules for all these various subdirectory
79 targets may be in run in parallel: there is only one `make'
82 You can define other per-directory recursive targets too: simply
83 mention (usually, by setting) the variable &TARGETS_zonk, or whatever.
84 This will create a src/zonk target. (&TARGETS is magic.)
85 Unlike `all', these other targets only exist in areas of the project
86 where at least something mentions them. So for example, if
87 &TARGETS_zonk is mentioned in src but not lib, `make zonk' in
88 lib will fail. If you want to make a target exist everywhere,
89 mention its name in Perdir.mk.in (see below).
91 Perdir.mk.in, inclusion
92 -----------------------
94 The file Perdir.mk.in in the toplevel of fthe source is automatically
95 processed after each individual directory's Subdir.mk.in, and the
96 &-substituted contents therefore appear once for each subdirectory.
98 This lets you do per-directory boilerplate. Some useful boilerplate
99 is already provided in subdirmk, for you to reference like this:
100 &:include subdirmk/cdeps.mk.in
101 &:include subdirmk/clean.mk.in
103 Note that you must use &:include, which is an include processed during
104 the generation of the per-directory Subdir.mk files. That ensures
105 that the contents of these files is replicated, with appropriate
106 per-directory substitutions, for each directory.
111 If want to set global variables, such as CC
124 (None of this prevents
130 https://web.archive.org/web/20150330111905/http://miller.emu.id.au/pmiller/books/rmch/
135 &CAPS => subdir_CAPS or TOP_CAPS
136 &lc => subdir/lc or lc
138 &_ => subdir_ or TOP_
139 &/ => subdir/ or nothing
142 &^ => $(top_srcdir)/subdir or $(top_srcdir)
143 &~ => $(abs_top_srcdir)/subdir or $(abs_top_srcdir)
148 & thing thing... & => each thing prefixed by &/ &^/ &~/ resp
149 & ^ thing thing... & each thing is any non-ws
150 & ~ thing thing... & & may be omitted before EOL or before \EOL
151 other &'s not recognised
153 start of line (maybe after ws):
154 &:<directive> <args>....
155 args are processed for & first
156 &:include filename filename should usually be foo.mk.in
159 CAPS is [A-Z][0-9_A-Z]*(?!\w)
160 lc is [a-z][-+,0-9_a-z]*(?!\w)
162 &!<spaces or tabs> disables & *until* EOL (and disappears)
164 &!STUFF<lwsp> STUFF is recognised instead of &
165 the terminating lwsp is discarded too
166 may also occur at eol
169 STUFF!& now & is recognised instead (ie back to normal)
173 &!@@@ @@@ is recognised instead of &
176 &TARGETS[_things] is handled specially
177 must be spelled precisely this way
178 if no _things, means _all
180 Also, `all' is weird in that it is present even if not specified