NAME

myke - my make program; maintain, update, and regenerate groups of programs


SYNOPSIS

myke [-deikmnpqrstuvENR] [-D level] [-S shell] [-f makefile]... [-j jobs] [--] [macro-name=string]... [target]...


DESCRIPTION

Myke is a program used to maintain groups of files which depend upon one another. Supplied with a description of how the files are related and the actions implied by those relationships, myke will undertake to re-establish the relationships after the files have changed.


OPTIONS

-d
Activate debug mode. Displays decision paths and information pertinent to debugging a Makefile. This option overrides the -s option.

-D level
Super debug mode. This usually prints out extremely verbose debugging information. Level is an integer, broken into bit fields. Bits 0 and 1 are passed as an argument to the malloc_debug() routine if myke was compiled with the -DEBUG option on a Sun. On other systems the low two bits are ignored. Bit 2 causes myke to dump core in certain error conditions which would otherwise cause it merely to exit with an error status. If any of the higher bits are set, extremely verbose debugging information is emitted. This option implies the -d option. Note that this option does not imply the -p option.

-S shell
Shell for actions. By default, myke uses /bin/sh to run actions. This option changes that default. Note that the :shell directive still overrides this.

-e
Import environment variables as macro definitions after reading any Makefiles. Strings of the form ``name=value'' in the environment will be used as macro definitions. These definitions supercede definitions in the Makefiles.

-E
Import environment variables as macro definitions prior to reading any local Makefiles, but after reading the built-in rules. This option provides the same behaviour that make exhibits with respect to the environment. The -e and -E options may not both be used.

-f makefile
Specify a description file. If a -f option is not supplied, myke will search for description files as described below under Execution. Specifying `-' will cause standard input to be read.

-i
Ignore error codes returned by invoked commands.

-j jobs
Specify how many jobs may run at once. This flag implies the -k flag. If the -k flag is used without the -j flag, jobs defaults to 4 (a somewhat arbitrary small integer).

-k
Normally, when a target cannot be made, all work is abandoned. Specifying this option permits work to continue on targets which do not depend on the target which failed.

-m
Do not treat undefined macros as errors. Undefined macros will evaluate to empty strings.

-n
No execute mode. Commands are printed but not executed unless they contain the special macro $(MAKE), in which case they are executed anyway. Even actions beginning with `@' are printed. This option implies the -x option.

-N
Really no execute mode. Not even lines containing the macro $(MAKE) will be executed. This option implies the -n option.

-p
Print out the complete set of macro definitions and target descriptions. This option has side effects; see the NOTES section.

-q
Query mode. The command returns zero or non-zero status depending on whether the target file is or is not up to date. This option implies the -n option. This option has a side effect associated with the $(MAKE) macro, outlined in the NOTES section.

-r
Ignore built-in rules. This option implies the -R option.

-R
Ignore global built-in rules. Personal built-in rules are still read.

-s
Silent mode. Do not print out command lines. This option is overridden by the -n option.

-t
Touch targets which must be remade in order to bring them up to date, rather than performing the appropriate actions.

-u
Unconditionally make targets. Do not worry about modification dates; assume all targets are out of date.

-v
Verbose mode. List Makefiles as they are read in.

