123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144 |
- #! /usr/bin/env python
- # encoding: utf-8
- # Thomas Nagy, 2010 (ita)
- VERSION='0.0.1'
- APPNAME='cpp_gen'
- top = '.'
- out = 'build'
- def options(opt):
- opt.load('compiler_cxx')
- def configure(conf):
- conf.load('compiler_cxx')
- conf.check(header_name='stdio.h', features='cxx cxxprogram', mandatory=False)
- def build(bld):
- bld.program(source='main.cpp a.cpp', target='app')
- #--------
- import os
- from waflib import Task, TaskGen, Utils
- from waflib.Tools import cxx
- @TaskGen.extension('.cpp')
- def more_tasks_at_once(self, node):
- task1 = self.create_task('prog1', node, [])
- task2 = self.create_compiled_task('cxx', node)
- def cmpnodes(a, b):
- return cmp(a.abspath(), b.abspath())
- class prog1(Task.Task):
- before = ['cxxprogram', 'cxxshlib', 'cxxstlib']
- def uid(self):
- """
- the unique id of this task should only depend on the file inputs
- """
- m = Utils.md5()
- up = m.update
- up(self.__class__.__name__.encode())
- for x in self.inputs:
- up(x.abspath().encode())
- return m.digest()
- def runnable_status(self):
- """
- since it is called after the build has started,
- any task added must be passed through 'more_tasks'
- """
- for x in self.run_after:
- if not x.hasrun:
- return Task.ASK_LATER
- # so this is a bit special, the goal here is to set the output nodes
- # and to create the c++ tasks before the normal processing is done
- sig = self.signature()
- for x in self.generator.bld.raw_deps.get(sig, []):
- self.outputs.append(self.generator.bld.srcnode.find_node(x))
- if not self.outputs:
- self.read_outputs_from_cache()
- if self.outputs:
- self.create_cxx_task()
- ret = Task.Task.runnable_status(self)
- return ret
- def create_cxx_task(self):
- """
- create a task dynamically during the build
- notice the use of 'more_tasks'
- """
- tsk = cxx.cxx_hook(self.generator, self.outputs[0])
- tsk.set_run_after(self) # the build has started, so the order must be set manually
- self.more_tasks = [tsk] # add tasks dynamically during the build
- self.generator.link_task.inputs.append(tsk.outputs[0]) # add another input for the link task
- try:
- self.generator.link_task.inputs.sort(cmp=cmpnodes) # eliminate the random order (more tasks like this)
- except:
- self.generator.link_task.inputs.sort(key=lambda x: x.abspath()) # python3
- self.generator.link_task.set_run_after(tsk) # do not forget to set the build order there too
- def run(self):
- """
- actual execution
- this code should not be executed if the files are retrieved from the cache
- """
- if self.inputs[0].name == 'a.cpp':
- # simulate the creation of an interface file
- out = self.inputs[0].parent.get_bld().make_node('a.ser.cpp')
- out.write('\n\n')
- # read the file system
- # remember that nodes cannot be created concurrently
- # so you might to crate a lock if several tasks want the same nodes
- inp = self.inputs[0]
- node = inp.parent.get_bld().find_node(inp.name.replace('.cpp', '.ser.cpp'))
- if node:
- self.outputs = [node]
- h_node = inp.parent.find_node(inp.name.replace('.cpp', '.ser.h'))
- if h_node:
- self.outputs.append(h_node)
- # if there are outputs, create a new c++ task
- if self.outputs:
- self.create_cxx_task()
- # access the scanner data
- self.generator.bld.raw_deps[self.signature()] = [x.path_from(self.generator.bld.srcnode) for x in self.outputs]
- def read_outputs_from_cache(self):
- """
- set the outputs from the results found in the cache
- we assume that the files are created in the same folder as the inputs
- if it is not like this, the nodes should be restored by another system, for example
- by storing them in a separate file during run()
- """
- env = self.env
- sig = self.signature()
- ssig = Utils.to_hex(sig)
- # first try to access the cache folder for the task
- dname = os.path.join(self.generator.bld.cache_global, ssig)
- try:
- t1 = os.stat(dname).st_mtime
- except OSError:
- return None
- try:
- lst = os.listdir(dname)
- except:
- return
- for x in lst:
- self.outputs.append(self.inputs[0].parent.find_or_declare(x))
- # not a fresh build and the cache is removed -> remember the files in the scanner data
- self.generator.bld.raw_deps[self.signature()] = [x.path_from(self.generator.bld.srcnode) for x in self.outputs]
|