Running tasks in parallel is a simple problem, but in practice it is more complicated:
To make the problem more simple, it is divided by the different concerns, and the ordering constraints can be given on three different levels:
In some circumstances it is necessary to build a compiler and all its dependencies before using it for executing some other tasks (bootstrapping). The following demonstrates how declare groups of tasks to be executed after other groups of tasks:
def build(bld): bld.new_task_gen(features='cc cprogram', source='main.c', target='mycompiler') bld.add_group() bld.new_task_gen(features='cc cprogram', source='user.c', target='someotherapp')
The effect of task groups when running tasks in parallel is illustrated by the following diagram. Three groups of tasks have been added, and the execution of the next group only starts when the execution of the tasks in the previous group is complete.
It is possible to create groups at any point in the scripts, and to add the task generators to any group previously created. Adding groups for specific folders or scripts enables a behaviour similar to projects organized in recursive Makefiles.
def build(bld): bld.add_group('test1') bld.add_group('test2') bld.add_group('test3') bld.add_group('test4') print('adding task generators') bld.set_group('test3') bld.new_task_gen(features='cxx cprogram', source='main3.c', target='g3') bld.set_group('test1') bld.new_task_gen(features='cxx cprogram', source='main1.c', target='g1') bld.set_group('test2') obj2 = bld.new_task_gen(features='cxx cprogram', source='main2.c', target='g2') bld.set_group('test4') obj2.clone('debug')
Because task groups prevent parallelization, they reduce performance. On the other hand, they make projects more structured and improve the maintainance.
The attributes before and after are used to declare ordering constraints between tasks:
import Task class task_test_a(Task.TaskBase): before = 'task_test_b' class task_test_b(Task.TaskBase): after = 'task_test_a'
Another way to declare precedence constraints is to declare a file extension production, for example:
import Task class task_test_a(Task.TaskBase): ext_in = '.c' class task_test_b(Task.TaskBase): ext_out = '.c'
The extensions have to match to add a valid precedence constraint, but they are only annotations, they do not mean the tasks actually have to produce files of that type.