chiark / gitweb /
wip docs, before rename .mk.in
[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 Invocation, "recursive" per-directory targets
57 ---------------------------------------------
58
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.
63
64 But `foo' can also be a conventional target like `all'.
65
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.)
71
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.
77
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'
80 invocation at a time.
81
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).
90
91 Perdir.mk.in, inclusion
92 -----------------------
93
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.
97
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
102
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.
107
108 Global definitions
109 ------------------
110
111 If want to set global variables, such as CC
112
113
114
115   subdirmk/cdeps.mk.in
116   subdirmk/cdeps.mk.in
117   
118
119
120
121
122
123
124   (None of this prevents
125
126
127
128
129
130   https://web.archive.org/web/20150330111905/http://miller.emu.id.au/pmiller/books/rmch/
131
132
133
134
135 &CAPS           =>      subdir_CAPS                     or TOP_CAPS
136 &lc             =>      subdir/lc                       or lc
137
138 &_              =>      subdir_                         or TOP_
139 &/              =>      subdir/                         or nothing
140 &=_             =>      subdir                          or TOP
141 &=/             =>      subdir                          or .
142 &^              =>      $(top_srcdir)/subdir            or $(top_srcdir)
143 &~              =>      $(abs_top_srcdir)/subdir        or $(abs_top_srcdir)
144
145 &&              =>      &&
146 \&              =>      &
147
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
152
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
157 &:-include filename
158
159 CAPS is [A-Z][0-9_A-Z]*(?!\w)
160 lc is [a-z][-+,0-9_a-z]*(?!\w)
161
162 &!<spaces or tabs>      disables & *until* EOL (and disappears)
163
164 &!STUFF<lwsp>           STUFF is recognised instead of &
165                         the terminating lwsp is discarded too
166                         may also occur at eol
167
168 eg notably
169  STUFF!&        now & is recognised instead (ie back to normal)
170  STUFFSTUFF     STUFF
171
172 eg
173  &!@@@          @@@ is recognised instead of &
174  @@@!&          go back to &
175
176 &TARGETS[_things]               is handled specially
177                                 must be spelled precisely this way
178                                 if no _things, means _all
179
180 Also, `all' is weird in that it is present even if not specified