This defines the recipe syntax (more or less). NOTE: this may still change quite a bit.
Table 26-1. Notation
| | separates alternatives |
() | grouping a sequence of items or alternatives |
[] | optional items (also does grouping) |
"" | contains literal text; """ is one double quote |
... | indicates the preceding item or group can be repeated |
EOL | an end-of-line, optionally preceded by a comment |
INDENT | an amount of white space, at least one space |
INDENT2 | an amount of white space, at least one space more than INDENT |
A comment starts with "#" and continues until the end-of-line. It may appear in many places.
White space may be inserted in between items. It is often ignored, but does have a meaning in a few places.
Line continuation is done with a backslash immediately before an end-of-line. It's not needed for an assignment and other commands that don't have a build_block: the item continues if the following line has more indent than the first line.
For items that have a build_block, the start of the build block is the line with the smallest indent that is larger than the indent of the line that started the command. The lines before this are continuation lines. Example:
mytarget : source1 source2 # continuation line :print $source # first build line of build block |
aapfile | ::= | ( [ aap_item ] EOL ) ... |
aap_item | ::= | dependency | rule | variant | otherfile | build_command |
dependency | ::= | targets ":" [ dependencies ] [ EOL build_block ] |
targets | ::= | item_list |
dependencies | ::= | item_list |
build_block | ::= | INDENT build_command [ EOL [ INDENT build_command ] ] ... |
rule | ::= | ":rule" pattern ... ":" pattern ... [ EOL build_block ] |
variant | ::= | ":variant" name ( EOL variant_item ) ... |
variant_item | ::= | INDENT varvalue EOL INDENT2 build_block |
otherfile | ::= | includefile | childfile |
includefile | ::= | ":include" item_list |
childfile | ::= | ":child" item_list |
build_command | ::= | assignment | script_item | generic_command | message |
assignment | ::= | assign_set | assign_append | assign_cond |
assign_set | ::= | name "=" item_list |
assign_append | ::= | name "+=" item_list |
assign_cond | ::= | name "?=" item_list |
script_item | ::= | script_line | script_block |
script_line | ::= | "@" script_command |
script_block | ::= | ":python" EOL ( script_command EOL ) ... ":end" |
generic_command | ::= | ":" command_name [ command_argument ] |
message | ::= | info_msg | error_msg |
info_msg | ::= | ":print" expression ... |
error_msg | ::= | ":error" expression ... |
# A list can contain white-separated items and Python style expressions. | ||
item_list | ::= | item [ white_space item ] ... |
item | ::= | ( simple_item | "(" item_list ")" ) [ attribute ... ] |
simple_item | ::= | ( expression | non_white_item ) ... |
attribute | ::= | "{" name [ "=" expression ] "}" |
expression | ::= | string_expr | python_expr |
string_expr | ::= | """ text """ | "'" text "'" |
python_expr | ::= | "`" python-expression "`" |
non_white_item | ::= | non-white-text | "$" [ "(" ] name [ ")" ] |
A backslash at the end of the line is used for line continuation. - Can't have white space after it! - Also for comments. - Also for Python commands; A leading @ char and white space before it is removed. - Lines are joined before inspecting indents. # comment \ continued comment @ python command \ @ continued python command \ still continued When lines are joined because a command continues with a line with more indent, the line break and leading white space of the next line are replaced with a sinble space. An exception is when the line ends in "$br": The $br is removed, the line break is inserted in the text and leading white space of the next line is removed. VARIABLES: When concatenating variables and using rc-style expansion, the attributes of the last variable overrule the identical attributes of a previous one. v1 = foo {check = 1} v2 = bar {check = 2} vv = $*v1$v2 -> vv = foobar{check = 1}{check = 2} When using rc-style expansion, quotes will not be kept as they are, but removed and re-inserted where used or necessary. Example: foo: "file 1.c" foo.c :print "dir/$*source" Results in: "dir/file 1.c" "dir/foo.c" Be careful with using "$\" and quotes, you may not always get what you wanted. To get one item out of a variable that is a list of items, use an index number in square brackets. Parenthesis or curly braces must be used around the variable name and the index. The first item is indexed with zero. Example: BAR = beer coffee cola :print $(BAR[0]) beer BAR_ONE = $(BAR[2]) :print $BAR_ONE cola Using an index for which no item exists gives an empty result. When $MESSAGE includes "warning" a message is printed about this. Normally using $VAR gets what you want. A-A-P will use the kind of quoting expected and add attributes when needed. However, when you want something else, this can be specified: $var depends on where it's used $?var when the variable is not set or defined use an empty string instead of generating an error $-var without attributes (may collapse white space) $+var with attributes $*var use rc-style expansion (may collapse white space) $=var no quotes or backslashes $'var aap quoted (using ' and/or " where required, no backslashes) $"var quoted with " (doubled for a literal ") $\var special characters escaped with a backslash $!var depends on the shell, either like $'var or $"var In most places $var is expanded as $+'var (with attributes, using ' and " for quoting). The exceptions are: :sys $-!var no attributes, shell quoting $n in $(v[$n]) $-=var no attributes, no quoting :del $-'var no attributes, normal quoting The quoted variables don't handle the backslash as a special character. This is useful for MS-Windows file names. Example: prog : "dir\file 1.c" :print $'source Results in: "dir\file 1.c" ASSIGNMENT: overview: var = value assign var += value append (assign if not set yet) var ?= value only assign when not set yet var $= value evaluate when used var $+= value append, evaluate when used var $?= value only when not set, evaluate when used Assignment with "+=" or "$+=" appends the argument as a separate item. This is actually done by inserting a space. But when the variable wasn't set yet it works like a normal assignment: VAR += something is equal to: @if globals().has_key("VAR"): @ VAR = VAR + " " + "something" @else: @ VAR = "something" Assignment with "?=" only does the assignment when the variable wasn't set yet. A variable that was set to an empty string also counts as being set. Thus when using "aap VAR=" the empty value overrules the value set with "?=". VAR ?= something is equal to: @if not globals().has_key("VAR"): VAR = something When using "$=", "$+=" or "$?=" variables in the argument are not evaluated at the time of assignment, but this is done when the variable is used. VAR = 1 TT $= $VAR VAR = 2 :print $TT prints "2". When first setting a variable with "$=" and later appending with "+=" the evaluation is done before the new value is appended: VAR = 1 TT $= $VAR TT += 2 VAR = 3 :print $TT prints "1 2" Note that evaluating a python expressions in `` is not postponed. BLOCK ASSIGNMENT The normal assignment command uses a single line of text. When broken into several lines they are joined together, just like with other commands. $br can be used to insert a line break. Example: foo = first line$br second line$br third line $br The block assignment keeps the line breaks as they are. The same example but using a block assignment: foo << EOF first line second line third line EOF The generic format is: {var} << {term} line1 ... {term} {term} can be any string without white space. The block ends when {term} is found in a line by itself, optionally preceded by white space and followed by white space and a comment. The amount of indent to be removed from all the lines is set by the first line. When the first line should start with white space use $empty. All the variations of the assignment command can be used: var << term assign var +<< term append (assign if not set yet) var ?<< term only assign when not set yet var $<< term evaluate when used var $+<< term append, evaluate when used var $?<< term only when not set, evaluate when used ATTRIBUTES Items can be given attributes. The form is: {name = value} "value" is expanded like other items, with the addition that "}" cannot appear outside of quotes. This form is also possible and uses the default value of 1: {name} Examples: bar : thatfile {check = $MYCHECK} foo {virtual} : somefile The "virtual" attribute is used for targets that don't exist (as file or directory) but are used for selecting the dependency to be build. These targets have the "virtual" attribute set by default: TARGET COMMONLY USED FOR all build the default targets clean remove intermediate build files distclean remove all generated files test run tests check same as "test" install build and install for use tryout build and install for trying out reference generate or update the cross-reference database fetch obtain the latest version of each file update fetch and build the default targets checkout checkout (and lock) from version control system commit commit changes to VCS without unlocking checkin checkin and unlock to VCS unlock unlock files from a VCS add add new files to VCS remove remove deleted files from VCS revise like checkin + remove tag add a tag to the current version prepare prepare for publishing (generated docs but no exe) publish distribute all files for the current version finally always executed last (using "aap finally" is uncommon) These specific targets may have multiple build commands. They are all executed to update the virtual target. Normally there is up to one target in each (child) recipe. Note that virtual targets are not related to a specific directory. Make sure no other item in this recipe or any child recipe has the same name as the virtual target to avoid confusion. Specifically using a directory "test" while there also is a virtual target "test". Name the directory "testdir" to avoid confusion. The "comment" attribute can be used for targets that are to be specified at the command line. "aap comment" will show them. % aap comment target "all": build everything target "foo": link the program EXECUTING COMMANDS A dependency and a rule can have a list of commands. For these commands the following variables are available: $source The list of input files as a string. $source_list The list of input files as a Python list. $source_dl Only for use in Python commands: A list of dictionaries, each input item is one entry. $depend The list of dependencies (source files plus virtual dependencies) as a string. $depend_list The list of dependencies (source files plus virtual dependencies) as a Python list. $depend_dl Only for use in Python commands: A list of dictionaries, each dependency item is one entry. $target The list of output files as a string. $target_list The list of output files as a Python list. $target_dl Only for use in Python commands: A list of dictionaries, each output item is one entry. $buildtarget The name of the target for which the commands are executed. It is one of the items in $target. $match For a rule: the string that matched with % Example: doit {virtual}: :print building $target prog : "main file.c" doit :print building $target from $source Results in: building doit{virtual=1} building prog from "main file.c" Note that quoting of expanded $var depends on the command used. The Python lists $source_list and $target_list can be used to loop over each item. Example: $OUT : foo.txt @for item in target_list: :print $source > $item Note the difference between $source and $depend: $source only contains real files, $depend also contains virtual dependencies. The list of dictionaires can be used to access the attributes of each item. Each dictionary has an entry "name", which is the (file) name of the item. Other entries are attributes. Example: prog : file.c {check = md5} @print sourcelist[0]["name"], sourcelist[0]["check"] Results in: file.c md5 RATIONALE In an assignment and other places a Python expression can be used in backticks. Expanding this is done before expanding $VAR items, because this allows the possibility to use the Python expression to result in the name of a variable. Example: foovaridx = 5 FOO = $SRC`foovaridx` Equal to: FOO = $SRC5 In the result of the Python expression $ characters are doubled, to avoid it being interpreted as the start of a variable reference. Otherwise Python expressions with arbitrary results would always have to be filtered explicitly. Variables can still be obtained without using the $, although none of the modifiers like $+ and $* are available. Example: FOO = foo/`glob("*.tmp")` May result in: FOO = foo/one.tmp two.tmp Note that "foo/" is only prepended to the whole result, not each white-separated item. If you do want rc-style expansion, use two commands: TT = `glob("*.tmp")` FOO = foo/$*TT Result: FOO = foo/one.tmp foo/two.tmp Watch out for unexpected results when rc-style expansion is done for $*VAR. Example: VAR = one two FOO = $*VAR/`glob("*.tmp")` Would result in: FOO = one/one.tmp two/one.tmp two.tmp because the `` part is expanded first, thus the assignment is executed like: FOO = $*VAR/one.tmp two.tmp The backticks for a Python expression are also recognized inside quotes, because this makes the rule for doubling backticks consistent. Example: FOO = "this``file" that``file Doubling the backtick to avoid it being recognized as a Python expression makes it impossible to have an empty Python expression. There appears to be no reason to use an empty Python expression. |