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