The example below demonstrates how to write the output of svnversion into a header. The command is always run, and the c/c++ compilation will be executed if the header changes (implicit dependencies obtained by the Waf preprocessor):
def build(bld): # 1. A simple program main = bld.new_task_gen( features = 'cc cprogram', source = 'main.c', target = 'test_c_program', uselib_local = 'teststaticlib', svn_header = 'ver.h') # 2. A simple static lib staticlib = bld.new_task_gen( features = 'cc cstaticlib', source = 'test_staticlib.c', target = 'teststaticlib' ) import subprocess from Constants import RUN_ME from TaskGen import feature, after import Task, Utils @feature('cc') @after('apply_core') def process_svn(self):
if getattr(self, 'svn_header', None): tsk = self.create_task('svn_ver') tsk.set_outputs(self.path.find_or_declare(self.svn_header)) def get_svn_rev():
try: p = subprocess.Popen(['svn', 'info', '--non-interactive'], stdout=subprocess.PIPE, \ stderr=subprocess.STDOUT, close_fds=False, env={'LANG' : 'C'}) stdout = p.communicate()[0] if p.returncode == 0: lines = stdout.splitlines(True) for line in lines: if line.startswith('Last Changed Rev'): key, value = line.split(': ', 1) return value.strip() return '-1' except: return '-1' def svnvars(self):
self.ver = get_svn_rev() fi = open(self.outputs[0].abspath(self.env), 'w') fi.write('#define VER "%d"\n' % self.ver) fi.close() cls = Task.task_type_from_func('svn_ver', vars=[], func=svnvars, color='BLUE', before='cc')
def always(self):
return RUN_ME cls.runnable_status = always def post_run(self):
sg = Utils.h_list(self.ver) node = self.outputs[0] variant = node.variant(self.env) self.generator.bld.node_sigs[variant][node.id] = sg cls.post_run = post_run
Example in a user script, the attribute svn_header is used to indicate a header to create as a build file | |
Process the attribute svn_header when present, create a task instance | |
A function for obtaining the svn version of the project | |
Obtain the svn version and write it to the header | |
Declaration of the task which will execute the svn processing | |
The task must be run each time - there is no signature involved | |
Mark the outputs as changed if necessary by changing the signature |
Task creation is performed through a new task generator method (process_svn) which is executed only when the task generator creates all its tasks. This organization makes it possible to compile only the code necessary for a specific target (tasks are created lazily, and are grouped by task generators). To address the scenario described, a new task type is created, and methods are replaced dynamically: runnable_status (execute each time), and post_run (change the signature of the outputs according to the contents of the file created).