waf

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

unity.py (2872B)


      1 #! /usr/bin/env python
      2 # encoding: utf-8
      3 
      4 """
      5 Compile whole groups of C/C++ files at once
      6 (C and C++ files are processed independently though).
      7 
      8 To enable globally::
      9 
     10 	def options(opt):
     11 		opt.load('compiler_cxx')
     12 	def build(bld):
     13 		bld.load('compiler_cxx unity')
     14 
     15 To enable for specific task generators only::
     16 
     17 	def build(bld):
     18 		bld(features='c cprogram unity', source='main.c', ...)
     19 
     20 The file order is often significant in such builds, so it can be
     21 necessary to adjust the order of source files and the batch sizes.
     22 To control the amount of files processed in a batch per target
     23 (the default is 50)::
     24 
     25 	def build(bld):
     26 		bld(features='c cprogram', unity_size=20)
     27 
     28 """
     29 
     30 from waflib import Task, Options
     31 from waflib.Tools import c_preproc
     32 from waflib import TaskGen
     33 
     34 MAX_BATCH = 50
     35 
     36 EXTS_C = ('.c',)
     37 EXTS_CXX = ('.cpp','.cc','.cxx','.C','.c++')
     38 
     39 def options(opt):
     40 	global MAX_BATCH
     41 	opt.add_option('--batchsize', action='store', dest='batchsize', type='int', default=MAX_BATCH,
     42 		help='default unity batch size (0 disables unity builds)')
     43 
     44 @TaskGen.taskgen_method
     45 def batch_size(self):
     46 	default = getattr(Options.options, 'batchsize', MAX_BATCH)
     47 	if default < 1:
     48 		return 0
     49 	return getattr(self, 'unity_size', default)
     50 
     51 
     52 class unity(Task.Task):
     53 	color = 'BLUE'
     54 	scan = c_preproc.scan
     55 	def to_include(self, node):
     56 		ret = node.path_from(self.outputs[0].parent)
     57 		ret = ret.replace('\\', '\\\\').replace('"', '\\"')
     58 		return ret
     59 	def run(self):
     60 		lst = ['#include "%s"\n' % self.to_include(node) for node in self.inputs]
     61 		txt = ''.join(lst)
     62 		self.outputs[0].write(txt)
     63 	def __str__(self):
     64 		node = self.outputs[0]
     65 		return node.path_from(node.ctx.launch_node())
     66 
     67 def bind_unity(obj, cls_name, exts):
     68 	if not 'mappings' in obj.__dict__:
     69 		obj.mappings = dict(obj.mappings)
     70 
     71 	for j in exts:
     72 		fun = obj.mappings[j]
     73 		if fun.__name__ == 'unity_fun':
     74 			raise ValueError('Attempt to bind unity mappings multiple times %r' % j)
     75 
     76 		def unity_fun(self, node):
     77 			cnt = self.batch_size()
     78 			if cnt <= 1:
     79 				return fun(self, node)
     80 			x = getattr(self, 'master_%s' % cls_name, None)
     81 			if not x or len(x.inputs) >= cnt:
     82 				x = self.create_task('unity')
     83 				setattr(self, 'master_%s' % cls_name, x)
     84 
     85 				cnt_cur = getattr(self, 'cnt_%s' % cls_name, 0)
     86 				c_node = node.parent.find_or_declare('unity_%s_%d_%d.%s' % (self.idx, cnt_cur, cnt, cls_name))
     87 				x.outputs = [c_node]
     88 				setattr(self, 'cnt_%s' % cls_name, cnt_cur + 1)
     89 				fun(self, c_node)
     90 			x.inputs.append(node)
     91 
     92 		obj.mappings[j] = unity_fun
     93 
     94 @TaskGen.feature('unity')
     95 @TaskGen.before('process_source')
     96 def single_unity(self):
     97 	lst = self.to_list(self.features)
     98 	if 'c' in lst:
     99 		bind_unity(self, 'c', EXTS_C)
    100 	if 'cxx' in lst:
    101 		bind_unity(self, 'cxx', EXTS_CXX)
    102 
    103 def build(bld):
    104 	if bld.env.CC_NAME:
    105 		bind_unity(TaskGen.task_gen, 'c', EXTS_C)
    106 	if bld.env.CXX_NAME:
    107 		bind_unity(TaskGen.task_gen, 'cxx', EXTS_CXX)
    108