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