In this section, we provide the syntactic details for each of the
capabilities described in the previous section. There are some
aspects of how Abuild.interface files are
interpreted that are different from other systems you have likely
encountered. If you are already familiar with the basics of how
these files work, this section can serve as a quick reference.
If you only read one thing, read about list assignment.
Assignment to list variables is probably different for
Abuild.interface files than for any other
variable assignment system you're likely to have encountered.
It is specifically designed to support building up lists
gradually by interpreting multiple files in a specific order.
Any line beginning with a # optionally
preceded by whitespace is treated as a comment. Comments are
completely ignored and, as such, have no effect on line
continuation. Note that the # does not
have any special meaning when it appears in another context.
There is no syntax for including comments within a line that
contains other content.
A scalar variable declaration takes the form
declarevariabletype
where variable is the name of the
variable and type is one of
boolean, string, or
filename. Example scalar variable declarations:
declare CODEGEN filename declare HAS_CLASS boolean
A list variable declaration takes the form
declarevariablelisttypeappend-type
where variable is the name of the
variable, type is one of
boolean, string, or
filename, and
append-type is one of
append or prepend. Example list
variable declarations:
declare QFLAGS list string append declare QPATHS list filename prepend
Scalar variables start off uninitialized. List variables start off containing zero items.
Scalar variables may be assigned in one of three ways: normal, override, or default. A normal assignment looks like this:
variable=value
where variable is the variable name
and value is a single word (leading
and trailing space ignored). Extra whitespace is permitted
around the = sign.
Override assignments look like this:
overridevariable=value
Fallback assignments look like this:
fallbackvariable=value
Example scalar variable assignments:
fallback CODEGEN = gen_code.pl HAS_CLASS = 0 override HAS_CLASS = 1
List variables are assigned using a simple
= operator:
list-variable=value
where value consists of zero or
more words, and the semantics of the assignment depend on how
the list was declared. For append lists, the
assignment operator appends the words to the existing list in
the order in which they appear. For prepend
lists, the assignment operator prepends
the words to the existing value of list in the order in which
they appear. For example, if the variables
LIBS is declared as a prepend
list of strings, these two statements would
result in LIBS containing the value
lib3 lib4 lib1 lib2:
LIBS = lib1 lib2 LIBS = lib3 lib4
The distinction of whether a list is declared as
append or prepend generally doesn't
matter to the user, but there are cases in a build environment
in which it is important to prepend to a list. One notable
example is the list of libraries that are linked into an
application: if one library calls functions from another
library, the depending library must come
before the dependent library in the link
command. Since abuild reads the dependent library's
interface file first, the depending library must
prepend itself to the list of libraries.
Note that multiple assignments to a single list variable would
ordinarily not occur in the same
Abuild.interface file, but would instead
occur over successive files. It is perfectly valid to assign
multiple times in the same file, however. One instance in
which this would typically occur would be with private
interfaces, as illustrated in Section 20.3, “Private Interface Example”. Another common
case would be with conditional assignments.
List and scalar variables can both be reset. After a variable is reset, its value becomes uninitialized just as if it had just been declared. The syntax for resetting a variable is
reset variable
It is also possible to reset all variables with
reset-all
A reset of a specific variable, either by an explicit
reset or a
reset-all, can be blocked within the
scope of a single Abuild.interface file
or any files it loads with after-build.
To block a variable from being reset, use
no-reset variable
Any no-reset commands will apply to the
next reset or
reset-all that appears in the current
file or files it explicitly loads. (Although there would be
no real reason to use no-reset before a
specific reset of a specific variable,
abuild does support this construct.)
Variable reset operations are used fairly infrequently, but there are use cases that justify all of the various reset operations. For examples of using them, please see Section 21.2, “Cross-Platform Dependencies” and Chapter 25, Opaque Wrappers.
There are some subtleties about the effect of a variable reset when interface files are loaded. For details, see Section 29.7, “Implementation of the Abuild Interface System”.
An Abuild.interface file may prefix any
variable assignment (normal,
override, fallback,
scalar, or list) with a flag statement.
This indicates that that particular assignment will be ignored
by build items that don't request the particular flag through
the
-flag=
syntax in their interface-flagAbuild.conf files. A
flag-based assignment looks like this:
flaginterface-flagassignment-statement
Abuild enforces that a build item's
Abuild.interface and any
after-build files that it reads may only
use the flag statement for a flag
declared in the build item's
supported-flags key in its own
Abuild.conf. For an example of using
flag-based assignment, see Section 20.3, “Private Interface Example”.
Abuild allows you to specify the name of an additional
interface file with the same syntax as
Abuild.interface that is loaded
immediately after the current item has been built, before any
items that depend on this item are built. Because the file is
loaded after the build has been completed, any directives in
this file will be visible to items that depend on this item
but not by this item itself. To specify the name of such a
file, use
after-build filename
where filename is the path to the
file to be loaded. A relative path is interpreted as relative
to the original Abuild.interface file.
Note that files loaded by after-build may
themselves not include after-build
directives. It is also not permitted to have
after-build statements in interface files
belonging to plugins or build items that have no build files.
(Having them would be meaningless since such build items are
not built.)
Since interface statements in after-build
files are visible to items that depend on this build item but
not to the item itself, this mechanism is useful for changing
interface variables for the item's reverse dependencies
without changing what the build item itself sees. The Java
code generator example (Section 19.2, “Java Code Generator Example”) does this. It
also makes this construct useful for automatically generated
interface data. For an example of that use, see Section 15.3, “Autoconf Example”.
To specify the target type to which subsequent variable declarations belong, use
target-type type
where type is the name of the
target type. For information about target types, see Chapter 5, Target Types, Platform Types, and Platforms. In addition to the built-in target
types, the special type all may be used to
indicate that variables should be made available to all target
types. In practice, there is little reason to ever restrict a
variable to a particular target type, though many of the
abuild predefined variables are restricted. Restricting the
target type of a variable only determines whether that
variable is passed to the backend, so the only reason to
restrict a variable to a specific target type would be to
reduce the number of unneeded variables that were passed to
the backend. It has no impact on variable scope, visibility,
or even availability for use in other
Abuild.interface files.
Conditionals in Abuild.interface take the
following form:
if (condition) ...valid code... elseif (condition) ...valid code... elseif (condition) ...valid code... else ...valid code... endif
An if block may contain zero or more
elseif clauses and an optional
else clause. Any valid
Abuild.interface code, including nested
conditionals, is permitted inside a conditional block. Recall
that all variables have global scope including variables
declared inside of conditional blocks. Code inside of
conditions that are not satisfied is ignored but must be
syntactically valid.
The conditions specified above may
be of one of the following forms:
$(variable)
where variable is a boolean
variable, or
function(arg,arg, ...)
where function is a valid
Abuild.interface conditional function and
each arg consists of one or more
words. Only variables declared as Boolean and specific
conditional functions, described in the next section, are
permitted in conditionals. There are no relational operators,
and variables of other types whose values happen to be valid
boolean values are not allowed in conditionals.