11.4. Task Branch Example

In this example, we'll demonstrate a task branch. Suppose our task branch makes changes to project but not to common or derived. We can set up a new build forest in which to do our work. We would populate this build forest with whatever parts of project we wanted to modify. We have set up this forest in doc/example/general/task. Additionally, we have set this forest's backing area to ../reference so that it would resolve any missing build items or trees to that location:

general/task/Abuild.backing

backing-areas: ../reference

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. Since we are not making modifications to any build items in common or derived, we don't have to include those build trees in our task branch. Note that our forest root Abuild.conf still lists common and derived as children, since it is just a copy of the root Abuild.conf from reference:

general/task/Abuild.conf

child-dirs: common project derived

Since this forest has a backing area, abuild ignores the fact that the common and derived directories do not exist. For a diagram of the task branch build trees, see Figure 11.2, “Build Trees in general/task.

Figure 11.2. Build Trees in general/task

Build Trees in general/task

The derived build tree declares a tree dependency on the project build tree. The project build tree declares a tree dependency on the common build tree. Since the common and derived build trees are not shadowed in the task branch, those trees are resolved in the backing area, reference, instead.


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=deptrees no-op in task/project. This generates the following output:

task-project-no-op.out

abuild: build starting
abuild: project-lib.src (abuild-<native>): no-op
abuild: project-lib.test (abuild-<native>): no-op
abuild: project-main.src (abuild-<native>): no-op
abuild: build complete

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

name: project-lib.extra
platform-types: native

general/task/project/lib/Abuild.conf

name: project-lib
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 11.3, “Integrity Checks”. This is the output we see when running abuild --build=deptrees check from task/project:

task-project-check.out

abuild: build starting
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>'
abuild: build complete

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.