In this example, we'll demonstrate a task branch. Suppose our
task branch makes changes to project but not
to common. We can set up a new build tree
in which to do our work. We would populate this build tree with
whatever parts of project we wanted to
modify. We have set up this build tree in
doc/example/general/task/project.
Additionally, we have set this build tree's backing area to
../../reference/project so that it would
resolve any missing build items or externals to that location:
general/task/project/Abuild.backing
../../reference/project
Note that, although we used a relative path for our backing area
in this example, we would ordinarily set our backing area to an
absolute path. We use a relative path here only so that the
examples can remain independent of the location of
doc/example. Our task branch also includes
the derived project. Since we are not making modifications to
any build items in common, we don't have to
create a build tree at task/common, even
though our root Abuild.conf lists
../common as an external:
general/task/project/Abuild.conf
external-dirs: ../common child-dirs: main lib
Since that relative path exists as a valid build tree relative to
our backing area, abuild will just use
../common relative to the backing area
(../../reference/project/../common, which is
../../reference/common) to resolve the
external. For a diagram of the task branch build trees, see
Figure 10.4, “Build Trees in general/task”.
Figure 10.4. Build Trees in general/task

The derived build tree in the
task branch declares the
project build tree as an external. The
project build tree in the
task branch declares the
common build tree as an external, but
since the common build tree isn't
shadowed in the task branch, that
external is resolved to the reference
tree instead. The derived and
project build trees in the
task branch both back to their
corresponding build trees in reference.
As always, for this example to work properly, our
backing area must be fully built. If you are following along, to
make sure this is the case, you should run abuild
--build=all in reference/derived.
Next run abuild --build=all no-op in
task/project. This generates the following
output:
example.task-project-no-op.out
abuild: project-lib.src (abuild-<native>): no-op abuild: project-lib.test (abuild-<native>): no-op abuild: project-main.src (abuild-<native>): no-op
This includes only items in our task branch. No items in our backing area are included because abuild never attempts to build or modify build items in backing areas.
If you study include/ProjectLib.hpp and
src/ProjectLib.cpp in
task/project/lib in comparison to their
counterparts in reference/project/lib, you'll
notice that the only change we made in this task branch is the
addition of an optional parameter to
ProjectLib's constructor. We also updated the
test suite to pass a different argument to
ProjectLib. This new value comes from a new
build item we added: project-lib.extra. To
add the new build item, we created
task/project/lib/extra/Abuild.conf:
and also added the extra directory in
task/project/lib/Abuild.conf:
general/task/project/lib/extra/Abuild.conf
this: project-lib.extra platform-types: native parent-dir: ..
general/task/project/lib/Abuild.conf
this: project-lib parent-dir: .. child-dirs: src test extra deps: project-lib.src
We didn't modify anything under
task/project/main at all, but we included it
in our task branch so we could run its test suite. Remember that
abuild won't try to build the copy of
project-main there, and even if it did,
that copy of project-main would not see
our local copy of project-lib: it would
see the copy in its own local build tree, which we have shadowed.
This is an example of a shadowed dependency as described in Section 10.4, “Integrity Checks”. This is the output we see when
running abuild --build=all check from
task/project:
example.task-project-check.out
abuild: project-lib.src (abuild-<native>): check make: Entering directory `--topdir--/general/task/project/lib/src/abuild\ \-<native>' Compiling ../ProjectLib.cpp as C++ Creating project-lib library make: Leaving directory `--topdir--/general/task/project/lib/src/abuild-\ \<native>' abuild: project-lib.test (abuild-<native>): check make: Entering directory `--topdir--/general/task/project/lib/test/abuil\ \d-<native>' Compiling ../main.cpp as C++ Creating lib_test executable ********************************* STARTING TESTS on ---timestamp--- ********************************* Running ../qtest/lib.test lib 1 (test lib class) ... PASSED Overall test suite ... PASSED TESTS COMPLETE. Summary: Total tests: 1 Passes: 1 Failures: 0 Unexpected Passes: 0 Expected Failures: 0 Missing Tests: 0 Extra Tests: 0 make: Leaving directory `--topdir--/general/task/project/lib/test/abuild\ \-<native>' abuild: project-main.src (abuild-<native>): check make: Entering directory `--topdir--/general/task/project/main/src/abuil\ \d-<native>' Compiling ../main.cpp as C++ Creating main executable ********************************* STARTING TESTS on ---timestamp--- ********************************* Running ../qtest/main.test main 1 (testing project-main) ... PASSED Overall test suite ... PASSED TESTS COMPLETE. Summary: Total tests: 1 Passes: 1 Failures: 0 Unexpected Passes: 0 Expected Failures: 0 Missing Tests: 0 Extra Tests: 0 make: Leaving directory `--topdir--/general/task/project/main/src/abuild\ \-<native>'
As with the no-op build, we only see output relating to local build items, not to build items in our backing areas as they are assumed to be already built.