Table of Contents
In this chapter, we will examine interface flags. Both interface flags and standard abuild interface conditionals allow us to cause a particular interface variable assignment to be evaluated only under a specific condition. When such assignments are implemented inside normal abuild interface conditional blocks, all depending build items will see the results of such assignments in the same way (as would be typical of any variable assignment system). With interface flags, it is possible to have different build items see the effects of different assignments to certain variables, a concept we describe in greater depth below. This is an unusual capability, but it is very useful for implementing private interfaces. In this chapter, we will explore interface flags in enough detail to see how to use them to implement private interfaces, which is their primary use.
If there were a contest to select the most unusual feature of abuild, interface flags would probably be the strongest contender for the prize. This section presents a conceptual overview that should be good enough to enable you to make use of interface flags to implement private interfaces. We provide a private interface example at the end of this chapter. In order to provide a conceptual overview of how interface flags work, we will present a partial but accurate explanation of how they work, and we will focus our attention on list variables only. To understand interface flags in full detail, see Section 33.7, “Implementation of the Abuild Interface System”.
     Every build item in abuild, whether it has an
     Abuild.interface file or not, has an
     abuild interface.  The abuild interface for a build item is
     the union of all the interfaces of all its dependencies, taken in
     dependency order, along with its own
     Abuild.interface, if any.  To understand
     what we mean by the “union” of abuild interfaces,
     you have to know a little bit about how abuild stores
     interfaces.
    
     Recall that abuild interface files contain a series of variable
     declarations and assignments, and that variables may be declared
     in one file and assigned to in other files.  In particular, it is
     standard operating procedure for numerous
     Abuild.interface files to all assign to the
     same list variables (INCLUDES,
     LIBDIRS, LIBS,
     abuild.classpath, etc.).  As abuild reads
     interface files and encounters multiple assignments to the same
     list variable, it doesn't actually update some internal notion of
     that variable's value as you might suspect.  Rather than storing
     the values of variables in a build item's interface, abuild
     actually retains a list of all the assignments to a given
     variable throughout all the relevant
     Abuild.interface files.  This enables
     abuild to compute the values of variables when they are needed.
     When we say that an abuild interface is the union of the
     interfaces of its dependencies, what we really mean is that the
     value of each interface variable comes from the union of all
     assignments to those variables across all the dependencies'
     interface files.
    
     There are two different times when abuild computes the value of
     an interface variable.  The first is when that variable is
     expanded in an Abuild.interface file using
     the $(VARIABLE) syntax.  The second is when
     abuild generates the dynamic output file as introduced in Section 17.1, “Abuild Interface Functionality Overview”.  In each
     case, abuild computes the value of a variable by looking at all
     the assignments it knows about at that time and combining them
     together based on whether the list variable is an
     append list or a prepend list.  Either
     way, since abuild has a history of all assignments to the
     variable, it has everything it needs to compute the value of the
     variable.
    
     Now this is where flags come in.  As we saw in Section 17.2, “Abuild.interface Syntactic Details”, it is
     possible to associate a given variable assignment with an
     interface flag.  When a variable assignment is associated with an
     interface flag, abuild simply stores this fact in the list of
     assignments to the variable.  When it is time to compute a value
     for the variable, abuild filters out all assignments that are
     associated with a flag that isn't set.  Consider the following
     example.  Suppose the variable VAR1 is
     declared as an append list of strings,
     and that you have the following assignments to
     VAR1:
     
VAR1 = one flag flag1 VAR1 = two VAR1 = three
     If you evaluate this sequence of assignments with the
     flag1 flag set, the value of
     VAR1 would be one two
     three.  If you evaluate this list of assignments
     without the flag1 flag
     set, the value of VAR1 would just be
     one three.
    
     Here is a subtle but important point.  You don't really have to
     understand it to make use of private interfaces, but if you can
     understand it, you will be well on your way to grasping how
     interface flags really work.  This handling of interface flags
     means that the value of a variable is based on the collection of
     flags that are set when its value is
     computed.  As we already noted, there are two
     instances in which abuild computes the values of variables:
     when it encounters a variable expansion while reading
     Abuild.interface files, and when it creates
     dynamic output files.  Interface flags are only set when creating
     dynamic output files.  At the time that
     Abuild.interfaces are being read, flags
     haven't been set yet.  If this worked any other way, it would not
     be possible for multiple build items to see different values for
     certain variables, and that is the whole reason for being of
     interface flags.  We defer further discussion of this point to
     Section 33.7, “Implementation of the Abuild Interface System”.