By default, build items are allowed to refer to other build items
directly in their Abuild.conf
files subject
to certain scoping rules as described in Section 6.3, “Build Item Name Scoping”. In some rare instances,
in order to resolve a conflict between what a given build item is
supposed to be able to see and which items a given item is
supposed to be seen by, it is necessary to increase the visibility
of a build item. In this chapter, we describe a mechanism for
doing this and present a real-world example in which it would be
required.
The Abuild.conf
file supports an optional
visible-to key has a value consisting of a
single scope identifier. It may have one of the following two
forms:
ancestor-scope.*
: the current build
item is visible to all build items under the named
ancestor-scope. The ancestor-scope must be at or above the
“grandparent” of the current build item since
build items belong by default to the scope named by the parent
build item.
*
: this build item may be seen by any build
item.
For example, if the item A.B.C
declared
itself as visible to A.*
, then the items
A.P
, A.Q.R
, or
anything else under A
would be allowed to
access it directly. Even though it is hidden beneath
A.B
, access to it would be checked as if
it were directly under A
. The
A.B.C
build item would increase its
visibility by adding this line to its
Abuild.conf
:
visible-to: A.*
Here we describe a more concrete example. The next section demonstrates an actual implementation of the pattern described here. Suppose you needed to implement a project that contained build items at different levels of classification, which we'll call public and sensitive. We want the sensitive build items to be able to see the public ones, but the public ones should never be allowed to see the sensitive ones. To achieve this, we create an public build tree and a sensitive build tree, and then we have the sensitive build tree list the public build tree as a tree dependency. The explanation that follows refers to Figure 25.1, “Build Item Visibility”.
Figure 25.1. Build Item Visibility
B.sensitive
can see
B.W
and B.X
because of its scope. B.sensitive
can
be seen by A.sensitive
because of its
visibility.
Suppose you have software components A
and
B
and that A
depends on B
. Let's say that
B
has two public subcomponents called
B.Q
and B.R
and
that B
's Abuild.conf
declares those as dependencies, making it a facade build item for
its subcomponents. When A
depends on
B
, it will automatically get
B.Q
's and B.R
's
interfaces through B
's dependency on them.
Now suppose that both A
and
B
have some additional subcomponents that
are sensitive. In order to avoid having the public items even
know that the sensitive items exist and to prevent them from ever
accidentally depending on them even when they are being modified
in a sensitive environment, we add sensitive subcomponents to
A
and B
in a
completely separate build tree. Suppose B
has sensitive subcomponents B.W
and
B.X
. Those need to be under the scope
B
so that they can see
B.Q
and B.R
. Now
we can create a facade build item called
B.sensitive
that depends on
B
and also on B.W
and B.X
. Then anyone who depends on
B.sensitive
can see all four subcomponents
of B
. Suppose we have a sensitive version
of A
called
A.sensitive
. Unfortunately, by our normal
scoping rules, A.sensitive
would not be
allowed to depend on B.sensitive
because
B.sensitive
would be hidden beneath
B
. We can't move
B.sensitive
out of
B
(by calling it something like
B_sensitive
, for example) since then it
would not be able to depend on B.W
and
B.X
. Instead, we have to have
B.sensitive
make itself globally visible
by adding visible-to: *
to its
Abuild.conf
. Now any build item that can
resolve its name, which by design means only build items in the
sensitive build tree, can declare a dependency directly on
B.sensitive
. That way, the public
A
build item depends on the public
B
build item, and the sensitive
A.sensitive
build item depends on the
sensitive B.sensitive
build item, and all
constraints are satisfied. This pattern can be useful whenever
separate build trees are used to add new private subcomponents to
something defined in a different build tree. In this case, the
use of a separate tree and a tree dependency creates what is
effectively a one-way dependency gate:
items in the sensitive tree can see items in the public tree, but
items in the public tree can't see items in the sensitive tree.
The next section demonstrates an actual implementation of this
pattern.