Executing tasks, accessing the file system and consulting the results of a previous build are very different concerns which have to be encapsulated properly. The core class representing a build is a build context.
The build context holds all the information necessary for a build. To accelerate the start-up, a part of the information is stored and loaded between the runs. The persistent attributes are the following:
Table 12.2. Build context persistence
Attribute | Information |
---|---|
root | Node representing the root of the file system |
srcnode | Node representing the source directory |
bldnode | Node representing the build directory |
node_sigs | File hashes (dict mapping Node ids to hashes) |
node_deps | Implicit dependencies (dict mapping Node ids) |
raw_deps | Implicit file dependencies which could not be resolved (dict mapping Node ids to lists of strings) |
task_sigs | Signature of the tasks previously run (dict mapping a Task id to a hash) |
id_nodes | Sequence for generating unique node instance ids (id of the last Node created) |
In previous Waf releases, the build context was supposed to be a unique object (one build active at a time). To enable the use of Waf as a library, the dependency on the singleton Build.bld was removed. This implies that each object should be able to obtain its build context from its attributes. Here are a few examples:
Table 12.3. Build context access
Object type | Build context access |
---|---|
Node | self.__class__.bld |
task_gen | self.bld |
Task | self.generator.bld |
Build contexts perform an os.chdir call before starting to execute the tasks. When running build contexts within build contexts (tasks), the current working directory may cause various problems. To work around them, it may be necessary to change the compilation rules (compile from the file system root) and to inject code (replace bld.compile).
Direct Node instances are not used anywhere in the Waf code. Instead, each build context creates a new Node subclass (bld.node_class), on which the build context instance is attached as a class attribute.
Nearly all the code is executed in the main thread. The other threads are merely waiting for new tasks, and executing the methods run from the task instances. Such methods should contain as little code as possible, and access the BuildContext in a read-only manner.
If the run methods have to modify the build context, it is recommended to overload the method get_out of the scheduler and to execute methods in an event-like manner (data is attached to the task, and the method get_out executes the code). Adding more tasks from a running task is demonstrated the section called “A compiler producing source files with names unknown in advance”.