chiark / gitweb /
refactor filter_subdir_mk, breaking out $pi, nfc
[subdirmk.git] / subdirmk / README
1 subdirmk - assistance for non-recursive use of make
2 ===================================================
3
4 Introduction
5 ------------
6
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.
11
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)
20
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
23 builds well).
24
25 Basic approach
26 --------------
27
28 The developer is expected to write a makefile fragment in each
29 relevant subdirectory called `Subdir.mk.in'.
30
31 These fragments may contain ordinary make language.
32
33 However, the sigil & is treated specially.  By and large, it refers to
34 `the current directory'.  There are a variety of convenient
35 constructions.
36
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.
40
41 The Subdir.mk.in's are filtered, fed through autoconf in the usual way
42 (for @..@-substitutions) and included by one autogenerated toplevel
43 makefile.
44
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.
48
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.
52
53 Where there are dependencies between subdirectories, each Subdir.mk.in
54 can simply refer to files in other subdirectories directly.
55
56 Per-directory targets, "recursion"
57 ----------------------------------
58
59 Each subdirectory has its own `all' target.  For example a
60 subdirectory `src' has a target `src/all'.  The rules for these are
61 automatically generated from the settings of the per-directory
62 &TARGETS variables.  (In src/Subdir.mk.in, this of course refers to a
63 make variable called src_TARGETS.)
64
65 The `all' target in a parent directory is taken to imply the `all'
66 targets in all of its subdirectories, recursively.  And in the
67 autogenerated stub Makefiles, `all' is the default target.  So if you
68 just type `make' in the toplevel, you are asking for `&all'
69 (<subdir>/all) for every directory in the project.
70
71 In a parallel build, the rules for all these various subdirectory
72 targets may be in run in parallel: there is only one `make'
73 invocation at a time.
74
75 There may also be other 
76
77
78
79
80
81
82   (None of this prevents
83
84
85
86
87
88   https://web.archive.org/web/20150330111905/http://miller.emu.id.au/pmiller/books/rmch/
89
90
91
92
93 &CAPS           =>      subdir_CAPS                     or TOP_CAPS
94 &lc             =>      subdir/lc                       or lc
95
96 &_              =>      subdir_                         or TOP_
97 &/              =>      subdir/                         or nothing
98 &=_             =>      subdir                          or TOP
99 &=/             =>      subdir                          or .
100 &^              =>      $(top_srcdir)/subdir            or $(top_srcdir)
101 &~              =>      $(abs_top_srcdir)/subdir        or $(abs_top_srcdir)
102
103 &&              =>      &&
104 \&              =>      &
105
106 & thing thing... &      =>      each thing prefixed by &/ &^/ &~/ resp
107 & ^ thing thing... &            each thing is any non-ws
108 & ~ thing thing... &            & may be omitted before EOL or before \EOL
109                                 other &'s not recognised
110
111 start of line (maybe after ws):
112 &:<directive> <args>....
113 args are processed for & first
114 &:include filename              filename should usually be foo.mk.in
115 &:-include filename
116
117 CAPS is [A-Z][0-9_A-Z]*(?!\w)
118 lc is [a-z][-+,0-9_a-z]*(?!\w)
119
120 &!<spaces or tabs>      disables & *until* EOL (and disappears)
121
122 &!STUFF<lwsp>           STUFF is recognised instead of &
123                         the terminating lwsp is discarded too
124                         may also occur at eol
125
126 eg notably
127  STUFF!&        now & is recognised instead (ie back to normal)
128  STUFFSTUFF     STUFF
129
130 eg
131  &!@@@          @@@ is recognised instead of &
132  @@@!&          go back to &
133
134 &TARGETS[_things]               is handled specially
135                                 must be spelled precisely this way
136                                 if no _things, means _all
137
138 Also, `all' is weird in that it is present even if not specified