DMAKE(p)             Unsupported Free Software            DMAKE(p)



NNAAMMEE
     ddmmaakkee - maintain program groups, or interdependent files

SSYYNNOOPPSSIISS
     ddmmaakkee [-P#] [-{f|C|K} file] [-{w|W} target ...]
     [macro[[!][*][+][:]]=_v_a_l_u_e ...] [-v{cdfimt}]
     [-ABcdeEghiknpqrsStTuVxX] [target ...]

DDEESSCCRRIIPPTTIIOONN
     ddmmaakkee is a re-implementation of the UNIX Make utility with
     significant enhancements.  ddmmaakkee executes commands found in
     an external file called a _m_a_k_e_f_i_l_e to update one or more
     target names.  Each target may depend on zero or more prere-
     quisite targets.  If any of the target's prerequisites is
     newer than the target or if the target itself does not
     exist, then ddmmaakkee will attempt to make the target.

     If no --ff command line option is present then ddmmaakkee searches
     for an existing _m_a_k_e_f_i_l_e from the list of prerequisites
     specified for the special target _._M_A_K_E_F_I_L_E_S (see the STARTUP
     section for more details).  If "-" is the name of the file
     specified to the --ff flag then ddmmaakkee uses standard input as
     the source of the makefile text.

     Any macro definitions (arguments with embedded "=" signs)
     that appear on the command line are processed first and
     supercede definitions for macros of the same name found
     within the makefile.  In general it is impossible for defin-
     itions found inside the makefile to redefine a macro defined
     on the command line, see the MACROS section for exceptions.

     If no _t_a_r_g_e_t names are specified on the command line, then
     ddmmaakkee uses the first non-special target found in the
     makefile as the default target.  See the SSPPEECCIIAALL TTAARRGGEETTSS
     section for the list of special targets and their function.
     Makefiles written for most previous versions of _M_a_k_e will be
     handled correctly by ddmmaakkee.. Known differences between ddmmaakkee
     and other versions of make are discussed in the CCOOMMPPAATTIIBBIILL----
     IITTYY section found at the end of this document.  ddmmaakkee
     returns 0 if no errors were detected and a non-zero result
     if an error occurred.

OOPPTTIIOONNSS
     --AA   Enable AUGMAKE special inference rule transformations
          (see the "PERCENT(%) RULES" section), these are set to
          off by default.

     --BB   Enable the use of spaces instead of <tabs> to begin
          recipe lines.  This flag equivalent to the .NOTABS spe-
          cial macro and is further described below.





Version 3.9 PL0                 UW                              1
DMAKE(p)             Unsupported Free Software            DMAKE(p)



     --cc   Use non-standard comment stripping.  If you specify --cc
          then ddmmaakkee will treat any ## character as a start of
          comment character wherever it may appear unless it is
          escaped by a \.

     --CC [[++]]ffiillee
          This option writes to _f_i_l_e a copy of standard output
          and standard error from any child processes and from
          the ddmmaakkee process itself.  If you specify a ++ prior to
          the file name then the text is appended to the previous
          contents of _f_i_l_e.  This option is active in the MSDOS
          implementation only and is ignored by non-MSDOS ver-
          sions of ddmmaakkee..

     --dd   Disable the use of the directory cache.  Normally ddmmaakkee
          caches directories as it checks file timestamps.  Giv-
          ing this flag is equivalent to the .DIRCACHE attribute
          or macro being set to _n_o.

     --EE   Read the environment and define all strings of the form
          'EENNVV--VVAARR=_e_v_a_l_u_e' defined within as macros whose name is
          EENNVV--VVAARR, and whose value is '_e_v_a_l_u_e'.  The environment
          is processed prior to processing the user specified
          makefile thereby allowing definitions in the makefile
          to override definitions in the environment.

     --ee   Same as -E, except that the environment is processed
          after the user specified makefile has been processed
          (thus definitions in the environment override defini-
          tions in the makefile).  The -e and -E options are
          mutually exclusive.  If both are given the latter takes
          effect.

     --ff ffiillee
          Use ffiillee as the source for the makefile text.  Only one
          --ff option is allowed.

     --gg   Globally disable group recipe parsing, equivalent to
          the .IGNOREGROUP attribute or macro being set to _y_e_s at
          the start of the makefile.

     --hh   Print the command summary for ddmmaakkee.

     --ii   Tells ddmmaakkee to ignore errors, and continue making other
          targets.  This is equivalent to the .IGNORE attribute
          or macro.

     --KK ffiillee
          Turns on ..KKEEEEPP__SSTTAATTEE state tracking and tells ddmmaakkee to
          use _f_i_l_e as the state file.





Version 3.9 PL0                 UW                              2
DMAKE(p)             Unsupported Free Software            DMAKE(p)



     --kk   Causes ddmmaakkee to ignore errors caused by command execu-
          tion and to make all targets not depending on targets
          that could not be made. Ordinarily ddmmaakkee stops after a
          command returns a non-zero status, specifying --kk causes
          ddmmaakkee to ignore the error and continue to make as much
          as possible.

     --nn   Causes ddmmaakkee to print out what it would have executed,
          but does not actually execute the commands.  A special
          check is made for the string "$(MAKE)" inside a recipe
          line, if found, the line is expanded and invoked,
          thereby enabling recursive makes to give a full
          description of all that they will do.  The check for
          "$(MAKE)" is disabled inside group recipes.

     --pp   Print out a version of the digested makefile in human
          readable form.  (useful for debugging, but cannot be
          re-read by ddmmaakkee)

     --PP##  On systems that support multi-processing cause ddmmaakkee to
          use _# concurrent child processes to make targets.  See
          the "MULTI PROCESSING" section for more information.

     --qq   Check and see if the target is up to date.  Exits with
          code 0 if up to date, 1 otherwise.

     --rr   Tells ddmmaakkee not to read the initial startup makefile,
          see STARTUP section for more details.

     --ss   Tells ddmmaakkee to do all its work silently and not echo
          the commands it is executing to stdout (also suppresses
          warnings).  This  is equivalent to the .SILENT attri-
          bute or macro.

     --SS   Force sequential execution of recipes on architectures
          which support concurrent makes.  For backward compati-
          bility with old makefiles that have nasty side-effect
          prerequisite dependencies.

     --tt   Causes ddmmaakkee to touch the targets and bring them up to
          date without executing any commands.  Note that targets
          will not be created if they do not already exist.

     --TT   Tells ddmmaakkee to not perform transitive closure on the
          inference graph.

     --uu   Force an unconditional update.  (ie. do everything that
          would be done if everything that a target depended on
          was out of date)

     --vv[[ddffiimmtt]]
          Verbose flag, when making targets print to stdout what



Version 3.9 PL0                 UW                              3
DMAKE(p)             Unsupported Free Software            DMAKE(p)



          we are going to make and what we think its time stamp
          is.  The optional flags [[ddffiimmtt]] can be used to restrict
          the information that is displayed.  In the absence of
          any optional flags all are assumed to be given (ie. --vv
          is equivalent to --vvddffiimmtt).  The meanings of the
          optional flags are:

          dd    Notify of change directory operations only.

          ff    Notify of file I/O operations only.

          ii    Notify of inference algorithm operation only.

          mm    Notify of target update operations only.

          tt    Keep any temporary files created; normally they
               are automatically deleted.

     --VV   Print the version of ddmmaakkee, and values of builtin mac-
          ros.

     --WW ttaarrggeett
          Run ddmmaakkee pretending that _t_a_r_g_e_t is out of date.

     --ww ttaarrggeett
          _W_h_a_t _i_f_? Show what would be made if _t_a_r_g_e_t were out of
          date.

     --xx   Upon processing the user makefile export all non-
          internally defined macros to the user's environment.
          This option together with the -e option allows SYSV
          AUGMAKE recursive makes to function as expected.

     --XX   Inhibit the execution of ##!! lines found at the begin-
          ning of a makefile.  The use of this flag prevents
          non-termination of recursive make invocations.

IINNDDEEXX
     Here is a list of the sections that follow and a short
     description of each.  Perhaps you won't have to read the
     entire man page to find what you need.

     SSTTAARRTTUUPP            Describes ddmmaakkee initialization.

     SSYYNNTTAAXX             Describes the syntax of makefile expres-
                        sions.

     AATTTTRRIIBBUUTTEESS         Describes the notion of attributes and
                        how they are used when making targets.

     MMAACCRROOSS             Defining and expanding macros.




Version 3.9 PL0                 UW                              4
DMAKE(p)             Unsupported Free Software            DMAKE(p)



     RRUULLEESS AANNDD TTAARRGGEETTSS  How to define targets and their prere-
                        quisites.

     RREECCIIPPEESS            How to tell ddmmaakkee how to make a target.

     TTEEXXTT DDIIVVEERRSSIIOONNSS    How to use text diversions in recipes and
                        macro expansions.

     SSPPEECCIIAALL TTAARRGGEETTSS    Some targets are special.

     SSPPEECCIIAALL MMAACCRROOSS     Macros used by ddmmaakkee to alter the pro-
                        cessing of the makefile, and those
                        defined by ddmmaakkee for the user.

     CCOONNTTRROOLL MMAACCRROOSS     Itemized list of special control macros.

     RRUUNN--TTIIMMEE MMAACCRROOSS    Discussion of special run-time macros
                        such as $@ and $<.

     FFUUNNCCTTIIOONN MMAACCRROOSS    GNU style function macros, only $(mktmp
                        ...) for now.

     CCOONNDDIITTIIOONNAALL MMAACCRROOSS Target specific conditional macros.

     DDYYNNAAMMIICC PPRREERREEQQUUIISSIITTEESS
                        Processing of prerequisites which contain
                        macro expansions in their name.

     BBIINNDDIINNGG TTAARRGGEETTSS    The rules that ddmmaakkee uses to bind a tar-
                        get to an existing file in the file sys-
                        tem.

     PPEERRCCEENNTT((%%)) RRUULLEESS   Specification of recipes to be used by
                        the inference algorithm.

     MMAAKKIINNGG IINNFFEERREENNCCEESS  The rules that ddmmaakkee uses when inferring
                        how to make a target which has no expli-
                        cit recipe.  This and the previous sec-
                        tion are really a single section in the
                        text.

     MMAAKKIINNGG TTAARRGGEETTSS     How ddmmaakkee makes targets other than
                        libraries.

     MMAAKKIINNGG LLIIBBRRAARRIIEESS   How ddmmaakkee makes libraries.

     KKEEEEPP SSTTAATTEE         A discussion of how .KEEP_STATE works.

     MMUULLTTII PPRROOCCEESSSSIINNGG   Discussion of ddmmaakkee''ss parallel make
                        facilities for architectures that support
                        them.




Version 3.9 PL0                 UW                              5
DMAKE(p)             Unsupported Free Software            DMAKE(p)



     CCOONNDDIITTIIOONNAALLSS       Conditional expressions which control the
                        processing of the makefile.

     EEXXAAMMPPLLEESS           Some hopefully useful examples.

     CCOOMMPPAATTIIBBIILLIITTYY      How ddmmaakkee compares with previous versions
                        of make.

     LLIIMMIITTSS             Limitations of ddmmaakkee.

     PPOORRTTAABBIILLIITTYY        Comments on writing portable makefiles.

     FFIILLEESS              Files used by ddmmaakkee.

     SSEEEE AALLSSOO           Other related programs, and man pages.

     AAUUTTHHOORR             The guy responsible for this thing.

     BBUUGGSS               Hope not.

SSTTAARRTTUUPP
     When ddmmaakkee begins execution it first processes the command
     line and then processes an initial startup-makefile.  This
     is followed by an attempt to locate and process a user sup-
     plied makefile.  The startup file defines the default values
     of all required control macros and the set of default rules
     for making targets and inferences.  When searching for the
     startup makefile, ddmmaakkee searches the following locations, in
     the order specified, until a startup file is located:

          1.   The location given as the value of the macro MAK-
               ESTARTUP defined on the command line.

          2.   The location given as the value of the environment
               variable MAKESTARTUP defined in the current
               environment.

          3.   The location given as the value of the macro MAK-
               ESTARTUP defined internally within ddmmaakkee.

     The above search is disabled by specifying the -r option on
     the command line.  An error is issued if a startup makefile
     cannot be found and the -r option was not specified.  A user
     may substitute a custom startup file by defining the MAKES-
     TARTUP environment variable or by redefining the MAKESTARTUP
     macro on the command line.  To determine where ddmmaakkee looks
     for the default startup file, check your environment or
     issue the command _"_d_m_a_k_e _-_V_".

     A similar search is performed to locate a default user
     makefile when no --ff command line option is specified.  By
     default, the prerequisite list of the special target



Version 3.9 PL0                 UW                              6
DMAKE(p)             Unsupported Free Software            DMAKE(p)



     .MAKEFILES specifies the names of possible makefiles and the
     search order that ddmmaakkee should use to determine if one
     exists.  A typical definition for this target is:

          .MAKEFILES : makefile.mk Makefile makefile

     ddmmaakkee will first look for makefile.mk and then the others.
     If a prerequisite cannot be found ddmmaakkee will try to make it
     before going on to the next prerequisite.  For example,
     makefile.mk can be checked out of an RCS file if the proper
     rules for doing so are defined in the startup file.

     If the first line of the user makefile is of the form:

          #! command command_args

     then ddmmaakkee will expand and run the command prior to reading
     any additional input.  If the return code of the command is
     zero then ddmmaakkee will continue on to process the remainder of
     the user makefile, if the return code is non-zero then dmake
     will exit.

     ddmmaakkee builds the internal dependency graph as it parses a
     user specified makefile.  The graph is rooted at the special
     target ..RROOOOTT. .ROOT is the top level target that dmake
     builds when it starts to build targets.  All user specified
     targets (those from the command line or taken as defaults
     from the makefile) are made prerequisites of the special
     target ..TTAARRGGEETTSS.  ddmmaakkee by default creates the relationship
     that .ROOT depends on .TARGETS and as a result everything is
     made.  This approach allows the user to customize, within
     their makefile, the order and which, target, is built first.
     For example the default makefiles come with settings for
     .ROOT that specify:

          .ROOT .PHONY .NOSTATE .SEQUENTIAL : .INIT .TARGETS
          .DONE

     with .INIT and .DONE defined as:

          .INIT .DONE :;

     which nicely emulates the behaviour of Sun's make exten-
     sions.  The building of .ROOT's prerequisites is always
     forced to be sequential.

SSYYNNTTAAXX
     This section is a summary of the syntax of makefile state-
     ments.  The description is given in a style similar to BNF,
     where { } enclose items that may appear zero or more times,
     and [ ] enclose items that are optional.  Alternative pro-
     ductions for a left hand side are indicated by '->', and



Version 3.9 PL0                 UW                              7
DMAKE(p)             Unsupported Free Software            DMAKE(p)



     newlines are significant.  All symbols in bboolldd type are text
     or names representing text supplied by the user.



          Makefile -> { Statement }

          Statement -> Macro-Definition
                    -> Conditional-Macro-Definition
                    -> Conditional
                    -> Rule-Definition
                    -> Attribute-Definition

          Macro-Definition -> MMAACCRROO == LLIINNEE
                           -> MMAACCRROO [[!!]*= LINE
                           ---->>>> MMAACCRROO [[!!]:= LINE
                           ---->>>> MMAACCRROO [[!!]*:= LINE
                           ---->>>> MMAACCRROO [[!!]+= LINE
                           ---->>>> MMAACCRROO [[!!]+:= LINE

          CCoonnddiittiioonnaall--MMaaccrroo--DDeeffiinniittiioonn ---->>>>  TTAARRGGEETT ?= Macro-
                                           Definition

          Conditional ->  ..IIFF expression
                             Makefile
                          [ ..EELLIIFF expression
                             Makefile ]
                          [ ..EELLSSEE
                             Makefile ]
                          ..EENNDD

          expression -> LLIINNEE
                     -> SSTTRRIINNGG ==== LLIINNEE
                     -> SSTTRRIINNGG !!== LLIINNEE


          Rule-Definition ->  target-definition
                                 [ recipe ]

          target-definition -> targets [attrs] op { PPRREERREEQQUUIISSIITTEE } [;; rcp-line]

          targets -> target { targets }
                  -> ""target"" { targets }

          target -> special-target
                 -> TTAARRGGEETT

          attrs -> attribute { attrs }
                -> ""attribute"" { attrs }

          op -> :: { modifier }




Version 3.9 PL0                 UW                              8
DMAKE(p)             Unsupported Free Software            DMAKE(p)



          modifier -> ::
                   -> ^^
                   -> !!
                   -> --
                   -> ||

          recipe -> { TTAABB rcp-line }
                 -> [@@][%%][--] [[
                       { LLIINNEE }
                    ]]

          rcp-line -> [@@][%%][--][++] LLIINNEE


          Attribute-Definition -> attrs :: targets


          attribute -> ..EEPPIILLOOGG
                    -> ..GGRROOUUPP
                    -> ..IIGGNNOORREE
                    -> ..IIGGNNOORREEGGRROOUUPP
                    -> ..LLIIBBRRAARRYY
                    -> ..MMKKSSAARRGGSS
                    -> ..NNOOIINNFFEERR
                    -> ..NNOOSSTTAATTEE
                    -> ..PPHHOONNYY
                    -> ..PPRREECCIIOOUUSS
                    -> ..PPRROOLLOOGG
                    -> ..SSEETTDDIIRR==_p_a_t_h
                    -> ..SSIILLEENNTT
                    -> ..SSEEQQUUEENNTTIIAALL
                    -> ..SSWWAAPP
                    -> ..UUSSEESSHHEELLLL
                    -> ..SSYYMMBBOOLL
                    -> ..UUPPDDAATTEEAALLLL

          special-target -> ..EERRRROORR
                         -> ..EEXXIITT
                         -> ..EEXXPPOORRTT
                         -> ..GGRROOUUPPEEPPIILLOOGG
                         -> ..GGRROOUUPPPPRROOLLOOGG
                         -> ..IIMMPPOORRTT
                         -> ..IINNCCLLUUDDEE
                         -> ..IINNCCLLUUDDEEDDIIRRSS
                         -> ..MMAAKKEEFFIILLEESS
                         -> ..RREEMMOOVVEE
                         -> ..SSOOUURRCCEE
                         -> ..SSOOUURRCCEE.._s_u_f_f_i_x
                         -> ._s_u_f_f_i_x_1._s_u_f_f_i_x_2






Version 3.9 PL0                 UW                              9
DMAKE(p)             Unsupported Free Software            DMAKE(p)



     Where, TTAABB represents a <tab> character, SSTTRRIINNGG represents
     an arbitrary sequence of characters, and LLIINNEE represents a
     possibly empty sequence of characters terminated by a non-
     escaped (not immediately preceded by a backslash '\') new-
     line character.  MMAACCRROO, PPRREERREEQQUUIISSIITTEE, and TTAARRGGEETT each
     represent a string of characters not including space or tab
     which respectively form the name of a macro, prerequisite or
     target.  The name may itself be a macro expansion expres-
     sion.  A LLIINNEE can be continued over several physical lines
     by terminating it with a single backslash character.  Com-
     ments are initiated by the pound ## character and extend to
     the end of line.  All comment text is discarded, a '#' may
     be placed into the makefile text by escaping it with '\'
     (ie. \# translates to # when it is parsed).  An exception to
     this occurs when a # is seen inside a recipe line that
     begins with a <tab> or is inside a group recipe.  If you
     specify the --cc command line switch then this behavior is
     disabled and ddmmaakkee will treat all # characters as start of
     comment indicators unless they are escaped by \.  A set of
     continued lines may be commented out by placing a single #
     at the start of the first line.  A continued line cannot
     span more than one makefile.

     wwhhiittee ssppaaccee is defined to be any combination of <space>,
     <tab>, and the sequence \<nl> when \<nl> is used to ter-
     minate a LINE.  When processing mmaaccrroo definition lines, any
     amount of white space is allowed on either side of the macro
     operator and white space is stripped from both before and
     after the macro value string.  The sequence \<nl> is treated
     as white space during recipe expansion and is deleted from
     the final recipe string.  You must escape the \<nl> with
     another \ in order to get a \ at the end of a recipe line.
     The \<nl> sequence is deleted from macro values when they
     are expanded.

     When processing ttaarrggeett definition lines, the recipe for a
     target must, in general, follow the first definition of the
     target (See the RULES AND TARGETS section for an exception),
     and the recipe may not span across multiple makefiles.  Any
     targets and prerequisites found on a target definition line
     are taken to be white space separated tokens.  The rule
     operator (_o_p in SYNTAX section) is also considered to be a
     token but does not require white space to precede or follow
     it.  Since the rule operator begins with a `:', traditional
     versions of make do not allow the `:' character to form a
     valid target name.  ddmmaakkee allows `:' to be present in
     target/prerequisite names as long as the entire
     target/prerequisite name is quoted.  For example:

          a:fred : test

     would be parsed as TARGET = a, PREREQUISITES={fred, :,



Version 3.9 PL0                 UW                             10
DMAKE(p)             Unsupported Free Software            DMAKE(p)



     test}, which is not what was intended.  To fix this you must
     write:

          "a:fred" : test

     Which will be parsed as expected.  Quoted target and prere-
     quisite specifications may also contain white space thereby
     allowing the use of complex function macro expressions..
     See the EXAMPLES section for how to apply "" quoting to a
     list of targets.

AATTTTRRIIBBUUTTEESS
     ddmmaakkee defines several target attributes.  Attributes may be
     assigned to a single target, a group of targets, or to all
     targets in the makefile.  Attributes are used to modify
     ddmmaakkee actions during target update.  The recognized attri-
     butes are:


     ..EEPPIILLOOGG     Insert shell epilog code when executing a group
                 recipe associated with any target having this
                 attribute set.

     ..FFIIRRSSTT      Used in conjunction with .INCLUDE.  Terminates
                 the inclusion with the first successfully
                 included prerequisite.

     ..GGRROOUUPP      Force execution of a target's recipe as a group
                 recipe.

     ..IIGGNNOORREE     Ignore an error when trying to make any target
                 with this attribute set.

     ..IIGGNNOORREEGGRROOUUPP
                 Disable the special meaning of '[' to initiate a
                 group recipe.

     ..LLIIBBRRAARRYY    Target is a library.

     ..MMKKSSAARRGGSS    If running in an MSDOS environment then use MKS
                 extended argument passing conventions to pass
                 arguments to commands.  Non-MSDOS environments
                 ignore this attribute.

     ..NNOOIINNFFEERR    Any target with this attribute set will not be
                 subjected to transitive closure if it is
                 inferred as a prerequisite of a target whose
                 recipe and prerequisites are being inferred.
                 (i.e. the inference algorithm will not use any
                 prerequisite with this attribute set, as a tar-
                 get) If specified as '.NOINFER:' (ie. with no
                 prerequisites or targets) then the effect is



Version 3.9 PL0                 UW                             11
DMAKE(p)             Unsupported Free Software            DMAKE(p)



                 equivalent to specifying --TT on the command line.

     ..NNOOSSTTAATTEE    Any target with this attribute set will not have
                 command line flag information stored in the
                 state file if .KEEP_STATE has been enabled.

     ..PPHHOONNYY      Any target with this attribute set will have its
                 recipe executed each time the target is made
                 even if a file matching the target name can be
                 located.  Any targets that have a .PHONY attri-
                 buted target as a prerequisite will be made each
                 time the .PHONY attributed prerequisite is made.

     ..PPRREECCIIOOUUSS   Do not remove associated target under any cir-
                 cumstances.  Set by default for any targets
                 whose corresponding files exist in the file sys-
                 tem prior to the execution of ddmmaakkee.

     ..PPRROOLLOOGG     Insert shell prolog code when executing a group
                 recipe associated with any target having this
                 attribute set.

     ..SSEEQQUUEENNTTIIAALL Force a sequential make of the associated
                 target's prerequisites.

     ..SSEETTDDIIRR     Change current working directory to specified
                 directory when making the associated target.
                 You must specify the directory at the time the
                 attribute is specified.  To do this simply give
                 _._S_E_T_D_I_R_=_p_a_t_h as the attribute.  _p_a_t_h is expanded
                 and the result is used as the value of the
                 directory to change to.  If _p_a_t_h contains $$$$@@
                 then the name of the target to be built is used
                 in computing the path to change directory to.
                 If path is surrounded by single quotes then path
                 is not expanded, and is used literally as the
                 directory name.  If the _p_a_t_h contains any `:'
                 characters then the entire attribute string must
                 be quoted using ".  If a target having this
                 attribute set also has the .IGNORE attribute set
                 then if the change to the specified directory
                 fails it will be ignored, and no error message
                 will be issued.

     ..SSIILLEENNTT     Do not echo the recipe lines when making any
                 target with this attribute set, and do not issue
                 any warnings.

     ..SSWWAAPP       Under MSDOS when making a target with this
                 attribute set swap the ddmmaakkee executable to disk
                 prior to executing the recipe line.  Also see
                 the '%' recipe line flag defined in the RECIPES



Version 3.9 PL0                 UW                             12
DMAKE(p)             Unsupported Free Software            DMAKE(p)



                 section.

     ..SSYYMMBBOOLL     Target is a library member and is an entry point
                 into a module in the library.  This attribute is
                 used only when searching a library for a target.
                 Targets of the form lib((entry)) have this
                 attribute set automatically.

     ..UUSSEESSHHEELLLL   Force each recipe line of a target to be exe-
                 cuted using a shell.  Specifying this attribute
                 is equivalent to specifying the '+' character at
                 the start of each line of a non-group recipe.

     ..UUPPDDAATTEEAALLLL  Indicates that all the targets listed in this
                 rule are updated by the execution of the accom-
                 panying recipe.  A common example is the produc-
                 tion of the _y_._t_a_b_._c and _y_._t_a_b_._h files by yyaacccc
                 when it is run on a grammar.  Specifying
                 .UPDATEALL in such a rule prevents the running
                 of yacc twice, once for the y.tab.c file and
                 once for the y.tab.h file.  .UPDATEALL targets
                 that are specified in a single rule are treated
                 as a single target and all timestamps are
                 updated whenever any target in the set is made.
                 As a side-effect, ddmmaakkee internally sorts such
                 targets in ascending alphabetical order and the
                 value of $@ is always the first target in the
                 sorted set.

     All attributes are user setable and except for .UPDATEALL,
     .SETDIR and .MKSARGS may be used in one of two forms.  The
     .MKSARGS attribute is restricted to use as a global attri-
     bute, and the use of the .UPDATEALL and .SETDIR attributes
     is restricted to rules of the second form only.

          ATTRIBUTE_LIST : _t_a_r_g_e_t_s

     assigns the attributes specified by ATTRIBUTE_LIST to each
     target in _t_a_r_g_e_t_s or

          _t_a_r_g_e_t_s ATTRIBUTE_LIST : ...

     assigns the attributes specified by ATTRIBUTE_LIST to each
     target in _t_a_r_g_e_t_s_. In the first form if _t_a_r_g_e_t_s is empty
     (ie. a NULL list), then the list of attributes will apply to
     all targets in the makefile (this is equivalent to the com-
     mon Make construct of _"_._I_G_N_O_R_E _:_" but has been modified to
     the notion of an attribute instead of a special target).
     Not all of the attributes have global meaning.  In particu-
     lar, .LIBRARY, .NOSTATE, .PHONY, .SETDIR, .SYMBOL and
     .UPDATEALL have no assigned global meaning.




Version 3.9 PL0                 UW                             13
DMAKE(p)             Unsupported Free Software            DMAKE(p)



     Any attribute may be used with any target, even with the
     special targets.  Some combinations are useless (e.g.
     .INCLUDE .PRECIOUS: ... ), while others are useful (e.g.
     .INCLUDE .IGNORE : "file.mk" will not complain if file.mk
     cannot be found using the include file search rules, see the
     section on SPECIAL TARGETS for a description of .INCLUDE).
     If a specified attribute will not be used with the special
     target a warning is issued and the attribute is ignored.

MMAACCRROOSS
     ddmmaakkee supports six forms of macro assignment.


     MMAACCRROO == LLIINNEE    This is the most common and familiar form of
                     macro assignment.  It assigns LINE literally
                     as the value of MACRO.  Future expansions of
                     MACRO recursively expand its value.

     MMAACCRROO **== LLIINNEE   This form behaves exactly as the simple '='
                     form with the exception that if MACRO
                     already has a value then the assignment is
                     not performed.

     MMAACCRROO ::== LLIINNEE   This form differs from the simple '=' form
                     in that it expands LINE prior to assigning
                     it as the value of MACRO.  Future expansions
                     of MACRO do not recursively expand its
                     value.

     MMAACCRROO **::== LLIINNEE  This form behaves exactly as the ':=' form
                     with the exception that if MACRO already has
                     a value then the assignment and expansion
                     are not performed.

     MMAACCRROO ++== LLIINNEE   This form of macro assignment allows macro
                     values to grow.  It takes the literal value
                     of LINE and appends it to the previous value
                     of MACRO separating the two by a single
                     space.  Future expansions of MACRO recur-
                     sively expand its value.

     MMAACCRROO ++::== LLIINNEE  This form is similar to the '+=' form except
                     that the value of LINE is expanded prior to
                     being added to the value of MACRO.

     Macro expressions specified on the command line allow the
     macro value to be redefined within the makefile only if the
     macro is defined using the '+=' and '+:=' operators.  Other
     operators will define a macro that cannot be further modi-
     fied.





Version 3.9 PL0                 UW                             14
DMAKE(p)             Unsupported Free Software            DMAKE(p)



     Each of the preceeding macro assignment operators may be
     prefixed by !!  to indicate that the assignment should be
     forced and that no warnings should be issued.  Thus, speci-
     fying !! has the effect of silently forcing the specified
     macro assignment.

     When ddmmaakkee defines a non-environment macro it strips leading
     and trailing white space from the macro value.  Macros
     imported from the environment via either the .IMPORT special
     target (see the SPECIAL TARGETS section), or the --ee, or --EE
     flags are an exception to this rule.  Their values are
     always taken literally and white space is never stripped.
     In addition, named macros defined using the .IMPORT special
     target do not have their values expanded when they are used
     within a makefile.  In contrast, environment macros that are
     imported due to the specification of the --ee or --EE flags are
     subject to expansion when used.

     To specify a macro expansion enclose the name in () or {}
     and precede it with a dollar sign $.  Thus $(TEST)
     represents an expansion of the macro variable named TEST.
     If TEST is defined then $(TEST) is replaced by its expanded
     value.  If TEST is not defined then $(TEST) expands to the
     NULL string (this is equivalent to defining a macro as
     'TEST=' ).  A short form may be used for single character
     named macros.  In this case the parentheses are optional,
     and $(I) is equivalent to $I.  Macro expansion is recursive,
     hence, if the value string contains an expression represent-
     ing a macro expansion, the expansion is performed.  Circular
     macro expansions are detected and cause an error to be
     issued.

     When defining a macro the given macro name is first expanded
     before being used to define the macro.  Thus it is possible
     to define macros whose names depend on values of other mac-
     ros.  For example, suppose CWD is defined as

          CWD = $(PWD:b)

     then the value of $(CWD) is the name of the current direc-
     tory.  This can be used to define macros specific to this
     directory, for example:

          _$(CWD).prt = list of files to print...

     The actual name of the defined macro is a function of the
     current directory.  A construct such as this is useful when
     processing a hierarchy of directories using .SETDIR attri-
     buted targets and a collection of small distributed makefile
     stubs.





Version 3.9 PL0                 UW                             15
DMAKE(p)             Unsupported Free Software            DMAKE(p)



     Macro variables may be defined within the makefile, on the
     command line, or imported from the environment.

     ddmmaakkee supports several non-standard macro expansions: The
     first is of the form:

          _$_(_m_a_c_r_o___n_a_m_e_:_m_o_d_i_f_i_e_r___l_i_s_t_:_m_o_d_i_f_i_e_r___l_i_s_t_:_._._._)

     where _m_o_d_i_f_i_e_r___l_i_s_t is chosen from the set { B or b, D or d,
     E or e, F or f, I or i, L or l, S or s, T or t, U or u, ^, +
     } and

          b  - file (not including suffix) portion of path names
          d  - directory portion of all path names
          e  - suffix portion of path names
          f  - file (including suffix) portion of path names
          i  - inferred names of targets
          l  - macro value in lower case
          s  - simple pattern substitution
          t  - tokenization.
          u  - macro value in upper case
          ^  - prepend a prefix to each token
          +  - append a suffix to each token

     Thus if we have the example:

          test = d1/d2/d3/a.out f.out d1/k.out

     The following macro expansions produce the values on the
     right of '->' after expansion.

          $(test:d)             -> d1/d2/d3/ d1/
          $(test:b)             -> a f k
          $(test:f)             -> a.out f.out k.out
          ${test:db}            -> d1/d2/d3/a f d1/k
          ${test:s/out/in/:f}   -> a.in f.in k.in
          $(test:f:t"+")        -> a.out+f.out+k.out
          $(test:e)             -> .out .out .out
          $(test:u)             -> D1/D2/D3/A.OUT F.OUT D1/K.OUT

     If a token ends in a string composed from the value of the
     macro DIRBRKSTR (ie. ends in a directory separator string,
     e.g. '/' in UNIX) and you use the ::dd modifier then the
     expansion returns the directory name less the final direc-
     tory separator string.  Thus successive pairs of :d modif-
     iers each remove a level of directory in the token string.

     The tokenization modifier takes all white space separated
     tokens from the macro value and separates them by the quoted
     separator string.  The separator string may contain the fol-
     lowing escape codes \a => <bel>, \b => <backspace>, \f =>
     <formfeed>, \n => <nl>, \r => <cr>, \t => <tab>, \v =>



Version 3.9 PL0                 UW                             16
DMAKE(p)             Unsupported Free Software            DMAKE(p)



     <vertical tab>, \" => ", and \xxx => <xxx> where xxx is the
     octal representation of a character.  Thus the expansion:

          $(test:f:t"+\n")
     produces:
          a.out+
          f.out+
          k.out

     The prefix operator ^^ takes all white space separated tokens
     from the macro value and prepends _s_t_r_i_n_g to each.

          $(test:f:^mydir/)
     produces:
          mydir/a.out mydir/f.out mydir/k.out

     The suffix operator ++ takes all white space separated tokens
     from the macro value and appends _s_t_r_i_n_g to each.

          $(test:b:+.c)
     produces:
          a.c f.c k.c

     The next non-standard form of macro expansion allows for
     recursive macros.  It is possible to specify a $(_m_a_c_r_o___n_a_m_e)
     or ${_m_a_c_r_o___n_a_m_e} expansion where _m_a_c_r_o___n_a_m_e contains more $(
     ... ) or ${ ... } macro expansions itself.

     For example $(CC$(_HOST)$(_COMPILER)) will first expand
     CC$(_HOST)$(_COMPILER) to get a result and use that result
     as the name of the macro to expand.  This is useful for
     writing a makefile for more than one target environment.  As
     an example consider the following hypothetical case. Suppose
     that _HOST and _COMPILER are imported from the environment
     and are set to represent the host machine type and the host
     compiler respectively.

          CFLAGS_VAX_CC = -c -O     # _HOST == "_VAX", _COMPILER == "_CC"
          CFLAGS_PC_MSC = -c -ML # _HOST == "_PC",  _COMPILER == "_MSC"

          # redefine CFLAGS macro as:

          CFLAGS := $(CFLAGS$(_HOST)$(_COMPILER))

     This causes CFLAGS to take on a value that corresponds to
     the environment in which the make is being invoked.

     The final non-standard macro expansion is of the form:

          string1{token_list}string2





Version 3.9 PL0                 UW                             17
DMAKE(p)             Unsupported Free Software            DMAKE(p)



     where string1, string2 and token_list are expanded.  After
     expansion, string1 is prepended to each token found in
     token_list and string2 is appended to each resulting token
     from the previous prepend.  string1 and string2 are not del-
     imited by white space whereas the tokens in token_list are.
     A null token in the token list is specified using "".  Thus
     using another example we have:

          test/{f1 f2}.o     --> test/f1.o test/f2.o
          test/ {f1 f2}.o    --> test/ f1.o f2.o
          test/{f1 f2} .o    --> test/f1 test/f2 .o
          test/{"f1"  ""}.o  --> test/f1.o test/.o

          and

          test/{d1 d2}/{f1 f2}.o --> test/d1/f1.o test/d1/f2.o
                                     test/d2/f1.o test/d2/f2.o

     This last expansion is activated only when the first charac-
     ters of _t_o_k_e_n___l_i_s_t appear immediately after the opening '{'
     with no intervening white space.  The reason for this res-
     triction is the following incompatibility with Bourne Shell
     recipes.  The line

          { echo hello;}

     is valid /bin/sh syntax; while

          {echo hello;}

     is not.  Hence the latter triggers the enhanced macro expan-
     sion while the former causes it to be suppressed.  See the
     SPECIAL MACROS section for a description of the special mac-
     ros that ddmmaakkee defines and understands.

RRUULLEESS AANNDD TTAARRGGEETTSS
     A makefile contains a series of entries that specify depen-
     dencies.  Such entries are called _t_a_r_g_e_t_/_p_r_e_r_e_q_u_i_s_i_t_e or
     _r_u_l_e definitions.  Each rule definition is optionally fol-
     lowed by a set of lines that provide a recipe for updating
     any targets defined by the rule.  Whenever ddmmaakkee attempts to
     bring a target up to date and an explicit recipe is provided
     with a rule defining the target, that recipe is used to
     update the target.  A rule definition begins with a line
     having the following syntax:

          _<_t_a_r_g_e_t_s_> [_<_a_t_t_r_i_b_u_t_e_s_>] _<_r_u_l_e_o_p_> [_<_p_r_e_r_e_q_u_i_s_i_t_e_s_>] [;_<_r_e_c_i_p_e_>]

     _t_a_r_g_e_t_s is a non-empty list of targets.  If the target is a
     special target (see SPECIAL TARGETS section below) then it
     must appear alone on the rule line.  For example:




Version 3.9 PL0                 UW                             18
DMAKE(p)             Unsupported Free Software            DMAKE(p)



          .IMPORT .ERROR : ...

     is not allowed since both .IMPORT and .ERROR are special
     targets.  Special targets are not used in the construction
     of the dependency graph and will not be made.

     _a_t_t_r_i_b_u_t_e_s is a possibly empty list of attributes.  Any
     attribute defined in the ATTRIBUTES section above may be
     specified.  All attributes will be applied to the list of
     named targets in the rule definition.  No other targets will
     be affected.


     NOTE:   As stated earlier, if both the target list and
             prerequisite list are empty but the attributes list
             is not, then the specified attributes affect all
             targets in the makefile.


     _r_u_l_e_o_p is a separator which is used to identify the targets
     from the prerequisites.  Optionally it also provides a
     facility for modifying the way in which ddmmaakkee handles the
     making of the associated targets.  In its simplest form the
     operator is a single ':', and need not be separated by white
     space from its neighboring tokens.  It may additionally be
     followed by any of the modifiers { !, ^, -, :, | }, where:


     !!    says execute the recipe for the associated targets once
          for each out of date prerequisite.  Ordinarily the
          recipe is executed once for all out of date prere-
          quisites at the same time.

     ^^    says to insert the specified prerequisites, if any,
          before any other prerequisites already associated with
          the specified targets.  In general, it is not useful to
          specify ^ with an empty list of prerequisites.

     --    says to clear the previous list of prerequisites before
          adding the new prerequisites.  Thus,

               .SUFFIXES :
               .SUFFIXES : .a .b

          can be replaced by

               .SUFFIXES :- .a .b

          however the old form still works as expected.  NOTE:
          .SUFFIXES is ignored by ddmmaakkee it is used here simply as
          an example.




Version 3.9 PL0                 UW                             19
DMAKE(p)             Unsupported Free Software            DMAKE(p)



     ::    When the rule operator is not modified by a second ':'
          only one set of rules may be specified for making a
          target.  Multiple definitions may be used to add to the
          list of prerequisites that a target depends on.  How-
          ever, if a target is multiply defined only one defini-
          tion may specify a recipe for making the target.

          When a target's rule operator is modified by a second
          ':' (:: for example) then this definition may not be
          the only definition with a recipe for the target.
          There may be other :: target definition lines that
          specify a different set of prerequisites with a dif-
          ferent recipe for updating the target. Any such target
          is made if any of the definitions find it to be out of
          date with respect to the related prerequisites and the
          corresponding recipe is used to update the target.  By
          definition all '::' recipes that are found to be out of
          date for are executed.

          In the following simple example, each rule has a `::'
          _r_u_l_e_o_p.  In such an operator we call the first `:' the
          operator, and the second `:' the modifier.

          a.o :: a.c b.h
             first recipe for making a.o

          a.o :: a.y b.h
             second recipe for making a.o

          If a.o is found to be out of date with respect to a.c
          then the first recipe is used to make a.o.  If it is
          found out of date with respect to a.y then the second
          recipe is used.  If a.o is out of date with respect to
          b.h then both recipes are invoked to make a.o.  In the
          last case the order of invocation corresponds to the
          order in which the rule definitions appear in the
          makefile.

     ||    Is defined only for PERCENT rule target definitions.
          When specified it indicates that the following con-
          struct should be parsed using the old semantinc mean-
          ing:

          %.o :| %.c %.r %.f ; some rule

          is equivalent to:

          %.o : %.c ; some rule
          %.o : %.r ; some rule
          %.o : %.f ; some rule





Version 3.9 PL0                 UW                             20
DMAKE(p)             Unsupported Free Software            DMAKE(p)



     Targets defined using a single `:' operator with a recipe
     may be redefined again with a new recipe by using a `:'
     operator with a `:' modifier.  This is equivalent to a tar-
     get having been initially defined with a rule using a `:'
     modifier.  Once a target is defined using a `:' modifier it
     may not be defined again with a recipe using only the `:'
     operator with no `:' modifier.  In both cases the use of a
     `:' modifier creates a new list of prerequisites and makes
     it the current prerequisite list for the target.  The `:'
     operator with no recipe always modifies the current list of
     prerequisites.  Thus assuming each of the following defini-
     tions has a recipe attached, then:

          joe :  fred ...     (1)
          joe :: more ...     (2)

          and

          joe :: fred ...     (3)
          joe :: more ...     (4)

     are legal and mean:  add the recipe associated with (2), or
     (4) to the set of recipes for joe, placing them after exist-
     ing recipes for making joe.  The constructs:

          joe :: fred ...     (5)
          joe : more ... (6)

          and

          joe : fred ... (7)
          joe : more ... (8)

     are errors since we have two sets of perfectly good recipes
     for making the target.

     _p_r_e_r_e_q_u_i_s_i_t_e_s is a possibly empty list of targets that must
     be brought up to date before making the current target.

     _r_e_c_i_p_e is a short form and allows the user to specify short
     rule definitions on a single line.  It is taken to be the
     first recipe line in a larger recipe if additional lines
     follow the rule definition.  If the semi-colon is present
     but the recipe line is empty (ie. null string) then it is
     taken to be an empty rule.  Any target so defined causes the
     _D_o_n_'_t _k_n_o_w _h_o_w _t_o _m_a_k_e _._._. error message to be suppressed
     when ddmmaakkee tries to make the target and fails.  This silence
     is maintained for rules that are terminated by a semicolon
     and have no following recipe lines, for targets listed on
     the command line, for the first target found in the
     makefile, and for any target having no recipe but containing
     a list of prerequisites (see the COMPATIBILITY section for



Version 3.9 PL0                 UW                             21
DMAKE(p)             Unsupported Free Software            DMAKE(p)



     an exception to this rule if the AUGMAKE (--AA) flag was
     specified.

RREECCIIPPEESS
     The traditional format used by most versions of Make defines
     the recipe lines as arbitrary strings that may contain macro
     expansions.  They follow a rule definition line and may be
     spaced apart by comment or blank lines.  The list of recipe
     lines defining the recipe is terminated by a new target
     definition, a macro definition, or end-of-file.  Each recipe
     line MMUUSSTT begin with a <<TTAABB>> character which may optionally
     be followed with one or all of the characters _'_@_%_+_-_'.  The
     _'_-_' indicates that non-zero exit values (ie. errors) are to
     be ignored when this recipe line is executed, the _'_+_' indi-
     cates that the current recipe line is to be executed using
     the shell, the _'_%_' indicates that ddmmaakkee should swap itself
     out to secondary storage (MSDOS only) before running the
     recipe and the _'_@_' indicates that the recipe line should NOT
     be echoed to the terminal prior to being executed.  Each
     switch is off by default (ie. by default, errors are signi-
     ficant, commands are echoed, no swapping is done and a shell
     is used only if the recipe line contains a character found
     in the value of the SHELLMETAS macro).  Global settings
     activated via command line options or special attribute or
     target names may also affect these settings.  An example
     recipe:

          target :
               first recipe line
               second recipe line, executed independently of the first.
               @a recipe line that is not echoed
               -and one that has errors ignored
               %and one that causes dmake to swap out
               +and one that is executed using a shell.

     The second and new format of the recipe block begins the
     block with the character '[' (the open group character) in
     the last non-white space position of a line, and terminates
     the block with the character ']' (the close group character)
     in the first non-white space position of a line.  In this
     form each recipe line need not have a leading TAB.  This is
     called a recipe group.  Groups so defined are fed intact as
     a single unit to a shell for execution whenever the
     corresponding target needs to be updated.  If the open group
     character '[' is preceded by one or all of -, @ or % then
     they apply to the entire group in the same way that they
     apply to single recipe lines.  You may also specify '+' but
     it is redundant as a shell is already being used to run the
     recipe.  See the MAKING TARGETS section for a description of
     how ddmmaakkee invokes recipes.  Here is an example of a group
     recipe:




Version 3.9 PL0                 UW                             22
DMAKE(p)             Unsupported Free Software            DMAKE(p)



          target :
          [
               first recipe line
               second recipe line
               all of these recipe lines are fed to a
               single copy of a shell for execution.
          ]


TTEEXXTT DDIIVVEERRSSIIOONNSS
     ddmmaakkee supports the notion of text diversions.  If a recipe
     line contains the macro expression

          $(mktmp[,[_f_i_l_e][,_t_e_x_t]] _d_a_t_a)

     then all text contained in the _d_a_t_a expression is expanded
     and is written to a temporary file.  The return value of the
     macro is the name of the temporary file.

     _d_a_t_a can be any text and must be separated from the 'mktmp'
     portion of the macro name by white-space.  The only restric-
     tion on the data text is that it must contain a balanced
     number of parentheses of the same kind as are used to ini-
     tiate the $(mktmp ...) expression.  For example:

          $(mktmp $(XXX))

     is legal and works as expected, but:

          $(mktmp text (to dump to file)

     is not legal.  You can achieve what you wish by either
     defining a macro that expands to '(' or by using {} in the
     macro expression; like this:

          ${mktmp text (to dump to file}

     Since the temporary file is opened when the macro containing
     the text diversion expression is expanded, diversions may be
     nested and any diversions that are created as part of ':='
     macro expansions persist for the duration of the ddmmaakkee run.
     The diversion text may contain the same escape codes as
     those described in the MACROS section.  Thus if the _d_a_t_a
     text is to contain new lines they must be inserted using the
     \n escape sequence.  For example the expression:

          all:
               cat $(mktmp this is a\n\
               test of the text diversion\n)

     is replaced by:




Version 3.9 PL0                 UW                             23
DMAKE(p)             Unsupported Free Software            DMAKE(p)



          cat /tmp/mk12294AA

     where the temporary file contains two lines both of which
     are terminated by a new-line.  If the _d_a_t_a text spans multi-
     ple lines in the makefile then each line must be continued
     via the use of a \.  A second more illustrative example gen-
     erates a response file to an MSDOS link command:

          OBJ = fred.obj mary.obj joe.obj
          all : $(OBJ)
               link @$(mktmp $(^:t"+\n")\n)

     The result of making `all' in the second example is the com-
     mand:

          link @/tmp/mk02394AA

     where the temporary file contains:

          fred.obj+
          mary.obj+
          joe.obj

     The last line of the file is terminated by a new-line which
     is inserted due to the \n found at the end of the _d_a_t_a
     string.

     If the optional _f_i_l_e specifier is present then its expanded
     value is the name of the temporary file to create.  Whenever
     a $(mktmp ...) macro is expanded the macro $(TMPFILE) is set
     to a new temporary file name.  Thus the construct:

          $(mktmp,$(TMPFILE) data)

     is completely equivalent to not specifying the $(TMPFILE)
     optional argument.  Another example that would be useful for
     MSDOS users with a Turbo-C compiler

          $(mktmp,turboc.cfg $(CFLAGS))

     will place the contents of CFLAGS into a local _t_u_r_b_o_c_._c_f_g
     file.  The second optional argument, _t_e_x_t, if present alters
     the name of the value returned by the $(mktmp ...) macro.

     Under MS-DOS text diversions may be a problem.  Many DOS
     tools require that path names which contain directories use
     the \ character to delimit the directories.  Some users how-
     ever wish to use the '/' to delimit pathnames and use
     environments that allow them to do so.  The macro USESHELL
     is set to "yes" if the current recipe is forced to use a
     shell via the .USESHELL or '+' directives, otherwise its
     value is "no".  The ddmmaakkee startup files define the macro



Version 3.9 PL0                 UW                             24
DMAKE(p)             Unsupported Free Software            DMAKE(p)



     DIVFILE whose value is either the value of TMPFILE or the
     value of TMPFILE edited to replace any '/' characters to the
     appropriate value based on the current shell and whether it
     will be used to execute the recipe.

     Previous versions of ddmmaakkee defined text diversions using <+,
     +> strings, where <+ started a text diversion and +> ter-
     minated one.  ddmmaakkee is backward compatible with this con-
     struct only if the <+ and +> appear literally on the same
     recipe line or in the same macro value string.  In such
     instances the expression:

          <+data+>

     is mapped to:

          $(mktmp data)

     which is fully output compatible with the earlier construct.
     <+, +> constructs whose text spans multiple lines must be
     converted by hand to use $(mktmp ...).

     If the environment variable TMPDIR is defined then the tem-
     porary file is placed into the directory specified by that
     variable.  A makefile can modify the location of temporary
     files by defining a macro named TMPDIR and exporting it
     using the .EXPORT special target.

SSPPEECCIIAALL TTAARRGGEETTSS
     This section describes the special targets that are recog-
     nized by ddmmaakkee.  Some are affected by attributes and others
     are not.

     ..EERRRROORR        If defined then the recipe associated with
                   this target is executed whenever an error con-
                   dition is detected by ddmmaakkee.  All attributes
                   that can be used with any other target may be
                   used with this target.  Any prerequisites of
                   this target will be brought up to date during
                   its processing.  NOTE:  errors will be ignored
                   while making this target, in extreme cases
                   this may cause some problems.

     ..EEXXIITT         If this target is encountered while parsing a
                   makefile then the parsing of the makefile is
                   immediately terminated at that point.

     ..EEXXPPOORRTT       All prerequisites associated with this target
                   are assumed to correspond to macro names and
                   they and their values are exported to the
                   environment as environment strings at the
                   point in the makefile at which this target



Version 3.9 PL0                 UW                             25
DMAKE(p)             Unsupported Free Software            DMAKE(p)



                   appears.  Any attributes specified with this
                   target are ignored.  Only macros which have
                   been assigned a value in the makefile prior to
                   the export directive are exported, macros as
                   yet undefined or macros whose value contains
                   any of the characters "+=:*" are not exported.
                   is suppre

     ..IIMMPPOORRTT       Prerequisite names specified for this target
                   are searched for in the environment and
                   defined as macros with their value taken from
                   the environment.  If the special name ..EEVVEERRYY----
                   TTHHIINNGG is used as a prerequisite name then all
                   environment variables defined in the environ-
                   ment are imported.  The functionality of the
                   --EE flag can be forced by placing the construct
                   _._I_M_P_O_R_T _: _._E_V_E_R_Y_T_H_I_N_G at the start of a
                   makefile.  Similarly, by placing the construct
                   at the end, one can emulate the effect of the
                   --ee command line flag.  If a prerequisite name
                   cannot be found in the environment an error
                   message is issued.  .IMPORT accepts the
                   .IGNORE attribute.  When given, it causes
                   ddmmaakkee to ignore the above error.  See the MAC-
                   ROS section for a description of the process-
                   ing of imported macro values.

     ..IINNCCLLUUDDEE      Parse another makefile just as if it had been
                   located at the point of the .INCLUDE in the
                   current makefile.  The list of prerequisites
                   gives the list of makefiles to try to read.
                   If the list contains multiple makefiles then
                   they are read in order from left to right.
                   The following search rules are used when try-
                   ing to locate the file.  If the filename is
                   surrounded by " or just by itself then it is
                   searched for in the current directory.  If it
                   is not found it is then searched for in each
                   of the directories specified as prerequisites
                   of the .INCLUDEDIRS special target.  If the
                   file name is surrounded by < and >, (ie.
                   <my_spiffy_new_makefile>) then it is searched
                   for only in the directories given by the
                   .INCLUDEDIRS special target.  In both cases if
                   the file name is a fully qualified name start-
                   ing at the root of the file system then it is
                   only searched for once, and the .INCLUDEDIRS
                   list is ignored.  .INCLUDE accepts the .IGNORE
                   and .SETDIR attributes.  If .IGNORE attribute
                   is given and the file cannot be found then
                   ddmmaakkee continues processing, otherwise an error
                   message is generated.  The .SETDIR attribute



Version 3.9 PL0                 UW                             26
DMAKE(p)             Unsupported Free Software            DMAKE(p)



                   causes ddmmaakkee to change directories to the
                   specified directory prior to attempting the
                   include operation.  If all fails ddmmaakkee
                   attempts to _m_a_k_e the file to be included.  If
                   making the file fails then ddmmaakkee terminates
                   unless the .INCLUDE directive also specified
                   the .IGNORE attribute.  If .FIRST is specified
                   along with .INCLUDE then ddmmaakkee attempts to
                   include each named prerequisite and will ter-
                   minate the inclusion with the first prere-
                   quisite that results in a successful inclu-
                   sion.

     ..IINNCCLLUUDDEEDDIIRRSS  The list of prerequisites specified for this
                   target defines the set of directories to
                   search when trying to include a makefile.

     ..KKEEEEPP__SSTTAATTEE   This special target is a synonym for the macro
                   definition

                        .KEEP_STATE := _state.mk

                   It's effect is to turn on STATE keeping and to
                   define ___s_t_a_t_e_._m_k as the state file.

     ..MMAAKKEEFFIILLEESS    The list of prerequisites is the set of files
                   to try to read as the default makefile.  By
                   default this target is defined as:

                        .MAKEFILES : makefile.mk Makefile
                   makefile


     ..SSOOUURRCCEE       The prerequisite list of this target defines a
                   set of directories to check when trying to
                   locate a target file name.  See the section on
                   BINDING of targets for more information.

     ..SSOOUURRCCEE..ssuuffff  The same as .SOURCE, except that the
                   .SOURCE.suff list is searched first when try-
                   ing to locate a file matching the a target
                   whose name ends in the suffix .suff.

     ..RREEMMOOVVEE       The recipe of this target is used whenever
                   ddmmaakkee needs to remove intermediate targets
                   that were made but do not need to be kept
                   around.  Such targets result from the applica-
                   tion of transitive closure on the dependency
                   graph.

     In addition to the special targets above, several other
     forms of targets are recognized and are considered special,



Version 3.9 PL0                 UW                             27
DMAKE(p)             Unsupported Free Software            DMAKE(p)



     their exact form and use is defined in the sections that
     follow.

SSPPEECCIIAALL MMAACCRROOSS
     ddmmaakkee defines a number of special macros.  They are divided
     into three classes: control macros, run-time macros, and
     function macros.  The control macros are used by ddmmaakkee to
     configure its actions, and are the preferred method of doing
     so.  In the case when a control macro has the same function
     as a special target or attribute they share the same name as
     the special target or attribute.  The run-time macros are
     defined when ddmmaakkee makes targets and may be used by the user
     inside recipes.  The function macros provide higher level
     functions dealing with macro expansion and diversion file
     processing.

CCOONNTTRROOLL MMAACCRROOSS
     To use the control macros simply assign them a value just
     like any other macro.  The control macros are divided into
     three groups: string valued macros, character valued macros,
     and boolean valued macros.

     The following are all of the string valued macros.  This
     list is divided into two groups.  The first group gives the
     string valued macros that are defined internally and cannot
     be directly set by the user.

     IINNCCDDEEPPTTHH        This macro's value is a string of digits
                     representing the current depth of makefile
                     inclusion.  In the first makefile level this
                     value is zero.

     MMFFLLAAGGSS          Is the list of flags that were given on the
                     command line including a leading switch
                     character.  The -f flag is not included in
                     this list.

     MMAAKKEECCMMDD         Is the name with which ddmmaakkee was invoked.

     MMAAKKEEDDIIRR         Is the full path to the initial directory in
                     which ddmmaakkee was invoked.

     MMAAKKEEFFIILLEE        Contains the string "-f _m_a_k_e_f_i_l_e" where,
                     _m_a_k_e_f_i_l_e is the name of initial user
                     makefile that was first read.

     MMAAKKEEFFLLAAGGSS       Is the same as $(MFLAGS) but has no leading
                     switch character. (ie. MFLAGS =
                     -$(MAKEFLAGS))

     MMAAKKEEMMAACCRROOSS      Contains the complete list of macro expres-
                     sions that were specified on the command



Version 3.9 PL0                 UW                             28
DMAKE(p)             Unsupported Free Software            DMAKE(p)



                     line.

     MMAAKKEETTAARRGGEETTSS     Contains the name(s) of the target(s), if
                     any, that were specified on the command
                     line.

     MMAAXXPPRROOCCEESSSSLLIIMMIITT Is a numeric string representing the maximum
                     number of processes that ddmmaakkee can use when
                     making targets using parallel mode.

     NNUULLLL            Is permanently defined to be the NULL
                     string.  This is useful when comparing a
                     conditional expression to an NULL value.

     PPWWDD             Is the full path to the current directory in
                     which make is executing.

     TTMMPPFFIILLEE         Is set to the name of the most recent tem-
                     porary file opened by ddmmaakkee.  Temporary
                     files are used for text diversions and for
                     group recipe processing.

     TTMMDD             Stands for "To Make Dir", and is the path
                     from the present directory (value of $(PWD))
                     to the directory that ddmmaakkee was started up
                     in (value of $(MAKEDIR)).  This macro is
                     modified when .SETDIR attributes are pro-
                     cessed.

     UUSSEESSHHEELLLL        The value of this macro is set to "yes" if
                     the current recipe is forced to use a shell
                     for its execution via the .USESHELL or '+'
                     directives, its value is "no" otherwise.


     The second group of string valued macros control ddmmaakkee
     behavior and may be set by the user.

     ..DDIIRRCCAACCHHEE       If set to "yes" enables the directory cache
                     (this is the default).  If set to "no" dis-
                     ables the directory cache (equivalent to -d
                     commandline flag).

     ..NNAAMMEEMMAAXX        Defines the maximum length of a filename
                     component.  The value of the variable is
                     initialized at startup to the value of the
                     compiled macro NAME_MAX.  On some systems
                     the value of NAME_MAX is too short by
                     default.  Setting a new value for .NAMEMAX
                     will override the compiled value.





Version 3.9 PL0                 UW                             29
DMAKE(p)             Unsupported Free Software            DMAKE(p)



     ..NNOOTTAABBSS         When set to non-NULL enables the use of
                     spaces as well as <tabs> to begin recipe
                     lines.  By default a non-group recipe is
                     terminated by a line without any leading
                     white-space or by a line not beggining with
                     a <tab> character.  Enabling this mode modi-
                     fies the first condition of the above termi-
                     nation rule to terminate a non-group recipe
                     with a line that contains only white-space.
                     This mode does not effect the parsing of
                     group recipes bracketed by [].

     AAUUGGMMAAKKEE         If set to a non NULL value will enable the
                     transformation of special meta targets to
                     support special AUGMAKE inferences (See the
                     COMPATIBILITY section).

     DDIIRRBBRRKKSSTTRR       Contains the string of chars used to ter-
                     minate the name of a directory in a path-
                     name.  Under UNIX its value is "/", under
                     MSDOS its value is "/\:".

     DDIIRRSSEEPPSSTTRR       Contains the string that is used to separate
                     directory components when path names are
                     constructed.  It is defined with a default
                     value at startup.

     DDIIVVFFIILLEE         Is defined in the startup file and gives the
                     name that should be returned for the diver-
                     sion file name when used in $(mktmp ...)
                     expansions, see the TEXT DIVERSION section
                     for details.

     DDYYNNAAMMIICCNNEESSTTIINNGGLLEEVVEELL
                     Specifies the maximum number of recursive
                     dynamic macro expansions.  Its initial value
                     is 100.

     ..KKEEEEPP__SSTTAATTEE     Assigning this macro a value tells ddmmaakkee the
                     name of the state file to use and turns on
                     the keeping of state information for any
                     targets that are brought up to date by the
                     make.

     GGRROOUUPPFFLLAAGGSS      This macro gives the set of flags to pass to
                     the shell when invoking it to execute a
                     group recipe.  The value of the macro is the
                     list of flags with a leading switch indica-
                     tor.  (ie. `-' under UNIX)

     GGRROOUUPPSSHHEELLLL      This macro defines the full path to the exe-
                     cutable image to be used as the shell when



Version 3.9 PL0                 UW                             30
DMAKE(p)             Unsupported Free Software            DMAKE(p)



                     processing group recipes.  This macro must
                     be defined if group recipes are used.  It is
                     assigned a default value in the startup
                     makefile.  Under UNIX this value is /bin/sh.

     GGRROOUUPPSSUUFFFFIIXX     If defined, this macro gives the string to
                     use as a suffix when creating group recipe
                     files to be handed to the command inter-
                     preter.  For example, if it is defined as
                     .sh, then all temporary files created by
                     ddmmaakkee will end in the suffix .sh.  Under
                     MSDOS if you are using command.com as your
                     GROUPSHELL, then this suffix must be set to
                     .bat in order for group recipes to function
                     correctly.  The setting of GROUPSUFFIX and
                     GROUPSHELL is done automatically for
                     command.com in the startup.mk files.

     MMAAKKEE            Is defined in the startup file by default.
                     The string $(MAKE) is recognized when using
                     the -n option for single line recipes.  Ini-
                     tially this macro is defined to have the
                     value "$(MAKECMD) $(MFLAGS)".

     MMAAKKEESSTTAARRTTUUPP     This macro defines the full path to the ini-
                     tial startup makefile.  Use the --VV command
                     line option to discover its initial value.

     MMAAXXLLIINNEELLEENNGGTTHH   This macro defines the maximum size of a
                     single line of makefile input text.  The
                     size is specified as a number, the default
                     value is defined internally and is shown via
                     the --VV option.  A buffer of this size plus 2
                     is allocated for reading makefile text.  The
                     buffer is freed before any targets are made,
                     thereby allowing files containing long input
                     lines to be processed without consuming
                     memory during the actual make.  This macro
                     can only be used to extend the line length
                     beyond it's default minimum value.

     MMAAXXPPRROOCCEESSSS      Specify the maximum number of child
                     processes to use when making targets.  The
                     default value of this macro is "1" and its
                     value cannot exceed the value of the macro
                     MAXPROCESSLIMIT.  Setting the value of MAX-
                     PROCESS on the command line or in the
                     makefile is equivalent to supplying a
                     corresponding value to the -P flag on the
                     command line.





Version 3.9 PL0                 UW                             31
DMAKE(p)             Unsupported Free Software            DMAKE(p)



     PPRREEPP            This macro defines the number of iterations
                     to be expanded automatically when processing
                     % rule definitions of the form:

                     % : %.suff

                     See the sections on PERCENT(%) RULES for
                     details on how PREP is used.

     SSHHEELLLL           This macro defines the full path to the exe-
                     cutable image to be used as the shell when
                     processing single line recipes.  This macro
                     must be defined if recipes requiring the
                     shell for execution are to be used.  It is
                     assigned a default value in the startup
                     makefile.  Under UNIX this value is /bin/sh.

     SSHHEELLLLFFLLAAGGSS      This macro gives the set of flags to pass to
                     the shell when invoking it to execute a sin-
                     gle line recipe.  The value of the macro is
                     the list of flags with a leading switch
                     indicator.  (ie. `-' under UNIX)

     SSHHEELLLLMMEETTAASS      Each time ddmmaakkee 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 exe-
                     cuted without the use of a shell.


     There is only one character valued macro defined by ddmmaakkee:
     SSWWIITTCCHHAARR 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 inter-
     nally defined and is not user setable.  The MSDOS version of
     ddmmaakkee 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.

     All boolean macros currently understood by ddmmaakkee 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



Version 3.9 PL0                 UW                             32
DMAKE(p)             Unsupported Free Software            DMAKE(p)



     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: ..EEPPIILLOOGG, ..IIGGNNOORREE, ..MMKKSSAARRGGSS, ..NNOOIINNFFEERR, ..PPRREECCIIOOUUSS, ..PPRROO----
     LLOOGG, ..SSEEQQUUEENNTTIIAALL, ..SSIILLEENNTT, ..SSWWAAPP, and ..UUSSEESSHHEELLLL.  Assigning
     any of these a non NULL value will globally set the
     corresponding attribute to on.

RRUUNN__TTIIMMEE MMAACCRROOSS
     These macros are defined when ddmmaakkee is making targets, and
     may take on different values for each target.  $$@@ is defined
     to be the full target name, $$?? is the list of all out of
     date prerequisites, $$&& is the list of all prerequisites, $$>>
     is the name of the library if the current target is a
     library member, and $$<< is the list of prerequisites speci-
     fied in the current rule.  If the current target had a
     recipe inferred then $$<< is the name of the inferred prere-
     quisite even if the target had a list of prerequisites sup-
     plied using an explicit rule that did not provide a recipe.
     In such situations $$&& gives the full list of prerequisites.

     $$** is defined as $$((@@::ddbb)) 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 $$** is the target name with no suffix, and in the second
     case, is the value of the matched % pattern from the associ-
     ated %-rule.  $$^^ expands to the set of out of date prere-
     quisites taken from the current value of $$<<.  In addition to
     these, $$$$ expands to $, {{{{ expands to {, }}}} expands to },
     and the strings <<++ and ++>> are recognized as respectively
     starting and terminating a text diversion when they appear
     literally together in the same input line.

     The difference between $? and $^ can best be illustrated by
     an example, consider:

          fred.out : joe amy hello
               rules for making fred

          fred.out : my.c your.h his.h her.h   # more prerequisites

     Assume joe, amy, and my.c are newer then fred.out.  When
     ddmmaakkee executes the recipe for making fred.out the values of
     the following macros will be:

          $@ --> fred.out
          $* --> fred
          $? --> joe amy my.c  # note the difference between $? and $^
          $^ --> joe amy
          $< --> joe amy hello



Version 3.9 PL0                 UW                             33
DMAKE(p)             Unsupported Free Software            DMAKE(p)



          $& --> joe amy hello my.c your.h his.h her.h


FFUUNNCCTTIIOONN MMAACCRROOSS
     ddmmaakkee 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.


          $(aassssiiggnn eexxpprreessssiioonn)
               Causes _e_x_p_r_e_s_s_i_o_n to be parsed as a macro assign-
               ment expression and results in the specified
               assignment being made.  An error is issued if the
               assignment is not syntatically correct.  _e_x_p_r_e_s_-
               _s_i_o_n may contain white space.  This is in effect a
               dynamic macro assignment facility and may appear
               anywhere any other macro may appear.  The result
               of the expanding a dynamic macro assignment
               expression is the name of the macro that was
               assigned and $(NULL) if the _e_x_p_r_e_s_s_i_o_n is not a
               valid macro assignment expression.  Some examples
               are:

               $(assign foo := fred)
               $(assign $(indirect_macro_name) +:= $(morejunk))

          $(nnuullll,_t_e_x_t ttrruuee ffaallssee)
               expands the value of _t_e_x_t_. If it is NULL then the
               macro returns the value of the expansion of ttrruuee
               and the expansion of ffaallssee otherwise.  The terms
               ttrruuee, and ffaallssee must be strings containing no
               white-space.

          $(!!nnuullll,_t_e_x_t ttrruuee ffaallssee)
               Behaves identically to the previous macro except
               that the ttrruuee string is chosen if the expansion of
               _t_e_x_t is not NULL.

          $(eeqq,_t_e_x_t___a,_t_e_x_t___b ttrruuee ffaallssee)
               expands _t_e_x_t___a and _t_e_x_t___b and compares their
               results.  If equal it returns the result of the
               expansion of the ttrruuee term, otherwise it returns
               the expansion of the ffaallssee term.

          $(!!eeqq,_t_e_x_t___a,_t_e_x_t___b ttrruuee ffaallssee)
               Behaves identically to the previous macro except
               that the ttrruuee string is chosen if the expansions
               of the two strings are not equal

          $(nniill eexxpprreessssiioonn)
               Always returns the value of $(NULL) regardless of
               what _e_x_p_r_e_s_s_i_o_n is.  This function macro can be



Version 3.9 PL0                 UW                             34
DMAKE(p)             Unsupported Free Software            DMAKE(p)



               used to discard results of expanding macro expres-
               sions.

          $(sshheellll ccoommmmaanndd)
               Runs _c_o_m_m_a_n_d 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:

                    $(shell ls *.c)

               will return _"_a_._c _b_._c _c_._c _d_._c_" if the files exist
               in the current directory.  The recipe modification
               flags [[++@@%%--]] are honored if they appear as the
               first characters in the command.  For example:

                    $(shell +ls *.c)

               will run the command using the current shell.

          $(sshheellll,,eexxppaanndd ccoommmmaanndd)
               Is an extension to the $$((sshheellll...... function macro
               that expands the result of running ccoommmmaanndd.

          $(ssoorrtt lliisstt)
               Will take all white-space separated tokens in _l_i_s_t
               and will return their sorted equivalent list.

          $(ssttrriipp ddaattaa)
               Will replace all strings of white-space in data by
               a single space.

          $(ssuubbsstt,_p_a_t,_r_e_p_l_a_c_e_m_e_n_t ddaattaa)
               Will search for _p_a_t in ddaattaa and will replace any
               occurrence of _p_a_t with the _r_e_p_l_a_c_e_m_e_n_t string.
               The expansion

               $(subst,.o,.c $(OBJECTS))

          is equivalent to:

               $(OBJECTS:s/.o/.c/)


CCOONNDDIITTIIOONNAALL MMAACCRROOSS
     ddmmaakkee supports conditional macros.  These allow the defini-
     tion of target specific macro values.  You can now say the
     following:

          ttaarrggeett ?= _M_a_c_r_o_N_a_m_e _M_a_c_r_o_O_p _V_a_l_u_e

     This creates a definition for _M_a_c_r_o_N_a_m_e whose value is _V_a_l_u_e



Version 3.9 PL0                 UW                             35
DMAKE(p)             Unsupported Free Software            DMAKE(p)



     only when ttaarrggeett is being made.  You may use a conditional
     macro assignment anywhere that a regular macro assignment
     may appear, including as the value of a $(assign ...) macro.

     The new definition is associated with the most recent cell
     definition for ttaarrggeett.  If no prior definition exists then
     one is created.  The implications of this are immediately
     evident in the following example:

          foo := hello

          all : cond;@echo "all done, foo=[$(foo)] bar=[$(bar)]"

          cond ?= bar := global decl

          cond .SETDIR=unix::;@echo $(foo) $(bar)
          cond ?= foo := hi

          cond .SETDIR=msdos::;@echo $(foo) $(bar)
               cond ?= foo := hihi

     The first conditional assignment creates a binding for 'bar'
     that is activated when 'cond' is made.  The bindings follow-
     ing the :: definitions are activated when their respective
     recipe rules are used.  Thus the first binding serves to
     provide a global value for 'bar' while any of the cond ::
     rules are processed, and the local bindings for 'foo' come
     into effect when their associated :: rule is processed.

     Conditionals for targets of .UPDATEALL are all activated
     before the target group is made.  Assignments are processed
     in order.  Note that the value of a conditional macro
     assignment is NOT AVAILABLE until the associated target is
     made, thus the construct

          mytarget ?= bar := hello
          mytarget ?= foo := $(bar)

     results in $(foo) expanding to "", if you want the result to
     be "hello" you must use:

          mytarget ?= bar := hello
          mytarget ?= foo  = $(bar)

     Once a target is made any associated conditional macros are
     deactivated and their values are no longer available.
     Activation occurrs after all inference, and .SETDIR direc-
     tives have been processed and after $@ is assigned, but
     before prerequisites are processed; thereby making the
     values of conditional macro definitions available during
     construction of prerequisites.




Version 3.9 PL0                 UW                             36
DMAKE(p)             Unsupported Free Software            DMAKE(p)



     If a %-meta rule target has associated conditional macro
     assignments, and the rule is chosen by the inference algo-
     rithm then the conditional macro assignments are inferred
     together with the associated recipe.

DDYYNNAAMMIICC PPRREERREEQQUUIISSIITTEESS
     ddmmaakkee 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:

          fred : $$@.c

     causes the $$@ to be expanded when ddmmaakkee is making fred, and
     it resolves to the target _f_r_e_d.  This enables dynamic prere-
     quisites to be generated.  The value of @ may be modified by
     any of the valid macro modifiers.  So you can say for exam-
     ple:

          fred.out : $$(@:b).c

     where the $$(@:b) expands to _f_r_e_d.  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 ini-
     tially 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.

     If dynamic macro expansion results in multiple white space
     separated tokens then these are inserted into the prere-
     quisite list inplace of the dynamic prerequisite.  If the
     new list contains additional dynamic prerequisites they will
     be expanded when they are processed.  The level of recursion
     in this expansion is controlled by the value of the variable
     DDYYNNAAMMIICCNNEESSTTIINNGGLLEEVVEELL and is set to 100 by default.

BBIINNDDIINNGG TTAARRGGEETTSS
     This operation takes a target name and binds it to an exist-
     ing file, if possible.  ddmmaakkee 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 per-
     form the binding, the following set of rules is used.
     Assume that we are trying to bind a target whose name is of
     the form _X_._s_u_f_f, where _._s_u_f_f is the suffix and _X is the stem
     portion (ie. that part which contains the directory and the
     basename).  ddmmaakkee 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 opera-
     tion is user controlled via the settings of the various



Version 3.9 PL0                 UW                             37
DMAKE(p)             Unsupported Free Software            DMAKE(p)



     .SOURCE targets.

          1.   If target has the .SYMBOL attribute set then look
               for it in the library.  If found, replace the tar-
               get name with the library member name and continue
               with step 2.  If the name is not found then
               return.

          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. _._s_u_f_f 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).

          3.   The search in step 2. failed.  Repeat the same
               search but this time use the special target
               .SOURCE.  (a default target of '.SOURCE : .NULL'
               is defined by ddmmaakkee at startup, and is user rede-
               finable)

          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.).

          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 ddmmaakkee 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.

     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



Version 3.9 PL0                 UW                             38
DMAKE(p)             Unsupported Free Software            DMAKE(p)



     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 ddmmaakkee stops, then the user may
     fix the error and make again.  ddmmaakkee will not remake any of
     the targets whose object files have already been generated
     as long as none of their prerequisite files have been modi-
     fied as a result of the fix.

     When ddmmaakkee constructs target pathnames './' substrings are
     removed and substrings of the form 'foo/..' are eliminated.
     This may result in somewhat unexpected values of the macro
     expansion $$@@, but is infact the corect result.

     When defining .SOURCE and .SOURCE.x targets the construct

          .SOURCE :
          .SOURCE : fred gery

     is equivalent to

          .SOURCE :- fred gery

     ddmmaakkee correctly handles the UNIX Make variable VPATH.  By
     definition VPATH contains a list of ':' separated direc-
     tories to search when looking for a target.  ddmmaakkee maps
     VPATH to the following special rule:

          .SOURCE :^ $(VPATH:s/:/ /)

     Which takes the value of VPATH and sets .SOURCE to the same
     set of directories as specified in VPATH.

PPEERRCCEENNTT((%%)) RRUULLEESS AANNDD MMAAKKIINNGG IINNFFEERREENNCCEESS
     When ddmmaakkee makes a target, the target's set of prerequisites
     (if any) must exist and the target must have a recipe which
     ddmmaakkee can use to make it.  If the makefile does not specify
     an explicit recipe for the target then ddmmaakkee 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 suf-
     fixes.  The exact workings of this mechanism were sometimes
     difficult to understand and often limiting in their useful-
     ness.  Instead, ddmmaakkee supports the concept of _%_-_m_e_t_a rules.
     The syntax and semantics of these rules differ from standard
     rule lines as follows:

          _<_%_-_t_a_r_g_e_t_> [_<_a_t_t_r_i_b_u_t_e_s_>] _<_r_u_l_e_o_p_> [_<_%_-_p_r_e_r_e_q_u_i_s_i_t_e_s_>] [;_<_r_e_c_i_p_e_>]




Version 3.9 PL0                 UW                             39
DMAKE(p)             Unsupported Free Software            DMAKE(p)



     where _%_-_t_a_r_g_e_t is a target containing exactly a single `%'
     sign, _a_t_t_r_i_b_u_t_e_s is a list (possibly empty) of attributes,
     _r_u_l_e_o_p is the standard set of rule operators, _%_-_p_r_e_r_e_-
     _q_u_i_s_i_t_e_s , if present, is a list of prerequisites containing
     zero or more `%' signs, and _r_e_c_i_p_e_, if present, is the first
     line of the recipe.

     The _%_-_t_a_r_g_e_t 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 pat-
     tern.  Consider the following examples:

          %.c       matches fred.c but not joe.c.Z
          dir/%.c   matches dir/fred.c but not dd/fred.c
          fred/%    matches fred/joe.c but not f/joe.c
          %         matches anything

     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 ddmmaakkee constructs the new
     dependency.  As an example the following %-meta rules
     describe the following:

          %.c : %.y ; recipe...

     describes how to make any file ending in .c if a correspond-
     ing file ending in .y can be found.

          foo%.o : fee%.k ; recipe...

     is used to describe how to make fooxxxx.o from feexxxx.k.

          %.a :; recipe...

     describes how to make a file whose suffix is .a without
     inferring any prerequisites.

          %.c : %.y yaccsrc/%.y ; recipe...

     is a short form for the construct:

          %.c : %.y ; recipe...
          %.c : yaccsrc/%.y ; recipe...

     ie. It is possible to specify the same recipe for two
     %-rules by giving more than one prerequisite in the prere-
     quisite list.  A more interesting example is:




Version 3.9 PL0                 UW                             40
DMAKE(p)             Unsupported Free Software            DMAKE(p)



          % : RCS/%,v ; co $<

     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:

          % : s.% ; get $<


     The previous RCS example defines an infinite rule, because
     it says how to make _a_n_y_t_h_i_n_g from RCS/%,v, and _a_n_y_t_h_i_n_g also
     includes RCS/fred.c,v.  To limit the size of the graph that
     results from such rules ddmmaakkee 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
     ddmmaakkee would generate the dependency graph:

          % --> RCS/%,v --> RCS/RCS/%,v,v

     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.  ddmmaakkee further assumes that any target
     that has no suffix can be made from a prerequisite that has
     at least one suffix.

     ddmmaakkee supports dynamic prerequisite generation for prere-
     quisites 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 _R_C_S_/_f_r_e_d_._c_,_v from
     the target _f_r_e_d_._c, but cannot infer how to find
     _s_r_c_d_i_r_/_R_C_S_/_f_r_e_d_._c_,_v from _s_r_c_d_i_r_/_f_r_e_d_._c because the above
     rule will cause ddmmaakkee 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).

     A more versatile formulation of the above RCS check out rule
     is the following:

          % :  $$(@:d)RCS/$$(@:f),v : co $@

     This rule uses the dynamic macro $@ to specify the prere-
     quisite 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 _R_C_S_/ to it, and appending the



Version 3.9 PL0                 UW                             41
DMAKE(p)             Unsupported Free Software            DMAKE(p)



     target file name with a trailing _,_v attached to the previous
     result.

     ddmmaakkee 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:

          fred.o : fred.c ; rule to make fred.o
          fred.o : local.h

     then this can be inferred for fred.o from the following
     inference rule:

          %.o : %.c 'local.h' ; rule to make a .o from a .c

     You may infer indirect prerequisites that are a function of
     the value of '%' in the current rule.  The meta-rule:

          %.o : %.c '$(INC)/%.h' ; rule to make a .o from a .c

     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:

          %.o : %.c %.f 'local.h'; recipe

     is equivalent to:

          %.o : %.c 'local.h' : recipe

     while:

          %.o :| %.c %.f 'local.h'; recipe

     is equivalent to:

          %.o : %.c 'local.h' : recipe
          %.o : %.f 'local.h' : recipe


     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



Version 3.9 PL0                 UW                             42
DMAKE(p)             Unsupported Free Software            DMAKE(p)



     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 ddmmaakkee
     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.

     ddmmaakkee 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:

          .c.o :; cc -c $< -o $@

     ddmmaakkee maps this into the following %-rule:

          %.o : %.c; cc -c $< -o $@

     Furthermore, ddmmaakkee 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

          .suff :; recipe

     gets mapped into:

          % : %.suff; recipe

     and the construct

          .c~.o :; recipe

     gets mapped into:

          %.o : s.%.c ; recipe

     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 sup-
     port.  When enabled, these mappings allow processing of
     existing SYSV makefiles without modifications.

     ddmmaakkee bases all of its inferences on the inference graph
     constructed from the %-rules defined in the makefile.  It



Version 3.9 PL0                 UW                             43
DMAKE(p)             Unsupported Free Software            DMAKE(p)



     knows exactly which targets can be made from which prere-
     quisites by making queries on the inference graph.  For this
     reason .SUFFIXES is not needed and is completely ignored.

     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 prere-
     quisite can be made.  Without _t_r_a_n_s_i_t_i_v_e _c_l_o_s_u_r_e on the
     inference graph the above rule describes precisely when an
     inference match terminates the search.  If transitive clo-
     sure is enabled (the usual case), and a prerequisite does
     not exist or cannot be made, then ddmmaakkee invokes the infer-
     ence 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 ddmmaakkee 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 clo-
     sure can be disabled by giving the -T switch on the command
     line.

     A word of caution.  ddmmaakkee bases its transitive closure on
     the %-meta rule targets.  When it performs transitive clo-
     sure 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:

          %.o : %.c :; rule for making .o from .c
          %.c : %.y :; rule for making .c from .y
          % : RCS/%,v :; check out of RCS file

     will, by performing transitive closure, allow ddmmaakkee 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:
          .NOINFER : RCS/%,v
     Thereby indicating that the RCS file is the end of the



Version 3.9 PL0                 UW                             44
DMAKE(p)             Unsupported Free Software            DMAKE(p)



     inference chain.  Whenever the inference algorithm deter-
     mines that a target can be made from more than one prere-
     quisite and the inference chains for the two methods are the
     same length the algorithm reports an ambiguity and prints
     the ambiguous inference chains.

     ddmmaakkee tries to remove intermediate files resulting from
     transitive closure if the file is not marked as being PRE-
     CIOUS, or the --uu 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
     ddmmaakkee 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 ddmmaakkee constructs a list of the inter-
     mediate files to be removed and makes them prerequisites of
     .REMOVE.  It then makes .REMOVE thereby removing the prere-
     quisites if the recipe of .REMOVE says to.  Typically
     .REMOVE is defined in the startup file as:

          .REMOVE :; $(RM) $<

MMAAKKIINNGG TTAARRGGEETTSS
     In order to update a target ddmmaakkee 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.  ddmmaakkee
     supports two types of recipes.  The regular recipes and
     group recipes.

     When a regular recipe is invoked ddmmaakkee 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 per-
     sist across recipe lines (e.g. cd requests in a recipe line
     do not carry over to the next recipe line).  This is true
     even in environments such as MMSSDDOOSS, where dmake internally
     sets the current working director to match the directory it
     was in before the command was executed.

     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 ddmmaakkee constructs the command line:

          $(SHELL) $(SHELLFLAGS) $(expanded_recipe_command)



Version 3.9 PL0                 UW                             45
DMAKE(p)             Unsupported Free Software            DMAKE(p)



     Normally ddmmaakkee 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.

     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 GROUP-
     SHELL, and its flags are taken from the value of the macro
     GROUPFLAGS.  If a target has the .PROLOG attribute set then
     ddmmaakkee 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 ].

     The recipe flags [+,-,%,@] are recognized at the start of a
     recipe line even if they appear in a macro.  For example:

          SH = +
          all:
               $(SH)echo hi

     is completely equivalent to writing

          SH = +
          all:
               +echo hi


     The last step performed by ddmmaakkee 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.  ddmmaakkee then expands the
     macro COMMAND which by default is set to

          COMMAND = $(CMNDNAME) $(CMNDARGS)

     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 ddmmaakkee. You can for
     example define COMMAND to be

          COMMAND = $(CMNDNAME) @$(mktmp $(CMNDARGS))

     which dumps the arguments into a temporary file and runs the
     command



Version 3.9 PL0                 UW                             46
DMAKE(p)             Unsupported Free Software            DMAKE(p)



          $(CMNDNAME) @/tmp/ASAD23043

     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 ddmmaakkee does not perform the above expansion.  On sys-
     tems, such as UNIX, that handle long command lines this pro-
     vides a slight saving in processing the makefiles.

MMAAKKIINNGG LLIIBBRRAARRIIEESS
     Libraries are easy to maintain using ddmmaakkee.  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 prere-
     quisites.  The prerequisites should be the object members
     that are to go into the library.  When ddmmaakkee 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.

          mylib.a .LIBRARY : mem1.o mem2.o mem3.o
               rules for making library...
               # remember to remove .o's when lib is made

          # equivalent to:  '%.o : %.c ; ...'
          .c.o :; rules for making .o from .c say

     ddmmaakkee 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.

     ddmmaakkee tries to handle the old library construct format in a
     sensible way.  The construct _l_i_b_(_m_e_m_b_e_r_._o_) is separated and
     the _l_i_b portion is declared as a library target.  The new
     target is defined with the .LIBRARY attribute set and the
     _m_e_m_b_e_r_._o portion of the construct is declared as a prere-
     quisite of the lib target.  If the construct _l_i_b_(_m_e_m_b_e_r_._o_)
     appears as a prerequisite of a target in the makefile, that
     target has the new name of the lib assigned as its prere-
     quisite.  Thus the following example:

          a.out : ml.a(a.o) ml.a(b.o); $(CC) -o $@  $<

          .c.o :; $(CC) -c $(CFLAGS) -o $@  $<
          %.a:
               ar rv $@ $?
               ranlib $@
               rm -rf $?




Version 3.9 PL0                 UW                             47
DMAKE(p)             Unsupported Free Software            DMAKE(p)



     constructs the following dependency graph.

          a.out : ml.a; $(CC) -o $@  $<
          ml.a .LIBRARY : a.o b.o

          %.o : %.c ; $(CC) -c $(CFLAGS) -o $@  $<
          %.a :
               ar rv $@ $?
               ranlib $@
               rm -rf $?

     and making a.out then works as expected.

     The same thing happens for any target of the form
     _l_i_b_(_(_e_n_t_r_y_)_).  These targets have an additional feature in
     that the _e_n_t_r_y target has the .SYMBOL attribute set automat-
     ically.

     NOTE:  If the notion of entry points is supported by the
     archive and by ddmmaakkee (currently not the case) then ddmmaakkee
     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 _e_n_t_r_y 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 dis-
     abled as there is little standardization among archive for-
     mats, 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).

     Finally, when ddmmaakkee 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 ddmmaakkee.

KKEEEEPP SSTTAATTEE
     ddmmaakkee 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



Version 3.9 PL0                 UW                             48
DMAKE(p)             Unsupported Free Software            DMAKE(p)



     keeping is used in the maintenance of ddmmaakkee 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.

     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.

     The Sun Microsystem's Make construct

          .KEEP_STATE :

     is recognized and is mapped to ..KKEEEEPP__SSTTAATTEE::==__ssttaattee..mmkk.  The
     ddmmaakkee 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.  ddmmaakkee instead provides the tool, ccddeeppeenndd,
     to scan C source files and to produce depedency information.
     Users are free to modify cdepend to produce other dependency
     files.  (NOTE: ccddeeppeenndd does not come with the distribution
     at this time, but will be available in a patch in the near
     future)

MMUULLTTII PPRROOCCEESSSSIINNGG
     If the architecture supports it then ddmmaakkee is capable of
     making a target's prerequisites in parallel.  ddmmaakkee 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.  ddmmaakkee
     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.  Note that when you
     specify --PP 44 then four child processes are run concurrently
     but ddmmaakkee actually displays the fifth command it will run
     immediately upon a child process becomming free.  This is an
     artifact of the method used to traverse the dependency graph
     and cannot be removed.  If a parallel make is being per-
     formed then the following restrictions on parallelism are
     enforced.

          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.

          2.   If a target contains multiple recipe definitions
               (cf. :: rules) then these are performed sequen-
               tially in the order in which the :: rules are
               specified within the makefile and in parallel with



Version 3.9 PL0                 UW                             49
DMAKE(p)             Unsupported Free Software            DMAKE(p)



               the recipes of other targets.

          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.

          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.

     Note:  If you specify a parallel make then the order of tar-
     get update and the order in which the associated recipes are
     invoked will not correspond to that displayed by the -n
     flag.

CCOONNDDIITTIIOONNAALLSS
     ddmmaakkee supports a makefile construct called a _c_o_n_d_i_t_i_o_n_a_l.
     It allows the user to conditionally select portions of
     makefile text for input processing and to discard other por-
     tions.  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:

          .IF  _e_x_p_r_e_s_s_i_o_n
             ... if text ...
          .ELIF  _e_x_p_r_e_s_s_i_o_n
             ... if text ...
          .ELSE
             ... else text ...
          .END

     The .ELSE and .ELIF portions are optional, and the condi-
     tionals 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.

     _e_x_p_r_e_s_s_i_o_n can be one of the following three forms:

          <text> | <text> == <text> | <text> != <text>

     where _t_e_x_t 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 dis-
     carded 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



Version 3.9 PL0                 UW                             50
DMAKE(p)             Unsupported Free Software            DMAKE(p)



     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.

EEXXAAMMPPLLEESS
          # A simple example showing how to use make
          #
          prgm : a.o b.o
               cc a.o b.o -o prgm
          a.o : a.c g.h
               cc a.c -o $@
          b.o : b.c g.h
               cc b.c -o $@

     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:

          %.o : %.c; cc -c $(CFLAGS) -o $@ $<

     Since there exists a rule (defined in the startup file) for
     making .o's from .c's ddmmaakkee will use that rule for manufac-
     turing a .o from a .c and we can specify our dependencies
     more concisely.

          prgm : a.o b.o
               cc -o prgm $<
          a.o b.o : g.h

     A more general way to say the above using the new macro
     expansions would be:

          SRC = a b
          OBJ = {$(SRC)}.o

          prgm : $(OBJ)
               cc -o $@ $<

          $(OBJ) : g.h

     If we want to keep the objects in a separate directory,
     called objdir, then we would write something like this.

          SRC = a b
          OBJ = {$(SRC)}.o

          prgm : $(OBJ)



Version 3.9 PL0                 UW                             51
DMAKE(p)             Unsupported Free Software            DMAKE(p)



               cc $< -o $@

          $(OBJ) : g.h
          %.o : %.c
               $(CC) -c $(CFLAGS) -o $(@:f) $<
               mv $(@:f) objdir

          .SOURCE.o : objdir       # tell make to look here for .o's

     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)

          SRC  = a b
          LIB  = lib
          LIBm = { $(SRC) }.o

          prgm: $(LIB)
               cc -o $@ $(LIB)

          $(LIB) .LIBRARY : $(LIBm)
               ar rv $@ $<
               rm $<

     Finally, suppose that each of the source files in the previ-
     ous example had the `:' character in their target name.
     Then we would write the above example as:

          SRC  = f:a f:b
          LIB  = lib
          LIBm = "{ $(SRC) }.o"         # put quotes around each token

          prgm: $(LIB)
               cc -o $@ $(LIB)

          $(LIB) .LIBRARY : $(LIBm)
               ar rv $@ $<
               rm $<

CCOOMMPPAATTIIBBIILLIITTYY
     There are two notable differences between ddmmaakkee and the
     standard version of BSD UNIX 4.2/4.3 Make.

          1. BSD UNIX 4.2/4.3 Make supports wild card filename
             expansion for prerequisite names.  Thus if a direc-
             tory contains a.h, b.h and c.h, then a line like

                  target: *.h

             will cause UNIX make to expand the *.h into "a.h b.h
             c.h".  ddmmaakkee does not support this type of filename
             expansion.



Version 3.9 PL0                 UW                             52
DMAKE(p)             Unsupported Free Software            DMAKE(p)



          2. Unlike UNIX make, touching a library member causes
             ddmmaakkee 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 ddmmaakkee touches the library file
             itself, and prints a warning.

     ddmmaakkee is not compatible with GNU Make.  In particular it
     does not understand GNU Make's macro expansions that query
     the file system.

     ddmmaakkee is fully compatible with SYSV AUGMAKE, and supports
     the following AUGMAKE features:

          1. The word iinncclluuddee appearing at the start of a line
             can be used instead of the ".INCLUDE :" construct
             understood by ddmmaakkee.

          2. 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:

                  str[ |\t][ |\t]*

             (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) Normally _s_u_b is expanded before the
             substitution is made, if you specify -A on the com-
             mand line then sub is not expanded.

          3. The macro % is defined to be $@ (ie. $% expands to
             the same value as $@).

          4. The AUGMAKE notion of libraries is handled
             correctly.

          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".

          6. Directories are always made if you specify --AA.  This
             is consistent with other UNIX versions of Make.

          7. Makefiles that utilize virtual targets to force mak-
             ing of other targets work as expected if AUGMAKE
             special target handling is enabled.  For example:

                  FRC:
                  myprog.o : myprog.c $(FRC) ; ...



Version 3.9 PL0                 UW                             53
DMAKE(p)             Unsupported Free Software            DMAKE(p)



             Works as expected if you issue the command

                  'ddmmaakkee -A FRC=FRC'

             but fails with a 'don't know how to make FRC' error
             message if you do not specify AUGMAKE special target
             handling via the -A flag (or by setting AUGMAKE:=yes
             internally).

LLIIMMIITTSS
     In some environments the length of an argument string is
     restricted.  (e.g. MSDOS command line arguments cannot be
     longer than 128 bytes if you are using the standard
     command.com command interpreter as your shell, ddmmaakkee text
     diversions may help in these situations.)

PPOORRTTAABBIILLIITTYY
     To write makefiles that can be moved from one environment to
     another requires some forethought.  In particular you must
     define as macros all those things that may be different in
     the new environment.  ddmmaakkee has two facilities that help to
     support writing portable makefiles, recursive macros and
     conditional expressions.  The recursive macros, allow one to
     define environment configurations that allow different
     environments for similar types of operating systems.  For
     example the same make script can be used for SYSV and BSD
     but with different macro definitions.

     To write a makefile that is portable between UNIX and MSDOS
     requires both features since in almost all cases you will
     need to define new recipes for making targets.  The recipes
     will probably be quite different since the capabilities of
     the tools on each machine are different.  Different macros
     will be needed to help handle the smaller differences in the
     two environments.

FFIILLEESS
     Makefile, makefile, startup.mk (use dmake -V to tell you
     where the startup file is)

SSEEEE AALLSSOO
     sh(1), csh(1), touch(1), f77(1), pc(1), cc(1)
     S.I. Feldman  _M_a_k_e _- _A _P_r_o_g_r_a_m _f_o_r _M_a_i_n_t_a_i_n_i_n_g _C_o_m_p_u_t_e_r _P_r_o_-
     _g_r_a_m_s

AAUUTTHHOORR
     Dennis Vadura, CS Dept. University of Waterloo.
     dvadura@watdragon.uwaterloo.ca
     Many thanks to Carl Seger for his helpful suggestions, and
     to Trevor John Thompson for his many excellent ideas and
     informative bug reports.




Version 3.9 PL0                 UW                             54
DMAKE(p)             Unsupported Free Software            DMAKE(p)



BBUUGGSS
     Some system commands return non-zero status inappropriately.
     Use --ii (`-' within the makefile) to overcome the difficulty.

     Some systems do not have easily accessible time stamps for
     library members (MSDOS, AMIGA, etc) for these ddmmaakkee uses the
     time stamp of the library instead and prints a warning the
     first time it does so.  This is almost always ok, except
     when multiple makefiles update a single library file.  In
     these instances it is possible to miss an update if one is
     not careful.

     This man page is way too long.

WWAARRNNIINNGGSS
     Rules supported by make(1) may not work if transitive clo-
     sure is turned off (-T, .NOINFER).

     PWD from csh/ksh will cause problems if a cd operation is
     performed and -e or -E option is used.

     Using internal macros such as COMMAND, may wreak havoc if
     you don't understand their functionality.
































Version 3.9 PL0                 UW                             55
