AMake Variables and Macros

AMake understands the following operators to set variables. Any of these functions can be preceeded by the override preprocessor keyword. The -e option can be used on the command line to force the use of the environment variables first.

Operator Comment
<variable names> = <value>

  or

#define <variable name> <value>

  or

define <variable names>
	<value on several lines>
endef
sets the list of variables to the following value; in the second syntax, only one variable can be defined at a time; in the third syntax the variable will include new line characters (useful to create macros of shell command lines)
<variable names> += <value>

  or

<variable> = $(<variable>) <value>
appends the <value> to what the given <variables> are already set to; undefined variables are set to <value>; using the = operator and a complex expression, you may transform a variable by prepending and appending values to it
<variable names> ?= <value>

  or

#ifndef <variable name>
<variable name> = <value>
#endif
sets the <variables> to <value> only if these are not defined yet
<variable names> := <value>
transforms <value> now and sets the result in the <variables>
<variable names> != <command>

  or

<variable names> = `<command>`

  or

<variable names>:sh := <command>

  or

<variable names> := $(shell <command>)
sets the <variables> to the output of the shell command;
<variable names> <= <filename>
sets the <variables> to the contents of the input <file>; each space and new-line in the input file is taken as a word separator.

For instance, if you have a response file, you can read it with the commands as shown below. We assume that a response file includes a list of object filenames. Names which start with a + character, one per line and the end of the line is marked with an ampersand:

+object1.obj &
+object2.obj &
+object3.obj

The following is the script necessary in an amakefile to read such a file:

OBJS<=mylib.rsp
OBJS:=$(OBJS:+*=*:-&)

## Now show the result:
#echo $(OBJS)

First the <= operator reads the file named mylib.rsp file and then the := operator is used to transform the input into a usable list by removing the + character from the filenames and the & from between the filenames. The result printed out by the #echo command looks like this:

object1.obj object2.obj object3.obj
		

AMake accepts macros absolutly everywhere but where the documentation says it doesn't (for instance, the preprocessor operators can't be defined in macros).

AMake supports full recursive retrieval. The following is a very simple example of such a use:

AMake also supports substitutions. The substitution patterns can include all of the following wild cards, operators, functions, etc.

