The exclicit rules described in the previous section becomes limited for processing several files of the same kind. Instead of adding loops, we will now describe how to process files using the name or the extension, for files declared in the source attribute. This scheme is the most common technique used in the Waf library.
The following example illustrates how to add a rule for transforming .lua files into .luac files:
import TaskGen TaskGen.declare_chain( name = 'luac', rule = '${LUAC} -s -o ${TGT} ${SRC}', ext_in = '.lua', ext_out = '.luac', install = '${LUADIR}', # env variable reentrant = 0, ) def build(bld): bld.new_task_gen(source='main.lua test.lua bar.lua')
In practice, the chaining declaration is located in a separate python file which may be re-used for other projects. When more control over the declaration is needed, it is recommended to use the @extension decorator (see below).
A special method named apply_core provides file extension processing using the attribute source. On the user side, this takes the following form:
def build(bld): main = bld.new_task_gen( features = 'cc cprogram', source = 'main.c foo.c bar.c', target = 'my_app')
The method to process .c files (main.c) is declared in the following manner:
from TaskGen import extension @extension('.c') def c_hook(self, node): task = self.create_task('cc') task.inputs = [node] task.outputs = [node.change_ext(obj_ext)]
When the method apply_core is called, the following operations are performed:
Now let's illustrate the @extension decorator on idl file processing. Files with .idl extension are processed to produce .c and .h files (foo.idl -> foo.c + foo.h). The .c files must be compiled after being generated.
import Task from TaskGen import extension Task.simple_task_type('idl', 'omniidl -bcxx ${SRC} -C${TGT}', color='BLUE', ext_out='.cxx') @extension('.idl') def process_idl(self, node): cc_node = node.change_ext('.cc') h_node = node.change_ext('.h') tsk = self.create_task('idl') tsk.inputs = node tsk.outputs = [cc_node, h_node] # reinject the c++ node to the list of nodes to process self.allnodes.append(cc_node) def build(bld): bld.new_task_gen( features = 'cxx cprogram', source = 'foo.idl main.cpp', target = 'myapp' )
The @extension decorator also accepts names instead of extensions. An entry in the source list may then be an abstract name. This may be used for executing arbitrary code (task creation is not mandatory).
@extension('debug') def debug_allnodes(self, code): print (self.allnodes) def build(bld): bld.new_task_gen( features = 'cxx cprogram', source = 'debug main.cpp debug', target = 'test' )