<html><title>data</title><body BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#0000FF" VLINK="#330088" ALINK="#FF0044"><H1>Maintaining Files on Plan 9 with Mk</H1><DL><DD><I>Andrew G. Hume<br>andrew@research.att.com<br>Bob Flandrena<br>bobf@plan9.bell-labs.com<br></I></DL><DL><DD><H4>ABSTRACT</H4><P><TT>Mk</TT>is a toolfor describing and maintaining dependencies betweenfiles.It is similar to theUNIX program<TT>make</TT>,but provides several extensions.<TT>Mk's</TT>flexible rule specifications, implieddependency derivation, and parallelexecution of maintenance actions arewell-suited to the Plan 9 environment.Almost all Plan 9 maintenance proceduresare automated using<TT>mk</TT>.</DL></P><H4>1 Introduction</H4><P>This document describes how<TT>mk</TT>,a program functionally similar to<TT>make</TT>[Feld79],is used to maintain dependencies betweenfiles in Plan 9.<TT>Mk</TT>provides several extensions to thecapabilities of its predecessor that workwell in Plan 9's distributed, multi-architectureenvironment. Itexploits the power of multiprocessors by executingmaintenance actions in parallel and interacts withthe Plan 9 command interpreter<TT>rc</TT>to provide a powerful set of maintenance tools.It accepts pattern-based dependency specificationsthat are not limited to describingrules for program construction.The result is a tool that is flexible enough toperform many maintenance tasks includingdatabase maintenance,hardware design, and document production.</P><P>This document begins by discussing the syntax of the control file,the pattern matching capabilities, andthe special rules for maintaining archives.A brief description of<TT>mk's</TT>algorithm for deriving dependenciesis followed by a discussionof the conventions used to resolve ambiguousspecifications. The final sectionsdescribe parallel executionand special features.</P><P>An earlier paper [Hume87]provides a detailed discussion of<TT>mk's</TT>design and an appendix summarizesthe differences between<TT>mk</TT>and<TT>make</TT>.</P><H4>2 The <TT>Mkfile</TT></H4><P><TT>Mk</TT>reads a file describing relationships among filesand executes commands to bring the files up to date.The specification file, called a<TT>mkfile</TT>,contains three types of statements:assignments, includes, and rules.Assignment and include statements are similarto those in C.Rules specify dependencies between a<I>target</I>and its<I>prerequisites</I>.When the target and prerequisites are files, theirmodification times determine if theyare out of date. Rules often contain a<I>recipe</I>,an<A href="/magic/man2html/1/rc"><I>rc</I>(1)</A>script that produces the target fromthe prerequisites.</P><P>This simple<TT>mkfile</TT>produces an executablefrom a C source file:<DL><DT><DD><TT><PRE>CC=pccf1: f1.c $CC -o f1 f1.c</PRE></TT></DL>The first line assigns the name of the portable ANSI/POSIX compilerto the<TT>mk</TT>variable<TT>CC</TT>;subsequent references of the form<TT>$CC</TT>select this compiler.The only rule specifies a dependence between the target file<TT>f1</TT>and the prerequisite file<TT>f1.c</TT>.If the target does not exist or if theprerequisite has been modified more recently thanthe target,<TT>mk</TT>passes the recipe to<TT>rc</TT>for execution. Here,<TT>f1.c</TT>is compiled and loaded to produce<TT>f1</TT>.</P><P>The native Plan 9 environmentrequires executables forall architectures, not only the current one.The Plan 9 version of the same<TT>mkfile</TT>looks like:<DL><DT><DD><TT><PRE></$objtype/mkfile f1: f1.$O $LD $LDFLAGS -o f1 f1.$Of1.$O: f1.c $CC $CFLAGS f1.c</PRE></TT></DL>The first line is an include statementthat replaces itself with the contents of the file<TT>/$objtype/mkfile</TT>.The variable<TT>$objtype</TT>is inherited from the environment andcontains the name of the target architecture.The prototype<TT>mkfile</TT>for that architecture defines architecture-specific variables:<TT>CC</TT>and<TT>LD</TT>are the names of the compiler and loader,<TT>O</TT>is the code character of the architecture.The rules compile the source file into an objectfile and invoke the loader to produce<TT>f1</TT>.Invoking<TT>mk</TT>from the command line as follows<DL><DT><DD><TT><PRE>% objtype=mips mkvc -w f1.cvl $LDFLAGS -o f1 f1.k%</PRE></TT></DL>produces the<TT>mips</TT>executable of program<TT>f1</TT>regardless of the current architecture type.</P><P>We can extend the<TT>mkfile</TT>to build two programs:<DL><DT><DD><TT><PRE></$objtype/mkfileALL=f1 f2 all:V: $ALL f1: f1.$O $LD $LDFLAGS -o f1 f1.$Of1.$O: f1.c $CC $CFLAGS f1.cf2: f2.$O $LD $LDFLAGS -o f2 f2.$Of2.$O: f2.c $CC $CFLAGS f2.c</PRE></TT></DL>The target<TT>all</TT>,modified by the<I>attribute</I><TT>V</TT>,builds both programs.The attribute identifies <TT>all</TT>as a dummy target that isnot related to a file of the same name;its precise effect is explained later.This example describes cascading dependencies:the first target depends on another which depends on a third andso on.Here, individual rules build eachprogram; later we'll see how to do this with ageneral rule.</P><H4>3 Variables and the environment</H4><P><TT>Mk</TT>does not distinguish between itsinternal variables and<TT>rc</TT>variables in the environment.When<TT>mk</TT>starts, it imports each environment variable into a<TT>mk</TT>variable of the same name. Before executing a recipe,<TT>mk</TT>exports all variables, including thoseinherited from the environment,to the environment in which<TT>rc</TT>executes the recipe.</P><P>There are several ways for avariable to take a value.It can be set with an assignment statement,inherited from the environment, or specifiedon the command line.<TT>Mk</TT>also maintains several special internal variablesthat are described in<A href="/magic/man2html/1/mk"><I>mk</I>(1).</A>Assignments have the following decreasing order of precedence:</P><br> <br><DL><DT><DD>1) Command line assignment<br>2) Assignment statement<br>3) Imported from the environment<br>4) Implicitly set by <TT>mk</TT></DL><br> <br>For example, a command line assignment overridesa value imported from the environment.<P>All variable values are strings. They can beused for pattern matching andcomparison but not for arithmetic.A<I>list</I>is a string containing several values separated bywhite space. Each member ishandled individually during pattern matching,target selection, and prerequisite evaluation.</P><P>A<I>namelist</I>is a list produced bytransforming the members of an existing list.The transform applies a pattern to each member,replacing each matched string with a new string,much as in the substitute command in<A href="/magic/man2html/1/sam"><I>sam</I>(1)</A>or<A href="/magic/man2html/1/ed"><I>ed</I>(1).</A>The syntax is<DL><DT><DD><TT><PRE>${<I>var</I>:A%B=C%D}</PRE></TT></DL>where<I>var</I>is a variable.The pattern<TT>A%B</TT>matches a member beginning with the string<I>A</I>and ending with the string<I>B</I>with any string in between;it behaves like the regular expression<TT>A.*B</TT>.When a member of the<I>var</I>listmatches this pattern,the string<I>C</I>replaces<I>A</I>,<I>D</I>replaces<I>B</I>,and the matched string replaces itself.Any of<I>A</I>,<I>B</I>,<I>C</I>,or<I>D</I>may be the empty string. In effect, a namelist isgenerated by applying the<A href="/magic/man2html/1/ed"><I>ed</I>(1)</A>substitute command<DL><DT><DD><TT><PRE> s/<I>A</I>(.*)<I>B</I>/<I>C</I>\1<I>D</I>/</PRE></TT></DL>to each member of a variable list.</P><P>Namelists are useful for generatinga list based on a predictable transformation.For example,<DL><DT><DD><TT><PRE> SRC=a.c b.c c.c OBJ=${SRC:%.c=%.v}</PRE></TT></DL>assigns the list <TT>(a.v b.v c.v)</TT> to<TT>OBJ</TT>.A namelist may be used anywhere a variable is allowedexcept in a recipe.</P><P>Command output is assigned to a variableusing the normal<TT>rc</TT>syntax:<DL><DT><DD><TT><PRE> var=`{rc command}</PRE></TT></DL>The command executes in an environment populatedwith previously assigned variables, including thoseinherited from<TT>mk's</TT>execution environment.The command maybe arbitrarily complex; for example,<DL><DT><DD><TT><PRE> TARG=`{ls -d *.[cy] | sed 's/..$//'}</PRE></TT></DL>assigns a list of the C and yacc source files in the currentdirectory, stripped of their suffix, to the variable<TT>TARG</TT>.</P><H4>4 The include statement</H4><P>The include statementreplaces itself with the contents of a file.It is functionally similar to the C<TT>#include</TT>statement but uses a different syntax:<DL><DT><DD><TT><PRE> <<I>filename</I></PRE></TT></DL>The contents of the file are evaluatedas they are read.An include statement may be used anywhere exceptin a recipe.</P><P>Unlike<TT>make</TT>,<TT>mk</TT>has no built-in rules. Instead,the include statement allows generic rulesto be imported from a prototype<TT>mkfile</TT>;most Plan 9<TT>mkfiles</TT>use this approach [Flan95].</P><H4>5 Rules</H4><P>A rule has four elements: targets,prerequisites, attributes, and a recipe.It has the form:<DL><DT><DD><TT><PRE><I>targets</I>:<I>attributes</I>:<I>prerequisites</I> <I>recipe</I></PRE></TT></DL>The first line, containing thetargets, attributes, and prerequisites isthe<I>rule header</I>;itmust begin at the left margin.The recipe contains zero or more lines,each of which begins with white space.One or more targets must be specified but theattributes, prerequisites, and recipe are optional.A rule specifiesa dependency between the target(s) and its prerequisite(s),the recipe brings the target(s)up to date with the prerequisite(s) andattributes modify<TT>mk's</TT>evaluation of the dependency.</P><P>Normally the target is a file that dependson one or more prerequisite files.<TT>Mk</TT>compares the modification times of each targetand each prerequisite; a target is considered out of datewhen it does not exist or when a prerequisite has been modifiedmore recently.When a target is out of date,<TT>mk</TT>executes therecipe to bring it up to date.When the recipe completes,the modification time of the target is checked andused in later dependency evaluations.If the recipe does not update the target,evaluation continues with the out of date target.</P><P>A prerequisite of one rulemay be the target of another. Whenthis happens, the rules cascadeto define a multi-step procedure.For example,an executable target depends on prerequisiteobject files, each of which is a targetin a rule with a C source file as the prerequisite.<TT>Mk</TT>follows a chain of dependencies until it encountersa prerequisite that is not a target of another ruleor it finds a target thatis up to date. It thenexecutes the recipes in reverse order to producethe desired target.</P><P>The rule header is evaluated when the rule is read.Variables are replaced by their values, namelists aregenerated, andcommands are replaced by theiroutput at this time.</P><P>Most attributes modify<TT>mk's</TT>evaluation of a rule.An attribute is usually a single letter but someare more complicated.This paper only discusses commonly used attributes;see<A href="/magic/man2html/1/mk"><I>mk</I>(1)</A>for a complete list.</P><P>The<TT>V</TT>attribute identifies a<I>virtual</I>target;that is, a target that is not a file.For example,<DL><DT><DD><TT><PRE>clean:V: rm *.$O $O.out</PRE></TT></DL>removes executables and compiler intermediate files.The target is virtual because it does not refer to a file named<TT>clean</TT>.Without the attribute, the recipe would not beexecuted if a file named<TT>clean</TT>Lines 1–500 of 1594. Load more
<html> <title> data </title> <body BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#0000FF" VLINK="#330088" ALINK="#FF0044"> <H1>Maintaining Files on Plan 9 with Mk </H1> <DL><DD><I>Andrew G. Hume<br> andrew@research.att.com<br> Bob Flandrena<br> bobf@plan9.bell-labs.com<br> </I></DL> <DL><DD><H4>ABSTRACT</H4> <P> <TT>Mk</TT> is a tool for describing and maintaining dependencies between files. It is similar to the UNIX program <TT>make</TT>, but provides several extensions. <TT>Mk's</TT> flexible rule specifications, implied dependency derivation, and parallel execution of maintenance actions are well-suited to the Plan 9 environment. Almost all Plan 9 maintenance procedures are automated using <TT>mk</TT>. </DL> </P> <H4>1 Introduction </H4> <P> This document describes how <TT>mk</TT>, a program functionally similar to <TT>make</TT> [Feld79], is used to maintain dependencies between files in Plan 9. <TT>Mk</TT> provides several extensions to the capabilities of its predecessor that work well in Plan 9's distributed, multi-architecture environment. It exploits the power of multiprocessors by executing maintenance actions in parallel and interacts with the Plan 9 command interpreter <TT>rc</TT> to provide a powerful set of maintenance tools. It accepts pattern-based dependency specifications that are not limited to describing rules for program construction. The result is a tool that is flexible enough to perform many maintenance tasks including database maintenance, hardware design, and document production. </P> <P> This document begins by discussing the syntax of the control file, the pattern matching capabilities, and the special rules for maintaining archives. A brief description of <TT>mk's</TT> algorithm for deriving dependencies is followed by a discussion of the conventions used to resolve ambiguous specifications. The final sections describe parallel execution and special features. </P> <P> An earlier paper [Hume87] provides a detailed discussion of <TT>mk's</TT> design and an appendix summarizes the differences between <TT>mk</TT> and <TT>make</TT>. </P> <H4>2 The <TT>Mkfile</TT> </H4> <P> <TT>Mk</TT> reads a file describing relationships among files and executes commands to bring the files up to date. The specification file, called a <TT>mkfile</TT>, contains three types of statements: assignments, includes, and rules. Assignment and include statements are similar to those in C. Rules specify dependencies between a <I>target</I> and its <I>prerequisites</I>. When the target and prerequisites are files, their modification times determine if they are out of date. Rules often contain a <I>recipe</I>, an <A href="/magic/man2html/1/rc"><I>rc</I>(1) </A>script that produces the target from the prerequisites. </P> <P> This simple <TT>mkfile</TT> produces an executable from a C source file: <DL><DT><DD><TT><PRE> CC=pcc f1: f1.c $CC -o f1 f1.c </PRE></TT></DL> The first line assigns the name of the portable ANSI/POSIX compiler to the <TT>mk</TT> variable <TT>CC</TT>; subsequent references of the form <TT>$CC</TT> select this compiler. The only rule specifies a dependence between the target file <TT>f1</TT> and the prerequisite file <TT>f1.c</TT>. If the target does not exist or if the prerequisite has been modified more recently than the target, <TT>mk</TT> passes the recipe to <TT>rc</TT> for execution. Here, <TT>f1.c</TT> is compiled and loaded to produce <TT>f1</TT>. </P> <P> The native Plan 9 environment requires executables for all architectures, not only the current one. The Plan 9 version of the same <TT>mkfile</TT> looks like: <DL><DT><DD><TT><PRE> </$objtype/mkfile f1: f1.$O $LD $LDFLAGS -o f1 f1.$O f1.$O: f1.c $CC $CFLAGS f1.c </PRE></TT></DL> The first line is an include statement that replaces itself with the contents of the file <TT>/$objtype/mkfile</TT>. The variable <TT>$objtype</TT> is inherited from the environment and contains the name of the target architecture. The prototype <TT>mkfile</TT> for that architecture defines architecture-specific variables: <TT>CC</TT> and <TT>LD</TT> are the names of the compiler and loader, <TT>O</TT> is the code character of the architecture. The rules compile the source file into an object file and invoke the loader to produce <TT>f1</TT>. Invoking <TT>mk</TT> from the command line as follows <DL><DT><DD><TT><PRE> % objtype=mips mk vc -w f1.c vl $LDFLAGS -o f1 f1.k % </PRE></TT></DL> produces the <TT>mips</TT> executable of program <TT>f1</TT> regardless of the current architecture type. </P> <P> We can extend the <TT>mkfile</TT> to build two programs: <DL><DT><DD><TT><PRE> </$objtype/mkfile ALL=f1 f2 all:V: $ALL f1: f1.$O $LD $LDFLAGS -o f1 f1.$O f1.$O: f1.c $CC $CFLAGS f1.c f2: f2.$O $LD $LDFLAGS -o f2 f2.$O f2.$O: f2.c $CC $CFLAGS f2.c </PRE></TT></DL> The target <TT>all</TT>, modified by the <I>attribute</I> <TT>V</TT>, builds both programs. The attribute identifies <TT>all</TT> as a dummy target that is not related to a file of the same name; its precise effect is explained later. This example describes cascading dependencies: the first target depends on another which depends on a third and so on. Here, individual rules build each program; later we'll see how to do this with a general rule. </P> <H4>3 Variables and the environment </H4> <P> <TT>Mk</TT> does not distinguish between its internal variables and <TT>rc</TT> variables in the environment. When <TT>mk</TT> starts, it imports each environment variable into a <TT>mk</TT> variable of the same name. Before executing a recipe, <TT>mk</TT> exports all variables, including those inherited from the environment, to the environment in which <TT>rc</TT> executes the recipe. </P> <P> There are several ways for a variable to take a value. It can be set with an assignment statement, inherited from the environment, or specified on the command line. <TT>Mk</TT> also maintains several special internal variables that are described in <A href="/magic/man2html/1/mk"><I>mk</I>(1). </A>Assignments have the following decreasing order of precedence: </P> <br> <br> <DL><DT><DD> 1) Command line assignment <br> 2) Assignment statement <br> 3) Imported from the environment <br> 4) Implicitly set by <TT>mk</TT> </DL> <br> <br> For example, a command line assignment overrides a value imported from the environment. <P> All variable values are strings. They can be used for pattern matching and comparison but not for arithmetic. A <I>list</I> is a string containing several values separated by white space. Each member is handled individually during pattern matching, target selection, and prerequisite evaluation. </P> <P> A <I>namelist</I> is a list produced by transforming the members of an existing list. The transform applies a pattern to each member, replacing each matched string with a new string, much as in the substitute command in <A href="/magic/man2html/1/sam"><I>sam</I>(1) </A>or <A href="/magic/man2html/1/ed"><I>ed</I>(1). </A>The syntax is <DL><DT><DD><TT><PRE> ${<I>var</I>:A%B=C%D} </PRE></TT></DL> where <I>var</I> is a variable. The pattern <TT>A%B</TT> matches a member beginning with the string <I>A</I> and ending with the string <I>B</I> with any string in between; it behaves like the regular expression <TT>A.*B</TT>. When a member of the <I>var</I> list matches this pattern, the string <I>C</I> replaces <I>A</I>, <I>D</I> replaces <I>B</I>, and the matched string replaces itself. Any of <I>A</I>, <I>B</I>, <I>C</I>, or <I>D</I> may be the empty string. In effect, a namelist is generated by applying the <A href="/magic/man2html/1/ed"><I>ed</I>(1) </A>substitute command <DL><DT><DD><TT><PRE> s/<I>A</I>(.*)<I>B</I>/<I>C</I>\1<I>D</I>/ </PRE></TT></DL> to each member of a variable list. </P> <P> Namelists are useful for generating a list based on a predictable transformation. For example, <DL><DT><DD><TT><PRE> SRC=a.c b.c c.c OBJ=${SRC:%.c=%.v} </PRE></TT></DL> assigns the list <TT>(a.v b.v c.v)</TT> to <TT>OBJ</TT>. A namelist may be used anywhere a variable is allowed except in a recipe. </P> <P> Command output is assigned to a variable using the normal <TT>rc</TT> syntax: <DL><DT><DD><TT><PRE> var=`{rc command} </PRE></TT></DL> The command executes in an environment populated with previously assigned variables, including those inherited from <TT>mk's</TT> execution environment. The command may be arbitrarily complex; for example, <DL><DT><DD><TT><PRE> TARG=`{ls -d *.[cy] | sed 's/..$//'} </PRE></TT></DL> assigns a list of the C and yacc source files in the current directory, stripped of their suffix, to the variable <TT>TARG</TT>. </P> <H4>4 The include statement </H4> <P> The include statement replaces itself with the contents of a file. It is functionally similar to the C <TT>#include</TT> statement but uses a different syntax: <DL><DT><DD><TT><PRE> <<I>filename</I> </PRE></TT></DL> The contents of the file are evaluated as they are read. An include statement may be used anywhere except in a recipe. </P> <P> Unlike <TT>make</TT>, <TT>mk</TT> has no built-in rules. Instead, the include statement allows generic rules to be imported from a prototype <TT>mkfile</TT>; most Plan 9 <TT>mkfiles</TT> use this approach [Flan95]. </P> <H4>5 Rules </H4> <P> A rule has four elements: targets, prerequisites, attributes, and a recipe. It has the form: <DL><DT><DD><TT><PRE> <I>targets</I>:<I>attributes</I>:<I>prerequisites</I> <I>recipe</I> </PRE></TT></DL> The first line, containing the targets, attributes, and prerequisites is the <I>rule header</I>; it must begin at the left margin. The recipe contains zero or more lines, each of which begins with white space. One or more targets must be specified but the attributes, prerequisites, and recipe are optional. A rule specifies a dependency between the target(s) and its prerequisite(s), the recipe brings the target(s) up to date with the prerequisite(s) and attributes modify <TT>mk's</TT> evaluation of the dependency. </P> <P> Normally the target is a file that depends on one or more prerequisite files. <TT>Mk</TT> compares the modification times of each target and each prerequisite; a target is considered out of date when it does not exist or when a prerequisite has been modified more recently. When a target is out of date, <TT>mk</TT> executes the recipe to bring it up to date. When the recipe completes, the modification time of the target is checked and used in later dependency evaluations. If the recipe does not update the target, evaluation continues with the out of date target. </P> <P> A prerequisite of one rule may be the target of another. When this happens, the rules cascade to define a multi-step procedure. For example, an executable target depends on prerequisite object files, each of which is a target in a rule with a C source file as the prerequisite. <TT>Mk</TT> follows a chain of dependencies until it encounters a prerequisite that is not a target of another rule or it finds a target that is up to date. It then executes the recipes in reverse order to produce the desired target. </P> <P> The rule header is evaluated when the rule is read. Variables are replaced by their values, namelists are generated, and commands are replaced by their output at this time. </P> <P> Most attributes modify <TT>mk's</TT> evaluation of a rule. An attribute is usually a single letter but some are more complicated. This paper only discusses commonly used attributes; see <A href="/magic/man2html/1/mk"><I>mk</I>(1) </A>for a complete list. </P> <P> The <TT>V</TT> attribute identifies a <I>virtual</I> target; that is, a target that is not a file. For example, <DL><DT><DD><TT><PRE> clean:V: rm *.$O $O.out </PRE></TT></DL> removes executables and compiler intermediate files. The target is virtual because it does not refer to a file named <TT>clean</TT>. Without the attribute, the recipe would not be executed if a file named <TT>clean</TT>