-x
Print all actions taken, including actions beginning with `@'. This option overrides the -s option.

macro=string
Macro definitions may appear on the command line. These are also exported to subsequent $(MAKE)s. Definition here overrides definition anywhere else, except for readonly macros, which may not be redefined.

targets...
Specify one or more targets to make. If no target is supplied here, the first target in the Makefile will be used.


MAKEFILES

When myke tries to bring a system up to date, it requires information about the system. This information is stored in Makefiles. The basic component of a Makefile is a dependency, which is a set of lines of the form:

        I<target>: I<prerequisites>
                I<actions...>

This asserts that target is made by performing the shell script recounted as actions, but only after the prerequisites have been brought up to date in a similar fashion. Myke looks in three places for this information:

{/usr/local/etc/mykerc}
This is the system-wide set of rules.

Local Mykerc
After reading the global mykerc, myke looks for a local mykerc for more information. Rules in the local mykerc override rules in the global mykerc where they conflict. Myke tries $MYKERC (if set and non-null), Mykerc, and mykerc in that order. If $MYKERC is chosen, it is considered to be a colon separated list of files to be used. Empty components will be silently dropped from the list. Definitions in later files in the list override definitions in earlier files in the list, and all override definitions in the global mykerc.

Local Makefile
Having consulted the above two files, myke looks for a local Makefile for information about this particular system. Rules in the local Makefile override rules in either of the above two files where they conflict. Myke tries $MYKEFILE (if set and non-null), Mykefile, mykefile, and $mykefile (if set and non-null) in that order. The make will abort if none of these is found. If you wish to get by without a local Makefile, set $mykefile to /dev/null.

Dependencies

Dependencies consist of three parts, a target, a list of prerequisites, and a list of actions to perform when the target is out of date with respect to the prerequisites. After the line with the target and prerequisites, all following lines which begin with a blank character are taken to be actions. These are each performed by a separate shell. More than one target may be named, in which case it is as though the entire dependency had been written out for each target.

Macros

Macros are variables containing expressions which evaluate to strings. A line of the form

        macro-name = value

defines a macro. A macro name may be any identifier. Where the sequence $(macro-name) is encountered, the named macro will be evaluated, and the resulting string inserted at that point. The syntax ${macro-name} may also be used. Should the macro's name be a single character the notation $x may be used, where x is the macro name. More than one macro may be named, in which case it is as though the entire macro definition had been written out for each macro. In fact, macro-name is a macro expression which should evaluate to a list of macro names.

There are several special macros which may be used. In the list below, those which refer to targets or prerequisites may only be used in actions associated with that target, except for $@ which may be used the the prerequisite list as well.

$$
The $$ macro evaluates to the $ character.

$@
The $@ macro stands for the full target name of the current target (but see $% below).

$%
The $% macro is only evaluated when the target is an archive library member of the form library(member). In this case, $@ evaluates to library and $% evaluates to member.

$?
The $? macro stands for the prerequisites which are out of date with respect to the current target.

$*
The macro $* is replaced by the current target with the suffix deleted. It corresponds to $(@P), and is maintained for historical reasons.

$<
The macro $< stands for the prerequisites of the current target. $? is a subset of this.

$/
The macro $/ stands for the prerequisites which were out of date in the last set of prerequisites. This will normally be the same as $?. However, if the :make pseudo-command has been used to introduce a new set of prerequisites $/ will be determined from this new set. $? does not change with new sets of prerequisites.

$>
The macro $> stands for the most recent set of prerequisites. $< does not change with new sets of prerequisites.

$.
The macro $. is replaced by the pathname of the current working directory.

Macros may also be invoked as $((macro-name)). In this case each word in the macro is enumerated with each word in the expansion of the macro. This is known as a repeating macro. For example, given

        x = a b c
        y = _
        z = f g

        w = fred frog$((x))$y$((z))

the value of $w is

        fred froga_f froga_g frogb_f frogb_g frogc_f frogc_g

In the above examples, macro-name may also be replaced with ``quoted-string'' or 'quoted-string', in which case the value of the string will be used instead of the value of the macro.

Macros may also be defined as

        macro-name(arg[,arg...]) = value

It may then be invoked as $(macro (args...)), and the arguments supplied will be available as macros named after the arguments in the definition. For example, given

        macro(arg1,arg2) = $(arg1)x$((arg2))

        it:
                echo '$(macro (this,and that)) $(macro (a,b))'

the echo action will expand to

        echo 'thisxand thisxthat axb'

In addition to the above invocations, the quoted-string or macro-name may be followed by a series of modifier characters to manipulate the value of the macro or string, such as:

        $(macro-name F)

which produces the filename part of the value of macro-name. If arguments are supplied as well as modifiers then the arguments must preceed the modifiers. Most modifiers affect each word of the macro individually. Appended to a macro as described above, the modifiers listed below have effect upon the words in the macro as follows:

blanks
Blanks and comments may appear in the modifier string, and have no effect, although they may be used to separate the macro name from the modifiers.

D
Return the directory part of the word. If there is no directory part, dot\ (`.') is generated. See the NOTES section.

