build: Enabling ability to use precompiled headers and some other build fixes
Change-Id: If2b216e5674fc762338929026733f3dcb801bb1b
Refs: #1588
diff --git a/.waf-tools/pch.py b/.waf-tools/pch.py
new file mode 100644
index 0000000..c0e3039
--- /dev/null
+++ b/.waf-tools/pch.py
@@ -0,0 +1,75 @@
+#! /usr/bin/env python
+# encoding: utf-8
+
+from waflib import Logs, Utils, Task, TaskGen, Build
+from waflib.Tools import c_preproc, cxx
+
+def options(opt):
+ opt.add_option('--with-pch', action='store_true', default=False, dest='with_pch',
+ help='''Try to use precompiled header to speed up compilation '''
+ '''(only gcc and clang)''')
+
+def configure(conf):
+ conf.env['WITH_PCH'] = conf.options.with_pch
+
+class gchx(Task.Task):
+ run_str = '${CXX} -x c++-header ${CXXFLAGS} ${FRAMEWORKPATH_ST:FRAMEWORKPATH} ' + \
+ '${CPPPATH_ST:INCPATHS} ${DEFINES_ST:DEFINES} ' + \
+ '${CXX_SRC_F}${SRC} ${CXX_TGT_F}${TGT}'
+ scan = c_preproc.scan
+ color = 'BLUE'
+
+
+PCH_COMPILER_OPTIONS = {
+ 'clang++': ['-include', '.pch', ''],
+ 'g++': ['-include', '.gch', ''],
+}
+
+@TaskGen.extension('.cpp')
+def cxx_hook(self, node):
+ if (self.env.WITH_PCH and
+ self.env['COMPILER_CXX'] in PCH_COMPILER_OPTIONS.keys() and
+ getattr(self, 'pch', None)):
+
+ (flag, pch_ext, include_ext) = PCH_COMPILER_OPTIONS[self.env['COMPILER_CXX']]
+
+ if not getattr(self, 'pch_task', None):
+ if isinstance(self.pch, str):
+ self.pch = self.path.find_node(self.pch)
+
+ output = self.pch.change_ext('.hpp%s' % pch_ext)
+
+ try:
+ # == Will reuse the existing task ==
+ # This could cause problem if different compiler flags were used for
+ # previous compilation of the precompiled header
+ existingTask = self.bld.get_tgen_by_name(output.abspath())
+ self.pch_task = existingTask
+ except:
+ self.pch_task = self.create_task('gchx', self.pch, output)
+ self.pch_task.name = output.abspath()
+
+ self.bld.task_gen_cache_names = {}
+ self.bld.add_to_group(self.pch_task, group=getattr(self, 'group', None))
+
+ task = self.create_compiled_task('cxx_pch', node)
+ # task.run_after.update(set([self.pch_task]))
+
+ task.pch_flag = flag
+ task.pch_include_file = self.pch.change_ext('.hpp%s' % include_ext).get_bld()
+
+ out = '%s%s' % (self.pch.name, pch_ext)
+ task.pch_file = self.pch.parent.get_bld().find_or_declare(out)
+ else:
+ self.create_compiled_task('cxx', node)
+
+class cxx_pch(Task.classes['cxx']):
+ run_str = '${CXX} ${tsk.pch_flag} ${tsk.pch_include_file.abspath()} '\
+ '${ARCH_ST:ARCH} ${CXXFLAGS} ${CPPFLAGS} ' \
+ '${FRAMEWORKPATH_ST:FRAMEWORKPATH} ${CPPPATH_ST:INCPATHS} ${DEFINES_ST:DEFINES} ' \
+ '${CXX_SRC_F}${SRC} ${CXX_TGT_F}${TGT[0].abspath()}'
+
+ def scan(self):
+ (nodes, names) = c_preproc.scan(self)
+ nodes.append(self.pch_file)
+ return (nodes, names)