xref: /plan9/sys/doc/mk.ms (revision 426d2b71458df9b491ba6c167f699b3f1f7b0428)
1*426d2b71SDavid du Colombier.HTML "Maintaining Files on Plan 9 with Mk
2219b2ee8SDavid du Colombier.TL
3219b2ee8SDavid du ColombierMaintaining Files on Plan 9 with Mk
4219b2ee8SDavid du Colombier.AU
5219b2ee8SDavid du ColombierAndrew G. Hume
67dd7cddfSDavid du Colombierandrew@research.att.com
7219b2ee8SDavid du ColombierBob Flandrena
87dd7cddfSDavid du Colombierbobf@plan9.bell-labs.com
9219b2ee8SDavid du Colombier.AB
10219b2ee8SDavid du Colombier.PP
11219b2ee8SDavid du Colombier.CW Mk
12219b2ee8SDavid du Colombieris a tool
13219b2ee8SDavid du Colombierfor describing and maintaining dependencies between
14219b2ee8SDavid du Colombierfiles.
15219b2ee8SDavid du ColombierIt is similar to the
16219b2ee8SDavid du ColombierUNIX program
17219b2ee8SDavid du Colombier.CW make ,
187dd7cddfSDavid du Colombierbut provides several extensions.
19219b2ee8SDavid du Colombier.CW Mk\fR'\fPs
20219b2ee8SDavid du Colombierflexible rule specifications, implied
21219b2ee8SDavid du Colombierdependency derivation, and parallel
22219b2ee8SDavid du Colombierexecution of maintenance actions are
23219b2ee8SDavid du Colombierwell-suited to the Plan 9 environment.
24219b2ee8SDavid du ColombierAlmost all Plan 9 maintenance procedures
25219b2ee8SDavid du Colombierare automated using
26219b2ee8SDavid du Colombier.CW mk .
27219b2ee8SDavid du Colombier.AE
28219b2ee8SDavid du Colombier.NH 1
29219b2ee8SDavid du ColombierIntroduction
30219b2ee8SDavid du Colombier.PP
317dd7cddfSDavid du ColombierThis document describes how
327dd7cddfSDavid du Colombier.CW mk ,
337dd7cddfSDavid du Colombiera program functionally similar to
34219b2ee8SDavid du Colombier.CW make
357dd7cddfSDavid du Colombier[Feld79],
367dd7cddfSDavid du Colombieris used to maintain dependencies between
377dd7cddfSDavid du Colombierfiles in Plan 9.
38219b2ee8SDavid du Colombier.CW Mk
397dd7cddfSDavid du Colombierprovides several extensions to the
407dd7cddfSDavid du Colombiercapabilities of its predecessor that work
417dd7cddfSDavid du Colombierwell in Plan 9's distributed, multi-architecture
427dd7cddfSDavid du Colombierenvironment.  It
43219b2ee8SDavid du Colombierexploits the power of multiprocessors by executing
447dd7cddfSDavid du Colombiermaintenance actions in parallel and interacts with
457dd7cddfSDavid du Colombierthe Plan 9 command interpreter
46219b2ee8SDavid du Colombier.CW rc
477dd7cddfSDavid du Colombierto provide a powerful set of maintenance tools.
487dd7cddfSDavid du ColombierIt accepts pattern-based dependency specifications
49219b2ee8SDavid du Colombierthat are not limited to describing
50219b2ee8SDavid du Colombierrules for program construction.
51219b2ee8SDavid du ColombierThe result is a tool that is flexible enough to
52219b2ee8SDavid du Colombierperform many maintenance tasks including
53219b2ee8SDavid du Colombierdatabase maintenance,
54219b2ee8SDavid du Colombierhardware design, and document production.
55219b2ee8SDavid du Colombier.PP
56219b2ee8SDavid du ColombierThis document begins by discussing
577dd7cddfSDavid du Colombierthe syntax of the control file,
58219b2ee8SDavid du Colombierthe pattern matching capabilities, and
59219b2ee8SDavid du Colombierthe special rules for maintaining archives.
60219b2ee8SDavid du ColombierA brief description of
61219b2ee8SDavid du Colombier.CW mk\fR'\fPs
62219b2ee8SDavid du Colombieralgorithm for deriving dependencies
63219b2ee8SDavid du Colombieris followed by a discussion
64219b2ee8SDavid du Colombierof the conventions used to resolve ambiguous
65219b2ee8SDavid du Colombierspecifications.  The final sections
66219b2ee8SDavid du Colombierdescribe parallel execution
67219b2ee8SDavid du Colombierand special features.
68219b2ee8SDavid du Colombier.PP
69219b2ee8SDavid du ColombierAn earlier paper [Hume87]
70219b2ee8SDavid du Colombierprovides a detailed discussion of
71219b2ee8SDavid du Colombier.CW mk\fR'\fPs
727dd7cddfSDavid du Colombierdesign and an appendix summarizes
737dd7cddfSDavid du Colombierthe differences between
747dd7cddfSDavid du Colombier.CW mk
757dd7cddfSDavid du Colombierand
767dd7cddfSDavid du Colombier.CW make .
77219b2ee8SDavid du Colombier.NH 1
78219b2ee8SDavid du ColombierThe \f(CWMkfile\fP
79219b2ee8SDavid du Colombier.PP
80219b2ee8SDavid du Colombier.CW Mk
81219b2ee8SDavid du Colombierreads a file describing relationships among files
82219b2ee8SDavid du Colombierand executes commands to bring the files up to date.
83219b2ee8SDavid du ColombierThe specification file, called a
84219b2ee8SDavid du Colombier.CW mkfile ,
85219b2ee8SDavid du Colombiercontains three types of statements:
86219b2ee8SDavid du Colombierassignments, includes, and rules.
87219b2ee8SDavid du ColombierAssignment and include statements are similar
88219b2ee8SDavid du Colombierto those in C.
89219b2ee8SDavid du ColombierRules specify dependencies between a
90219b2ee8SDavid du Colombier.I target
91219b2ee8SDavid du Colombierand its
92219b2ee8SDavid du Colombier.I prerequisites .
93219b2ee8SDavid du ColombierWhen the target and prerequisites are files, their
94219b2ee8SDavid du Colombiermodification times determine if they
95219b2ee8SDavid du Colombierare out of date.  Rules often contain a
96219b2ee8SDavid du Colombier.I recipe ,
97219b2ee8SDavid du Colombieran
98219b2ee8SDavid du Colombier.I rc (1)
99219b2ee8SDavid du Colombierscript that produces the target from
100219b2ee8SDavid du Colombierthe prerequisites.
101219b2ee8SDavid du Colombier.PP
102219b2ee8SDavid du ColombierThis simple
103219b2ee8SDavid du Colombier.CW mkfile
104219b2ee8SDavid du Colombierproduces an executable
105219b2ee8SDavid du Colombierfrom a C source file:
106219b2ee8SDavid du Colombier.P1
107219b2ee8SDavid du ColombierCC=pcc
108219b2ee8SDavid du Colombierf1:	f1.c
109219b2ee8SDavid du Colombier	$CC -o f1 f1.c
110219b2ee8SDavid du Colombier.P2
111219b2ee8SDavid du ColombierThe first line assigns the name of the portable ANSI/POSIX compiler
112219b2ee8SDavid du Colombierto the
113219b2ee8SDavid du Colombier.CW mk
114219b2ee8SDavid du Colombiervariable
115219b2ee8SDavid du Colombier.CW CC ;
116219b2ee8SDavid du Colombiersubsequent references of the form
117219b2ee8SDavid du Colombier.CW $CC
118219b2ee8SDavid du Colombierselect this compiler.
119219b2ee8SDavid du ColombierThe only rule specifies a dependence between the target file
120219b2ee8SDavid du Colombier.CW f1
121219b2ee8SDavid du Colombierand the prerequisite file
122219b2ee8SDavid du Colombier.CW f1.c .
123219b2ee8SDavid du ColombierIf the target does not exist or if the
124219b2ee8SDavid du Colombierprerequisite has been modified more recently than
125219b2ee8SDavid du Colombierthe target,
126219b2ee8SDavid du Colombier.CW mk
127219b2ee8SDavid du Colombierpasses the recipe to
128219b2ee8SDavid du Colombier.CW rc
129219b2ee8SDavid du Colombierfor execution.  Here,
130219b2ee8SDavid du Colombier.CW f1.c
131219b2ee8SDavid du Colombieris compiled and loaded to produce
132219b2ee8SDavid du Colombier.CW f1 .
133219b2ee8SDavid du Colombier.PP
134219b2ee8SDavid du ColombierThe native Plan 9 environment
135219b2ee8SDavid du Colombierrequires executables for
136219b2ee8SDavid du Colombierall architectures, not only the current one.
137219b2ee8SDavid du ColombierThe Plan 9 version of the same
138219b2ee8SDavid du Colombier.CW mkfile
139219b2ee8SDavid du Colombierlooks like:
140219b2ee8SDavid du Colombier.P1
141219b2ee8SDavid du Colombier</$objtype/mkfile
142219b2ee8SDavid du Colombier
143219b2ee8SDavid du Colombierf1:	f1.$O
144219b2ee8SDavid du Colombier	$LD $LDFLAGS -o f1 f1.$O
145219b2ee8SDavid du Colombierf1.$O:	f1.c
146219b2ee8SDavid du Colombier	$CC $CFLAGS f1.c
147219b2ee8SDavid du Colombier.P2
148219b2ee8SDavid du ColombierThe first line is an include statement
149219b2ee8SDavid du Colombierthat replaces itself with the contents of the file
150219b2ee8SDavid du Colombier.CW /$objtype/mkfile .
151219b2ee8SDavid du ColombierThe variable
152219b2ee8SDavid du Colombier.CW $objtype
153219b2ee8SDavid du Colombieris inherited from the environment and
154219b2ee8SDavid du Colombiercontains the name of the target architecture.
155219b2ee8SDavid du ColombierThe prototype
156219b2ee8SDavid du Colombier.CW mkfile
157219b2ee8SDavid du Colombierfor that architecture defines architecture-specific variables:
158219b2ee8SDavid du Colombier.CW CC
159219b2ee8SDavid du Colombierand
160219b2ee8SDavid du Colombier.CW LD
161219b2ee8SDavid du Colombierare the names of the compiler and loader,
162219b2ee8SDavid du Colombier.CW O
163219b2ee8SDavid du Colombieris the code character of the architecture.
164219b2ee8SDavid du ColombierThe rules compile the source file into an object
165219b2ee8SDavid du Colombierfile and invoke the loader to produce
166219b2ee8SDavid du Colombier.CW f1 .
167219b2ee8SDavid du ColombierInvoking
168219b2ee8SDavid du Colombier.CW mk
169219b2ee8SDavid du Colombierfrom the command line as follows
170219b2ee8SDavid du Colombier.P1
1717dd7cddfSDavid du Colombier% objtype=mips mk
1727dd7cddfSDavid du Colombiervc -w f1.c
1737dd7cddfSDavid du Colombiervl $LDFLAGS -o f1 f1.k
174219b2ee8SDavid du Colombier%
175219b2ee8SDavid du Colombier.P2
176219b2ee8SDavid du Colombierproduces the
1777dd7cddfSDavid du Colombier.CW mips
178219b2ee8SDavid du Colombierexecutable of program
179219b2ee8SDavid du Colombier.CW f1
180219b2ee8SDavid du Colombierregardless of the current architecture type.
181219b2ee8SDavid du Colombier.PP
182219b2ee8SDavid du ColombierWe can extend the
183219b2ee8SDavid du Colombier.CW mkfile
184219b2ee8SDavid du Colombierto build two programs:
185219b2ee8SDavid du Colombier.P1
186219b2ee8SDavid du Colombier</$objtype/mkfile
187219b2ee8SDavid du ColombierALL=f1 f2
188219b2ee8SDavid du Colombier
189219b2ee8SDavid du Colombierall:V:	$ALL
190219b2ee8SDavid du Colombier
191219b2ee8SDavid du Colombierf1:	f1.$O
192219b2ee8SDavid du Colombier	$LD $LDFLAGS -o f1 f1.$O
193219b2ee8SDavid du Colombierf1.$O:	f1.c
194219b2ee8SDavid du Colombier	$CC $CFLAGS f1.c
195219b2ee8SDavid du Colombierf2:	f2.$O
196219b2ee8SDavid du Colombier	$LD $LDFLAGS -o f2 f2.$O
197219b2ee8SDavid du Colombierf2.$O:	f2.c
198219b2ee8SDavid du Colombier	$CC $CFLAGS f2.c
199219b2ee8SDavid du Colombier.P2
200219b2ee8SDavid du ColombierThe target
201219b2ee8SDavid du Colombier.CW all ,
202219b2ee8SDavid du Colombiermodified by the
203219b2ee8SDavid du Colombier.I attribute
204219b2ee8SDavid du Colombier.CW V ,
205219b2ee8SDavid du Colombierbuilds both programs.
206219b2ee8SDavid du ColombierThe attribute identifies
207219b2ee8SDavid du Colombier.CW all
208219b2ee8SDavid du Colombieras a dummy target that is
209219b2ee8SDavid du Colombiernot related to a file of the same name;
210219b2ee8SDavid du Colombierits precise effect is explained later.
211219b2ee8SDavid du ColombierThis example describes cascading dependencies:
212219b2ee8SDavid du Colombierthe first target depends on another which depends on a third and
213219b2ee8SDavid du Colombierso on.
214219b2ee8SDavid du ColombierHere, individual rules build each
215219b2ee8SDavid du Colombierprogram; later we'll see how to do this with a
216219b2ee8SDavid du Colombiergeneral rule.
217219b2ee8SDavid du Colombier.NH 1
218219b2ee8SDavid du ColombierVariables and the environment
219219b2ee8SDavid du Colombier.PP
220219b2ee8SDavid du Colombier.CW Mk
221219b2ee8SDavid du Colombierdoes not distinguish between its
2227dd7cddfSDavid du Colombierinternal variables and
223219b2ee8SDavid du Colombier.CW rc
224219b2ee8SDavid du Colombiervariables in the environment.
225219b2ee8SDavid du ColombierWhen
226219b2ee8SDavid du Colombier.CW mk
227219b2ee8SDavid du Colombierstarts, it imports each environment variable into a
228219b2ee8SDavid du Colombier.CW mk
229219b2ee8SDavid du Colombiervariable of the same name.  Before executing a recipe,
230219b2ee8SDavid du Colombier.CW mk
231219b2ee8SDavid du Colombierexports all variables, including those
232219b2ee8SDavid du Colombierinherited from the environment,
233219b2ee8SDavid du Colombierto the environment in which
234219b2ee8SDavid du Colombier.CW rc
235219b2ee8SDavid du Colombierexecutes the recipe.
236219b2ee8SDavid du Colombier.PP
237219b2ee8SDavid du ColombierThere are several ways for a
238219b2ee8SDavid du Colombiervariable to take a value.
239219b2ee8SDavid du ColombierIt can be set with an assignment statement,
240219b2ee8SDavid du Colombierinherited from the environment, or specified
241219b2ee8SDavid du Colombieron the command line.
242219b2ee8SDavid du Colombier.CW Mk
2437dd7cddfSDavid du Colombieralso maintains several special internal variables
2447dd7cddfSDavid du Colombierthat are described in
245219b2ee8SDavid du Colombier.I mk (1).
246219b2ee8SDavid du ColombierAssignments have the following decreasing order of precedence:
247219b2ee8SDavid du Colombier.LP
248219b2ee8SDavid du Colombier.in .7i
249219b2ee8SDavid du Colombier1)  Command line assignment
250219b2ee8SDavid du Colombier.br
251219b2ee8SDavid du Colombier2)  Assignment statement
252219b2ee8SDavid du Colombier.br
253219b2ee8SDavid du Colombier3)  Imported from the environment
254219b2ee8SDavid du Colombier.br
255219b2ee8SDavid du Colombier4)  Implicitly set by \f(CWmk\fP
256219b2ee8SDavid du Colombier.in 0
257219b2ee8SDavid du Colombier.LP
258219b2ee8SDavid du ColombierFor example, a command line assignment overrides
259219b2ee8SDavid du Colombiera value imported from the environment.
260219b2ee8SDavid du Colombier.PP
261219b2ee8SDavid du ColombierAll variable values are strings.  They can be
262219b2ee8SDavid du Colombierused for pattern matching and
263219b2ee8SDavid du Colombiercomparison but not for arithmetic.
264219b2ee8SDavid du ColombierA
265219b2ee8SDavid du Colombier.I list
266219b2ee8SDavid du Colombieris a string containing several values separated by
267219b2ee8SDavid du Colombierwhite space.  Each member is
268219b2ee8SDavid du Colombierhandled individually during pattern matching,
269219b2ee8SDavid du Colombiertarget selection, and prerequisite evaluation.
270219b2ee8SDavid du Colombier.PP
271219b2ee8SDavid du ColombierA
272219b2ee8SDavid du Colombier.I namelist
273219b2ee8SDavid du Colombieris a list produced by
274219b2ee8SDavid du Colombiertransforming the members of an existing list.
275219b2ee8SDavid du ColombierThe transform applies a pattern to each member,
276219b2ee8SDavid du Colombierreplacing each matched string with a new string,
277219b2ee8SDavid du Colombiermuch as in the substitute command in
278219b2ee8SDavid du Colombier.I sam (1)
279219b2ee8SDavid du Colombieror
280219b2ee8SDavid du Colombier.I ed (1).
281219b2ee8SDavid du ColombierThe syntax is
282219b2ee8SDavid du Colombier.P1
283219b2ee8SDavid du Colombier${\fIvar\fP:A%B=C%D}
284219b2ee8SDavid du Colombier.P2
285219b2ee8SDavid du Colombierwhere
286219b2ee8SDavid du Colombier.I var
287219b2ee8SDavid du Colombieris a variable.
288219b2ee8SDavid du ColombierThe pattern
289219b2ee8SDavid du Colombier.CW A%B
290219b2ee8SDavid du Colombiermatches a member beginning with the string
291219b2ee8SDavid du Colombier.I A
292219b2ee8SDavid du Colombierand ending with the string
293219b2ee8SDavid du Colombier.I B
294219b2ee8SDavid du Colombierwith any string in between;
295219b2ee8SDavid du Colombierit behaves like the regular expression
296219b2ee8SDavid du Colombier.CW A.*B .
297219b2ee8SDavid du ColombierWhen a member of the
298219b2ee8SDavid du Colombier.I var
299219b2ee8SDavid du Colombierlist
300219b2ee8SDavid du Colombiermatches this pattern,
301219b2ee8SDavid du Colombierthe string
302219b2ee8SDavid du Colombier.I C
303219b2ee8SDavid du Colombierreplaces
304219b2ee8SDavid du Colombier.I A ,
305219b2ee8SDavid du Colombier.I D
306219b2ee8SDavid du Colombierreplaces
307219b2ee8SDavid du Colombier.I B ,
308219b2ee8SDavid du Colombierand the matched string replaces itself.
309219b2ee8SDavid du ColombierAny of
310219b2ee8SDavid du Colombier.I A ,
311219b2ee8SDavid du Colombier.I B ,
312219b2ee8SDavid du Colombier.I C ,
313219b2ee8SDavid du Colombieror
314219b2ee8SDavid du Colombier.I D
315219b2ee8SDavid du Colombiermay be the empty string.  In effect, a namelist is
316219b2ee8SDavid du Colombiergenerated by applying the
317219b2ee8SDavid du Colombier.I ed (1)
318219b2ee8SDavid du Colombiersubstitute command
319219b2ee8SDavid du Colombier.P1
320219b2ee8SDavid du Colombier	s/\fIA\fP(.*)\fIB\fP/\fIC\fP\e1\fID\fP/
321219b2ee8SDavid du Colombier.P2
3227dd7cddfSDavid du Colombierto each member of a variable list.
323219b2ee8SDavid du Colombier.PP
324219b2ee8SDavid du ColombierNamelists are useful for generating
325219b2ee8SDavid du Colombiera list based on a predictable transformation.
326219b2ee8SDavid du ColombierFor example,
327219b2ee8SDavid du Colombier.P1
328219b2ee8SDavid du Colombier	SRC=a.c b.c c.c
329219b2ee8SDavid du Colombier	OBJ=${SRC:%.c=%.v}
330219b2ee8SDavid du Colombier.P2
331219b2ee8SDavid du Colombierassigns the list \f(CW(a.v b.v c.v)\fP to
332219b2ee8SDavid du Colombier.CW OBJ .
333219b2ee8SDavid du ColombierA namelist may be used anywhere a variable is allowed
334219b2ee8SDavid du Colombierexcept in a recipe.
335219b2ee8SDavid du Colombier.PP
336219b2ee8SDavid du ColombierCommand output is assigned to a variable
337219b2ee8SDavid du Colombierusing the normal
338219b2ee8SDavid du Colombier.CW rc
339219b2ee8SDavid du Colombiersyntax:
340219b2ee8SDavid du Colombier.P1
341219b2ee8SDavid du Colombier	var=`{rc command}
342219b2ee8SDavid du Colombier.P2
343219b2ee8SDavid du ColombierThe command executes in an environment populated
344219b2ee8SDavid du Colombierwith previously assigned variables, including those
345219b2ee8SDavid du Colombierinherited from
346219b2ee8SDavid du Colombier.CW mk\fR'\fPs
347219b2ee8SDavid du Colombierexecution environment.
348219b2ee8SDavid du ColombierThe command may
349219b2ee8SDavid du Colombierbe arbitrarily complex; for example,
350219b2ee8SDavid du Colombier.P1
3517dd7cddfSDavid du Colombier	TARG=`{ls -d *.[cy] | sed 's/..$//'}
352219b2ee8SDavid du Colombier.P2
3537dd7cddfSDavid du Colombierassigns a list of the C and yacc source files in the current
354219b2ee8SDavid du Colombierdirectory, stripped of their suffix, to the variable
355219b2ee8SDavid du Colombier.CW TARG .
356219b2ee8SDavid du Colombier.NH 1
357219b2ee8SDavid du ColombierThe include statement
358219b2ee8SDavid du Colombier.PP
359219b2ee8SDavid du ColombierThe include statement
360219b2ee8SDavid du Colombierreplaces itself with the contents of a file.
361219b2ee8SDavid du ColombierIt is functionally similar to the C
362219b2ee8SDavid du Colombier.CW #include
363219b2ee8SDavid du Colombierstatement but uses a different syntax:
364219b2ee8SDavid du Colombier.P1
365219b2ee8SDavid du Colombier	<\fIfilename\fP
366219b2ee8SDavid du Colombier.P2
367219b2ee8SDavid du ColombierThe contents of the file are evaluated
368219b2ee8SDavid du Colombieras they are read.
369219b2ee8SDavid du ColombierAn include statement may be used anywhere except
370219b2ee8SDavid du Colombierin a recipe.
371219b2ee8SDavid du Colombier.PP
372219b2ee8SDavid du ColombierUnlike
373219b2ee8SDavid du Colombier.CW make ,
374219b2ee8SDavid du Colombier.CW mk
375219b2ee8SDavid du Colombierhas no built-in rules.  Instead,
376219b2ee8SDavid du Colombierthe include statement allows generic rules
377219b2ee8SDavid du Colombierto be imported from a prototype
378219b2ee8SDavid du Colombier.CW mkfile ;
379219b2ee8SDavid du Colombiermost Plan 9
380219b2ee8SDavid du Colombier.CW mkfiles
381219b2ee8SDavid du Colombieruse this approach [Flan95].
382219b2ee8SDavid du Colombier.NH 1
383219b2ee8SDavid du ColombierRules
384219b2ee8SDavid du Colombier.PP
385219b2ee8SDavid du ColombierA rule has four elements: targets,
386219b2ee8SDavid du Colombierprerequisites, attributes, and a recipe.
387219b2ee8SDavid du ColombierIt has the form:
388219b2ee8SDavid du Colombier.P1
389219b2ee8SDavid du Colombier\fItargets\fP:\fIattributes\fP:\fIprerequisites\fP
390219b2ee8SDavid du Colombier	\fIrecipe\fP
391219b2ee8SDavid du Colombier.P2
392219b2ee8SDavid du ColombierThe first line, containing the
393219b2ee8SDavid du Colombiertargets, attributes, and prerequisites is
394219b2ee8SDavid du Colombierthe
395219b2ee8SDavid du Colombier.I "rule header" ;
396219b2ee8SDavid du Colombierit
397219b2ee8SDavid du Colombiermust begin at the left margin.
398219b2ee8SDavid du ColombierThe recipe contains zero or more lines,
399219b2ee8SDavid du Colombiereach of which begins with white space.
400219b2ee8SDavid du ColombierOne or more targets must be specified but the
401219b2ee8SDavid du Colombierattributes, prerequisites, and recipe are optional.
402219b2ee8SDavid du ColombierA rule specifies
4037dd7cddfSDavid du Colombiera dependency between the target(s) and its prerequisite(s),
4047dd7cddfSDavid du Colombierthe recipe brings the target(s)
4057dd7cddfSDavid du Colombierup to date with the prerequisite(s) and
4067dd7cddfSDavid du Colombierattributes modify
407219b2ee8SDavid du Colombier.CW mk\fR'\fPs
4087dd7cddfSDavid du Colombierevaluation of the dependency.
409219b2ee8SDavid du Colombier.PP
410219b2ee8SDavid du ColombierNormally the target is a file that depends
411219b2ee8SDavid du Colombieron one or more prerequisite files.
412219b2ee8SDavid du Colombier.CW Mk
413219b2ee8SDavid du Colombiercompares the modification times of each target
414219b2ee8SDavid du Colombierand each prerequisite; a target is considered out of date
415219b2ee8SDavid du Colombierwhen it does not exist or when a prerequisite has been modified
416219b2ee8SDavid du Colombiermore recently.
417219b2ee8SDavid du ColombierWhen a target is out of date,
418219b2ee8SDavid du Colombier.CW mk
419219b2ee8SDavid du Colombierexecutes the
420219b2ee8SDavid du Colombierrecipe to bring it up to date.
421219b2ee8SDavid du ColombierWhen the recipe completes,
422219b2ee8SDavid du Colombierthe modification time of the target is checked and
423219b2ee8SDavid du Colombierused in later dependency evaluations.
424219b2ee8SDavid du ColombierIf the recipe does not update the target,
425219b2ee8SDavid du Colombierevaluation continues with the out of date target.
426219b2ee8SDavid du Colombier.PP
427219b2ee8SDavid du ColombierA prerequisite of one rule
428219b2ee8SDavid du Colombiermay be the target of another.  When
429219b2ee8SDavid du Colombierthis happens, the rules cascade
430219b2ee8SDavid du Colombierto define a multi-step procedure.
431219b2ee8SDavid du ColombierFor example,
432219b2ee8SDavid du Colombieran executable target depends on prerequisite
433219b2ee8SDavid du Colombierobject files, each of which is a target
434219b2ee8SDavid du Colombierin a rule with a C source file as the prerequisite.
435219b2ee8SDavid du Colombier.CW Mk
436219b2ee8SDavid du Colombierfollows a chain of dependencies until it encounters
437219b2ee8SDavid du Colombiera prerequisite that is not a target of another rule
438219b2ee8SDavid du Colombieror it finds a target that
439219b2ee8SDavid du Colombieris up to date.  It then
440219b2ee8SDavid du Colombierexecutes the recipes in reverse order to produce
441219b2ee8SDavid du Colombierthe desired target.
442219b2ee8SDavid du Colombier.PP
443219b2ee8SDavid du ColombierThe rule header is evaluated when the rule is read.
444219b2ee8SDavid du ColombierVariables are replaced by their values, namelists are
445219b2ee8SDavid du Colombiergenerated, and
446219b2ee8SDavid du Colombiercommands are replaced by their
447219b2ee8SDavid du Colombieroutput at this time.
448219b2ee8SDavid du Colombier.PP
449219b2ee8SDavid du ColombierMost attributes modify
450219b2ee8SDavid du Colombier.CW mk\fR'\fPs
451219b2ee8SDavid du Colombierevaluation of a rule.
452219b2ee8SDavid du ColombierAn attribute is usually a single letter but some
453219b2ee8SDavid du Colombierare more complicated.
454219b2ee8SDavid du ColombierThis paper only discusses commonly used attributes;
455219b2ee8SDavid du Colombiersee
456219b2ee8SDavid du Colombier.I mk (1)
457219b2ee8SDavid du Colombierfor a complete list.
458219b2ee8SDavid du Colombier.PP
459219b2ee8SDavid du ColombierThe
460219b2ee8SDavid du Colombier.CW V
461219b2ee8SDavid du Colombierattribute identifies a
462219b2ee8SDavid du Colombier.I virtual
463219b2ee8SDavid du Colombiertarget;
464219b2ee8SDavid du Colombierthat is, a target that is not a file.
465219b2ee8SDavid du ColombierFor example,
466219b2ee8SDavid du Colombier.P1
467219b2ee8SDavid du Colombierclean:V:
468219b2ee8SDavid du Colombier	rm *.$O $O.out
469219b2ee8SDavid du Colombier.P2
470219b2ee8SDavid du Colombierremoves executables and compiler intermediate files.
471219b2ee8SDavid du ColombierThe target is virtual because it does not refer to a file named
472219b2ee8SDavid du Colombier.CW clean .
473219b2ee8SDavid du ColombierWithout the attribute, the recipe would not be
474219b2ee8SDavid du Colombierexecuted if a file named
475219b2ee8SDavid du Colombier.CW clean
476219b2ee8SDavid du Colombierexisted.
477219b2ee8SDavid du ColombierThe
478219b2ee8SDavid du Colombier.CW Q
4797dd7cddfSDavid du Colombierattribute
4807dd7cddfSDavid du Colombiersilences the printing of a recipe before
4817dd7cddfSDavid du Colombierexecution.
482219b2ee8SDavid du ColombierIt is useful when the output of a recipe is
483219b2ee8SDavid du Colombiersimilar to the recipe:
484219b2ee8SDavid du Colombier.P1
485219b2ee8SDavid du Colombierdefault:QV:
486219b2ee8SDavid du Colombier	echo 'No default target; use mk all or mk install'
487219b2ee8SDavid du Colombier.P2
488219b2ee8SDavid du Colombier.PP
4897dd7cddfSDavid du ColombierThe recipe is an
490219b2ee8SDavid du Colombier.CW rc
4917dd7cddfSDavid du Colombierscript.  It is optional but when it is
492219b2ee8SDavid du Colombiermissing, the rule is handled specially, as described later.
493219b2ee8SDavid du ColombierUnlike
494219b2ee8SDavid du Colombier.CW make ,
495219b2ee8SDavid du Colombier.CW mk
496219b2ee8SDavid du Colombierexecutes recipes without interpretation.
497219b2ee8SDavid du ColombierAfter
498219b2ee8SDavid du Colombierstripping the first white space character from each line
499219b2ee8SDavid du Colombierit passes the entire recipe to
500219b2ee8SDavid du Colombier.CW rc
501219b2ee8SDavid du Colombieron standard input.
502219b2ee8SDavid du ColombierSince
503219b2ee8SDavid du Colombier.CW mk
504219b2ee8SDavid du Colombierdoes not interpret a recipe,
505219b2ee8SDavid du Colombierescape conventions are exactly those of
506219b2ee8SDavid du Colombier.CW rc .
507219b2ee8SDavid du ColombierScripts for
508219b2ee8SDavid du Colombier.CW awk
509219b2ee8SDavid du Colombierand
510219b2ee8SDavid du Colombier.CW sed
5117dd7cddfSDavid du Colombiercommands can be embedded exactly as they would
5127dd7cddfSDavid du Colombierbe entered from the command line.
513219b2ee8SDavid du Colombier.CW Mk
514219b2ee8SDavid du Colombierinvokes
515219b2ee8SDavid du Colombier.CW rc
516219b2ee8SDavid du Colombierwith the
517219b2ee8SDavid du Colombier.CW -e
518219b2ee8SDavid du Colombierflag, which causes
519219b2ee8SDavid du Colombier.CW rc
520219b2ee8SDavid du Colombierto stop if any command
521219b2ee8SDavid du Colombierin the recipe exits with a non-zero status; the
522219b2ee8SDavid du Colombier.CW E
523219b2ee8SDavid du Colombierattribute overrides this behavior and allows
524219b2ee8SDavid du Colombier.CW rc
525219b2ee8SDavid du Colombierto continue executing in the face of errors.
526219b2ee8SDavid du ColombierBefore a recipe is executed, variables are exported
5277dd7cddfSDavid du Colombierto the environment where they are available to
5287dd7cddfSDavid du Colombier.CW rc .
5297dd7cddfSDavid du ColombierCommands in the recipe may not read from
530219b2ee8SDavid du Colombierstandard input because
531219b2ee8SDavid du Colombier.CW mk
532219b2ee8SDavid du Colombieruses it internally.
533219b2ee8SDavid du Colombier.PP
534219b2ee8SDavid du ColombierReferences to a variable can yield different
535219b2ee8SDavid du Colombiervalues depending on the location of the
536219b2ee8SDavid du Colombierreference in the
537219b2ee8SDavid du Colombier.CW mkfile .
538219b2ee8SDavid du Colombier.CW Mk
539219b2ee8SDavid du Colombierresolves variable references
540219b2ee8SDavid du Colombierin assignment statements and rule headers
541219b2ee8SDavid du Colombierwhen the statement is read.  Variable references
542219b2ee8SDavid du Colombierin recipes are evaluated by
543219b2ee8SDavid du Colombier.CW rc
544219b2ee8SDavid du Colombierwhen the recipe is executed; this
545219b2ee8SDavid du Colombierhappens after the entire
546219b2ee8SDavid du Colombier.CW mkfile
547219b2ee8SDavid du Colombierhas been read.  The value of a variable in a recipe
548219b2ee8SDavid du Colombieris the last value assigned in the file.  For example,
549219b2ee8SDavid du Colombier.P1
550219b2ee8SDavid du ColombierSTRING=all
551219b2ee8SDavid du Colombier
552219b2ee8SDavid du Colombierall:VQ:
553219b2ee8SDavid du Colombier	echo $STRING
554219b2ee8SDavid du ColombierSTRING=none
555219b2ee8SDavid du Colombier.P2
556219b2ee8SDavid du Colombierproduces the message
557219b2ee8SDavid du Colombier.CW none .
558219b2ee8SDavid du ColombierA variable assignment in a recipe
559219b2ee8SDavid du Colombierdoes not affect the value of the variable in the
560219b2ee8SDavid du Colombier.CW mkfile
561219b2ee8SDavid du Colombierfor two reasons.
562219b2ee8SDavid du ColombierFirst,
563219b2ee8SDavid du Colombier.CW mk
564219b2ee8SDavid du Colombierdoes not import values from
565219b2ee8SDavid du Colombierthe environment when a recipe completes;
566219b2ee8SDavid du Colombierone recipe cannot pass a value through
567219b2ee8SDavid du Colombierthe environment to another recipe.
568219b2ee8SDavid du ColombierSecond, no recipe is executed until
569219b2ee8SDavid du Colombier.CW mk
570219b2ee8SDavid du Colombierhas completed its evaluation, so even if a variable
571219b2ee8SDavid du Colombierwere changed,
572219b2ee8SDavid du Colombierit would not affect the dependency evaluation.
573219b2ee8SDavid du Colombier.NH 1
574219b2ee8SDavid du ColombierMetarules
575219b2ee8SDavid du Colombier.PP
576219b2ee8SDavid du ColombierA
577219b2ee8SDavid du Colombier.I metarule
578219b2ee8SDavid du Colombieris a rule based on a pattern.
5797dd7cddfSDavid du ColombierThe pattern selects a class of target(s) and
580219b2ee8SDavid du Colombieridentifies related prerequisites.
581219b2ee8SDavid du Colombier.CW Mk
582219b2ee8SDavid du Colombiermetarules may select targets and prerequisites
583219b2ee8SDavid du Colombierbased on any criterion that can be described by a pattern, not just
584219b2ee8SDavid du Colombierthe suffix transformations associated with program
585219b2ee8SDavid du Colombierconstruction.
586219b2ee8SDavid du Colombier.PP
5877dd7cddfSDavid du ColombierMetarule patterns are either
588219b2ee8SDavid du Colombier.I intrinsic
5897dd7cddfSDavid du Colombieror regular expressions conforming to the
590219b2ee8SDavid du Colombiersyntax of
591219b2ee8SDavid du Colombier.I regexp (6).
592219b2ee8SDavid du ColombierThe intrinsic patterns are shorthand
593219b2ee8SDavid du Colombierfor common regular expressions.
594219b2ee8SDavid du ColombierThe intrinsic pattern
595219b2ee8SDavid du Colombier.CW %
596219b2ee8SDavid du Colombiermatches one or more of anything; it is equivalent to
597219b2ee8SDavid du Colombierthe regular expression
598219b2ee8SDavid du Colombier.CW `.+' .
599219b2ee8SDavid du ColombierThe other intrinsic pattern,
600219b2ee8SDavid du Colombier.CW & ,
601219b2ee8SDavid du Colombiermatches one or more of any characters except \f(CW`/'\fP
602219b2ee8SDavid du Colombierand \f(CW`.'\fP.
603219b2ee8SDavid du ColombierIt matches a portion of a path and is
604219b2ee8SDavid du Colombierequivalent to the regular expression
605219b2ee8SDavid du Colombier.CW `[^./]+' .
606219b2ee8SDavid du ColombierAn intrinsic pattern in a prerequisite references
607219b2ee8SDavid du Colombierthe string matched by the same intrinsic pattern in the target.
608219b2ee8SDavid du ColombierFor example, the rule
609219b2ee8SDavid du Colombier.P1
610219b2ee8SDavid du Colombier	%.v:	%.c
611219b2ee8SDavid du Colombier.P2
612219b2ee8SDavid du Colombiersays that a file ending in
613219b2ee8SDavid du Colombier.CW .v
614219b2ee8SDavid du Colombierdepends on a file of the same name with a
615219b2ee8SDavid du Colombier.CW .c
616219b2ee8SDavid du Colombiersuffix:
617219b2ee8SDavid du Colombier.CW foo.v
618219b2ee8SDavid du Colombierdepends on
619219b2ee8SDavid du Colombier.CW foo.c ,
620219b2ee8SDavid du Colombier.CW bar.v
621219b2ee8SDavid du Colombierdepends on
622219b2ee8SDavid du Colombier.CW bar.c ,
623219b2ee8SDavid du Colombierand so on.
624219b2ee8SDavid du ColombierThe string matched by an intrinsic pattern in the target
625219b2ee8SDavid du Colombieris supplied to the recipe in the variable
626219b2ee8SDavid du Colombier.CW $stem .
627219b2ee8SDavid du ColombierThus the rule
628219b2ee8SDavid du Colombier.P1
629219b2ee8SDavid du Colombier%.$O:	%.c
630219b2ee8SDavid du Colombier	$CC $CFLAGS $stem.c
631219b2ee8SDavid du Colombier.P2
632219b2ee8SDavid du Colombiercreates an object file for the target architecture from
633219b2ee8SDavid du Colombiera similarly named C source file.  If several object
634219b2ee8SDavid du Colombierfiles are out of date, the rule is applied repeatedly and
635219b2ee8SDavid du Colombier.CW $stem
636219b2ee8SDavid du Colombierrefers to each file in turn.
637219b2ee8SDavid du ColombierSince there is only one
638219b2ee8SDavid du Colombier.CW stem
639219b2ee8SDavid du Colombiervariable, there can only be one
640219b2ee8SDavid du Colombier.CW %
641219b2ee8SDavid du Colombieror
642219b2ee8SDavid du Colombier.CW &
643219b2ee8SDavid du Colombierpattern in a target;
644219b2ee8SDavid du Colombierthe pattern
645219b2ee8SDavid du Colombier.CW %-%.c
646219b2ee8SDavid du Colombieris illegal.
647219b2ee8SDavid du Colombier.PP
648219b2ee8SDavid du ColombierMetarules simplify the
649219b2ee8SDavid du Colombier.CW mkfile
650219b2ee8SDavid du Colombierfor building programs
651219b2ee8SDavid du Colombier.CW f1
652219b2ee8SDavid du Colombierand
653219b2ee8SDavid du Colombier.CW f2 :
654219b2ee8SDavid du Colombier.P1
655219b2ee8SDavid du Colombier</$objtype/mkfile
6567dd7cddfSDavid du Colombier
657219b2ee8SDavid du ColombierALL=f1 f2
658219b2ee8SDavid du Colombier
659219b2ee8SDavid du Colombierall:V:	$ALL
660219b2ee8SDavid du Colombier
661219b2ee8SDavid du Colombier%:	%.$O
662219b2ee8SDavid du Colombier	$LD -o $target $prereq
663219b2ee8SDavid du Colombier%.$O:	%.c
664219b2ee8SDavid du Colombier	$CC $CFLAGS $stem.c
665219b2ee8SDavid du Colombierclean:V:
666219b2ee8SDavid du Colombier	rm -f $ALL *.[$OS]
667219b2ee8SDavid du Colombier.P2
668219b2ee8SDavid du Colombier(The variable
669219b2ee8SDavid du Colombier.CW $OS
670219b2ee8SDavid du Colombieris a list of code characters for all architectures.)
671219b2ee8SDavid du ColombierHere, metarules specify
6727dd7cddfSDavid du Colombiercompile and load steps for all C source files.
673219b2ee8SDavid du ColombierThe loader rule relies on two internal variables
674219b2ee8SDavid du Colombierset by
675219b2ee8SDavid du Colombier.CW mk
676219b2ee8SDavid du Colombierduring evaluation of the rule:
677219b2ee8SDavid du Colombier.CW $target
6787dd7cddfSDavid du Colombieris the name of the target(s) and
679219b2ee8SDavid du Colombier.CW $prereq
6807dd7cddfSDavid du Colombierthe name of all prerequisite(s).
681219b2ee8SDavid du ColombierMetarules allow this
682219b2ee8SDavid du Colombier.CW mkfile
683219b2ee8SDavid du Colombierto be easily extended; a new program
684219b2ee8SDavid du Colombieris supported by adding its name to the third line.
685219b2ee8SDavid du Colombier.PP
686219b2ee8SDavid du ColombierA regular expression metarule must have an
687219b2ee8SDavid du Colombier.CW R
688219b2ee8SDavid du Colombierattribute.
689219b2ee8SDavid du ColombierPrerequisites may reference matching substrings in
690219b2ee8SDavid du Colombierthe target using the form
691219b2ee8SDavid du Colombier.CW \e\fIn\fP
692219b2ee8SDavid du Colombierwhere
693219b2ee8SDavid du Colombier.I n
694219b2ee8SDavid du Colombieris a digit from 1 to 9 specifying the
695219b2ee8SDavid du Colombier.I n th
696219b2ee8SDavid du Colombierparenthesized sub-expression.  In a recipe,
697219b2ee8SDavid du Colombier.CW $stem\fIn\fP
698219b2ee8SDavid du Colombieris the equivalent reference.
699219b2ee8SDavid du ColombierFor example, a compile rule could be
700219b2ee8SDavid du Colombierspecified using regular expressions:
701219b2ee8SDavid du Colombier.P1
702219b2ee8SDavid du Colombier(.+)\e.$O:R:	\e1.c
703219b2ee8SDavid du Colombier	$CC $CFLAGS $stem1.c
704219b2ee8SDavid du Colombier.P2
705219b2ee8SDavid du ColombierHere,
706219b2ee8SDavid du Colombier.CW \e1
707219b2ee8SDavid du Colombierand
708219b2ee8SDavid du Colombier.CW $stem1
709219b2ee8SDavid du Colombierrefer to the name of the target object file without the
710219b2ee8SDavid du Colombiersuffix.  The variable
711219b2ee8SDavid du Colombier.CW $stem
712219b2ee8SDavid du Colombierassociated with an intrinsic pattern is undefined
713219b2ee8SDavid du Colombierin a regular expression metarule.
714219b2ee8SDavid du Colombier.NH 1
715219b2ee8SDavid du ColombierArchives
716219b2ee8SDavid du Colombier.PP
717219b2ee8SDavid du Colombier.CW Mk
718219b2ee8SDavid du Colombierprovides a special mechanism for maintaining an archive.
719219b2ee8SDavid du ColombierAn archive member is referenced using the form
720219b2ee8SDavid du Colombier.CW \fIlib\fP(\fIfile\fP)
721219b2ee8SDavid du Colombierwhere
722219b2ee8SDavid du Colombier.I lib
723219b2ee8SDavid du Colombieris the name of the archive and
724219b2ee8SDavid du Colombier.I file
725219b2ee8SDavid du Colombieris the name of the member.  Two rules define the
726219b2ee8SDavid du Colombierdependency between an object file and its membership
727219b2ee8SDavid du Colombierin an archive:
728219b2ee8SDavid du Colombier.P1
7297dd7cddfSDavid du Colombier$LIB(foo.8):N:	foo.8
7307dd7cddfSDavid du Colombier$LIB:	$LIB(foo.8)
7317dd7cddfSDavid du Colombier	ar rv $LIB foo.8
732219b2ee8SDavid du Colombier.P2
733219b2ee8SDavid du ColombierThe first rule establishes a dependency between the
734219b2ee8SDavid du Colombierarchive member and the object file.
735219b2ee8SDavid du ColombierNormally,
736219b2ee8SDavid du Colombier.CW mk
737219b2ee8SDavid du Colombierdetects an error when a target does not exist and the rule
738219b2ee8SDavid du Colombiercontains no recipe; the
739219b2ee8SDavid du Colombier.CW N
740219b2ee8SDavid du Colombierattribute overrides this behavior because the subsequent rule
741219b2ee8SDavid du Colombierupdates the member.
742219b2ee8SDavid du ColombierThe second
743219b2ee8SDavid du Colombierrule establishes the dependency between the member and
744219b2ee8SDavid du Colombierthe archive; its recipe inserts the member
745219b2ee8SDavid du Colombierinto the archive.
7467dd7cddfSDavid du ColombierThis two-step specification allows the modification time
7477dd7cddfSDavid du Colombierof the archive
748219b2ee8SDavid du Colombierto represent the state of its members.  Other rules
749219b2ee8SDavid du Colombiercan then specify the archive as a prerequisite instead of
750219b2ee8SDavid du Colombierlisting each member.
751219b2ee8SDavid du Colombier.PP
752219b2ee8SDavid du ColombierA metarule generalizes library maintenance:
753219b2ee8SDavid du Colombier.P1
754219b2ee8SDavid du ColombierLIB=lib.a
755219b2ee8SDavid du ColombierOBJS=etoa.$O atoe.$O ebcdic.$O
756219b2ee8SDavid du Colombier
757219b2ee8SDavid du Colombier$LIB(%):N:	%
758219b2ee8SDavid du Colombier$LIB:	${OBJS:%=$LIB(%)}
759219b2ee8SDavid du Colombier	ar rv $LIB $OBJS
760219b2ee8SDavid du Colombier.P2
761219b2ee8SDavid du ColombierThe namelist prerequisite of the
762219b2ee8SDavid du Colombier.CW $LIB
763219b2ee8SDavid du Colombiertarget generates archive member names for each object file name;
764219b2ee8SDavid du Colombierfor example,
765219b2ee8SDavid du Colombier.CW etoa.$O
766219b2ee8SDavid du Colombierbecomes
767219b2ee8SDavid du Colombier.CW lib.a(etoa.$O) .
768219b2ee8SDavid du ColombierThis formulation always updates all members.
769219b2ee8SDavid du ColombierThis is acceptable for a small archive, but may
770219b2ee8SDavid du Colombierbe slow for a big one.
771219b2ee8SDavid du ColombierThe rule
772219b2ee8SDavid du Colombier.P1
773219b2ee8SDavid du Colombier$LIB:	${OBJS:%=$LIB(%)}
774219b2ee8SDavid du Colombier	ar rv $LIB `{membername $newprereq}
775219b2ee8SDavid du Colombier.P2
776219b2ee8SDavid du Colombieronly updates out of date object files.
777219b2ee8SDavid du ColombierThe internal variable
778219b2ee8SDavid du Colombier.CW $newprereq
779219b2ee8SDavid du Colombiercontains the names of the out of
780219b2ee8SDavid du Colombierdate prerequisites.  The
781219b2ee8SDavid du Colombier.CW rc
782219b2ee8SDavid du Colombierscript
783219b2ee8SDavid du Colombier.CW membername
784219b2ee8SDavid du Colombiertransforms an archive member specification into a file name:
785219b2ee8SDavid du Colombierit translates
786219b2ee8SDavid du Colombier.CW lib.a(etoa.$O)
787219b2ee8SDavid du Colombierinto
788219b2ee8SDavid du Colombier.CW etoa.$O .
789219b2ee8SDavid du Colombier.PP
790219b2ee8SDavid du ColombierThe
791219b2ee8SDavid du Colombier.CW mkfile
792219b2ee8SDavid du Colombier.P1
793219b2ee8SDavid du Colombier</$objtype/mkfile
794219b2ee8SDavid du ColombierLIB=lib.a
795219b2ee8SDavid du ColombierOBJS=etoa.$O atoe.$O ebcdic.$O
796219b2ee8SDavid du Colombier
797219b2ee8SDavid du Colombierprog:	main.$O $LIB
798219b2ee8SDavid du Colombier	$LD -o $target $prereq
799219b2ee8SDavid du Colombier
800219b2ee8SDavid du Colombier$LIB(%):N:	%
801219b2ee8SDavid du Colombier$LIB:	${OBJS:%=$LIB(%)}
802219b2ee8SDavid du Colombier	ar rv $LIB $OBJS
803219b2ee8SDavid du Colombier.P2
804219b2ee8SDavid du Colombierbuilds a program by loading it with a library.
805219b2ee8SDavid du Colombier.NH 1
806219b2ee8SDavid du ColombierEvaluation algorithm
807219b2ee8SDavid du Colombier.PP
808219b2ee8SDavid du ColombierFor each target of interest,
809219b2ee8SDavid du Colombier.CW mk
810219b2ee8SDavid du Colombieruses the rules in a
811219b2ee8SDavid du Colombier.CW mkfile
812219b2ee8SDavid du Colombierto build a data
813219b2ee8SDavid du Colombierstructure called a dependency graph.  The nodes of
814219b2ee8SDavid du Colombierthe graph represent targets and prerequisites;
815219b2ee8SDavid du Colombiera directed arc
816219b2ee8SDavid du Colombierfrom one node to another indicates that
817219b2ee8SDavid du Colombierthe file associated with the first node depends
818219b2ee8SDavid du Colombieron the file associated with the second.
819219b2ee8SDavid du ColombierWhen the
820219b2ee8SDavid du Colombier.CW mkfile
821219b2ee8SDavid du Colombierhas been completely read, the graph is analyzed.
822219b2ee8SDavid du ColombierIn the first step, implied dependencies are resolved by
823219b2ee8SDavid du Colombiercomputing the
824219b2ee8SDavid du Colombier.I "transitive closure"
825219b2ee8SDavid du Colombierof the graph.
826219b2ee8SDavid du ColombierThis calculation extends the graph to include all
827219b2ee8SDavid du Colombiertargets that are potentially
828219b2ee8SDavid du Colombierderivable from the rules in the
829219b2ee8SDavid du Colombier.CW mkfile .
830219b2ee8SDavid du ColombierNext the graph is checked for cycles;
831219b2ee8SDavid du Colombier.CW make
832219b2ee8SDavid du Colombieraccepts cyclic dependencies, but
833219b2ee8SDavid du Colombier.CW mk
834219b2ee8SDavid du Colombierdoes not allow them.
835219b2ee8SDavid du ColombierSubsequent steps
836219b2ee8SDavid du Colombierprune subgraphs that are irrelevant for producing the
837219b2ee8SDavid du Colombierdesired target and verify that there is only one way
838219b2ee8SDavid du Colombierto build it.
839219b2ee8SDavid du ColombierThe recipes associated with the
840219b2ee8SDavid du Colombiernodes on the longest path between the
841219b2ee8SDavid du Colombiertarget and an out of date prerequisite
842219b2ee8SDavid du Colombierare then executed in reverse order.
843219b2ee8SDavid du Colombier.PP
844219b2ee8SDavid du ColombierThe transitive closure calculation is sensitive to
845219b2ee8SDavid du Colombiermetarules; the patterns often select many potential targets
846219b2ee8SDavid du Colombierand cause the graph to grow rapidly.
847219b2ee8SDavid du ColombierFortunately,
848219b2ee8SDavid du Colombierdependencies associated with the desired target
849219b2ee8SDavid du Colombierusually form a small part of the graph, so, after
850219b2ee8SDavid du Colombierpruning, analysis is tractable.
851219b2ee8SDavid du ColombierFor example, the rules
852219b2ee8SDavid du Colombier.P1
853219b2ee8SDavid du Colombier%:	x.%
854219b2ee8SDavid du Colombier	recipe1
855219b2ee8SDavid du Colombierx.%:	%.k
856219b2ee8SDavid du Colombier	recipe2
857219b2ee8SDavid du Colombier%.k:	%.f
858219b2ee8SDavid du Colombier	recipe3
859219b2ee8SDavid du Colombier.P2
860219b2ee8SDavid du Colombierproduce a graph with four nodes for each file in the
861219b2ee8SDavid du Colombiercurrent directory.
862219b2ee8SDavid du ColombierIf the desired target is
863219b2ee8SDavid du Colombier.CW foo ,
864219b2ee8SDavid du Colombier.CW mk
865219b2ee8SDavid du Colombierdetects the dependency between it
866219b2ee8SDavid du Colombierand the original file
867219b2ee8SDavid du Colombier.CW foo.f
868219b2ee8SDavid du Colombierthrough intermediate dependencies on
869219b2ee8SDavid du Colombier.CW foo.k
870219b2ee8SDavid du Colombierand
871219b2ee8SDavid du Colombier.CW x.foo .
872219b2ee8SDavid du ColombierNodes associated with other files are deleted during pruning because
873219b2ee8SDavid du Colombierthey are irrelevant to the production of
874219b2ee8SDavid du Colombier.CW foo .
875219b2ee8SDavid du Colombier.PP
876219b2ee8SDavid du Colombier.CW Mk
877219b2ee8SDavid du Colombieravoids infinite cycles by evaluating
878219b2ee8SDavid du Colombiereach metarule once.
879219b2ee8SDavid du ColombierThus, the rule
880219b2ee8SDavid du Colombier.P1
881219b2ee8SDavid du Colombier%:	%.z
882219b2ee8SDavid du Colombier	cp $prereq $prereq.z
883219b2ee8SDavid du Colombier.P2
884219b2ee8SDavid du Colombiercopies the prerequisite file once.
885219b2ee8SDavid du Colombier.NH 1
886219b2ee8SDavid du ColombierConventions for evaluating rules
887219b2ee8SDavid du Colombier.PP
888219b2ee8SDavid du ColombierThere must be only one
889219b2ee8SDavid du Colombierway to build each target.  However, during evaluation
890219b2ee8SDavid du Colombiermetarule patterns often select potential targets that
891219b2ee8SDavid du Colombierconflict with the
892219b2ee8SDavid du Colombiertargets of other rules.
893219b2ee8SDavid du Colombier.CW Mk
894219b2ee8SDavid du Colombieruses several conventions to resolve ambiguities
895219b2ee8SDavid du Colombierand to select the proper dependencies.
896219b2ee8SDavid du Colombier.PP
897219b2ee8SDavid du ColombierWhen a target selects more than one rule,
898219b2ee8SDavid du Colombier.CW mk
899219b2ee8SDavid du Colombierchooses a regular rule
900219b2ee8SDavid du Colombierover a metarule.
901219b2ee8SDavid du ColombierFor example, the
902219b2ee8SDavid du Colombier.CW mkfile
903219b2ee8SDavid du Colombier.P1
904219b2ee8SDavid du Colombier</$objtype/mkfile
9057dd7cddfSDavid du Colombier
906219b2ee8SDavid du ColombierFILES=f1.$O f2.$O f3.$O
907219b2ee8SDavid du Colombier
908219b2ee8SDavid du Colombierprog:	$FILES
909219b2ee8SDavid du Colombier	$LD -o $target $prereq
910219b2ee8SDavid du Colombier
911219b2ee8SDavid du Colombier%.$O:	%.c
912219b2ee8SDavid du Colombier	$CC $CFLAGS $stem.c
913219b2ee8SDavid du Colombier
914219b2ee8SDavid du Colombierf2.$O:	f2.c
915219b2ee8SDavid du Colombier	$CC f2.c
916219b2ee8SDavid du Colombier.P2
917219b2ee8SDavid du Colombiercontains two rules that could build
918219b2ee8SDavid du Colombier.CW f2.$O .
919219b2ee8SDavid du Colombier.CW Mk
920219b2ee8SDavid du Colombierselects the last rule because its target,
921219b2ee8SDavid du Colombier.CW f2.$O ,
922219b2ee8SDavid du Colombieris explicitly specified, while the
923219b2ee8SDavid du Colombier.CW %.$O
924219b2ee8SDavid du Colombierrule is a metarule.  In effect,
925219b2ee8SDavid du Colombierthe explicit rule for
926219b2ee8SDavid du Colombier.CW f2.$O
927219b2ee8SDavid du Colombieroverrides the general rule for building object files from
928219b2ee8SDavid du ColombierC source files.
929219b2ee8SDavid du Colombier.PP
930219b2ee8SDavid du ColombierWhen a rule has a target and prerequisites but no recipe,
931219b2ee8SDavid du Colombierthose prerequisites are added to all other rules with
932219b2ee8SDavid du Colombierrecipes that have the same target.
933219b2ee8SDavid du ColombierAll prerequisites, regardless of where they were specified, are
9347dd7cddfSDavid du Colombierexported to the recipe in variable
935219b2ee8SDavid du Colombier.CW $prereq .
936219b2ee8SDavid du ColombierFor example, in
937219b2ee8SDavid du Colombier.P1
938219b2ee8SDavid du Colombier</$objtype/mkfile
9397dd7cddfSDavid du Colombier
940219b2ee8SDavid du ColombierFILES=f1.$O f2.$O f3.$O
941219b2ee8SDavid du Colombier
942219b2ee8SDavid du Colombierprog:	$FILES
943219b2ee8SDavid du Colombier	$LD -o $target $prereq
944219b2ee8SDavid du Colombier
945219b2ee8SDavid du Colombier%.$O:	hdr.h
946219b2ee8SDavid du Colombier
947219b2ee8SDavid du Colombier%.$O:	%.c
948219b2ee8SDavid du Colombier	$CC $CFLAGS $stem.c
949219b2ee8SDavid du Colombier.P2
950219b2ee8SDavid du Colombierthe second rule adds
951219b2ee8SDavid du Colombier.CW hdr.h
952219b2ee8SDavid du Colombieras a prerequisite of the compile metarule;
953219b2ee8SDavid du Colombieran object file produced from a C source file
954219b2ee8SDavid du Colombierdepends on
955219b2ee8SDavid du Colombier.CW hdr.h
956219b2ee8SDavid du Colombieras well as the source file.  Notice that the recipe of
957219b2ee8SDavid du Colombierthe compile rule uses
958219b2ee8SDavid du Colombier.CW $stem.c
959219b2ee8SDavid du Colombierinstead of
960219b2ee8SDavid du Colombier.CW $prereq
961219b2ee8SDavid du Colombierbecause the latter specification would attempt to compile
962219b2ee8SDavid du Colombier.CW hdr.h .
963219b2ee8SDavid du Colombier.PP
964219b2ee8SDavid du ColombierWhen a target is virtual and there is no other rule with
965219b2ee8SDavid du Colombierthe same target,
966219b2ee8SDavid du Colombier.CW mk
967219b2ee8SDavid du Colombierevaluates each prerequisite.
968219b2ee8SDavid du ColombierFor example, adding the rule
969219b2ee8SDavid du Colombier.P1
970219b2ee8SDavid du Colombierall:V:	prog
971219b2ee8SDavid du Colombier.P2
972219b2ee8SDavid du Colombierto the preceding example builds the executable
973219b2ee8SDavid du Colombierwhen either
974219b2ee8SDavid du Colombier.CW prog
975219b2ee8SDavid du Colombieror
976219b2ee8SDavid du Colombier.CW all
977219b2ee8SDavid du Colombieris the specified target.  In effect, the
978219b2ee8SDavid du Colombier.CW all
979219b2ee8SDavid du Colombiertarget is an alias for
980219b2ee8SDavid du Colombier.CW prog .
981219b2ee8SDavid du Colombier.PP
982219b2ee8SDavid du ColombierWhen two rules have identical rule headers and both have
983219b2ee8SDavid du Colombierrecipes, the later rule replaces the former one.
984219b2ee8SDavid du ColombierFor example,
985219b2ee8SDavid du Colombierif a file named
986219b2ee8SDavid du Colombier.CW mkrules
987219b2ee8SDavid du Colombiercontains
988219b2ee8SDavid du Colombier.P1
989219b2ee8SDavid du Colombier$O.out:	$OFILES
990219b2ee8SDavid du Colombier	$LD $LFLAGS $OFILES
991219b2ee8SDavid du Colombier%.$O:	%.c
992219b2ee8SDavid du Colombier	$CC $CFLAGS $stem.c
993219b2ee8SDavid du Colombier.P2
994219b2ee8SDavid du Colombierthe
995219b2ee8SDavid du Colombier.CW mkfile
996219b2ee8SDavid du Colombier.P1
997219b2ee8SDavid du ColombierOFILES=f1.$O f2.$O f3.$O
998219b2ee8SDavid du Colombier
999219b2ee8SDavid du Colombier<mkrules
1000219b2ee8SDavid du Colombier
1001219b2ee8SDavid du Colombier$O.out:	$OFILES
1002219b2ee8SDavid du Colombier	$LD $LFLAGS -l $OFILES -lbio -lc
1003219b2ee8SDavid du Colombier.P2
1004219b2ee8SDavid du Colombieroverrides the general loader rule with a special
1005219b2ee8SDavid du Colombierrule using a non-standard library search sequence.
1006219b2ee8SDavid du ColombierA rule is neutralized by overriding it with a rule
1007219b2ee8SDavid du Colombierwith a null recipe:
1008219b2ee8SDavid du Colombier.P1
1009219b2ee8SDavid du Colombier<mkrules
1010219b2ee8SDavid du Colombier
1011219b2ee8SDavid du Colombier$O.out:Q:	$OFILES
1012219b2ee8SDavid du Colombier	;
1013219b2ee8SDavid du Colombier.P2
1014219b2ee8SDavid du ColombierThe
1015219b2ee8SDavid du Colombier.CW Q
1016219b2ee8SDavid du Colombierattribute suppresses the printing of the semicolon.
1017219b2ee8SDavid du Colombier.PP
1018219b2ee8SDavid du ColombierWhen a rule has no prerequisites, the recipe is executed
1019219b2ee8SDavid du Colombieronly when the target does not exist.  For example,
1020219b2ee8SDavid du Colombier.P1
1021219b2ee8SDavid du Colombiermarker:
1022219b2ee8SDavid du Colombier	touch $target
1023219b2ee8SDavid du Colombier.P2
1024219b2ee8SDavid du Colombierdefines a rule to manage a marker file.
1025219b2ee8SDavid du ColombierIf the file exists, it is considered up to date
1026219b2ee8SDavid du Colombierregardless of its modification time.
1027219b2ee8SDavid du ColombierWhen a virtual target has no prerequisites the
1028219b2ee8SDavid du Colombierrecipe is always executed.
1029219b2ee8SDavid du ColombierThe
1030219b2ee8SDavid du Colombier.CW clean
1031219b2ee8SDavid du Colombierrule is of this type:
1032219b2ee8SDavid du Colombier.P1
1033219b2ee8SDavid du Colombierclean:V:
1034219b2ee8SDavid du Colombier	rm -f [$OS].out *.[$OS]
1035219b2ee8SDavid du Colombier.P2
1036219b2ee8SDavid du ColombierWhen a rule without prerequisites has multiple targets, the
1037219b2ee8SDavid du Colombierextra targets are aliases for the rule.
1038219b2ee8SDavid du ColombierFor example, in
1039219b2ee8SDavid du Colombier.P1
1040219b2ee8SDavid du Colombierclean tidy nuke:V:
1041219b2ee8SDavid du Colombier	rm -f [$OS].out *.[$OS]
1042219b2ee8SDavid du Colombier.P2
1043219b2ee8SDavid du Colombierthe
1044219b2ee8SDavid du Colombierrule can be invoked by any of three names.
1045219b2ee8SDavid du ColombierThe first rule in a
1046219b2ee8SDavid du Colombier.CW mkfile
1047219b2ee8SDavid du Colombieris handled specially:
1048219b2ee8SDavid du Colombierwhen
1049219b2ee8SDavid du Colombier.CW mk
1050219b2ee8SDavid du Colombieris invoked without a command line target
1051219b2ee8SDavid du Colombierall targets of the first non-metarule are built.
10527dd7cddfSDavid du ColombierIf that rule has multiple targets, the recipe
1053219b2ee8SDavid du Colombieris executed once for each target; normally, the recipe
1054219b2ee8SDavid du Colombierof a rule with multiple targets is only executed once.
1055219b2ee8SDavid du Colombier.PP
1056219b2ee8SDavid du ColombierA rule applies to a target only when its prerequisites
1057219b2ee8SDavid du Colombierexist or can be derived.  More than one rule may have the
1058219b2ee8SDavid du Colombiersame target as long as only one rule with a recipe
1059219b2ee8SDavid du Colombierremains applicable after the dependency evaluation completes.
1060219b2ee8SDavid du ColombierFor example, consider a program built from C
1061219b2ee8SDavid du Colombierand assembler source files.  Two rules produce
1062219b2ee8SDavid du Colombierobject files:
1063219b2ee8SDavid du Colombier.P1
1064219b2ee8SDavid du Colombier%.$O:	%.c
1065219b2ee8SDavid du Colombier	$CC $CFLAGS $stem.c
1066219b2ee8SDavid du Colombier%.$O:	%.s
1067219b2ee8SDavid du Colombier	$AS $AFLAGS $stem.s
1068219b2ee8SDavid du Colombier.P2
1069219b2ee8SDavid du ColombierAs long as there are not two source files with names like
1070219b2ee8SDavid du Colombier.CW \fIfoo\fP.c
1071219b2ee8SDavid du Colombierand
1072219b2ee8SDavid du Colombier.CW \fIfoo\fP.s ,
1073219b2ee8SDavid du Colombier.CW mk
1074219b2ee8SDavid du Colombiercan unambiguously select the proper rule.
1075219b2ee8SDavid du ColombierIf both files exist,
10767dd7cddfSDavid du Colombierthe rules are ambiguous
1077219b2ee8SDavid du Colombierand
1078219b2ee8SDavid du Colombier.CW mk
1079219b2ee8SDavid du Colombierexits with an error message.
1080219b2ee8SDavid du Colombier.PP
1081219b2ee8SDavid du ColombierIn Plan 9, many programs consist of portable code stored
1082219b2ee8SDavid du Colombierin one directory and architecture-specific source stored in
1083219b2ee8SDavid du Colombieranother.
1084219b2ee8SDavid du ColombierFor example, the
1085219b2ee8SDavid du Colombier.CW mkfile
1086219b2ee8SDavid du Colombier.P1
1087219b2ee8SDavid du Colombier</$objtype/mkfile
10887dd7cddfSDavid du Colombier
1089219b2ee8SDavid du ColombierFILES=f1.$O f2.$O f3.$O f3.$O
1090219b2ee8SDavid du Colombier
1091219b2ee8SDavid du Colombierprog:	$FILES
1092219b2ee8SDavid du Colombier	$LD -o $target $prereq
1093219b2ee8SDavid du Colombier
1094219b2ee8SDavid du Colombier%.$O:	%.$c
1095219b2ee8SDavid du Colombier	$CC $CFLAGS $stem.c
1096219b2ee8SDavid du Colombier
1097219b2ee8SDavid du Colombier%.$O:	../port/%.c
1098219b2ee8SDavid du Colombier	$CC $CFLAGS ../port/$stem.c
1099219b2ee8SDavid du Colombier.P2
1100219b2ee8SDavid du Colombierbuilds the program named
1101219b2ee8SDavid du Colombier.CW prog
1102219b2ee8SDavid du Colombierusing portable code in directory
1103219b2ee8SDavid du Colombier.CW ../port
1104219b2ee8SDavid du Colombierand architecture-specific code in the current directory.
1105219b2ee8SDavid du ColombierAs long as the
1106219b2ee8SDavid du Colombiernames of the C source files in
1107219b2ee8SDavid du Colombier.CW ../port
1108219b2ee8SDavid du Colombierdo not conflict with the names of files in the current directory,
1109219b2ee8SDavid du Colombier.CW mk
11107dd7cddfSDavid du Colombierselects the appropriate rule to build the object file.
1111219b2ee8SDavid du ColombierIf like-named files exist in both directories, the
11127dd7cddfSDavid du Colombierspecification is ambiguous and an explicit target
11137dd7cddfSDavid du Colombiermust be specified to resolve the ambiguity.
1114219b2ee8SDavid du ColombierFor example,
1115219b2ee8SDavid du Colombieradding the rule
1116219b2ee8SDavid du Colombier.P1
1117219b2ee8SDavid du Colombierf2.$O:	f2.c
1118219b2ee8SDavid du Colombier	$CC $CFLAGS $f2.c
1119219b2ee8SDavid du Colombier.P2
1120219b2ee8SDavid du Colombierto the previous
1121219b2ee8SDavid du Colombier.CW mkfile
1122219b2ee8SDavid du Colombieruses the architecture-specific version of
1123219b2ee8SDavid du Colombier.CW f2.c
1124219b2ee8SDavid du Colombierinstead of the portable one.
11257dd7cddfSDavid du ColombierHere, the explicit rule unambiguously
1126219b2ee8SDavid du Colombierdocuments which of the
1127219b2ee8SDavid du Colombierlike-named source files is used to build the program.
1128219b2ee8SDavid du Colombier.PP
1129219b2ee8SDavid du Colombier.CW Mk\fR'\fP s
1130219b2ee8SDavid du Colombierheuristics can produce unintended results
1131219b2ee8SDavid du Colombierwhen rules are not carefully specified.
1132219b2ee8SDavid du ColombierFor example, the rules that build
1133219b2ee8SDavid du Colombierobject files from C or assembler source files
1134219b2ee8SDavid du Colombier.P1
1135219b2ee8SDavid du Colombier%.$O:	%.c
1136219b2ee8SDavid du Colombier	$CC $CFLAGS $stem.c
1137219b2ee8SDavid du Colombier%.$O:	%.s
1138219b2ee8SDavid du Colombier	$AS $AFLAGS $stem.s
1139219b2ee8SDavid du Colombier.P2
1140219b2ee8SDavid du Colombierillustrate a subtle pratfall.
1141219b2ee8SDavid du ColombierAdding a header file dependency to the compile rule
1142219b2ee8SDavid du Colombier.P1
1143219b2ee8SDavid du Colombier%.$O:	%.c hdr.h
1144219b2ee8SDavid du Colombier	$CC $CFLAGS $stem.c
1145219b2ee8SDavid du Colombier.P2
1146219b2ee8SDavid du Colombierproduces the error message
1147219b2ee8SDavid du Colombier.P1
1148219b2ee8SDavid du Colombier.CW "don't know how to make '\fIfile\fP.c'"
1149219b2ee8SDavid du Colombier.P2
1150219b2ee8SDavid du Colombierwhen \fIfile\fP.s is an assembler
1151219b2ee8SDavid du Colombiersource file.
1152219b2ee8SDavid du ColombierThis occurs because
1153219b2ee8SDavid du Colombier.CW \fIfile\fP.s
1154219b2ee8SDavid du Colombiersatisfies the assemble rule and
1155219b2ee8SDavid du Colombier.CW hdr.h
1156219b2ee8SDavid du Colombiersatisfies the compile rule, so
1157219b2ee8SDavid du Colombiereither rule can potentially produce the target.
1158219b2ee8SDavid du ColombierWhen a prerequisite exists or can be
1159219b2ee8SDavid du Colombierderived,
1160219b2ee8SDavid du Colombierall other prerequisites in that
1161219b2ee8SDavid du Colombierrule header must exist or be derivable; here,
1162219b2ee8SDavid du Colombierthe existence of
1163219b2ee8SDavid du Colombier.CW hdr.h
1164219b2ee8SDavid du Colombierforces the evaluation of a C source file.
1165219b2ee8SDavid du ColombierSpecifying the dependencies in different
1166219b2ee8SDavid du Colombierrules avoids this interpretation:
1167219b2ee8SDavid du Colombier.P1
1168219b2ee8SDavid du Colombier%.$O:	hdr.h
1169219b2ee8SDavid du Colombier%.$O:	%.c
1170219b2ee8SDavid du Colombier	$CC $CFLAGS $stem.c
1171219b2ee8SDavid du Colombier.P2
1172219b2ee8SDavid du ColombierAlthough
1173219b2ee8SDavid du Colombier.CW hdr.h
1174219b2ee8SDavid du Colombieris an additional prerequisite of the compile rule,
1175219b2ee8SDavid du Colombierthe two rules are evaluated independently and
1176219b2ee8SDavid du Colombierthe existence of the C source file is not linked
1177219b2ee8SDavid du Colombierto the existence of the header file.
1178219b2ee8SDavid du ColombierHowever, this specification describes a different
1179219b2ee8SDavid du Colombierdependency.  Originally, only object
1180219b2ee8SDavid du Colombierfiles derived from C files depended on
1181219b2ee8SDavid du Colombier.CW hdr.h ;
1182219b2ee8SDavid du Colombiernow all object files, including those built
1183219b2ee8SDavid du Colombierfrom assembler source, depend on the header file.
1184219b2ee8SDavid du Colombier.PP
1185219b2ee8SDavid du ColombierMetarule patterns should be as restrictive as possible to
1186219b2ee8SDavid du Colombierprevent conflicts with other rules.
1187219b2ee8SDavid du ColombierConsider the
1188219b2ee8SDavid du Colombier.CW mkfile
1189219b2ee8SDavid du Colombier.P1
1190219b2ee8SDavid du Colombier</$objtype/mkfile
1191219b2ee8SDavid du ColombierBIN=/$objtype/bin
1192219b2ee8SDavid du ColombierPROG=foo
1193219b2ee8SDavid du Colombier
1194219b2ee8SDavid du Colombierinstall:V:	$BIN/$PROG
1195219b2ee8SDavid du Colombier
1196219b2ee8SDavid du Colombier%:	%.c
1197219b2ee8SDavid du Colombier	$CC $stem.c
1198219b2ee8SDavid du Colombier	$LD -o $target $stem.$O
1199219b2ee8SDavid du Colombier
1200219b2ee8SDavid du Colombier$BIN/%:	%
1201219b2ee8SDavid du Colombier	mv $stem $target
1202219b2ee8SDavid du Colombier.P2
1203219b2ee8SDavid du ColombierThe first target builds an executable
1204219b2ee8SDavid du Colombierin the local directory; the second
1205219b2ee8SDavid du Colombierinstalls it in the directory
1206219b2ee8SDavid du Colombierof executables for the architecture.
1207219b2ee8SDavid du ColombierInvoking
1208219b2ee8SDavid du Colombier.CW mk
1209219b2ee8SDavid du Colombierwith the
1210219b2ee8SDavid du Colombier.CW install
1211219b2ee8SDavid du Colombiertarget produces:
1212219b2ee8SDavid du Colombier.P1 0
1213219b2ee8SDavid du Colombiermk: ambiguous recipes for /mips/bin/foo:
1214219b2ee8SDavid du Colombier/mips/bin/foo <-(mkfile:8)- /mips/bin/foo.c <-(mkfile:12)- foo.c
1215219b2ee8SDavid du Colombier/mips/bin/foo <-(mkfile:12)- foo <-(mkfile:8)- foo.c
1216219b2ee8SDavid du Colombier.P2
1217219b2ee8SDavid du ColombierThe prerequisite of the
1218219b2ee8SDavid du Colombier.CW install
1219219b2ee8SDavid du Colombierrule,
1220219b2ee8SDavid du Colombier.CW $BIN/$PROG ,
1221219b2ee8SDavid du Colombiermatches both metarules because the
1222219b2ee8SDavid du Colombier.CW %
1223219b2ee8SDavid du Colombierpattern matches everything.
1224219b2ee8SDavid du ColombierThe
1225219b2ee8SDavid du Colombier.CW &
1226219b2ee8SDavid du Colombierpattern restricts the compile rule to files in the
1227219b2ee8SDavid du Colombiercurrent directory and avoids the conflict:
1228219b2ee8SDavid du Colombier.P1
1229219b2ee8SDavid du Colombier&:	&.c
1230219b2ee8SDavid du Colombier	$CC $stem.c
1231219b2ee8SDavid du Colombier	$LD -o $target $stem.$O
1232219b2ee8SDavid du Colombier.P2
1233219b2ee8SDavid du Colombier.NH 1
1234219b2ee8SDavid du ColombierMissing intermediates
1235219b2ee8SDavid du Colombier.PP
1236219b2ee8SDavid du Colombier.CW Mk
1237219b2ee8SDavid du Colombierdoes not build a missing intermediate file if a target
1238219b2ee8SDavid du Colombieris up to date with the prerequisites of the intermediate.
1239219b2ee8SDavid du ColombierFor example,
1240219b2ee8SDavid du Colombierwhen an executable is up to date with its source file,
1241219b2ee8SDavid du Colombier.CW mk
1242219b2ee8SDavid du Colombierdoes not compile the source to create a missing object file.
1243219b2ee8SDavid du ColombierThe evaluation only applies
1244219b2ee8SDavid du Colombierwhen a target is considered up to date by pretending that the
1245219b2ee8SDavid du Colombierintermediate exists.  Thus, it does not apply
1246219b2ee8SDavid du Colombierwhen the intermediate is a command line target
1247219b2ee8SDavid du Colombieror when it has no prerequisites.
1248219b2ee8SDavid du Colombier.PP
1249219b2ee8SDavid du ColombierThis capability is useful for
1250219b2ee8SDavid du Colombiermaintaining archives.  We can modify the archive
1251219b2ee8SDavid du Colombierupdate recipe to remove object files after
1252219b2ee8SDavid du Colombierthey are archived:
1253219b2ee8SDavid du Colombier.P1
1254219b2ee8SDavid du Colombier$LIB(%):N:	%
1255219b2ee8SDavid du Colombier$LIB:	${OBJS:%=$LIB(%)}
1256219b2ee8SDavid du Colombier	names=`{membername $newprereq}
1257219b2ee8SDavid du Colombier	ar rv $LIB $names
1258219b2ee8SDavid du Colombier	rm -f $names
1259219b2ee8SDavid du Colombier.P2
1260219b2ee8SDavid du ColombierA subsequent
1261219b2ee8SDavid du Colombier.CW mk
1262219b2ee8SDavid du Colombierdoes not remake the object files as long as the members
1263219b2ee8SDavid du Colombierof the archive remain up to date with the source files.
1264219b2ee8SDavid du ColombierThe
1265219b2ee8SDavid du Colombier.CW -i
1266219b2ee8SDavid du Colombiercommand line option overrides this behavior
1267219b2ee8SDavid du Colombierand causes all intermediates to be built.
1268219b2ee8SDavid du Colombier.NH 1
1269219b2ee8SDavid du ColombierAlternative out-of-date determination
1270219b2ee8SDavid du Colombier.PP
1271219b2ee8SDavid du ColombierSometimes the modification time is not useful
1272219b2ee8SDavid du Colombierfor deciding when a target and prerequisite are out of date.
1273219b2ee8SDavid du ColombierThe
1274219b2ee8SDavid du Colombier.CW P
1275219b2ee8SDavid du Colombierattribute replaces the default mechanism with the result of
1276219b2ee8SDavid du Colombiera command.  The command immediately follows the attribute
1277219b2ee8SDavid du Colombierand is repeatedly executed with each
1278219b2ee8SDavid du Colombiertarget and each prerequisite as its arguments;
1279219b2ee8SDavid du Colombierif its exit status is non-zero, they are considered out of date
1280219b2ee8SDavid du Colombierand the recipe is executed.  Consider the
1281219b2ee8SDavid du Colombier.CW mkfile
1282219b2ee8SDavid du Colombier.P1
1283219b2ee8SDavid du Colombierfoo.ref:Pcmp -s:	foo
1284219b2ee8SDavid du Colombier	cp $prereq $target
1285219b2ee8SDavid du Colombier.P2
1286219b2ee8SDavid du ColombierThe command
1287219b2ee8SDavid du Colombier.P1
1288219b2ee8SDavid du Colombiercmp -s foo.ref foo
1289219b2ee8SDavid du Colombier.P2
1290219b2ee8SDavid du Colombieris executed and if
1291219b2ee8SDavid du Colombier.CW foo.ref
1292219b2ee8SDavid du Colombierdiffers from
1293219b2ee8SDavid du Colombier.CW foo ,
1294219b2ee8SDavid du Colombierthe latter file is copied to the former.
1295219b2ee8SDavid du Colombier.NH 1
1296219b2ee8SDavid du ColombierParallel processing
1297219b2ee8SDavid du Colombier.PP
1298219b2ee8SDavid du ColombierWhen possible,
1299219b2ee8SDavid du Colombier.CW mk
1300219b2ee8SDavid du Colombierexecutes recipes in parallel.
1301219b2ee8SDavid du ColombierThe variable
1302219b2ee8SDavid du Colombier.CW $NPROC
1303219b2ee8SDavid du Colombierspecifies the maximum number of simultaneously executing
1304219b2ee8SDavid du Colombierrecipes.
1305219b2ee8SDavid du ColombierNormally it is imported from the environment,
1306219b2ee8SDavid du Colombierwhere the system has set it to the number of available processors.
1307219b2ee8SDavid du ColombierIt can be decreased by assigning a new
1308219b2ee8SDavid du Colombiervalue and can be set to 1 to force single-threaded recipe execution.
1309219b2ee8SDavid du ColombierThis is necessary when several targets access
1310219b2ee8SDavid du Colombiera common resource such as
1311219b2ee8SDavid du Colombiera status file or data base.
1312219b2ee8SDavid du ColombierWhen there is no dependency between targets,
1313219b2ee8SDavid du Colombier.CW mk
1314219b2ee8SDavid du Colombierassumes the
1315219b2ee8SDavid du Colombierrecipes can be
1316219b2ee8SDavid du Colombierexecuted concurrently.
1317219b2ee8SDavid du ColombierNormally, this allows
1318219b2ee8SDavid du Colombiermultiple prerequisites to be built simultaneously;
1319219b2ee8SDavid du Colombierfor example, the object file prerequisites of
1320219b2ee8SDavid du Colombiera load rule can be produced by compiling the source files in parallel.
1321219b2ee8SDavid du Colombier.CW Mk
1322219b2ee8SDavid du Colombierdoes not define the order of execution of independent recipes.
1323219b2ee8SDavid du ColombierWhen the prerequisites of a rule are not independent,
1324219b2ee8SDavid du Colombierthe dependencies between them should be specified in a rule or the
1325219b2ee8SDavid du Colombier.CW mkfile
1326219b2ee8SDavid du Colombiershould be single-threaded.
1327219b2ee8SDavid du ColombierFor example, the archive update rules
1328219b2ee8SDavid du Colombier.P1
1329219b2ee8SDavid du Colombier$LIB(%):N:	%
1330219b2ee8SDavid du Colombier$LIB:	${OBJS:%=$LIB(%)}
1331219b2ee8SDavid du Colombier	ar rv $LIB `{membername $newprereq}
1332219b2ee8SDavid du Colombier.P2
1333219b2ee8SDavid du Colombiercompile source files in parallel but update
1334219b2ee8SDavid du Colombierall members of the archive at once.
1335219b2ee8SDavid du ColombierIt is a mistake to merge the two rules
1336219b2ee8SDavid du Colombier.P1
1337219b2ee8SDavid du Colombier$LIB(%):	%
1338219b2ee8SDavid du Colombier	ar rv $LIB $stem
1339219b2ee8SDavid du Colombier.P2
1340219b2ee8SDavid du Colombierbecause an
1341219b2ee8SDavid du Colombier.CW ar
1342219b2ee8SDavid du Colombiercommand is executed for every
1343219b2ee8SDavid du Colombiermember of the library.  Not only is this
1344219b2ee8SDavid du Colombierinefficient, but the archive is updated
1345219b2ee8SDavid du Colombierin parallel, making interference likely.
1346219b2ee8SDavid du Colombier.PP
1347219b2ee8SDavid du ColombierThe
1348219b2ee8SDavid du Colombier.CW $nproc
1349219b2ee8SDavid du Colombierenvironment variable contains a number associated
1350219b2ee8SDavid du Colombierwith the processor executing a recipe.
1351219b2ee8SDavid du ColombierIt can be used to create unique
1352219b2ee8SDavid du Colombiernames when the
1353219b2ee8SDavid du Colombierrecipe may be executing simultaneously on several processors.
1354219b2ee8SDavid du ColombierOther maintenance tools provide mechanisms to control recipe
1355219b2ee8SDavid du Colombierscheduling explicitly [Cmel86], but
1356219b2ee8SDavid du Colombier.CW mk\fR'\fPs
1357219b2ee8SDavid du Colombiergeneral rules are sufficient for all but the most unusual cases.
1358219b2ee8SDavid du Colombier.NH 1
1359219b2ee8SDavid du ColombierDeleting target files on errors
1360219b2ee8SDavid du Colombier.PP
1361219b2ee8SDavid du ColombierThe
1362219b2ee8SDavid du Colombier.CW D
1363219b2ee8SDavid du Colombierattribute
1364219b2ee8SDavid du Colombiercauses
1365219b2ee8SDavid du Colombier.CW mk
1366219b2ee8SDavid du Colombierto remove the target file when a
1367219b2ee8SDavid du Colombierrecipe terminates prematurely.
1368219b2ee8SDavid du ColombierThe error message describing the
1369219b2ee8SDavid du Colombiertermination condition warns
1370219b2ee8SDavid du Colombierof the deletion.
1371219b2ee8SDavid du ColombierA partially built file is doubly dangerous:
1372219b2ee8SDavid du Colombierit is not only wrong, but is also
1373219b2ee8SDavid du Colombierconsidered to be up to date so
1374219b2ee8SDavid du Colombiera subsequent
1375219b2ee8SDavid du Colombier.CW mk
1376219b2ee8SDavid du Colombierwill not rebuild it.  For example,
1377219b2ee8SDavid du Colombier.P1
1378219b2ee8SDavid du Colombierpic.out:D:	mk.ms
1379219b2ee8SDavid du Colombier		pic $prereq | tbl | troff -ms > $target
1380219b2ee8SDavid du Colombier.P2
1381219b2ee8SDavid du Colombierproduces the message
1382219b2ee8SDavid du Colombier.P1
1383219b2ee8SDavid du Colombier.CW "mk: pic mk.ms | ...  : exit status=rc 685: deleting 'pic.out'"
1384219b2ee8SDavid du Colombier.P2
1385219b2ee8SDavid du Colombierif any program in the recipe exits with an error status.
1386219b2ee8SDavid du Colombier.NH 1
1387219b2ee8SDavid du ColombierUnspecified dependencies
1388219b2ee8SDavid du Colombier.PP
1389219b2ee8SDavid du ColombierThe
1390219b2ee8SDavid du Colombier.CW -w
1391219b2ee8SDavid du Colombiercommand line flag forces the
1392219b2ee8SDavid du Colombierfiles following the flag to be treated
1393219b2ee8SDavid du Colombieras if they were just modified.
1394219b2ee8SDavid du ColombierWe can use this flag with a command that selects files
1395219b2ee8SDavid du Colombierto force a build based on the selection criterion.
1396219b2ee8SDavid du ColombierFor example, if the declaration of
1397219b2ee8SDavid du Colombiera global variable named
1398219b2ee8SDavid du Colombier.I var
1399219b2ee8SDavid du Colombieris changed in a header file,
1400219b2ee8SDavid du Colombierall source files that reference
1401219b2ee8SDavid du Colombierit can be rebuilt with the command
1402219b2ee8SDavid du Colombier.P1
1403219b2ee8SDavid du Colombier$ mk -w`{grep -l \fIvar\fP *.[cyl]}
1404219b2ee8SDavid du Colombier.P2
1405219b2ee8SDavid du Colombier.NH 1
1406219b2ee8SDavid du ColombierConclusion
1407219b2ee8SDavid du Colombier.PP
1408219b2ee8SDavid du ColombierThere are many programs related to
1409219b2ee8SDavid du Colombier.CW make ,
1410219b2ee8SDavid du Colombiereach choosing a different balance between
1411219b2ee8SDavid du Colombierspecialization and generality.
1412219b2ee8SDavid du Colombier.CW Mk
1413219b2ee8SDavid du Colombieremphasizes generality but allows
1414219b2ee8SDavid du Colombiercustomization through its pattern specifications and
1415219b2ee8SDavid du Colombierinclude facilities.
1416219b2ee8SDavid du Colombier.PP
14177dd7cddfSDavid du ColombierPlan 9 presents a difficult maintenance environment
14187dd7cddfSDavid du Colombierwith its heterogeneous
1419219b2ee8SDavid du Colombierarchitectures and languages.
1420219b2ee8SDavid du Colombier.CW Mk\fR'\fPs
1421219b2ee8SDavid du Colombierflexible specification language and simple
1422219b2ee8SDavid du Colombierinteraction with
1423219b2ee8SDavid du Colombier.CW rc
1424219b2ee8SDavid du Colombierwork well in this environment.
1425219b2ee8SDavid du ColombierAs a result,
1426219b2ee8SDavid du ColombierPlan 9 relies on
1427219b2ee8SDavid du Colombier.CW mk
1428219b2ee8SDavid du Colombierto automate almost all maintenance.
1429219b2ee8SDavid du ColombierTasks as diverse as updating the
1430219b2ee8SDavid du Colombiernetwork data base, producing the manual,
1431219b2ee8SDavid du Colombieror building a release are expressed as
1432219b2ee8SDavid du Colombier.CW mk
1433219b2ee8SDavid du Colombierprocedures.
1434219b2ee8SDavid du Colombier.NH 1
1435219b2ee8SDavid du ColombierReferences
1436219b2ee8SDavid du Colombier.LP
1437219b2ee8SDavid du Colombier[Cmel86] R. F. Cmelik,
1438219b2ee8SDavid du Colombier``Concurrent Make: A Distributed Program in Concurrent C'',
1439219b2ee8SDavid du ColombierAT&T Bell Laboratories Technical Report, 1986.
1440219b2ee8SDavid du Colombier.LP
1441219b2ee8SDavid du Colombier[Feld79] S. I. Feldman,
1442219b2ee8SDavid du Colombier``Make \(em a program for maintaining computer programs'',
1443219b2ee8SDavid du Colombier.I
1444219b2ee8SDavid du ColombierSoftware Practice & Experience ,
1445219b2ee8SDavid du Colombier.R
1446219b2ee8SDavid du Colombier1979
1447219b2ee8SDavid du ColombierVol 9 #4,
1448219b2ee8SDavid du Colombierpp. 255-266.
1449219b2ee8SDavid du Colombier.LP
1450219b2ee8SDavid du Colombier[Flan95] Bob Flandrena,
1451219b2ee8SDavid du Colombier``Plan 9 Mkfiles'',
1452219b2ee8SDavid du Colombierthis volume.
1453219b2ee8SDavid du Colombier.LP
1454219b2ee8SDavid du Colombier[Hume87] A. G. Hume,
1455219b2ee8SDavid du Colombier``Mk: A Successor to Make'',
1456219b2ee8SDavid du Colombier.I
1457219b2ee8SDavid du ColombierUSENIX Summer Conf. Proc.,
1458219b2ee8SDavid du Colombier.R
1459219b2ee8SDavid du ColombierPhoenix, Az.
1460219b2ee8SDavid du Colombier.NH 1
1461219b2ee8SDavid du ColombierAppendix: Differences between
1462219b2ee8SDavid du Colombier.CW make
1463219b2ee8SDavid du Colombierand
1464219b2ee8SDavid du Colombier.CW mk
1465219b2ee8SDavid du Colombier.PP
1466219b2ee8SDavid du ColombierThe differences between
1467219b2ee8SDavid du Colombier.CW mk
1468219b2ee8SDavid du Colombierand
1469219b2ee8SDavid du Colombier.CW make
1470219b2ee8SDavid du Colombierare:
1471219b2ee8SDavid du Colombier.IP \(bu 3n
1472219b2ee8SDavid du Colombier.CW Make
1473219b2ee8SDavid du Colombierbuilds targets when it needs them, allowing systematic use of side effects.
1474219b2ee8SDavid du Colombier.CW Mk
1475219b2ee8SDavid du Colombierconstructs the entire dependency graph before building any target.
1476219b2ee8SDavid du Colombier.IP \(bu
1477219b2ee8SDavid du Colombier.CW Make
1478219b2ee8SDavid du Colombiersupports suffix rules and
1479219b2ee8SDavid du Colombier.CW %
1480219b2ee8SDavid du Colombiermetarules.
1481219b2ee8SDavid du Colombier.CW Mk
1482219b2ee8SDavid du Colombiersupports
1483219b2ee8SDavid du Colombier.CW %
1484219b2ee8SDavid du Colombierand regular expression metarules.
1485219b2ee8SDavid du Colombier(Older versions of
1486219b2ee8SDavid du Colombier.CW make
1487219b2ee8SDavid du Colombiersupport only suffix rules.)
1488219b2ee8SDavid du Colombier.IP \(bu
1489219b2ee8SDavid du Colombier.CW Mk
1490219b2ee8SDavid du Colombierperforms transitive closure on metarules,
1491219b2ee8SDavid du Colombier.CW make
1492219b2ee8SDavid du Colombierdoes not.
1493219b2ee8SDavid du Colombier.IP \(bu
1494219b2ee8SDavid du Colombier.CW Make
1495219b2ee8SDavid du Colombiersupports cyclic dependencies,
1496219b2ee8SDavid du Colombier.CW mk
1497219b2ee8SDavid du Colombierdoes not.
1498219b2ee8SDavid du Colombier.IP \(bu
1499219b2ee8SDavid du Colombier.CW Make
1500219b2ee8SDavid du Colombierevaluates recipes one line at a time, replacing variables by their values and
1501219b2ee8SDavid du Colombierexecuting some commands internally.
1502219b2ee8SDavid du Colombier.CW Mk
1503219b2ee8SDavid du Colombierpasses the entire recipe to the shell without
1504219b2ee8SDavid du Colombierinterpretation or internal execution.
1505219b2ee8SDavid du Colombier.IP \(bu
1506219b2ee8SDavid du Colombier.CW Make
1507219b2ee8SDavid du Colombiersupports parallel execution of single-line recipes when building
1508219b2ee8SDavid du Colombierthe prerequisites for specified targets.
1509219b2ee8SDavid du Colombier.CW Mk
1510219b2ee8SDavid du Colombiersupports parallel execution of all recipes.
1511219b2ee8SDavid du Colombier(Older versions of
1512219b2ee8SDavid du Colombier.CW make
1513219b2ee8SDavid du Colombierdid not support parallel execution.)
1514219b2ee8SDavid du Colombier.IP \(bu
1515219b2ee8SDavid du Colombier.CW Make
1516219b2ee8SDavid du Colombieruses special targets (beginning with a period)
1517219b2ee8SDavid du Colombierto indicate special processing.
1518219b2ee8SDavid du Colombier.CW Mk
1519219b2ee8SDavid du Colombieruses attributes to modify rule evaluation.
1520219b2ee8SDavid du Colombier.IP \(bu
1521219b2ee8SDavid du Colombier.CW Mk
1522219b2ee8SDavid du Colombiersupports virtual
1523219b2ee8SDavid du Colombiertargets that are independent of the file system.
1524219b2ee8SDavid du Colombier.IP \(bu
1525219b2ee8SDavid du Colombier.CW Mk
1526219b2ee8SDavid du Colombierallows non-standard out-of-date determination,
1527219b2ee8SDavid du Colombier.CW make
1528219b2ee8SDavid du Colombierdoes not.
1529219b2ee8SDavid du Colombier.PP
1530219b2ee8SDavid du ColombierIt is usually easy to convert a
1531219b2ee8SDavid du Colombier.CW makefile
1532219b2ee8SDavid du Colombierto or from an equivalent
1533219b2ee8SDavid du Colombier.CW mkfile .
1534