F
Return the filename part of the word.

P
Return the long prefix to the word. This is everything up to, but not including, the last dot in the word. If this modifier is followed by the sequence [c] then c will be used instead of a dot as the delimiter.

p
Return the short prefix to the word. This is everything up to, but not including, the first dot in the word. As with the P modifier, another character may be used instead of a dot.

S
Return the short suffix to the word. This is everything after, but not including, the last dot in the word. As with the P modifier, another character may be used instead of a dot.

s
Return the long suffix to the word. This is everything after, but not including, the first dot in the word. As with the P modifier, another character may be used instead of a dot.

L
With a library member specification of the form library(member), returns library.

M
With a library member specification of the form library(member), returns member.

U
Returns the unique set of words.

N
Normalises a path by stripping ., .., and empty components. Paths relative to the current directory remain relative, other paths become full paths.

G
Treat the word as a shell pattern and do the necessary expansion (a process known as globbing). If this modifier is followed by a query ('?') the pattern need not match any existing files, in which case it will be replaced by the empty string. Otherwise this must match at least one file. Unlike the shell, myke will not sort the globbed files. The globbing supported by myke is a superset of that supported by /bin/sh(1), as follows:
~ or ~user
at the start of a pattern is expanded to the home directory of the current user or user respectively.

?
matches a single character. It will not match a dot at the start of a component.

  • matches zero or more characters. It will not match a dot at the start of a component.

    [[^]range]
    matches any character in range. If a circumflex (`^') is present immediately after the opening [, it will match any character not in range. A range is a list composed of [c1]-[c2] where either c1 or c2 may be omitted, defaulting to the lowest and highest characters available respectively. Any character may be specified in a range by escaping it with a slosh. It will not match a dot at the start of a component. This can be construed as a bug.

    {pattern}
    Perform grouping. This is most useful with the ! metacharacter (vide infra). Patterns enclosed in {} may nest.

    !item
    Match any string which does not match item. Item may be a single character, a metacharacter (?, *), a range specifier (vide supra), or sub-pattern grouped with { and }.

  • g
    As for G except in the case of symbolic links. Globbing with G will match a symbolic link which does not resolve to a file; g will not. As with G, g may be followed by a query, with the same effect.

    E
    Evaluate the string again. Performs macro substitution at this point then proceeds with the rest of the modifiers.

    :,pattern,replacement,
    Introduce a substitution at this point, after the style of ed(1). The first non-blank character after the colon is taken to be a delimiter for the pattern and replacement strings which follow. This delimiter (represented by the commas above) must be a printable non-alphanumeric character. The pattern is a regular expression (see egrep(1)). In place of the each occurrence of the pattern the replacement string is copied with the following substitutions: `&' or `\0' is replaced by the string matched by the entire pattern, and `\n'' (where n is a digit other than 0), is replaced by the string matched by the nth parenthesised sub-expression, numbered left-to-right in order of opening parentheses.

    <
    Treat the string as a list of files to be opened, and replace the string with the concatenation of all words found in the files. If followed by a query, any file may be absent or inaccessable. Otherwise all the opens must succeed.

    +, -, *
    Following this may be a quoted string, the name of a macro, or a macro expression inside $(...). The string will be treated as a set of words and will have the argument applied to it with the appropriate operation (addition, subtraction, or intersection).

    [!]{comma-list}[?]
    Treat the string as a list of words and select those specified in comma-list, discarding the others. A comma-list is a list of integral ranges separated by blank space or commas. An integral range is either a positive integer or a pair of positive integers separated by a dash ('-'). These integers are indices of words in the list, with 1 corresponding to the first word, 2 to the second, and so on. The comma-list may be replaced by an identifier which is the name of a macro which evaluates to a comma-list. If the list is preceeded by an exclaimation point ('!') the comma-list specifies words to discard rather than words to keep. If followed by a query, the indices may fall outside the list (i.e. 0, or n where n is greater than the number of words in the list).

    [!]/regexp/
    Treat the string as a list of words, and select those which match regexp, which is a macro expression which evaluates to a regular expression after the style of ed(1). If the expression is preceeded by an exclaimation point then regexp selects words to discard rather than words to keep.

    It should be noted that the S, s, P, and p modifiers do not respect slashes (`/'). To apply them to macros with directory parts one should say something like:

            $(thing D)/$(thing FP)

    Preprocessor

    Some preprocessing is done to Makefiles. When reading them, the sequence slosh (`\') followed by a newline is replaced by a single newline and the lines so separated are treated as single lines. For example, one may say:

            a_macro = something \
                    and something else

    In actions the preprocessing stops at this point. In other lines the comment character (`#') introduces a comment which extends through to the next newline, and is treated like a blank. For example:

            a_macro = something          # anything you like \
                    and something else # likewise

    After comments are stripped, lines beginning with colons (`:') are considered to be preprocessor directives. Directives are case-insensitive and may be invoked by any unique prefix. The following directives are recognised:

    :shell program
    The specified program is used instead of /bin/sh to perform any following actions. Note that this does not affect the nature of the globbing performed by the G modifier character.

    :import names...
    The specified environment strings are treated as macro definitions.

    :export names...
    The macros named are marked to be exported to subsequent mykes via the $(MAKE) macro, should they be defined.

    :readonly names...
    The macros named are marked readonly, and may not be redefined later in the description. Undefined macros may not be marked readonly.

    :setenv names...
    The named macros are made available as entries in the environment of actions.

    :ifdef name
    Text from here until a matching :else or :endif directive will only be interpreted if the macro $(name) has been defined. :ifdef constructs may be nested.

    :ifndef name
    Succeeding text will only be interpreted if the macro $(name) has not been defined.

    :if expression
    Succeeding text will only be interpreted if the expression is `true'. Macro substitution is performed upon expression before evaluation. An expression is counted as true if it has a non-zero value (for numeric expressions) or if it has a non-zero length (for string expressions).

    Expressions

    :else [args]
    Invert the interpretation of succeeding text; if text was being interpreted cease doing so, and vice versa. Args is ignored, and thus may be used as a comment.

    :elifdef name
    Continues an :ifdef construct with a new alternative. It combines an :else with an :ifdef without introducing an extra level of nesting. The construct
            :ifdef   A
            I<A-stuff>
            :elifdef B
            I<B-stuff>
            :endif   A

    is equivalent to

            :ifdef   A
            I<A-stuff>
            :else    !A
            : ifdef  B
            I<B-stuff>
            : endif  B
            :endif   A

    :elifndef name
    As for :elifdef but indicates that name should not be defined.

    :elif expression
    Continues a :if construct with a new alternative without introducing an extra level of nesting.

    :endif [args]
    Terminate conditionally interpreted text. As with :else, args is ignored.

    :include files...
    The specified files is included into the description as though it occurred at this point in the file. Macro substitution is done on the files. Each of the resultant words is treated as a file to include.

    If a file is not a full pathname, then if it begins with ./ or ../ it will be searched for relative to the directory in which the file containing the :include directive resides.

    Otherwise the environment variable $MYKEPATH is consulted, and file is searched for relative to all the directories named therein. $MYKEPATH is a conventional colon separated list of directory names. Note that any relative pathnames in this list will be relative to the directory in which myke is running, rather than the directory of the file containing the :include directive.

    :require files...
    This directive works just like :include except that a file will not be used if it has previously been :included or :required.

    :append files...
    The specified files are included into the description after any local Makefiles have been read. These files will be read in at the same level as the Makefile.
            :start, :finish, and :precious need info here.

    Expressions

    Simple C-like (or Perl-like) expressions are supported, and are used by the :if and :elif directives. Both strings and integers may be intermixed in expressions, with conversions being implied by operators. The operators include:

    !, ~
    Logical and bitwise NOT.

    +, -
    Numeric addition and subtraction.

  • Numeric multiplication, division, and modulus (well, C's % operator).

    .
    String concatenation a la Perl.

    &&, ||
    Logical conjunction and disjunction.

    &, |
    Binary conjunction and disjunction.

    ==, !=, <, <=, >=, >
    Comparison operators. Comparison is number only if both sides of the expression are numeric, otherwise comparison is lexical.

    macro-name
    Insert the value of $(macro-name) as a string value.

    length(string)
    Return the length of the supplied string.

    defined(macro-name)
    Return one if macro-name is defined and zero otherwise.

  • Things to note: logical operators return one for true and zero for false; strings can be coerced to integers by adding them to zero - the numeric value is that of the leading numeric portion of the string, or zero if there is none; integers can be coerced to strings by concatenating them with ``''. In view of this, the cleanest way to get a macro's string value is to say

            frob

    and the cleanest way to get its numeric value is to say

            $(frob)

    which takes advantage of the macro substitution performed prior to evaluation of the expression.

    Pseudo-Actions

    In addition to invoking a shell, actions may also invoke some built-in functions. An action beginning with a colon is taken to be a pseudo-action. These include:

    :lock names...
    Work on this target is halted until a lock can be obtained on the symbols named. This can be used around actions which do not use unique temporary files, such as a use of the yacc command.

    :unlock names...
    Release the named locks held by this target. When the actions complete, any locks will be released anyway.

    :touch names...
    The named targets have their modification dates set to the current time. (Actually, to the time when myke commenced running.)

    :make names...
    The named targets are brought up to date before proceeding to the next action.

    :shell shell
    Further actions in this target will be run with the named shell.

    :link source dest
    Make a hard link between source and dest. If the link is across two filesystems and source is a full pathname then a symbolic link will be made.

    :symlink source dest
    Make a symbolic link between source and dest.

    :mkdir dir
    Make the directory dir. This will succeed trivially if dir already exists and is a directory or a symbolic link to a directory.

    Per-Target Macros

    A line of the form

            I<targets> := I<macro-names> = I<value>

    defines macros which only apply to the named targets. For example, one may say:

            PYR_BIN    = /n/otc/bin
            SUN_BIN    = /n/arrakis/usr/local/bin
            Bins       = $(PYR_BIN) $(SUN_BIN)
    
    
            Binaries   = $((Bins))/it
    
            $(PYR_BIN)/it := CFLAGS = -Dpyramid -Dthis=that
            $(SUN_BIN)/it := CFLAGS = -Dsun -Dthis=the_other
    
            $(Binaries): $(@F).c
                    $(CC) $(CFLAGS) -o $@ $?

    Rules

    A more general form of dependency is a rule. Any dependency where the target contains a percent sign (`%') is taken to be a rule. The target is taken to be a pattern. The prerequisites are taken to be names derived from the pattern. Any percent in the pattern will match zero or more characters in a target name. In the prerequisites, a percent on its own matches the first percent in the pattern, except as follows: a percent followed by a digit from 1 to 9 matches the first to ninth percents in the pattern respectively; a percent followed by a 0 matches the entire pattern; two consecutive percents are replaced by a single percent.

    If the Makefile does not explicitly supply a complete dependency for a target, the set of rules is consulted in an attempt to infer a method of making the target.

    The prerequisites of a rule are divided into two groups, the primary and secondary prerequisites. These as separated by a colon, vis

            %_y.c: %.y : $("%.y.depend" <?G?)
                    :lock y.tab.c
                    yacc $(@PP[_]).y
                    mv y.tab.c $@
                    :unlock y.tab.c

    The secondary set of prerequisites and its delimiting colon may be missing. Should the rule be chosen then both groups will be taken to be prerequisites. However, only the primary prerequisites are examined when considering a rule. If a rule which matches the target is found, all of the primary derived prerequisites are examined. If they can all be made then the rule is accepted. A prerequisite is considered makable if it already exists, if it has an explicit mentioned dependency in the Makefile, if it has acquired a dependency as a result of an earlier successful inference, or if rules can be successfully inferred to make it. Only after the rule is chosen is the secondary group expanded into a list of names.

    For example, the following Makefile uses a rule to infer how to make the intermediate object files.

            binary = foo
            cfiles = a.c b.c
            $(binary): $(cfiles)
                    :make $((cfiles P)).o   # produces a.o b.o
                    cc -o $@ $>
                    rm $>
            %.o: %.c
                    cc -c $?

    The inference algorithm tries to chose the shallowest inference it can, measuring the length of the longest branch to make the comparison. Other things being equal, rules named earlier in the Makefile supercede rules named later.

    It is important to know how macro expressions in rule prerequisites are handled. In the primary group, macro expansion is performed to derive a list of names, which are only then examined for locations to perform percent substitution. In the secondary group, percent substitution is performed first, and macro expansion performed second. It is permitted to use the $@ macro in the secondary prerequisite group.

    It is very easy for inference to become exponential with the number of rules, since rules will chain fairly freely. This overhead can be greatly reduced through sensible choice of filename to reflect the processing it will undergo. For example, the above yacc rule will only be considered for targets whose names end in _y.c. This sort of approach to naming can reduce inference time by orders of magnitude.


    NOTES

    If the -q option is specified, the -n option is implied. Thus, submakes will still be performed via the $(MAKE) macro. To arrange that meaningful results are obtained from this, successful submakes with the -q option are taken to mean that the submake is also up to date.

    Command line definitions are exported to subsequent makes as command line arguments via the $(MAKE) macro. To protect any strings in them, they are placed in single quotes, and any single quotes within them are appropriately escaped. This mechanism is sufficient for Bourne shells and C shells. It may not be sufficient if another shell is specified via a :shell directive.

    The names produced by shell globbing are not sorted. This could be changed, but it would cost run time (probably very little) and would also encourage bad habits. I don't think that Makefiles which depend on a generated list of names being sorted are a good thing; such dependencies should be explicit.

    The result of shell globbing necessarily depends on the current content of the directories involved. Since macros are expanded at need, a pattern such as *.o will not always evaluate to the same set of names. Writers of Makefiles should keep this in mind when writing actions and dependencies. It is usually better to glob on sources than resultant files. The -p option forces prerequisites of targets to be expanded prior to making anything, and thus may produce different results from simply running the Makefile. It is for this reason that the -D option does not imply the -p option. This effect should also be kept in mind when running Makefiles with the -n option. A macro like *.o may well fail to expand and abort the program because the files have not been made.

    PDP archives are only recognised on PDPs, and the portable ones only on others.


    CAVEATS

    It is common for Makefiles to include actions like:

            $(sources): $(headers)
                    :touch $@

    in order to arrange that modifications to the header files propagate modification dates through to source files which include them. It is important to remember to include the line

            :precious $(sources)

    in the Makefile, lest a source file get removed when an interrupt is sent while the touch command is running.

    While it is conventional to name this program myke, the program may also be linked to other names. This has effects upon the names myke uses to invoke various things, as follows: upon commencing, myke examines argv[0], and extracts the leading identifier from the string equivalent to $(argv[0]) were it a macro. It then uses this string as the basic name on which to model the other names it invokes. For example, if the string were fred, myke would look for a global file /usr/local/lib/fredrc, a file named by the variable $FREDRC, for local Makefiles named $FREDFILE or Fredfile or fredfile or $fredfile. When searching for :include files, it would look along the path specified in $FREDPATH.


    BUGS

    Multiple mykes don't know about each other. This can be a killer with nested makes and parallelism.

    NULs in Makefiles will truncate input lines.

    Support for double colon targets is missing from version 2.

    There is no way to imbed a newline in a macro. However, one may be imbedded directly in an action.

    The D modifier character produces `.' if applied to a name with no directory part. `.' is just a convention, admittedly almost universal. To be pure about this contingency it should really return the empty string, which is the real name for the current directory, excepting certain broken Unices (which shall remain nameless). However, this has undesirable effects upon the writing of general purpose macros, as the sequence $(X D)/$(X F) where $X is a basename will give /$X, which is obviously wrong. This problem could be resolved if the D modifier returned dirpart/ except for basenames, when it would return the empty string. However, this would break many existing Makefiles, as the construct $(X D)$(X F) would then be required in the general case. It can also be considered more cryptic.

    The N modifier can be confused by symbolic links.

    Although the N modifier tries to determine such things as the full path of the current working directory and similar information as necessary, if it fails it uses not entirely general substitutes. These can fail. Probably it should fail outright if necessary information cannot be obtained.

    On pre-SR10 Apollo systems archives of object files do not conform to the ar(5) manual entry, nor to the <ar.h> include file. In fact, I have failed entirely to find any documentation of their format. Archives of non-object files are ok.

    Myke does not yet know about all the built-in rules of make. When I get the time I will supply a file to support these. Currently I just support my own needs.

    A semi-colon (';') on the dependency line is not treated specially. In make, a semicolon at this point introduces the first action.

    Globbing should support the {...,...,...} enumeration ala csh.

    Myke will never support the -b option of make.

    The 5K exec limit still applies to command lines. This can (and should) be fixed by using a temporary file as a script if the exec() fails with E2BIG.

    Inferred targets should also be marked for automatic deletion unless they are mentioned in a :precious directive.

    Myke does not know how to touch directories.

    Perhaps there should be a way to call a program to test whether two files are out of date with respect to each other. Use of such a facility will also be discouraged when implemented, due to the performance penalty incurred.

    If a target is supplied on the command line, a Makefile should not be required.

    During parallel execution, concurrent actions intersperse their output.

    There should be a way to access any targets supplied on the command line, and possibly to determine what flags have been set in some suitably symbolic manner.

    I am not entirely happy with the criteria for recognising repeated references to a file in :require directives. It mostly works, but certain unusual incantations can result in multiple inclusion of the same file. This might be a feature.


    FILES AND ENVIRONMENT

            C<{/usr/local/etc/mykerc}>      global Makefile
            C<$MYKERC>      personal global Makefile list
            C<$MYKEFILE>    default local Makefile if set
            C<Mykefile>     local Makefile if C<$MYKEFILE> not set, or absent
            C<mykefile>     local Makefile if C<Mykefile> is absent
            C<$mykefile>    local Makefile if set and C<mykefile> is absent
            C<$MYKEPATH>    where to look for Makefile B<:include>s


    SEE ALSO

    sh(1), touch(1), ar(1)

    make(1): the original make utility by S.I.Feldman

    mike(1): a much faster and slightly incompatible make utility by Michael Rourke

    cake(1): a slower but more versatile make utility by Zoltan Somogyi

    mk(1), nmake(1), gmake(1), smake(1), et al: other variously incompatible make utilities

    imake(1), makemake(1), mkdep(1), etc: tools for creating Makefiles

    mtmk(1): metamake, a tool to obsolete Makefiles by Mike Mowbray

    regexp(3): Henry Spencer's V8 compatible regular expression routines

    S.I.Feldman: Make - A Program for Maintaining Computer Programs, Software - Practice and Experience, April 1979, pp. 255-265.

    G.S.Fowler: A Fourth Generation Make, Proceedings of the 1985 Summer Usenix Conference, pp 159-174.

    Z.Somogyi: Cake: a fifth generation version of make, Australian Unix system User Group Newsletter 7:6, April 1987, pp. 22-31.


    AUTHOR

    Cameron Simpson <cs@zip.com.au>