Characters Comment
$(<name>: ... ) normal substitution operator (transforms what matches and keep what's left)
$(<name>:: ... )
$(patsubst ...,...,
   $(filter $(<name>)))
selection operator (keeps and transform only what matches)
$(<name>:- ... )
$(filter-out ...,$(<name>))
reverse selection operator (keeps only what doesn't match; don't transform)
$(<name>:E)
$(<name>::?*.[^/.]*=^>*)
$(suffix $(<name>))
keep only the suffix of each word (extensions)
$(<name>:H)
$(<name>::*/[^/]*=*)
$(dir $(<name>))
keep all but the basename of each word (head)
$(<name>:I)
transforms each file name with itself plus all the automatically generated dependencies (searched in the C files like mkdepend)
$(<name>:M<pattern>)
$(<var>::<pattern>)
keep the words which match the pattern (match)
$(<name>:N<pattern>)
$(<var>:-<pattern>)
keep the words which don't match the pattern (not match)
$(<name>:R)
$(<name>:?*.[^/.]*=?*)
$(basename $(<name>))
keep all but the suffix of each word (root)
$(<name>:S/[^]<pattern>[$]
   /<transform>/[g])
$(<name>:[<][*]<pattern>[*]
   =[=][*]<transform>[<])
$(subst <pattern>,
   <transform>,$(<name>))
simple (yet complicated and rather useless) search and replace for BSD/SGI compatibility (substitute); the <pattern> defined with the S letter can include the ampersand (&)
$(<name>:sh)
$(shell $(<name>))
execute the contents of the variable as a shell command and return its output
$(<name>:T)
$(<name>::*/[^/]*=>*)
keep only the basename of each word (tail)
$(<name>:U)
ensures each word in <name> is unique
$(<name>:<user defined>)
other letters can be defined by the user through the use of a macro as in:
    O = :*.c=*.o
    $(<name>:O)
$(<name>:...*... [=...])
any character zero or more times
$(<name>:...%... [=...])
any character zero or more times
$(<name>:...?... [=...])
accept any one character
$(<name>:..[..].. [=...])
accept any of the characters defined in the range
$(<name>:..[..]*.. [=...])
accept any of the characters defined in the range zero or more times
$(<name>:..[!..].. [=...])
accept any character not defined in the range
$(<name>:..[!..]*.. [=...])
accept any character not defined in the range zero or more times
$(<name>:..^<l>.. [=...])
accept any character but the letter <l>
$(<name>:..^<l>*.. [=...])
accept any character but the letter <l> zero or more times
$(<name>:<... [=...])
match once, whatever the number of words in the variable
$(<name>:...=...*...)
insert a matching word
$(<name>:...=...%...)
insert a matching word
$(<name>:...=...>...)
skip one matching word
$(<name>:...=...?...)
insert one matching character
$(<name>:...=...^...)
skip one matching character
$(<name>:...=...<...)
insert what's left of the matching words
$(<name>:..=..[<value>]..)
reposition the insertion pointer to the matching word number <value>
$(<name>:..=..[<wp>,<cp>]..)
reposition the insertion pointer to the matching word number <wp>; and the character position <cp> inside that word
$(<name>:<pattern>
   =<transform>)
$(patsubst <pattern>,
   <transform>,$(<name>))
apply the <pattern> and <transform> once per word
$(<name>:<pattern>
   ==<transform>)
apply the <pattern> and <transform> as many times as the <pattern> is found in each word
$(<function> ... [, ...])
execute the <function> with the following list(s) of words

AMake will automatically use an asterisk at the beginning of a pattern whenever that pattern doesn't include any wildcard character. Thus, the following:

is equivalent to:

AMake supports all the following <functions> in variables:

Function Comments
$(addprefix <prefix>,<list>) add <prefix> to each word in the <list>
$(addsuffix <suffix>,<list>) add <suffix> to each word in the <list>
$(basename <list>) suppresses the suffix of each filename in <list>
$(concat <list>) concatenate in one word the <list> of words
$(dir <list>) return the path of each word in <list>
$(filter <pattern>,<list>) filter out the word of the <list> which don't match the <pattern>
$(filter-out <pattern>,<list>) filter out the word of the <list> which match the <pattern>
$(findstring <find>,<list>) search for <find> and returns it if found, return an empty word otherwise
$(firstword <list>) return the first word of <list>
$(foreach <variable>,<list>,<text>) evalutate <text> once per word in <list> with <variable> set to that word
$(join <list 1>,<list 2>) concat the corresponding words of both lists
$(lastword <list>) return the last word in <list>
$(lowercase <list>) return the <list> in lowercase
$(notdir <list>) return but the path of each word in <list>
$(origin <name>) return a name giving the origin of the named variable (automatic, command, default, environment, file, override, undefined)
$(patsubst <pattern>,
<transform>,<list>)
transform words in <list> which match <pattern> with the <transform>
$(shell <command>) execute the shell <command> and return its output
$(sort <list>) sorts the <list> of words
$(strip <string>) ensures that <string> has no startup, double or final spaces
$(subst <from>,<to>,<string>) repaces any occurance of <from> by <to> in <string>
$(suffix <list>) keeps only the suffixes of each word
$(uppercase <list>) return the <list> in uppercase
$(wildcard <list>) transform the <list> as a list of filenames which uses wildcards like targets
$(word <index>,<list>) return the word at the position <index> from the <list>
$(words <list>) the number of words in <list> or zero (0)

AMake, like all file makers, has a certain amount of automatic variables (i.e. variables set automatically in some contexts). There is a list of these variables:

Variable Comments
$(.ALLSRC)
$>
$+
$**
all the sources (or dependencies) which are not marked invisible
$(.ARCHIVE)
$%
the filename of the archive we're working on
$(.DIRECTORY)
$(@D)
$(@@D)
$^:
$(.TARGET:H)
the directory of the target
$(.FIRSTSRC)
$(.IMPSRC)
$<
the first source (or dependency) of the current target
$(.INVISIBLE) the invisible sources (or dependencies)
$(.MEMBER)
$!
the name of the archive member we're working on
$(.OODATE)
$?
the list of out of date dependencies
$(.PREFIX)
$(@B)
$(@@B)
$(.TARGET:T:R)
the name of the target with no suffix and no path
$(.STEM)
$*
$^&
the pattern in an easy pattern rule; the percent (%) sign can also be used as a stand alone in the list of dependencies
$(.ROOT)
$(@R)
$(@@R)
$(.TARGET:R)
the name of the target without it's suffix
$(.SERIAL) a unique number within this invocation of AMake
$(.SOURCES)
$^
$(.ALLSRC:U)
all the sources without duplicates
$(.SUFFIX)
$(.EXTENSION)
$(@E)
$(@@E)
$(.TARGET:E)
only the target suffixes
$(.TAIL)
$(@F)
$(@@F)
$(.TARGET:T)
$^.
the name of the target with no path
$(.TARGET)
$@
$@@
$$@
$^@
the target being created
$^@, $[@, $]@
$^*, $[*, $]*
$^&, $[&, $]&
$^., $[., $].
$^:, $[:, $]:
WatcomMake support, these are similar to other macros. The ^, [ and ] represent the target filename (^), the first dependency ([) and the last dependency (]). Note that $^ by itself is a different macro. The @, *, &, . and : are defined as the full name (@), the name without the extension (*), the name without the path nor the extension (&), the name without the path (.) and only the path (:) of the corresponding filename.

AMake also accepts specifiers after the variable names of one letter (>, <, +, %, !, ?, ^, *, @) as in $(@D) for the directory of the target to be built. The possible speciciers are as follow:

Letter Name Comment
B basename no path and no suffix
D directory no filename, only the path
E extension no path and no filename, only the suffix
F filename no path
R root no suffix