waf

FORK: waf with some random patches
git clone https://git.neptards.moe/neptards/waf.git
Log | Files | Refs | README

wscript (4216B)


      1 #! /usr/bin/env python
      2 # encoding: utf-8
      3 # Thomas Nagy, 2010 (ita)
      4 
      5 VERSION='0.0.1'
      6 APPNAME='cpp_gen'
      7 
      8 top = '.'
      9 out = 'build'
     10 
     11 def options(opt):
     12 	opt.load('compiler_cxx')
     13 
     14 def configure(conf):
     15 	conf.load('compiler_cxx')
     16 	conf.check(header_name='stdio.h', features='cxx cxxprogram', mandatory=False)
     17 
     18 def build(bld):
     19 	bld.program(source='main.cpp a.cpp', target='app')
     20 
     21 #--------
     22 
     23 import os
     24 from waflib import Task, TaskGen, Utils
     25 from waflib.Tools import cxx
     26 
     27 @TaskGen.extension('.cpp')
     28 def more_tasks_at_once(self, node):
     29    task1 = self.create_task('prog1', node, [])
     30    task2 = self.create_compiled_task('cxx', node)
     31 
     32 def cmpnodes(a, b):
     33 	return cmp(a.abspath(), b.abspath())
     34 
     35 class prog1(Task.Task):
     36 	before = ['cxxprogram', 'cxxshlib', 'cxxstlib']
     37 
     38 	def uid(self):
     39 		"""
     40 		the unique id of this task should only depend on the file inputs
     41 		"""
     42 		m = Utils.md5()
     43 		up = m.update
     44 		up(self.__class__.__name__.encode())
     45 		for x in self.inputs:
     46 			up(x.abspath().encode())
     47 		return m.digest()
     48 
     49 	def runnable_status(self):
     50 		"""
     51 		since it is called after the build has started,
     52 		any task added must be passed through 'more_tasks'
     53 		"""
     54 		for x in self.run_after:
     55 			if not x.hasrun:
     56 				return Task.ASK_LATER
     57 
     58 		# so this is a bit special, the goal here is to set the output nodes
     59 		# and to create the c++ tasks before the normal processing is done
     60 		sig = self.signature()
     61 		for x in self.generator.bld.raw_deps.get(sig, []):
     62 			self.outputs.append(self.generator.bld.srcnode.find_node(x))
     63 
     64 		if not self.outputs:
     65 			self.read_outputs_from_cache()
     66 
     67 		if self.outputs:
     68 			self.create_cxx_task()
     69 
     70 		ret = Task.Task.runnable_status(self)
     71 		return ret
     72 
     73 	def create_cxx_task(self):
     74 		"""
     75 		create a task dynamically during the build
     76 		notice the use of 'more_tasks'
     77 		"""
     78 		tsk = cxx.cxx_hook(self.generator, self.outputs[0])
     79 		tsk.set_run_after(self) # the build has started, so the order must be set manually
     80 		self.more_tasks = [tsk] # add tasks dynamically during the build
     81 		self.generator.link_task.inputs.append(tsk.outputs[0]) # add another input for the link task
     82 		try:
     83 			self.generator.link_task.inputs.sort(cmp=cmpnodes) # eliminate the random order (more tasks like this)
     84 		except:
     85 			self.generator.link_task.inputs.sort(key=lambda x: x.abspath()) # python3
     86 		self.generator.link_task.set_run_after(tsk) # do not forget to set the build order there too
     87 
     88 	def run(self):
     89 		"""
     90 		actual execution
     91 		this code should not be executed if the files are retrieved from the cache
     92 		"""
     93 		if self.inputs[0].name == 'a.cpp':
     94 			# simulate the creation of an interface file
     95 			out = self.inputs[0].parent.get_bld().make_node('a.ser.cpp')
     96 			out.write('\n\n')
     97 
     98 		# read the file system
     99 		# remember that nodes cannot be created concurrently
    100 		# so you might to crate a lock if several tasks want the same nodes
    101 		inp = self.inputs[0]
    102 		node = inp.parent.get_bld().find_node(inp.name.replace('.cpp', '.ser.cpp'))
    103 		if node:
    104 			self.outputs = [node]
    105 			h_node = inp.parent.find_node(inp.name.replace('.cpp', '.ser.h'))
    106 			if h_node:
    107 				self.outputs.append(h_node)
    108 
    109 		# if there are outputs, create a new c++ task
    110 		if self.outputs:
    111 			self.create_cxx_task()
    112 
    113 			# access the scanner data
    114 			self.generator.bld.raw_deps[self.signature()] = [x.path_from(self.generator.bld.srcnode) for x in self.outputs]
    115 
    116 	def read_outputs_from_cache(self):
    117 		"""
    118 		set the outputs from the results found in the cache
    119 		we assume that the files are created in the same folder as the inputs
    120 		if it is not like this, the nodes should be restored by another system, for example
    121 		by storing them in a separate file during run()
    122 		"""
    123 		env = self.env
    124 		sig = self.signature()
    125 		ssig = Utils.to_hex(sig)
    126 
    127 		# first try to access the cache folder for the task
    128 		dname = os.path.join(self.generator.bld.cache_global, ssig)
    129 		try:
    130 			t1 = os.stat(dname).st_mtime
    131 		except OSError:
    132 			return None
    133 
    134 		try:
    135 			lst = os.listdir(dname)
    136 		except:
    137 			return
    138 
    139 		for x in lst:
    140 			self.outputs.append(self.inputs[0].parent.find_or_declare(x))
    141 
    142 		# not a fresh build and the cache is removed -> remember the files in the scanner data
    143 		self.generator.bld.raw_deps[self.signature()] = [x.path_from(self.generator.bld.srcnode) for x in self.outputs]
    144