24.3. Explicit Cross-Platform Dependencies

Ordinarily, when A depends on
B, abuild requires that
B be buildable on platforms that are
compatible with all the platforms A is
being built on. In this case, the instance of
A being built on platform p
depends specifically on the instance of B
being built on platform p or some other platform
that is compatible with p. Under these rules, it
would be impossible for A to depend on
B if B couldn't be
built on at least one platform that was compatible with each of
A's platforms. This would make it
impossible for a platform-independent item to depend on any
object-code or Java build items, object-code and Java build items
to depend on each other, or for non-compatible object-code
platform types to depend on each other. (Recall from the
previous section that any item can depend on a
platform-independent build item since the platform type
indep is compatible with all other platform types.)
To make these other cases possible, abuild allows a dependency
to declare that the dependency should be on a specific platform
by using the -platform flag to the dependency
declaration. Rather than declaring a platform by name, the
argument to the -platform argument is either a
platform type or a platform-type-qualified platform selector. In
this case, the instance of A on each of
its platforms depends on the specifically selected instance of
B.
[50]

To choose which of B's platforms will be
used, abuild picks the first platform in the given type that
matches the platform selector. Matches are performed using the
same technique as when platform selectors are specified on the
command line with two exceptions: the criteria field
may be omitted, and the selector only ever matches a single
platform even if * appears as one of the
fields. Abuild versions prior to 1.1 ignored any platform
specifiers given on the command line or in the environment when
resolving cross-platform dependencies, but the current abuild
does take them into consideration. If you want to specify a
platform-specific dependency on the default platform for a given
platform type regardless of any platform
selectors, you can specify
platform-type:default as
the -platform option to your dependency.

24.3.1. Interface Errors

Under a very specific set of circumstances, it is possible to
have a subtle and hard-to-understand error condition involving
interface variables with cross-platform dependencies. You
should feel free to skip this section unless you are either
determined to understand the deepest subtleties of how abuild
works or you have been directed here by an error message issued
by abuild. To understand the material in this section, it
will help to understand Section 33.6, “Construction of the Build Graph” and Section 33.7, “Implementation of the Abuild Interface System”.

Internally, when abuild builds a build item, it loads the
interfaces of all the other build items that the item depends
on. If item A depends on item
B in two different ways (say directly and
indirectly or indirectly through two different dependency
paths), abuild will effectively still load
B's interface file only one time because
of the way the interface system keeps track of things. At least
this is what happens under normal circumstances. If, however,
the two different instances of B in
A's dependency chain are from different
platforms, problems can arise.

We should note that this can happen only under the following
conditions:

Build item A depends (directly or
indirectly) on two items, which we'll call
X1 and X2.

Both X1 and X2
depend on B.

At least one of X1 and
X2 depends on B
with a platform-specific dependency. If both do, they do so
with different platform specifications.

When all of the above conditions have been met,
A will have two different instances of
B in its dependency chain.

Once this situation has occurred, it becomes possible for there
two be conflicting assignments to a variable, both of which
originate from the same line of the same interface file. For
example, if B's
Abuild.interface file assigns the value of
$(ABUILD_OUTPUT_DIR) to a scalar interface
variable, the effect of that assignment will differ across the
two different instances of B. Abuild
will detect this case and issue an error message. (That error
message will direct you here to this section of the manual!) If
B assigns this to a list variable,
there's no problem—abuild will honor both assignments.
It's also no problem if the assignment doesn't have different
meanings on the different platforms. It's only when the same
assignment causes a conflict that abuild will complain.

If you should run into this situation, there are several
possible remedies you should consider.

Rethink why you are using cross-platform dependencies in this
way. If you're just trying to make sure that some other
build item gets built, consider whether you can use
build-also instead of platform-specific
dependencies to meet your needs.

If you want both values and doing this won't hurt other build
items, use a list variable instead of a non-list variable.
In this case, abuild will give you both (all) values.

If you don't care which value you get, and doing so doesn't
cause other problems for other build items, use a fallback or
override assignment instead of a regular assignment. Then
you'll get the first (in the case of fallback) or last (in
the case of override) assignment that is processed.

If you can't change B's interface and
A doesn't care about the value of the
value, you can do a reset on the offending variable from the
one or more of the items that A
depends on and that depend on different instances of
B. For example,
X1 could have an after-build file that
resets the offending variable. Then when
A imports X1's
interface, it will no longer include the conflicting
assignment from B's interface.

[50]
Note that a platform-specific dependency overrides the
dependency platform choice for all platforms on which the
depending is being built. It is not presently possible to make
the platform-specific dependency behave differently for
different platform types of the depending item. This behavior
could be simulated by making use of separate intermediate build
items, but if you find yourself doing that, you may need to
rethink how you're using the various platform types.