mirror of https://gitlab.com/ita1024/waf.git
Provide unity builds per task generator
This commit is contained in:
parent
512bbfd819
commit
f7a16da8fc
|
@ -2,22 +2,52 @@
|
||||||
# encoding: utf-8
|
# encoding: utf-8
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Compile whole groups of C/C++ files at once.
|
Compile whole groups of C/C++ files at once
|
||||||
|
(C and C++ files are processed independently though).
|
||||||
|
|
||||||
|
To enable globally::
|
||||||
|
|
||||||
|
def options(opt):
|
||||||
|
opt.load('compiler_cxx')
|
||||||
|
def build(bld):
|
||||||
|
bld.load('compiler_cxx unity')
|
||||||
|
|
||||||
|
To enable for specific task generators only::
|
||||||
|
|
||||||
|
def build(bld):
|
||||||
|
bld(features='c cprogram unity', source='main.c', ...)
|
||||||
|
|
||||||
|
The file order is often significant in such builds, so it can be
|
||||||
|
necessary to adjust the order of source files and the batch sizes.
|
||||||
|
To control the amount of files processed in a batch per target
|
||||||
|
(the default is 50)::
|
||||||
|
|
||||||
|
def build(bld):
|
||||||
|
bld(features='c cprogram', unity_size=20)
|
||||||
|
|
||||||
def build(bld):
|
|
||||||
bld.load('compiler_cxx unity')
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import sys
|
|
||||||
from waflib import Task, Options
|
from waflib import Task, Options
|
||||||
from waflib.Tools import c_preproc
|
from waflib.Tools import c_preproc
|
||||||
from waflib import TaskGen
|
from waflib import TaskGen
|
||||||
|
|
||||||
MAX_BATCH = 50
|
MAX_BATCH = 50
|
||||||
|
|
||||||
|
EXTS_C = ('.c',)
|
||||||
|
EXTS_CXX = ('.cpp','.cc','.cxx','.C','.c++')
|
||||||
|
|
||||||
def options(opt):
|
def options(opt):
|
||||||
global MAX_BATCH
|
global MAX_BATCH
|
||||||
opt.add_option('--batchsize', action='store', dest='batchsize', type='int', default=MAX_BATCH, help='batch size (0 for no batch)')
|
opt.add_option('--batchsize', action='store', dest='batchsize', type='int', default=MAX_BATCH,
|
||||||
|
help='default unity batch size (0 disables unity builds)')
|
||||||
|
|
||||||
|
@TaskGen.taskgen_method
|
||||||
|
def batch_size(self):
|
||||||
|
default = getattr(Options.options, 'batchsize', MAX_BATCH)
|
||||||
|
if default < 1:
|
||||||
|
return 0
|
||||||
|
return getattr(self, 'unity_size', default)
|
||||||
|
|
||||||
|
|
||||||
class unity(Task.Task):
|
class unity(Task.Task):
|
||||||
color = 'BLUE'
|
color = 'BLUE'
|
||||||
|
@ -30,43 +60,49 @@ class unity(Task.Task):
|
||||||
lst = ['#include "%s"\n' % self.to_include(node) for node in self.inputs]
|
lst = ['#include "%s"\n' % self.to_include(node) for node in self.inputs]
|
||||||
txt = ''.join(lst)
|
txt = ''.join(lst)
|
||||||
self.outputs[0].write(txt)
|
self.outputs[0].write(txt)
|
||||||
|
def __str__(self):
|
||||||
|
node = self.outputs[0]
|
||||||
|
return node.path_from(node.ctx.launch_node())
|
||||||
|
|
||||||
@TaskGen.taskgen_method
|
def bind_unity(obj, cls_name, exts):
|
||||||
def batch_size(self):
|
if not 'mappings' in obj.__dict__:
|
||||||
return getattr(Options.options, 'batchsize', MAX_BATCH)
|
obj.mappings = dict(obj.mappings)
|
||||||
|
|
||||||
def make_batch_fun(ext):
|
for j in exts:
|
||||||
# this generic code makes this quite unreadable, defining the function two times might have been better
|
fun = obj.mappings[j]
|
||||||
def make_batch(self, node):
|
if fun.__name__ == 'unity_fun':
|
||||||
cnt = self.batch_size()
|
raise ValueError('Attempt to bind unity mappings multiple times %r' % j)
|
||||||
if cnt <= 1:
|
|
||||||
return self.create_compiled_task(ext, node)
|
|
||||||
x = getattr(self, 'master_%s' % ext, None)
|
|
||||||
if not x or len(x.inputs) >= cnt:
|
|
||||||
x = self.create_task('unity')
|
|
||||||
setattr(self, 'master_%s' % ext, x)
|
|
||||||
|
|
||||||
cnt_cur = getattr(self, 'cnt_%s' % ext, 0)
|
def unity_fun(self, node):
|
||||||
cxxnode = node.parent.find_or_declare('unity_%s_%d_%d.%s' % (self.idx, cnt_cur, cnt, ext))
|
cnt = self.batch_size()
|
||||||
x.outputs = [cxxnode]
|
if cnt <= 1:
|
||||||
setattr(self, 'cnt_%s' % ext, cnt_cur + 1)
|
return fun(self, node)
|
||||||
self.create_compiled_task(ext, cxxnode)
|
x = getattr(self, 'master_%s' % cls_name, None)
|
||||||
x.inputs.append(node)
|
if not x or len(x.inputs) >= cnt:
|
||||||
return make_batch
|
x = self.create_task('unity')
|
||||||
|
setattr(self, 'master_%s' % cls_name, x)
|
||||||
|
|
||||||
def enable_support(cc, cxx):
|
cnt_cur = getattr(self, 'cnt_%s' % cls_name, 0)
|
||||||
if cxx or not cc:
|
c_node = node.parent.find_or_declare('unity_%s_%d_%d.%s' % (self.idx, cnt_cur, cnt, cls_name))
|
||||||
TaskGen.extension('.cpp', '.cc', '.cxx', '.C', '.c++')(make_batch_fun('cxx'))
|
x.outputs = [c_node]
|
||||||
if cc:
|
setattr(self, 'cnt_%s' % cls_name, cnt_cur + 1)
|
||||||
TaskGen.extension('.c')(make_batch_fun('c'))
|
fun(self, c_node)
|
||||||
else:
|
x.inputs.append(node)
|
||||||
TaskGen.task_gen.mappings['.c'] = TaskGen.task_gen.mappings['.cpp']
|
|
||||||
|
|
||||||
has_c = '.c' in TaskGen.task_gen.mappings or 'waflib.Tools.compiler_c' in sys.modules
|
obj.mappings[j] = unity_fun
|
||||||
has_cpp = '.cpp' in TaskGen.task_gen.mappings or 'waflib.Tools.compiler_cxx' in sys.modules
|
|
||||||
enable_support(has_c, has_cpp) # by default
|
@TaskGen.feature('unity')
|
||||||
|
@TaskGen.before('process_source')
|
||||||
|
def single_unity(self):
|
||||||
|
lst = self.to_list(self.features)
|
||||||
|
if 'c' in lst:
|
||||||
|
bind_unity(self, 'c', EXTS_C)
|
||||||
|
if 'cxx' in lst:
|
||||||
|
bind_unity(self, 'cxx', EXTS_CXX)
|
||||||
|
|
||||||
def build(bld):
|
def build(bld):
|
||||||
# it is best to do this
|
if bld.env.CC_NAME:
|
||||||
enable_support(bld.env.CC_NAME, bld.env.CXX_NAME)
|
bind_unity(TaskGen.task_gen, 'c', EXTS_C)
|
||||||
|
if bld.env.CXX_NAME:
|
||||||
|
bind_unity(TaskGen.task_gen, 'cxx', EXTS_CXX)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue