123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666 |
- <html>
- <title>
- data
- </title>
- <body BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#0000FF" VLINK="#330088" ALINK="#FF0044">
- <H1>Plan 9 Mkfiles
- </H1>
- <DL><DD><I>Bob Flandrena<br>
- bobf@plan9.bell-labs.com<br>
- </I></DL>
- <H4>Introduction
- </H4>
- <br> <br>
- Every Plan 9 source directory contains a file, called
- <TT>mkfile</TT>,
- specifying the rules for building the executable or
- library that is the product of the directory.
- <A href="/magic/man2html/1/mk"><I>mk</I>(1)
- </A>interprets the rules in the file, calculates
- the dependencies, and executes an
- <A href="/magic/man2html/1/rc"><I>rc</I>(1)
- </A>script to construct the product.
- If necessary components are supplied by
- neighboring directories or sub-directories, the mkfiles in those
- directories are first executed to build the components
- before the local construction proceeds.
- <br> <br>
- Most application source directories produce one of
- four types of product:
- a single executable, several
- executables, a local library, or
- a system library.
- Four generic
- mkfiles
- define the normal rules
- for building each type of product. The simplest
- mkfiles need only
- list the components
- and include the appropriate
- generic
- mkfile
- to do the work.
- More complex
- mkfiles
- may supply additional rules
- to augment, modify, or override the generic rules.
- <H4>Using a Mkfile
- </H4>
- <br> <br>
- To build a product, change to the directory containing
- its source and invoke
- <I>mk</I>
- with the appropriate target as an argument.
- All mkfiles provide the following standard targets:
- <br><img src="data.19114400.gif"><br>
- <br> <br>
- If no target is specified on the
- <TT>mk</TT>
- command line, the
- <TT>all</TT>
- target is built by default. In a directory
- producing multiple executables, there is
- no default target.
- <br> <br>
- In addition to the five standard targets,
- additional targets may be supplied by each
- generic mkfile or by the directory's mkfile.
- <br> <br>
- The environment variable
- <TT>NPROC</TT>
- is set by the system to the number of
- available processors.
- Setting
- this variable, either in the environment or in
- a mkfile, controls the amount of parallelism in
- the build. For example, the command
- <DL><DT><DD><TT><PRE>
- NPROC=1 mk
- </PRE></TT></DL>
- restricts a build to a single thread of execution.
- <H4>Creating a Mkfile
- </H4>
- <br> <br>
- The easiest way to build a new mkfile is to copy and modify
- an existing mkfile of the same type.
- Failing that, it is usually possible to create a new
- mkfile with minimal effort, since the appropriate
- generic mkfile predefines the rules that do all the work.
- In the simplest and most common cases, the new mkfile
- need only define a couple of variables and include the appropriate
- architecture-specific
- and generic mkfiles.
- <H4></H4>
- <br> <br>
- There are four generic mkfiles containing commonly
- used rules for building a product:
- <TT>mkone</TT>,
- <TT>mkmany</TT>,
- <TT>mklib</TT>,
- and
- <TT>mksyslib</TT>.
- These rules
- perform such actions as compiling C source files,
- loading object files, archiving libraries, and
- installing executables in the
- <TT>bin</TT>
- directory of the appropriate architecture.
- The generic mkfiles are stored in directory
- <TT>/sys/src/cmd</TT>.
- Mkfile
- <TT>mkone</TT>
- builds a single executable,
- <TT>mkmany</TT>
- builds several executables from the source in a single
- directory, and
- <TT>mklib</TT>
- and
- <TT>mksyslib</TT>,
- maintain local and system libraries, respectively.
- The rules in the generic mkfiles are driven by
- the values of variables, some of which must be
- set by the product mkfile and some of which are
- supplied by the generic mkfile. Variables in the
- latter class include:
- <br><img src="data.19114401.gif"><br>
- <br> <br>
- The following variables are set by the product mkfile
- and used by the generic mkfile.
- Any may be empty depending on the specific product being
- made.
- <br><img src="data.19114402.gif"><br>
- <H4>Mkfile Organization
- </H4>
- <br> <br>
- All
- mkfiles
- share the following common structure:
- <DL><DT><DD><TT><PRE>
- </<I>objtype/mkfile # </I>architecture-dependent definitions<I>
- <br> <br>
- </I><I>variable definitions</I><I> # TARG</I>, <I>OFILES</I>, <I>HFILES</I>, etc.<I>
- <br> <br>
- </sys/src/cmd/</I><I>generic</I><I> # mkone</I>, <I>mkmany</I>, <I>mklib</I>, or <I>mksyslib
- <br> <br>
- </I><I>variable overrides</I><I> # CFLAGS</I>, <I>objtype</I>, etc.<I>
- <br> <br>
- </I><I>extra rules</I><I> # </I>overrides, augmented rules, additional targets<I>
- </PRE></TT></DL>
- Note that the architecture-dependent mkfiles include file
- </I><TT>/sys/src/mkfile.proto</TT><I>
- for system-wide variables that are common to all architectures.
- </I><br> <br>
- The variables driving the expansion of the generic mkfile
- may be specified in any order as long as they are defined
- before the inclusion of the generic mkfile. The value
- of a variable may be changed by assigning a new value
- following the inclusion of the generic mkfile, but the
- effects are sometimes counter-intuitive.
- Such variable assignments do not apply to the target and
- prerequisite portions of any previously defined rules;
- the new values only apply to the recipes of rules preceding
- the assignment statement and
- to all parts of any rules following it.
- <br> <br>
- The rules supplied by the generic mkfile may
- be overridden or augmented. The new rules must
- be specified after the inclusion of the generic
- mkfile. If the target and prerequisite portion
- of the rule exactly match the target and prerequisite
- portion of a previously defined rule and the new rule contains
- a recipe, the new rule replaces the old one.
- If the target of a new rule exactly matches the
- target of a previous rule and one or more new
- prerequisites are specified and the new rule contains
- no recipe, the new prerequisites are added to the prerequisites
- of the old rule.
- <br> <br>
- Following sections discuss
- each generic mkfile in detail.
- <H4>Mkone
- </H4>
- <br> <br>
- The
- <TT>mkone</TT>
- generic mkfile contains rules for building
- a single executable from one or more files
- in a directory.
- The variable
- <TT>TARG</TT>
- specifies the name of the executable and
- variables
- <TT>OFILES</TT>
- and
- <TT>YFILES</TT>
- specify the object files and
- <TT>yacc</TT>
- source files used to build it.
- <TT>HFILES</TT>
- contains the names of the local header files
- included in all source files.
- <TT>BIN</TT>
- is the name of the directory where the executable
- is installed.
- <TT>LIB</TT>
- contains the names of local libraries used by the
- linker. This variable is rarely needed
- as libraries referenced by a
- <TT>#pragma</TT>
- directive in an associated header file, including
- all system libraries, are automatically
- searched by the loader.
- <br> <br>
- If
- <TT>mk</TT>
- is executed without a target, the
- <TT>all</TT>
- target is built; it
- produces an executable in
- <TT></TT>O.out<TT>.
- Variable
- </TT><TT>HFILES</TT><TT>
- identifies the header files that
- are included in all or most or
- the C source files. Occasionally,
- a program has other header files
- that are only used in some
- source files. A
- header can be added to the prerequisites for
- those object files by adding a rule of
- the following form following the inclusion of generic mkfile
- </TT><TT>mkone</TT><TT>:
- <DL><DT><DD><TT><PRE>
- file.</TT><I>O: header.h
- </PRE></TT></DL>
- </I><br> <br>
- The mkfile for a directory producing a single
- executable using the normal set of rules is
- trivial: a list of some files followed by the
- inclusion of
- <I>mkone.</I>
- For example,
- <TT>/sys/src/cmd/diff/mkfile</TT>
- contains:
- <DL><DT><DD><TT><PRE>
- < /objtype/mkfile
- TARG=diff
- OFILES=\
- diffdir.<I>O\
- diffio.</I>O\
- diffreg.<I>O\
- main.</I>O\
- HFILES=diff.h
- BIN=/<I>objtype/bin
- </sys/src/cmd/mkone
- </PRE></TT></DL>
- The more complex mkfile in
- </I><TT>/sys/src/cmd/awk</TT><I>
- overrides compiler and loader variables to
- select the ANSI/POSIX Computing Environment with appropriately
- defined command line variables. It also overrides
- the default
- </I><TT>yacc</TT><I>
- rule to place the output soure in file
- </I><TT>awkgram.c</TT><I>
- and the
- </I><TT>clean</TT><I>
- and
- </I><TT>nuke</TT><I>
- rules, so it can remove the non-standard intermediate
- files. Finally, the last three rules build a version of
- </I><TT>maketab</TT><I>
- appropriate for the architecture where the
- </I><TT>mk</TT><I>
- is being
- run and then executes it to create source file
- </I><TT>proctab.c</TT><I>:
- <DL><DT><DD><TT><PRE>
- </</I>objtype/mkfile
- TARG=awk
- OFILES=re.<I>O\
- lex.</I>O\
- main.<I>O\
- parse.</I>O\
- proctab.<I>O\
- tran.</I>O\
- lib.<I>O\
- run.</I>O\
- awkgram.<I>O\
- HFILES=awk.h\
- y.tab.h\
- proto.h\
- YFILES=awkgram.y
- BIN=/</I>objtype/bin
- </sys/src/cmd/mkone
- CFLAGS=-c -D_REGEXP_EXTENSION -D_RESEARCH_SOURCE \
- -D_BSD_EXTENSION -DUTF
- YFLAGS=-S -d -v
- CC=pcc
- LD=pcc
- cpuobjtype=`{sed -n 's/^O=//p' /<I>cputype/mkfile}
- y.tab.h awkgram.c: </I>YFILES
- <I>YACC -o awkgram.c </I>YFLAGS <I>prereq
- clean:V:
- rm -f *.[</I>OS] [<I>OS].out [</I>OS].maketab y.tab.? y.debug\
- y.output <I>TARG
- nuke:V:
- rm -f *.[</I>OS] [<I>OS].out [</I>OS].maketab y.tab.? y.debug\
- y.output awkgram.c <I>TARG
- proctab.c: </I>cpuobjtype.maketab
- ./<I>cpuobjtype.maketab >proctab.c
- </I>cpuobjtype.maketab: y.tab.h maketab.c
- objtype=<I>cputype
- mk maketab.</I>cputype
- maketab.<I>cputype:V: y.tab.h maketab.</I>O
- <I>LD -o </I>O.maketab maketab.<I>O
- </PRE></TT></DL>
- </I><H4>Mkmany
- </H4>
- <br> <br>
- The
- <TT>mkmany</TT>
- generic mkfile builds several
- executables from the files in a
- directory. It differs from the operation of
- <TT>mkone</TT>
- in three respects:
- <TT>TARG</TT>
- specifies the names of all executables,
- there is no default command-line target,
- and additional rules allow a single executable to
- be built or installed.
- <br> <br>
- The
- <TT>TARG</TT>
- variable specifies the names of all
- executables produced by the mkfile. The
- rules assume the name of each executable is also
- the name of the file containing its
- <TT>main</TT>
- function.
- <TT>OFILES</TT>
- specifies files containing
- common subroutines loaded with all executables.
- Consider the mkfile:
- <DL><DT><DD><TT><PRE>
- </objtype/mkfile
- TARG=alpha beta
- OFILES=common.<I>O
- BIN=/</I>objtype/bin
- </sys/src/cmd/mkmany
- </PRE></TT></DL>
- It assumes the main functions for executables
- <TT>alpha</TT>
- and
- <TT>beta</TT>
- are in files
- <TT>alpha.</TT><I>O</I><TT>
- and
- </TT><TT>beta.</TT><TT>O</TT><TT>
- and that both programs use the subroutines
- in file
- </TT><TT>common.</TT><I>O</I><TT>.
- The
- </TT><TT>all</TT><TT>
- target builds all executables, leaving each in
- a file with a name of the form
- </TT><TT></TT><TT>O.</TT><I>progname</I><TT></TT><I>
- where
- </I><I>progname</I><I>
- is the name of the executable. In this
- example the
- </I><TT>all</TT><I>
- target produces executables
- </I><TT></TT><I>O.alpha</I><TT>
- and
- </TT><TT></TT><TT>O.beta</TT><TT>.
- </TT><br> <br>
- The
- <TT>mkmany</TT>
- rules provide additional
- targets for building a single
- executable:
- <br><img src="data.19114403.gif"><br>
- <H4>Mklib
- </H4>
- <br> <br>
- The
- <TT>mklib</TT>
- generic mkfile builds a local library.
- Since this form of mkfile constructs no
- executable, the
- <TT>TARG</TT>
- and
- <TT>BIN</TT>
- variables are not needed. Instead, the
- <TT>LIB</TT>
- variable specifies the library
- to be built or updated. Variable
- <TT>OFILES</TT>
- contains the names of the object files to be archived
- in the library. The use of variables
- <TT>YFILES</TT>
- and
- <TT>HFILES</TT>
- does not change. When possible, only the
- out-of-date members of the library are updated.
- <br> <br>
- The variable
- <TT>LIBDIR</TT>
- contains the name of the directory where the
- library is installed; by default it selects
- the current directory. It can be overridden
- by assigning the new directory name after the
- point where
- <TT>mklib</TT>
- is included.
- <br> <br>
- The
- <TT>clean</TT>
- target removes object files and
- <TT>yacc</TT>
- intermediate files but does not touch the
- library. The
- <TT>nuke</TT>
- target removes the library as well as the
- files removed by the
- <TT>clean</TT>
- target. The command
- <DL><DD>
- <TT>mk -s clean all</TT>
- </DL>
- causes the existing library to be updated, or
- created if it doesn't already exist. The command
- <DL><DD>
- <TT>mk -s nuke all</TT>
- </DL>
- forces the library to be rebuilt from scratch.
- <br> <br>
- The mkfile from
- <TT>/sys/src/cmd/upas/libString</TT>
- contains the following specifications to
- build the local library
- <TT>libString.a</TT><I>O</I><TT>
- for the object architecture referenced by
- </TT><TT></TT><TT>O</TT>:<TT></TT>
- <DL><DT><DD><TT><PRE>
- </<I>objtype/mkfile
- LIB=libString.a</I>O
- OFILES= s_alloc.<I>O\
- s_append.</I>O\
- s_array.<I>O\
- s_copy.</I>O\
- s_getline.<I>O\
- s_grow.</I>O\
- s_nappend.<I>O\
- s_parse.</I>O\
- s_read.<I>O\
- s_read_line.</I>O\
- s_tolower.<I>O\
- </sys/src/cmd/mklib
- nuke:V:
- mk clean
- rm -f libString.a[</I>OS]
- </PRE></TT></DL>
- The override of the rule for target
- <TT>nuke</TT>
- removes the libraries for all architectures as
- opposed to the default recipe for this target
- which removes the library for the current architecture.
- <H4>Mksyslib
- </H4>
- <br> <br>
- The
- <TT>mksyslib</TT>
- generic mkfile is similar to the
- <TT>mklib</TT>
- mkfile except that it operates on a system library
- instead of a local library.
- The
- <TT>install</TT>
- and
- <TT>all</TT>
- targets are the same; since there is no local copy of
- the library, all updates are performed on the
- installed library.
- The rule for the
- <TT>nuke</TT>
- target is identical to that of the
- <TT>clean</TT>
- target; unlike the
- <TT>nuke</TT>
- target for local libraries,
- the library is never removed.
- <br> <br>
- No attempt is made to determine if individual library
- members are up-to-date; all members of a
- library are always updated.
- Special targets support manipulation of a single
- object file; the target
- <TT>objfile</TT>
- updates file
- <TT>objfile</TT><TT>.</TT><I>O</I><TT></TT><I>
- in the library of the current architecture and the target
- </I><TT>objfile.all</TT><I>
- updates
- </I><TT>objfile</TT><TT>.</TT><TT>O</TT><TT></TT><TT>
- in the libraries of all architectures.
- </TT><H4>Overrides
- </H4>
- <br> <br>
- The rules provided by a generic mkfile or
- the variables used to control the evaluation
- of those rules may be overridden in most
- circumstances. Overrides
- must be specified in the product mkfile
- after the point where the generic
- mkfile is included; in general, variable
- and rule overrides occupy the end of a
- product mkfile.
- <br> <br>
- The value of a variable is overridden by
- assigning a new value to the variable.
- Most variable overrides modify the
- values of flags or the names of commands executed
- in recipes. For example, the default value of
- <TT>CFLAGS</TT>
- is often overridden or augmented and
- the ANSI/POSIX Computing Environment is selected by
- setting the
- <TT>CC</TT>
- and
- <TT>LD</TT>
- variables to
- <TT>pcc.</TT>
- <br> <br>
- Modifying rules is trickier than modifying
- variables. Additional constraints can be added
- to a rule by specifying the target and
- the new prerequisite. For example,
- <DL><DT><DD><TT><PRE>
- %.<I>O: header.h
- </PRE></TT></DL>
- adds file
- </I><TT>header.h</TT><I>
- the set of prerequisites for all object files.
- There is no mechanism for adding additional
- commands to an existing recipe; if a
- recipe is unsatisfactory, the rule and its recipe
- must be completely overridden.
- A rule is overridden only when the replacement rule
- matches the target and prerequisite portions
- of the original rule exactly. The recipe
- associated with the new rule
- then replaces the recipe of the original rule.
- For example,
- </I><TT>/sys/src/cmd/lex/mkfile</TT><I>
- overrides the default
- </I><TT>installall</TT><I>
- rule to perform the normal loop on all
- architectures and then copy a prototype file
- to the system library directory.
- <DL><DT><DD><TT><PRE>
- </</I>objtype/mkfile
- TARG=lex
- OFILES=lmain.<I>O\
- y.tab.</I>O\
- sub1.<I>O\
- sub2.</I>O\
- header.<I>O\
- HFILES=ldefs.h\
- YFILES=parser.y\
- BIN=/</I>objtype/bin
- </sys/src/cmd/mkone
- installall:V:
- for(objtype in <I>CPUS)
- mk install
- cp ncform /sys/lib/lex
- </PRE></TT></DL>
- Another way to perform the same override is to
- add a dependency to the default
- </I><TT>installall</TT><I>
- rule that executes an additional rule to
- install the prototype file:
- <DL><DT><DD><TT><PRE>
- installall:V: ncform.install
- ncform.install:V:
- cp ncform /sys/lib/lex
- </PRE></TT></DL>
- </I><H4>Special Tricks
- </H4>
- <br> <br>
- Two special cases
- require extra deviousness.
- <br> <br>
- In the first, a file needed to build an
- executable is generated by a program that,
- in turn, is built from a source file that
- is not part of the product. In this case,
- the
- executable must be built for the
- target architecture, but the intermediate
- executable must be built for the architecture
- <TT>mk</TT>
- is executing on. The intermediate executable
- is built by recursively invoking
- <TT>mk</TT>
- with the appropriate target and the
- executing architecture as the target
- architecture. When that
- <TT>mk</TT>
- completes, the intermediate is
- executed to generate the source file to
- complete the build for the target architecture.
- The earlier example of
- <TT>/sys/src/cmd/awk/mkfile</TT>
- illustrates this technique.
- <br> <br>
- Another awkward situation
- occurs when a directory contains
- source to build an executable as
- well as source for auxiliary executables
- that are not to be installed. In this case
- the
- <TT>mkmany</TT>
- generic rules are inappropriate, because
- all executables would be built and installed.
- Instead, use the
- <TT>mkone</TT>
- generic file to build the primary executable
- and provide extra targets to
- build the auxiliary files. This
- approach is also useful when the auxiliary
- files are not executables;
- <TT>/sys/src/cmd/spell/mkfile</TT>
- augments the default rules to build and install the
- <TT>spell</TT>
- executable with
- elaborate rules to generate
- and maintain the auxiliary spelling lists.
- <br> <br>
- <A href=http://www.lucent.com/copyright.html>
- Copyright</A> © 2004 Lucent Technologies Inc. All rights reserved.
- </body></html>
|