chiark / gitweb /
do not demand \W after CAPS and lc
[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.sd.mk'.
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.sd.mk 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.sd.mk'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.sd.mk
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.sd.mk, 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.sd.mk (see below).
90
91 Perdir.sd.mk, inclusion
92 -----------------------
93
94 The file Perdir.sd.mk in the toplevel of fthe source is automatically
95 processed after each individual directory's Subdir.sd.mk, 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.sd.mk
101   &:include subdirmk/clean.sd.mk
102 (for example in Perdir.sd.mk).
103
104 Subdirectory templates `.sd.mk' vs plain autoconf templates `.mk.in'
105 --------------------------------------------------------------------
106
107 There are two kinds of template files.
108
109  Filename                 .sd.mk                  .mk.in
110
111  Processed by             &-substitution,         autoconf only
112                           then autoconf
113
114  Need to be mentioned     No, but Subdir.sd.mk    All not in subdirmk/
115  in configure.ac          via SUBDIRMK_SUBDIRS    via SUBDIRMK_MAKEFILES
116
117  How to include           `&:include foo.sd.mk'   `include foo.mk'
118                           in all relevant .sd.mk  in only one
119                           (but not needed for     Subdir.sd.mk
120                            Subdir and Perdir)
121
122 If you `include subdirmk/regen.mk', dependency management and
123 automatic regeneration for all of this template substitution, and for
124 config.status etc. is done for you.
125
126 Global definitions
127 ------------------
128
129 If want to set global variables, such as CC, that should only be done
130 once.  The usual approach is to include 
131
132
133
134   subdirmk/cdeps.mk.in
135   subdirmk/cdeps.mk.in
136   
137
138
139
140
141
142
143   (None of this prevents
144
145
146
147
148
149   https://web.archive.org/web/20150330111905/http://miller.emu.id.au/pmiller/books/rmch/
150
151
152
153
154 &CAPS           =>      subdir_CAPS                     or TOP_CAPS
155 &lc             =>      subdir/lc                       or lc
156
157 &_              =>      subdir_                         or TOP_
158 &/              =>      subdir/                         or nothing
159 &=_             =>      subdir                          or TOP
160 &=/             =>      subdir                          or .
161 &^              =>      $(top_srcdir)/subdir            or $(top_srcdir)
162 &~              =>      $(abs_top_srcdir)/subdir        or $(abs_top_srcdir)
163
164 &&              =>      &&
165 \&              =>      &
166
167 & thing thing... &      =>      each thing prefixed by &/ &^/ &~/ resp
168 & ^ thing thing... &            each thing is any non-ws
169 & ~ thing thing... &            & may be omitted before EOL or before \EOL
170                                 other &'s not recognised
171
172 start of line (maybe after ws):
173 &:<directive> <args>....
174 args are processed for & first
175 &:include filename              filename should usually be foo.mk.in
176 &:-include filename
177
178 CAPS is [A-Z][0-9_A-Z]*(?!\w)
179 lc is [a-z][-+,0-9_a-z]*(?!\w)
180
181 &!<spaces or tabs>      disables & *until* EOL (and disappears)
182
183 &!STUFF<lwsp>           STUFF is recognised instead of &
184                         the terminating lwsp is discarded too
185                         may also occur at eol
186
187 eg notably
188  STUFF!&        now & is recognised instead (ie back to normal)
189  STUFFSTUFF     STUFF
190
191 eg
192  &!@@@          @@@ is recognised instead of &
193  @@@!&          go back to &
194
195 &TARGETS[_things]               is handled specially
196                                 must be spelled precisely this way
197                                 if no _things, means _all
198
199 Also, `all' is weird in that it is present even if not specified