The ARM Make Utility (armmake) [PC release only]
------------------------------------------------


About armmake
.............

<armmake> assists with the management of programs, documents, applications, and 
other complex, structured objects made from several components, each of which 
needs to be translated or processed in some way, and which have some 
consistency constraints between them.  Most often, however, it is used to ease 
rebuilding programs from their source code, recompiling a piece of source only 
when it, or other code upon which it depends has been updated.

The input to <armmake> is a text file describing the system to be managed.  The 
text file is usually called <makefile>, and its format is almost identical to 
that of most other make utilities.

In its simplest form, a makefile consists of a sequence of entries which 
describe: 

 *  what each component of a system depends on

 *  what commands to execute to make an up-to-date version of that component.

Details of the format of the entries in an <armmake> makefile are given in "
<Makefile Format for armmake>".


Command Line Options
....................

The <armmake> command has the following syntax:

    armmake [<options>] [<list-of-targets-and-macro-definitions>]

The list of targets and macro definitions is space separated, and is optional.  
Elements in this list are:

 *  deemed a target to be built by armmake if they contain no '=' character.  
    The target is added to the list of objects to be built by <armmake>.  If no 
    targets are specified then the first target in the makefile is built.

 *  deemed to be a macro definition if they contain an '=' character. The 
    string to the left of the '=' is interpreted as a macro name, which is 
    initialised to be the string to the right of the '=' character.  Note that 
    if any spaces are to be specified in the value of the macro, then the whole 
    list element should be enclosed in double quotes.  e.g.

          armmake myprog "STRING=Three Blind Mice"

<options> are as follows:


-f <makefile>

Read the system description from <makefile>.  <makefile> defaults to 'makefile' 
if omitted.


-i

Ignore return codes from commands (equivalent to .IGNORE). <armmake> usually 
stops if it encounters a bad (non-0) return code.


-k

On encountering a bad (non-0) return code, don't give up, but continue with 
each branch of the makefile that doesn't depend on the failing command.  This 
is likely to be useful if rebuilding a large system after many changes have 
been made and <armmake> is required to do as much rebuilding as possible, 
omitting only those steps which cannot be completed because of previous errors.


-n

Don't execute any commands; just show on the screen what commands would be 
executed, giving a reason for wanting to execute each one.


-o command-file

Don't execute commands to make the target(s) up to date; write them to 
<command-file> for later execution.


-s

Don't echo commands to be executed (equivalent to .SILENT).  Usually, <armmake> 
is reassuringly chatty, but option will  stop <armmake> from outputting 
messages.  However, it does not stop the commands it issues from outputting 
messages.


-t

Generate commands to make target(s) up to date by setting source time stamps 
consistently (only guaranteed to succeed if all sources exist).


Makefile Format for armmake
...........................

An <armmake> makefile consists of a sequence of logical lines.  A logical line 
may be continued over several physical lines provided each but the last line 
ends with a '\'.

Comments are ignored by <armmake>.  A comment is introduced by a hash character 
('#') and runs to the end of the logical line.  A literal '#' character can be 
produced by escaping it with a backslash thus: '\#'.

