[comp.sources.misc] v19i041: dmake - dmake version 3.7, Part20/37

dvadura@watdragon.waterloo.edu (Dennis Vadura) (05/12/91)

Submitted-by: Dennis Vadura <dvadura@watdragon.waterloo.edu>
Posting-number: Volume 19, Issue 41
Archive-name: dmake/part20
Supersedes: dmake-3.6: Volume 15, Issue 52-77

---- Cut Here and feed the following to sh ----
#!/bin/sh
# this is dmake.shar.20 (part 20 of a multipart archive)
# do not concatenate these parts, unpack them in order with /bin/sh
# file dmake/man/dmake.tf continued
#
if test ! -r _shar_seq_.tmp; then
	echo 'Please unpack part 1 first!'
	exit 1
fi
(read Scheck
 if test "$Scheck" != 20; then
	echo Please unpack part "$Scheck" next!
	exit 1
 else
	exit 0
 fi
) < _shar_seq_.tmp || exit 1
if test -f _shar_wnt_.tmp; then
sed 's/^X//' << 'SHAR_EOF' >> 'dmake/man/dmake.tf' &&
This macro gives the set of flags to pass to the shell when
invoking it to execute a single line recipe.  The value of the macro is the
list of flags with a leading switch indicator.  (ie. `-' under UNIX)
.IP \fBSHELLMETAS\fP 1.6i
Each time
.B dmake
executes a single recipe line (not a group recipe) the line is
searched for any occurrence of a character defined in the value of SHELLMETAS.
If such a character is found the recipe line is defined to require a shell
to ensure its correct execution.  In such instances
a shell is used to invoke the recipe line.
If no match is found the recipe line is executed without the use of a shell.
.sp
.PP
There is only one character valued macro defined by \fBdmake\fP:
\fBSWITCHAR\fP contains the switch character used
to introduce options on command lines.  For UNIX its value is '-', and for
MSDOS its value may be '/' or '-'.
The macro is internally defined and is not user setable.
The MSDOS version of \fBdmake\fP attempts to first extract SWITCHAR from an
environment variable of the same name.  If that fails it then attempts to
use the undocumented getswitchar system call, and returns the result of
that.  Under MSDOS version 4.0 you must set the value of the environment
macro SWITCHAR to '/' to obtain predictable behavior.
.PP
All boolean macros currently understood by 
.B dmake
correspond directly to the previously defined attributes.
These macros provide
a second way to apply global attributes, and represent the
preferred method of doing so.  They are used by assigning them a
value.  If the value is not a NULL string then the boolean condition
is set to on.
If the value is a NULL string then the condition is set to off.
There are five conditions defined and they correspond directly to the
attributes of the same name.  Their meanings are defined in the ATTRIBUTES
section above.
The macros are:
\&\fB.EPILOG\fP,
\&\fB.IGNORE\fP,
\&\fB.MKSARGS\fP,
\&\fB.NOINFER\fP,
\&\fB.PRECIOUS\fP,
\&\fB.PROLOG\fP,
\&\fB.SEQUENTIAL\fP,
\&\fB.SILENT\fP,
\&\fB.SWAP\fP, and
\&\fB.USESHELL\fP.
Assigning any of these a non NULL value will globally set
the corresponding attribute to on.
.SH "RUN_TIME MACROS"
These macros are defined
when \fBdmake\fP is making targets, and may take on different values for each
target.  \fB$@\fP is defined to be the full target name, \fB$?\fP is the
list of all out of date prerequisites, \fB$&\fP is the list of all
prerequisites, \fB$>\fP is the name of the library if the current target is a
library member, and
\fB$<\fP is the list of prerequisites specified in the current rule.
If the current target had a recipe inferred then \fB$<\fP is the name of the
inferred prerequisite even if the target had a list of prerequisites supplied
using an explicit rule that did not provide a recipe.  In such situations
\fB$&\fP gives the full list of prerequisites.
.PP
\fB$*\fP is defined as
\fB$(@:db)\fP when making targets with explicit recipes and is defined as the
value of % when making targets whose recipe is the result of an inference.
In the first case \fB$*\fP is the target name with no suffix,
and in the second case, is the value of the matched % pattern from
the associated %-rule.
\fB$^\fP expands to the set of out of date prerequisites taken from the
current value of \fB$<\fP.
In addition to these,
\fB$$\fP expands to $, \fB{{\fP expands to {, \fB}}\fP expands to }, and the
strings \fB<+\fP and \fB+>\fP are recognized
as respectively starting and terminating a text diversion when they appear
literally together in the same input line.
.PP
The difference between $? and $^ can best be illustrated by an example,
consider:
.RS
.sp
.nf
fred.out : joe amy hello
\trules for making fred
X
fred.out : my.c your.h his.h her.h	  # more prerequisites
.fi
.sp
.RE
Assume joe, amy, and my.c are newer then fred.out.  When
.B dmake
executes the recipe for making fred.out the values of the following macros
will be:
.RS
.sp
.nf
.Is "$@ "
.Ii "$@"
--> fred.out
.Ii "$*"
--> fred
.Ii "$?"
--> joe amy my.c  # note the difference between $? and $^
.Ii "$^"
--> joe amy
.Ii "$<"
--> joe amy hello
.Ii "$&"
--> joe amy hello my.c your.h his.h her.h
.fi
.sp
.RE
.SH "FUNCTION MACROS"
.B dmake
supports a full set of functional macros.  One of these, the $(mktmp ...)
macro, is discussed in detail in the TEXT DIVERSION section and is not
covered here.
.RS
.sp
.IP "$(\fBnull\fP,\fItext\fP \fBtrue\fP \fBfalse\fP)"
expands the value of
.I text.
If it is NULL then the macro returns the value of the expansion of \fBtrue\fP
and the expansion of \fBfalse\fP otherwise.  The terms \fBtrue\fP, and
\fBfalse\fP must be strings containing no white\-space.
.IP "$(\fB!null\fP,\fItext\fP \fBtrue\fP \fBfalse\fP)"
Behaves identically to the previous macro except that the 
.B true
string is chosen if the expansion of
.I text
is not NULL.
.IP "$(\fBeq\fP,\fItext_a\fP,\fItext_b\fP \fBtrue\fP \fBfalse\fP)"
expands
.I text_a
and
.I text_b
and compares their results.  If equal it returns the result of the expansion
of the 
.B true
term, otherwise it returns the expansion of the
.B false
term.
.IP "$(\fB!eq\fP,\fItext_a\fP,\fItext_b\fP \fBtrue\fP \fBfalse\fP)"
Behaves identically to the previous macro except that the 
.B true
string is chosen if the expansions of the two strings are not equal
.IP "$(\fBshell\fP \fBcommand\fP)"
Runs \fIcommand\fP as if it were part of a recipe and returns,
separated by a single space, all the non-white
space terms written to stdout by the command.
For example:
.RS
.RS
.sp
$(shell ls *.c)
.sp
.RE
will return \fI"a.c b.c c.c d.c"\fP if the files exist in the current
directory.  The recipe modification flags \fB[+@%-]\fP are honored if they
appear as the first characters in the command.  For example:
.RS
.sp
$(shell +ls *.c)
.sp
.RE
will run the command using the current shell.
.RE
.IP "$(\fBsort\fP \fBlist\fP)"
Will take all white\-space separated tokens in \fIlist\fP and will
return their sorted equivalent list.
.IP "$(\fBstrip\fP \fBdata\fP)"
Will replace all strings of white\-space in data by a single space.
.IP "$(\fBsubst\fP,\fIpat\fP,\fIreplacement\fP \fBdata\fP)"
Will search for \fIpat\fP in
.B data
and will replace any occurrence of
.I pat
with the
.I replacement
string.
.RS
The expansion
.RS
.sp
$(subst,.o,.c $(OBJECTS))
.sp
.RE
is equivalent to:
.RS
.sp
$(OBJECTS:s/.o/.c/)
.sp
.RE
.RE
.SH "DYNAMIC PREREQUISITES"
.B dmake
looks for prerequisites whose names contain macro expansions during target
processing.  Any such prerequisites are expanded and the result of the
expansion is used as the prerequisite name.  As an example the line:
.sp
\tfred : $$@.c
.sp
causes the $$@ to be expanded when \fBdmake\fP is making fred, and it resolves
to the target \fIfred\fP.
This enables dynamic prerequisites to be generated.  The value
of @ may be modified by any of the valid macro modifiers.  So you can say for
example:
.sp
\tfred.out : $$(@:b).c
.sp
where the $$(@:b) expands to \fIfred\fP.
Note the use of $$ instead of $ to indicate the dynamic expansion, this
is due to the fact that the rule line is expanded when it is initially parsed,
and $$ then returns $ which later triggers the dynamic prerequisite expansion.
If you really want a $ to be part of a prerequisite name you must use $$$$.
Dynamic macro expansion is performed in all user defined rules,
and the special targets .SOURCE*, and .INCLUDEDIRS.
.SH "BINDING TARGETS"
This operation takes a target name and binds it to an existing file, if
possible.
.B dmake
makes a distinction between the internal target name of a target and its
associated external file name.
Thus it is possible for a target's internal name and its external
file name to differ.
To perform the binding, the following set of rules is used.
Assume that we are
trying to bind a target whose name is of the form \fIX.suff\fP,
where \fI.suff\fP is the suffix and \fIX\fP is the stem portion
(ie. that part which contains the directory and the basename).
.B dmake
takes this target name and performs a series of search operations that try to
find a suitably named file in the external file system.
The search operation is user controlled
via the settings of the various .SOURCE targets.
.RS
.IP 1.
If target has the .SYMBOL attribute set then look for it in the library.
If found, replace the target name with the library member name and continue
with step 2.  If the name is not found then return.
.IP 2.
Extract the suffix portion (that following the `.') of the target name.
If the suffix is not null, look up the special target .SOURCE.<suff>
(<suff> is the suffix).  
If the special target exists then search each directory given in
the .SOURCE.<suff> prerequisite list for the target.
If the target's suffix was null (ie. \fI.suff\fP was empty) then 
perform the above search but use the special target .SOURCE.NULL instead.
If at any point a match is found then terminate the search.
If a directory in the prerequisite list is the special name `.NULL ' perform
a search for the full target name without prepending any directory portion
(ie. prepend the NULL directory).
(a default target of '.SOURCE : .NULL' is defined by \fBdmake\fP at startup,
and is user redefinable)
.IP 3.
The search in step 2. failed.  Repeat the same search but this time
use the special target .SOURCE.
.IP 4.
The search in step 3. failed.
If the target has the library member attribute (.LIBMEMBER)
set then try to find the target in the library which was passed along
with the .LIBMEMBER attribute (see the MAKING LIBRARIES section).
The bound file name assigned to a target which is successfully
located in a library is the same name that would be assigned had the search
failed (see 5.).
.IP 5.
The search failed.  Either the target was not found in any of the search
directories or no applicable .SOURCE special targets exist.
If applicable .SOURCE special targets exist, but the target was not found,
then \fBdmake\fP assigns the first name searched as the bound file name.
If no applicable .SOURCE special targets exist,
then the full original target name becomes the bound file name.
.RE
.PP
There is potential here for a lot of search operations.  The trick is to
define .SOURCE.x special targets with short search lists and leave .SOURCE
as short as possible.
The search algorithm has the following useful side effect.
When a target having the .LIBMEMBER (library member) attribute is searched for,
it is first searched for as an ordinary file.
When a number of library members require updating it is desirable to compile
all of them first and to update the library at the end in a single operation.
If one of the members does not compile and \fBdmake\fP stops, then
the user may fix the error and make again.  \fBdmake\fP will not remake any
of the targets whose object files have already been generated as long as
none of their prerequisite files have been modified as a result of the fix.
.PP
When defining .SOURCE and .SOURCE.x targets the construct
.sp
\t.SOURCE :
.br
\t.SOURCE : fred gery
.sp
is equivalent to
.sp
\t.SOURCE :- fred gery
.PP
\fBdmake\fP correctly handles the UNIX Make variable VPATH.  By definition VPATH
contains a list of ':' separated directories to search when looking for a
target.  \fBdmake\fP maps VPATH to the following special rule:
.sp
\t.SOURCE :^ $(VPATH:s/:/ /)
.sp
Which takes the value of VPATH and sets .SOURCE to the same set of directories
as specified in VPATH.
.SH "PERCENT(%) RULES AND MAKING INFERENCES"
When \fBdmake\fP makes a target, the target's set of prerequisites (if any)
must exist and the target must have a recipe which \fBdmake\fP
can use to make it.
If the makefile does not specify an explicit recipe for the target then
.B dmake
uses special rules to try to infer a recipe which it can use
to make the target.  Previous versions of Make perform this task by using
rules that are defined by targets of the form .<suffix>.<suffix> and by
using the .SUFFIXES list of suffixes.  The exact workings of this mechanism
were sometimes difficult to understand and often limiting in their usefulness.
Instead, \fBdmake\fP supports the concept of \fI%-meta\fP rules.  
The syntax and semantics of these rules differ from standard rule lines as
follows:
.sp
.nf
.RS
\fI<%-target>\fP [\fI<attributes>\fP] \fI<ruleop>\fP [\fI<%-prerequisites>\fP] [;\fI<recipe>\fP]
.RE
.fi
.sp
where \fI%-target\fP is a target containing exactly a single `%' sign,
.I attributes
is a list (possibly empty) of attributes,
.I ruleop
is the standard set of rule operators,
.I "%-prerequisites"
\&, if present, is a list of prerequisites containing zero or more `%' signs,
and
.I recipe,
if present, is the first line of the recipe.
.PP
The
.I %-target
defines a pattern against which a target whose recipe is
being inferred gets matched.  The pattern match goes as follows:  all chars are
matched exactly from left to right up to but not including the % sign in the
pattern, % then matches the longest string from the actual target name
not ending in
the suffix given after the % sign in the pattern.
Consider the following examples:
.RS
.sp
.nf
.Is "dir/%.c   "
.Ii "%.c"
matches fred.c but not joe.c.Z
.Ii "dir/%.c"
matches dir/fred.c but not dd/fred.c
.Ii "fred/%"
matches fred/joe.c but not f/joe.c
.Ii "%"
matches anything
.fi
.sp
.RE
In each case the part of the target name that matched the % sign is retained
and is substituted for any % signs in the prerequisite list of the %-meta rule
when the rule is selected during inference and
.B dmake
constructs the new dependency.
As an example the following %-meta rules describe the following:
.RS
.sp
%.c : %.y ; recipe...
.sp
.RE
describes how to make any file ending in .c if a corresponding file ending
in .y can be found.
.RS
.sp
foo%.o : fee%.k ; recipe...
.sp
.RE
is used to describe how to make fooxxxx.o from feexxxx.k.
.RS
.sp
%.a :; recipe...
.sp
.RE
describes how to make a file whose suffix is .a without inferring any
prerequisites.
.RS
.sp
%.c : %.y yaccsrc/%.y ; recipe...
.sp
.RE
is a short form for the construct:
.RS
.sp
%.c : %.y ; recipe...
.br
%.c : yaccsrc/%.y ; recipe...
.sp
.RE
ie. It is possible to specify the same recipe for two %-rules by giving
more than one prerequisite in the prerequisite list.
A more interesting example is:
.RS
.sp
% : RCS/%,v ; co $@
.sp
.RE
which describes how to take any target and check it out of
the RCS directory if the corresponding file exists in the RCS directory.
The equivalent SCCS rule would be:
.RS
.sp
% : s.% ; get $@
.sp
.RE
.PP
The previous RCS example defines an infinite rule, because it says how to make
.I anything
from RCS/%,v, and
.I anything
also includes RCS/fred.c,v.
To limit the size of the graph that results from such rules
.B dmake
uses the macro variable PREP (stands for % repetition).  By default the value
of this variable is 0, which says that no repetitions of a %-rule are to be
generated.  If it is set to something greater than 0, then that many
repetitions of any infinite %-rule are allowed.  If in the above
example PREP was set to 1, then \fBdmake\fP would generate the dependency
graph:
.RS
.sp
% --> RCS/%,v --> RCS/RCS/%,v,v
.sp
.RE
Where each link is assigned the same recipe as the first link.
PREP should be used only in special cases, since it may result in
a large increase in the number of possible prerequisites tested.
.B dmake
further assumes that any target that has no suffix can be made from
a prerequisite that has at least one suffix.
.PP
.B dmake
supports dynamic prerequisite generation for prerequisites of %-meta rules.
This is best illustrated by an example.  The RCS rule shown above can infer
how to check out a file from a corresponding RCS file only if the target
is a simple file name with no directory information.  That is, the above rule
can infer how to find \fIRCS/fred.c,v\fP from the target \fIfred.c\fP,
but cannot infer how to find \fIsrcdir/RCS/fred.c,v\fP from \fIsrcdir/fred.c\fP
because the above rule will cause \fBdmake\fP to look for RCS/srcdir/fred.c,v;
which does not exist (assume that srcdir has its own RCS directory as is the
common case).
.PP
A more versatile formulation of the above RCS check out rule is the following:
.RS
.sp
% :  $$(@:d)RCS/$$(@:f),v : co $@
.sp
.RE
This rule uses the dynamic macro $@ to specify the prerequisite to try to
infer.  During inference of this rule the macro $@ is set to the value of
the target of the %-meta rule and the appropriate prerequisite is generated by
extracting the directory portion of the target name (if any), appending the
string \fIRCS/\fP to it, and appending the target file name with a trailing
\fI,v\fP attached to the previous result.
.PP
.B dmake
can also infer indirect prerequisites.
An inferred target can have a list of prerequisites added that will not
show up in the value of $< but will show up in the value of $? and $&.
Indirect prerequisites are specified in an inference rule by quoting the
prerequisite with single quotes.  For example, if you had the explicit
dependency:
.RS
.sp
.nf
fred.o : fred.c ; rule to make fred.o
fred.o : local.h
.fi
.sp
.RE
then this can be inferred for fred.o from the following inference rule:
.RS
.sp
%.o : %.c 'local.h' ; rule to make a .o from a .c
.sp
.RE
You may infer indirect prerequisites that are a function of the value of '%'
in the current rule.  The meta-rule:
.RS
.sp
%.o : %.c '$(INC)/%.h' ; rule to make a .o from a .c
.sp
.RE
infers an indirect prerequisite found in the INC directory whose name is the
same as the expansion of $(INC), and the prerequisite name depends on the
base name of the current target.
The set of indirect prerequisites is attached to the meta rule in which they
are specified and are inferred only if the rule is used to infer a recipe
for a target.  They do not play an active role in driving the inference
algorithm.
The construct:
.RS
.sp
%.o : %.c %.f 'local.h'; recipe
.sp
.RE
is equivalent to:
.RS
.sp
.nf
%.o : %.c 'local.h' : recipe
%.o : %.f 'local.h' : recipe
.fi
.sp
.RE
.PP
If any of the attributes .SETDIR, .EPILOG, .PROLOG, .SILENT,
\&.USESHELL, .SWAP, .PRECIOUS, .LIBRARY, .NOSTATE and .IGNORE
are given for a %-rule then when that rule is bound to a target
as the result of an inference, the target's set of attributes is augmented by
the attributes from the above set that are specified in the bound %-rule.
Other attributes specified for %-meta rules are not inherited by the target.
The .SETDIR attribute is treated in a special way.
If the target already had a .SETDIR attribute set then
.B dmake
changes to that directory prior to performing the inference.
During inference any .SETDIR attributes for the inferred prerequisite
are honored.
The directories must exist for a %-meta rule to be selected as a possible
inference path.  If the directories do not exist no error message is issued,
instead the corresponding path in the inference graph is rejected.
.PP
.B dmake
also supports the old format special target .<suffix>.<suffix>
by identifying any rules
of this form and mapping them to the appropriate %-rule.  So for example if
an old makefile contains the construct:
.RS
.sp
\&.c.o :; cc -c $< -o $@
.sp
.RE
.B dmake
maps this into the following %-rule:
.RS
.sp
%.o : %.c; cc -c $< -o $@
.sp
.RE
Furthermore,
.B dmake
understands several SYSV AUGMAKE special targets and maps them into
corresponding %-meta rules.  These transformation must be enabled by providing
the -A flag on the command line or by setting the value of AUGMAKE to
non\-NULL.
The construct
.RS
.sp
\&.suff :; recipe
.sp
.RE
gets mapped into:
.RS
.sp
% : %.suff; recipe
.sp
.RE
and the construct
.RS
.sp
\&.c~.o :; recipe
.sp
.RE
gets mapped into:
.RS
.sp
%.o : s.%.c ; recipe
.sp
.RE
In general, a special target of the form .<str>~ is replaced by the %-rule
construct s.%.<str>, thereby providing support for the syntax used by SYSV
AUGMAKE for providing SCCS support.
When enabled, these mappings allow processing of existing SYSV
makefiles without modifications.
.PP
.B dmake
bases all of its inferences on the inference graph constructed from the
%-rules defined in the makefile.
It knows exactly which targets can be made from which prerequisites by
making queries on the inference graph.  For this reason .SUFFIXES is not
needed and is completely ignored.
.PP
For a %-meta rule to be inferred as the
rule whose recipe will be used to make a target, the target's name must match
the %-target pattern, and any inferred %-prerequisite must already exist or
have an explicit recipe so that the prerequisite can be made.
Without \fItransitive closure\fP on the inference graph the above rule
describes precisely when an inference match terminates the search.
If transitive closure is enabled (the usual case), and a prerequisite does
not exist or cannot be made, then
.B dmake
invokes the inference algorithm recursively on the prerequisite to see if
there is some way the prerequisite can be manufactured.  For, if the
prerequisite can be made then the current target can also be made using the
current %-meta rule.
This means that there is no longer a need to give a rule
for making a .o from a .y if you have already given a rule for making a .o
from a .c and a .c from a .y.  In such cases
.B dmake
can infer how to make the
\&.o from the .y via the intermediary .c and will remove the .c when the .o is
made.  Transitive closure can be disabled by giving the -T switch on the
command line.
.PP
A word of caution.
.B dmake
bases its transitive closure on the %-meta rule targets.
When it performs transitive closure it infers how to make a target from a
prerequisite by performing a pattern match as if the potential prerequisite
were a new target.
The set of rules:
.RS
.nf
.sp
%.o : %.c :; rule for making .o from .c
%.c : %.y :; rule for making .c from .y
% : RCS/%,v :; check out of RCS file
.fi
.sp
.RE
will, by performing transitive closure, allow \fBdmake\fP to infer how to make
a .o from a .y using a .c as an intermediate temporary file.  Additionally
it will be able to infer how to make a .y from an RCS file, as long as that
RCS file is in the RCS directory and has a name which ends in .y,v.
The transitivity computation is performed dynamically for each target that
does not have a recipe.  This has potential to be costly if the %-meta
rules are not carefully specified.  The .NOINFER attribute is used to mark
a %-meta node as being a final target during inference.  Any node with this
attribute set will not be used for subsequent inferences.  As an example
the node RCS/%,v is marked as a final node since we know that if the RCS file
does not exist there likely is no other way to make it.  Thus the standard
startup makefile contains an entry similar to:
.RS
.nf
\&.NOINFER : RCS/%,v
.fi
.RE
Thereby indicating that the RCS file is the end of the inference chain.
X
Whenever the inference algorithm determines that a target can be made from
more than one prerequisite and the inference chains for the two methods
are the same length the algorithm reports an ambiguity and prints the
ambiguous inference chains.
.PP
.B dmake
tries to
remove intermediate files resulting from transitive closure if the file
is not marked as being PRECIOUS, or the \fB-u\fP flag was not given on the
command line, and if the inferred intermediate did not previously exist.
Intermediate targets that existed prior to being made are never removed.
This is in keeping with the philosophy that
.B dmake
should never remove things from the file system that it did not add.
If the special target .REMOVE is defined and has a recipe then
.B dmake
constructs a list of the intermediate files to be removed and makes them
prerequisites of .REMOVE.  It then makes .REMOVE thereby removing the
prerequisites if the recipe of .REMOVE says to.  Typically .REMOVE is defined
in the startup file as:
.sp
\t.REMOVE :; $(RM) $<
.SH "MAKING TARGETS"
In order to update a target \fBdmake\fP must execute a recipe.
When a recipe needs to be executed it is first expanded so that any macros
in the recipe text are expanded, and it is then either executed directly or
passed to a shell.
.B dmake
supports two types of recipes.  The regular recipes and group recipes.
.PP
When a regular recipe is invoked \fBdmake\fP executes each line of the recipe
separately using a new copy of a shell if a shell is required.
Thus effects of commands do not generally persist across recipe lines.
(e.g. cd requests in a recipe line do not carry over to the next recipe line)
The decision on whether a shell is required to execute a command is based on
the value of the macro SHELLMETAS or on the specification of '+' or .USESHELL
for the current recipe or target respectively.
If any character in the value of
SHELLMETAS is found in the expanded recipe text-line or the use of a shell
is requested explicitly via '+' or .USESHELL then the command is
executed using a shell, otherwise the command is executed directly.
The shell that is used for execution is given by the value of the macro SHELL.
The flags that are passed to the shell are given by the value of SHELLFLAGS.
Thus \fBdmake\fP constructs the command line:
.sp
\t$(SHELL) $(SHELLFLAGS) $(expanded_recipe_command)
.sp
Normally
.B dmake
writes the command line that it is about to invoke to standard output.
If the .SILENT attribute is set for the target or for
the recipe line (via @), then the recipe line is not echoed.
.PP
Group recipe processing is similar to that of regular recipes, except that
a shell is always invoked.  The shell that is invoked is given by the value of
the macro GROUPSHELL, and its flags are taken from the value of the macro
GROUPFLAGS.  If a target has the .PROLOG attribute set then
.B dmake
prepends to the shell script the recipe associated with the special target
\&.GROUPPROLOG, and if the attribute .EPILOG is set as well, then the recipe
associated with the special target .GROUPEPILOG is appended to the script
file.
This facility can be used to always prepend a common header and common trailer
to group recipes.
Group recipes are echoed to standard output just like standard recipes, but
are enclosed by lines beginning with [ and ].
.PP
The recipe flags [+,-,%,@] are recognized at the start of a recipe line
even if they appear in a macro.  For example:
.RS
.sp
.nf
SH = +
all:
\t$(SH)echo hi
.fi
.sp
.RE
is completely equivalent to writing
.RS
.sp
.nf
SH = +
all:
\t+echo hi
.fi
.sp
.RE
.PP
The last step performed by
.B dmake
prior to running a recipe is to set the macro CMNDNAME to the name of the
command to execute (determined by finding the first white\-space ending token
in the command line).  It then sets the macro CMNDARGS to be the remainder
of the line.
.B dmake
then expands the macro COMMAND which by default is set to
.RS
.sp
COMMAND = $(CMNDNAME) $(CMNDARGS)
.sp
.RE
The result of this final expansion is the command that will be executed.
The reason for this expansion is to allow for a different interface to
the argument passing facilities (esp. under DOS) than that provided by
.B dmake\fR.\fP
You can for example define COMMAND to be
.RS
.sp
COMMAND = $(CMNDNAME) @$(mktmp $(CMNDARGS))
.sp
.RE
which dumps the arguments into a temporary file and runs the command
.RS
.sp
$(CMNDNAME) @/tmp/ASAD23043
.sp
.RE
which has a much shorter argument list.  It is now up to the command to
use the supplied argument as the source for all other arguments.
As an optimization, if COMMAND is not defined
.B dmake
does not perform the above expansion.  On systems, such as UNIX, that
handle long command lines this provides a slight saving in processing the
makefiles.
.SH "MAKING LIBRARIES"
Libraries are easy to maintain using \fBdmake\fP.  A library is a file
containing a collection of object files.
Thus to make a library you simply specify it as a target with the .LIBRARY
attribute set and specify its list of prerequisites.  The prerequisites should
be the object members that are to go into the library.  When
.B dmake
makes the library target it uses the .LIBRARY attribute to pass to the
prerequisites the .LIBMEMBER attribute and the name of the library.  This
enables the file binding mechanism to look for the member in the library if an
appropriate object file cannot be found. A small example best illustrates
this.
.RS
.nf
.sp
mylib.a .LIBRARY : mem1.o mem2.o mem3.o
\trules for making library...
\t# remember to remove .o's when lib is made
.sp
# equivalent to:  '%.o : %.c ; ...'
\&.c.o :; rules for making .o from .c say
.sp
.fi
.RE
.B dmake
will use the .c.o rule for making the library members if appropriate .c files
can be found using the search rules.  NOTE:  this is not specific in any way
to C programs, they are simply used as an example.
.PP
.B dmake
tries to handle the old library construct format in a sensible way.
The construct 
.I lib(member.o)
is separated and the \fIlib\fP portion is declared
as a library target.
The new target is defined
with the .LIBRARY attribute set and the \fImember.o\fP portion of the
construct is
declared as a prerequisite of the lib target.
If the construct \fIlib(member.o)\fP
appears as a prerequisite of a target in the
makefile, that target has the new name of the lib assigned as its
prerequisite.  Thus the following example:
.RS
.sp
.nf
a.out : ml.a(a.o) ml.a(b.o); $(CC) -o $@  $<
X
\&.c.o :; $(CC) -c $(CFLAGS) -o $@  $<
%.a:
\tar rv $@ $<
\tranlib $@
\trm -rf $<
.sp
.fi
.RE
constructs the following dependency
graph.
.RS
.sp
.nf
a.out : ml.a; $(CC) -o $@  $<
ml.a .LIBRARY : a.o b.o
X
%.o : %.c ; $(CC) -c $(CFLAGS) -o $@  $<
%.a :
\tar rv $@ $<
\tranlib $@
\trm -rf $<
.sp
.fi
.RE
and making a.out then works as expected.
.PP
The same thing happens for any target of the form \fIlib((entry))\fP.
These targets have an
additional feature in that the \fIentry\fP target has the .SYMBOL attribute
set automatically.
.PP
NOTE:  If the notion of entry points is supported by the archive and by
\fBdmake\fP (currently not the case) then
.B dmake
will search the archive for the entry point and return not only the
modification time of the member which defines the entry but also the name of
the member file.  This name will then replace \fIentry\fP and will be used for
making the member file.  Once bound to an archive member the .SYMBOL
attribute is removed from the target.
This feature is presently disabled as there is little standardization
among archive formats, and we have yet to find a makefile utilizing this
feature (possibly due to the fact that it is unimplemented in most versions
of UNIX Make).
.PP
Finally, when
.B dmake
looks for a library member it must first locate the library file.
It does so by first looking for the library relative to the current directory
and if it is not found it then looks relative to the current value of
$(TMD).  This allows commonly used libraries to be kept near the root of
a source tree and to be easily found by
.B dmake\fR.\fP
.SH "KEEP STATE"
.B dmake
supports the keeping of state information for targets that it makes whenever
the macro .KEEP_STATE is assigned a value.  The value of the macro should be
the name of a state file that will contain the state information.  If state
keeping is enabled then each target that does not poses the .NOSTATE
attribute will have a record written into the state file indicating the
target's name, the current directory, the command used to update the target,
and which, if any, :: rule is being used.  When you make this target again
if any of this information does not match the previous settings and the
target is not out dated it will still be re\-made.  The assumption is that one
of the conditions above has changed and that we wish to remake the target.
For example,
state keeping is used in the maintenance of
.B dmake
to test compile different versions of the source using different compilers.
Changing the compiler causes the compilation flags to be modified and hence
all sources to be recompiled.
.PP
The state file is an ascii file and is portable, however it is
not in human readable form as the entries represent hash keys of the above
information.
.PP
The Sun Microsystem's Make construct
.RS
.sp
\&.KEEP_STATE :
.sp
.RE
is recognized and is mapped to \fB.KEEP_STATE:=_state.mk\fP.
The
.B dmake
version of state keeping does not include scanning C source files for
dependencies like Sun Make.  This is specific to C programs and it was
felt that it does not belong in make.
.B dmake
instead provides the tool, \fBcdepend\fP, to scan C source files and to produce
depedency information.  Users are free to modify cdepend to produce other
dependency files.  (NOTE:
.B cdepend
does not come with the distribution at this time, but will be available in
a patch in the near future)
.SH "MULTI PROCESSING"
If the architecture supports it then \fBdmake\fP is capable of making a target's
prerequisites in parallel.  \fBdmake\fP will make as much in parallel as it
can and use a number of child processes up to the maximum specified by
MAXPROCESS or by the value supplied to the -P command line flag.
A parallel make is enabled by setting the value of MAXPROCESS (either directly
or via -P option) to a value which is > 1.
\fBdmake\fP guarantees that all dependencies as specified in the makefile are
honored.  A target will not be made until all of its prerequisites have been
made.
If a parallel make is being performed then the following restrictions on
parallelism are enforced.
.RS
.IP 1.
Individual recipe lines in a non-group recipe are performed sequentially in
the order in which they are specified within the makefile and in parallel with
the recipes of other targets.
.IP 2.
If a target contains multiple recipe definitions (cf. :: rules) then these are
performed sequentially in the order in which the :: rules are specified within
the makefile and in parallel with the recipes of other targets.
.IP 3.
If a target rule contains the `!' modifier, then the recipe is performed
sequentially for the list of outdated prerequisites and in parallel with the recipes of other targets.
.IP 4.
If a target has the .SEQUENTIAL attribute set then all of its prerequisites
are made sequentially relative to one another (as if MAXPROCESS=1), but in
parallel with other targets in the makefile.
.RE
.PP
Note:  If you specify a parallel make then
the order of target update and the order in which the associated recipes are
invoked will not correspond to that displayed by the -n flag.
.SH "CONDITIONALS"
.B dmake
supports a makefile construct called a \fIconditional\fR.  It allows
the user
to conditionally select portions of makefile text for input processing
and to discard other portions.  This becomes useful for
writing makefiles that are intended to function for more than one target
host and environment.  The conditional expression is specified as follows:
.sp
.RS
.nf
\&.IF  \fIexpression\fR
X   ... if text ...
\&.ELIF  \fIexpression\fR
X   ... if text ...
\&.ELSE
X   ... else text ...
\&.END
.RE
.fi
.sp
The .ELSE and .ELIF portions are optional, and the conditionals may be
nested (ie.  the text may contain another conditional).
\&.IF, .ELSE, and .END
may appear anywhere in the makefile, but a single conditional expression
may not span multiple makefiles.
.PP
\fIexpression\fR can be one of the following three forms:
.sp
\t<text> | <text> == <text> | <text> != <text>
.sp
where \fItext\fR is either text or a macro expression.  In any case,
before the comparison is made, the expression is expanded.  The text
portions are then selected and compared.  White space at the start and
end of the text portion is discarded before the comparison.  This means
that a macro that evaluates to nothing but white space is considered a
NULL value for the purpose of the comparison.
In the first case the expression evaluates TRUE if the text is not NULL
otherwise it evaluates FALSE.  The remaining two cases both evaluate the
expression on the basis of a string comparison.
If a macro expression needs to be equated to a NULL string then compare it to
the value of the macro $(NULL).
You can use the $(shell ...) macro to construct more complex test expressions.
.SH "EXAMPLES"
.RS
.nf
.sp
# A simple example showing how to use make
#
prgm : a.o b.o
X	cc a.o b.o -o prgm
a.o : a.c g.h
X	cc a.c -o $@
b.o : b.c g.h
X	cc b.c -o $@
.fi
.RE
.sp
In the previous
example prgm is remade only if a.o and/or b.o is out of date with
respect to prgm.
These dependencies can be stated more concisely
by using the inference rules defined in the standard startup file.
The default rule for making .o's from .c's looks something like this:
.sp
\&\t%.o : %.c; cc -c $(CFLAGS) -o $@ $<
.sp
Since there exists a rule (defined in the startup file)
for making .o's from .c's
\fBdmake\fR will use that rule
for manufacturing a .o from a .c and we can specify our dependencies
more concisely.
.sp
.RS
.nf
prgm : a.o b.o
X	cc -o prgm $<
a.o b.o : g.h
.fi
.RE
.sp
A more general way to say the above using the new macro expansions
would be:
.sp
.RS
.nf
SRC = a b
OBJ = {$(SRC)}.o
.sp
prgm : $(OBJ)
X	cc -o $@ $<
.sp
$(OBJ) : g.h
.fi
.RE
.sp
If we want to keep the objects in a separate directory, called
objdir, then we would write
something like this.
.sp
.RS
.nf
SRC = a b
OBJ = {$(SRC)}.o
.sp
prgm : $(OBJ)
X	cc $< -o $@
.sp
$(OBJ) : g.h
\&%.o : %.c
X	$(CC) -c $(CFLAGS) -o $(@:f) $<
X	mv $(@:f) objdir
X
\&.SOURCE.o : objdir		# tell make to look here for .o's
.fi
.RE
.sp
An example of building library members would go something like this:
(NOTE:  The same rules as above will be used to produce .o's from .c's)
.sp
.RS
.nf
SRC\t= a b
LIB\t= lib
LIBm\t= { $(SRC) }.o
.sp
prgm: $(LIB)
X	cc -o $@ $(LIB)
.sp
$(LIB) .LIBRARY : $(LIBm)
X	ar rv $@ $<
X	rm $<
.fi
.RE
.sp
Finally, suppose that each of the source files in the previous example had
the `:' character in their target name.  Then we would write the above example
as:
.sp
.RS
.nf
SRC\t= f:a f:b
LIB\t= lib
LIBm\t= "{ $(SRC) }.o"		# put quotes around each token
.sp
prgm: $(LIB)
X	cc -o $@ $(LIB)
.sp
$(LIB) .LIBRARY : $(LIBm)
X	ar rv $@ $<
X	rm $<
.fi
.RE
.SH "COMPATIBILITY"
There are two notable differences between 
.B \fBdmake\fR
and the standard version of BSD UNIX 4.2/4.3 Make.
.RS
.IP 1. .3i
BSD UNIX 4.2/4.3 Make supports wild card filename expansion for
prerequisite names.  Thus if a directory contains a.h, b.h and c.h, then a
line like
.sp
\ttarget: *.h
.sp
will cause UNIX make to expand the *.h into "a.h b.h c.h".  \fBdmake\fR
does not support this type of filename expansion.
.IP 2. .3i
Unlike UNIX make, touching a library member causes \fBdmake\fR
to search the library for the member name and to update the library time stamp.
This is only implemented in the UNIX version.
MSDOS and other versions may not have librarians that keep file time stamps,
as a result \fBdmake\fR touches the library file itself, and prints a warning.
.RE
.PP
\fBdmake\fP is not compatible with GNU Make.  In particular it does not
understand GNU Make's macro expansions that query the file system.
.PP
.B dmake
is fully compatible with SYSV AUGMAKE, and supports the following AUGMAKE
features:
.RS
.IP 1. .3i
The word \fBinclude\fP appearing at the start of a line can be used instead of
the ".INCLUDE :" construct understood by \fBdmake\fP.
.IP 2. .3i
The macro modifier expression $(macro:str=sub) is understood and is equivalent
to the expression $(macro:s/str/sub), with the restriction that str must match
the following regular expression:
.sp
\tstr[ |\\t][ |\\t]*
.sp
(ie. str only matches at the end of a token where str is a suffix and is
terminated by a space, a tab, or end of line)
.IP 3.
The macro % is defined to be $@ (ie. $% expands to the same value as $@).
.IP 4.
The AUGMAKE notion of libraries is handled correctly.
.IP 5.
When defining special targets for the inference rules and the AUGMAKE special
target handling is enabled then the special target
\&.X is equivalent to the %-rule "% : %.X".
.IP 6.
Directories are always made if you specify \fB-A\fP.  This is consistent
with other UNIX versions of Make.
.IP 7.
Makefiles that utilize virtual targets to force making of other targets work
SHAR_EOF
true || echo 'restore of dmake/man/dmake.tf failed'
fi
echo 'End of part 20, continue with part 21'
echo 21 > _shar_seq_.tmp
exit 0

exit 0 # Just in case...
-- 
Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
Sterling Software, IMD           UUCP:     uunet!sparky!kent
Phone:    (402) 291-8300         FAX:      (402) 291-4362
Please send comp.sources.misc-related mail to kent@uunet.uu.net.