diff options
Diffstat (limited to 'extras/batched_cc.py')
-rw-r--r-- | extras/batched_cc.py | 173 |
1 files changed, 0 insertions, 173 deletions
diff --git a/extras/batched_cc.py b/extras/batched_cc.py deleted file mode 100644 index aad2872..0000000 --- a/extras/batched_cc.py +++ /dev/null @@ -1,173 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 -# Thomas Nagy, 2006-2015 (ita) - -""" -Instead of compiling object files one by one, c/c++ compilers are often able to compile at once: -cc -c ../file1.c ../file2.c ../file3.c - -Files are output on the directory where the compiler is called, and dependencies are more difficult -to track (do not run the command on all source files if only one file changes) -As such, we do as if the files were compiled one by one, but no command is actually run: -replace each cc/cpp Task by a TaskSlave. A new task called TaskMaster collects the -signatures from each slave and finds out the command-line to run. - -Just import this module to start using it: -def build(bld): - bld.load('batched_cc') - -Note that this is provided as an example, unity builds are recommended -for best performance results (fewer tasks and fewer jobs to execute). -See waflib/extras/unity.py. -""" - -from waflib import Task, Utils -from waflib.TaskGen import extension, feature, after_method -from waflib.Tools import c, cxx - -MAX_BATCH = 50 - -c_str = '${CC} ${ARCH_ST:ARCH} ${CFLAGS} ${FRAMEWORKPATH_ST:FRAMEWORKPATH} ${tsk.batch_incpaths()} ${DEFINES_ST:DEFINES} -c ${SRCLST} ${CXX_TGT_F_BATCHED} ${CPPFLAGS}' -c_fun, _ = Task.compile_fun_noshell(c_str) - -cxx_str = '${CXX} ${ARCH_ST:ARCH} ${CXXFLAGS} ${FRAMEWORKPATH_ST:FRAMEWORKPATH} ${tsk.batch_incpaths()} ${DEFINES_ST:DEFINES} -c ${SRCLST} ${CXX_TGT_F_BATCHED} ${CPPFLAGS}' -cxx_fun, _ = Task.compile_fun_noshell(cxx_str) - -count = 70000 -class batch(Task.Task): - color = 'PINK' - - after = ['c', 'cxx'] - before = ['cprogram', 'cshlib', 'cstlib', 'cxxprogram', 'cxxshlib', 'cxxstlib'] - - def uid(self): - return Utils.h_list([Task.Task.uid(self), self.generator.idx, self.generator.path.abspath(), self.generator.target]) - - def __str__(self): - return 'Batch compilation for %d slaves' % len(self.slaves) - - def __init__(self, *k, **kw): - Task.Task.__init__(self, *k, **kw) - self.slaves = [] - self.inputs = [] - self.hasrun = 0 - - global count - count += 1 - self.idx = count - - def add_slave(self, slave): - self.slaves.append(slave) - self.set_run_after(slave) - - def runnable_status(self): - for t in self.run_after: - if not t.hasrun: - return Task.ASK_LATER - - for t in self.slaves: - #if t.executed: - if t.hasrun != Task.SKIPPED: - return Task.RUN_ME - - return Task.SKIP_ME - - def get_cwd(self): - return self.slaves[0].outputs[0].parent - - def batch_incpaths(self): - st = self.env.CPPPATH_ST - return [st % node.abspath() for node in self.generator.includes_nodes] - - def run(self): - self.outputs = [] - - srclst = [] - slaves = [] - for t in self.slaves: - if t.hasrun != Task.SKIPPED: - slaves.append(t) - srclst.append(t.inputs[0].abspath()) - - self.env.SRCLST = srclst - - if self.slaves[0].__class__.__name__ == 'c': - ret = c_fun(self) - else: - ret = cxx_fun(self) - - if ret: - return ret - - for t in slaves: - t.old_post_run() - -def hook(cls_type): - def n_hook(self, node): - - ext = '.obj' if self.env.CC_NAME == 'msvc' else '.o' - name = node.name - k = name.rfind('.') - if k >= 0: - basename = name[:k] + ext - else: - basename = name + ext - - outdir = node.parent.get_bld().make_node('%d' % self.idx) - outdir.mkdir() - out = outdir.find_or_declare(basename) - - task = self.create_task(cls_type, node, out) - - try: - self.compiled_tasks.append(task) - except AttributeError: - self.compiled_tasks = [task] - - if not getattr(self, 'masters', None): - self.masters = {} - self.allmasters = [] - - def fix_path(tsk): - if self.env.CC_NAME == 'msvc': - tsk.env.append_unique('CXX_TGT_F_BATCHED', '/Fo%s\\' % outdir.abspath()) - - if not node.parent in self.masters: - m = self.masters[node.parent] = self.master = self.create_task('batch') - fix_path(m) - self.allmasters.append(m) - else: - m = self.masters[node.parent] - if len(m.slaves) > MAX_BATCH: - m = self.masters[node.parent] = self.master = self.create_task('batch') - fix_path(m) - self.allmasters.append(m) - m.add_slave(task) - return task - return n_hook - -extension('.c')(hook('c')) -extension('.cpp','.cc','.cxx','.C','.c++')(hook('cxx')) - -@feature('cprogram', 'cshlib', 'cstaticlib', 'cxxprogram', 'cxxshlib', 'cxxstlib') -@after_method('apply_link') -def link_after_masters(self): - if getattr(self, 'allmasters', None): - for m in self.allmasters: - self.link_task.set_run_after(m) - -# Modify the c and cxx task classes - in theory it would be best to -# create subclasses and to re-map the c/c++ extensions -for x in ('c', 'cxx'): - t = Task.classes[x] - def run(self): - pass - - def post_run(self): - pass - - setattr(t, 'oldrun', getattr(t, 'run', None)) - setattr(t, 'run', run) - setattr(t, 'old_post_run', t.post_run) - setattr(t, 'post_run', post_run) - |