Other than comments there are four kinds of non-empty logical lines in a 
makefile:

 *  dependency lines;

 *  command lines;

 *  macro definition lines;

 *  rule and other special lines (see "<Rule patterns, .SUFFIXES, $@, $*, $< 
    and $?>").


Dependency Lines

Dependency lines have the form:

    space-separated-target-list COLON space-separated-prerequisite-list.

For example:

    program.exe : module1.obj module2.obj module3.obj library.lib

A dependency line cannot begin with white space.  Spaces before the ':' are 
optional, but some white space must follow the ':', to distinguish ':' 
separating targets and prerequisites from ':' as part of a filename.

A line with multiple targets is shorthand for several lines, each with one 
target and the same righthand side (and the same associated commands, if any).

Multiple dependency lines referring to the same target accumulate, though only 
one such line may have commands associated with it (<armmake> would not know in 
what order to execute the commands otherwise).  For example, the above 
dependency line could be rewritten as several dependency lines:

    program.exe : module1.obj
    program.exe : module2.obj
    program.exe : module3.obj
    program.exe : library.lib


Command Lines

Command lines immediately follow a dependency line and begin with white space.

For maximum compatibility with UNIX makefiles ensure that the first character 
of every command line is a Tab.  Although one or more spaces will do for 
<armmake>.

A semi-colon may be used instead of a new line to introduce commands on a 
dependency line.  This is most often useful when there are no prerequisites and 
only a single command associated with a target. For example:

    clean:; del *.obj

Note that, in this case, no white space is needed between the colon and the 
semicolon.


Macro Definition Lines

Macro definition lines are lines of the form:

    macro-name = some-text-to-the-end-of-the-logical-line

For example: 

    CC = armcc
    CFLAGS = -li -apcs 3/32bit -fah -c
    LINK = armlink
    LIB = \release\lib\armlib.32l

The '=' can be surrounded with white space, or not, to taste.  Thereafter, 
wherever <$(name)> or <${name}> is encountered, if <name> is the name of a 
macro then the whole of <$(name)> or <${name}> is replaced by its definition. A 
reference to an undefined macro simply vanishes.  An example which uses the 
above macro definitions is:

    program:  program.obj $(LIB)
          $(LINK) -o program $(LFLAGS) program.obj $(LIB)

Note that <$(LFLAGS)> expands to nothing, as it is undefined.

Macros can also be defined on <armmake>'s command line as described in "<Command 
Line Options>".


Command Execution
.................

When attempting to build a target, <armmake> uses all the dependency lines 
specifying the current target as a target, and generates a list of all the 
corresponding prerequisites.  Each of these prerequisites is checked, and if 
they are not up to date will be made up to date before any further processing 
is performed.  Finally the commands on the command lines for the current target 
are executed.

These commands are executed sequentially.  If a command returns a non zero 
return code <armmake> will normally stop processing, taking this to mean that 
the build has failed.

Note that there is an MSDOS command length limit of 127 characters.  If this is 
exceeded <armmake> will give a warning message.  This limit may prove 
troublesome, particularly with <armlink>, which is often passed many object 
files to link together.  However, <armlink> can read its object files from a 
file, thus avoiding the problem.  See "<-VIA file>" for more 
information. In addition, batch files can be executed from the command lines so 
that complicated or long commands can be put there instead.


Advanced Features
.................


File naming

To help you use UNIX makefiles with <armmake> under MSDOS, <armmake> accepts 
both UNIX and MSDOS filenames, internally converting  them to the host system 
style.  Thus all of the following are acceptable:

    UNIX-like:          /tools/prog/test.c      ../include/defs.h

    MSDOS-like:         \tool\prog\test.c       ..\include\defs.h

In addition to filename interpretation on the dependency lines, <armmake> 
attempts to convert files on the command-lines too.  This is not straight 
forward as command lines may contain anything.  <armmake> only changes a 
suspected filename if the filename has already been found on a dependency line 
in the file.

For more information see "<File Naming Conventions>" of the 
Reference Manual.


VPATH

Usually <armmake> looks for files relative to the current directory or in 
places implicit in the filename.  The previous example contains the line:

    program:  program.obj $(LIB)

which refers to <.\program.obj>

Sometimes, particularly when dealing with multiple versions of large systems, 
it is convenient to have a complete set of object files locally, a few sources 
locally, but most sources in a central place shared between versions.

If the macro VPATH is defined, <armmake> will look in the list of places 
defined in it for any files it can't find in the places implied by their names.

For example, we might have sources in <\shared> and <\oldvsn>.  In order to 
tell <armmake> to look in these places if the normal search fails, use the 
following VPATH setting:

    VPATH = \shared \oldvsn

Unlike UNIX VPATH's, the path elements are separated by spaces rather than 
colons. 

NOTE:  VPATH is not applied to any target  names.


Rule patterns, .SUFFIXES, $@, $*, $< and $?

All the examples given so far have used explicit rules for making targets.  In 
fact, <armmake> can make inferences if you supply the appropriate rule 
patterns.  These are specified using special target names consisting of the 
concatenation of two suffixes from the pseudo-dependency .SUFFIXES.

This sounds very complicated, but is actually quite simple.  For example:

    .SUFFIXES:  .obj .c
    program:    program.obj $(LIB)
    .c.obj:     $(CC) $(CFLAGS) -o $@ $*.c

The rule pattern .c.obj describes how to make .obj files from .c files.  If, as 
in the above fragment, there is no explicit entry describing how to make a 
particular .obj file (<program.obj> in the above example) <armmake> will apply 
the first rule it has for making .obj files.  Here, order is determined by 
order in the .SUFFIXES pseudo-dependency.

For example, suppose .SUFFIXES were defined as .obj .c .s and that there were 
two rules, .c.obj: ... and .s.obj: ...  Then armmake would choose the .c.obj 
rule because .c precedes .s in the .SUFFIXES dependency.  In applying the 
.c.obj rule, <armmake> infers a dependence on the corresponding .c file (here 
<program.c>).  So, in effect, it infers:

    program.obj:  program.c

                  $(CC) $(CFLAGS) -o program.obj program.c

Note that $@ is replaced by the name of the target and $* by the name of the 
target with the extension deleted from it.  In a similar fashion, $< refers to 
the list of inferred prerequisites.  So the above example could be rewritten 
using the rule:

    .c.obj:;        $(CC) $(CFLAGS) -o $@ $<

However, if a VPATH were being used, this second form is obligatory.  Consider, 
for example, the fragment:

    VPATH = \shared \oldvsn
    program:      ... module.obj ...
    .c.obj:;      $(CC) $(CFLAGS) -o $@ $<

There is no explicit rule for making <module.obj>, so <armmake> will apply the 
rule pattern .c.obj.  This might expand to:

    module.obj:   \shared\module.c
                  $(CC) $(CFLAGS) -o module.obj \shared\module.c

Clearly $* could not have been used in this case.

Finally, $? can be used in any command to stand for the list of prerequisites 
with respect to which the target is out of date (which may be only some of the 
prerequisites).


Use of ::

If you use '::', rather than ':', to separate targets from prerequisites, the 
righthand sides of dependencies which refer to the same targets are not merged.  
Furthermore, each such dependency can have separate commands associated with 
it.  Consider, for example:

    t1.obj::   t1.c t1.h
               armcc -g -c t1.c     # executed if t1.obj is out of
                                    # date wrt t1.c or t1.h
    t1.obj::   t1.c t2.h
               armcc -c t1.c        # executed if t1.obj is out of
                                    # date wrt t1.c or t2.h


Miscellaneous Features
......................

The special pseudo-target .SILENT tells <armmake> not to echo commands to be 
executed to your screen.  Its effect is as if you used <armmake -s>.

The special pseudo-target .IGNORE tells <armmake> to ignore the return code 
from the commands it executes. Its effect is as if you used <armmake -i>.

A command line, the first non-white-space character of which is @ is locally 
silent; just that command is not echoed.

A command line, the first non-white-space character of which is '-' has its  
return code ignored when it is executed. This is extremely useful in makefiles 
which use commands which do not set the return code conventionally.  Note 
particularly, that for built-in commands under DOS, the return codes are 
meaningless, and as such should not be relied upon to stop makefile execution 
when they fail.

The special macro MFLAGS is given the value of the command line arguments 
passed to <armmake>.  This is most useful when a makefile itself contains 
<armmake> commands (for example, when a system consists of a collection of 
subsystems, each described by its own makefile).  MFLAGS allows the same 
command line arguments to be passed to every invocation of <armmake>, even the 
recursive ones.


DOS4GW and armmake
..................

DOS4GW is the DOS Extender used to by <armmake> compiled with the Watcom C/386 
compiler.  By default DOS4GW dies not allow programs which run under it to 
'shell out' other programs, and since this is essential for the operation of 
armmake the following environment variable should be set up to allow armmake to 
do this (you may well want to add this to your <autoexec.bat> file):

    set DOS16M=:1M

The ARM Software Toolkit installer gives an option to update your <autoexec.bat> 
file, and if this was selected then this command will already have been set up 
in your <autoexec.bat> file.

