#! /usr/bin/env python
# encoding: utf-8
# Alexander Afanasyev (UCLA), 2014

"""
Enable precompiled C++ header support (currently only clang++ and g++ are supported)

To use this tool, wscript should look like:

	def options(opt):
		opt.load('pch')
		# This will add `--with-pch` configure option.
		# Unless --with-pch during configure stage specified, the precompiled header support is disabled

	def configure(conf):
		conf.load('pch')
		# this will set conf.env.WITH_PCH if --with-pch is specified and the supported compiler is used
		# Unless conf.env.WITH_PCH is set, the precompiled header support is disabled

	def build(bld):
		bld(features='cxx pch',
			target='precompiled-headers',
			name='precompiled-headers',
			headers='a.h b.h c.h', # headers to pre-compile into `precompiled-headers`

			# Other parameters to compile precompiled headers
			# includes=...,
			# export_includes=...,
			# use=...,
			# ...

			# Exported parameters will be propagated even if precompiled headers are disabled
		)

		bld(
			target='test',
			features='cxx cxxprogram',
			source='a.cpp b.cpp d.cpp main.cpp',
			use='precompiled-headers',
		)

		# or

		bld(
			target='test',
			features='pch cxx cxxprogram',
			source='a.cpp b.cpp d.cpp main.cpp',
			headers='a.h b.h c.h',
		)

Note that precompiled header must have multiple inclusion guards.  If the guards are missing, any benefit of precompiled header will be voided and compilation may fail in some cases.
"""

import os
from waflib import Task, TaskGen, Logs, Utils
from waflib.Tools import c_preproc, cxx


PCH_COMPILER_OPTIONS = {
	'clang++': [['-include'], '.pch', ['-x', 'c++-header']],
	'g++':     [['-include'], '.gch', ['-x', 'c++-header']],
}


def options(opt):
	opt.add_option('--without-pch', action='store_false', default=True, dest='with_pch', help='''Try to use precompiled header to speed up compilation (only g++ and clang++)''')

def configure(conf):
	if (conf.options.with_pch and conf.env['COMPILER_CXX'] in PCH_COMPILER_OPTIONS.keys()):
		if Utils.unversioned_sys_platform() == "darwin" and conf.env['CXX_NAME'] == 'clang':
			version = tuple(int(i) for i in conf.env['CC_VERSION'])
			if version < (6, 1, 0):
				# Issue #2804
				return
		conf.env.WITH_PCH = True
		flags = PCH_COMPILER_OPTIONS[conf.env['COMPILER_CXX']]
		conf.env.CXXPCH_F = flags[0]
		conf.env.CXXPCH_EXT = flags[1]
		conf.env.CXXPCH_FLAGS = flags[2]


@TaskGen.feature('pch')
@TaskGen.before('process_source')
def apply_pch(self):
	if not self.env.WITH_PCH:
		return

	if getattr(self.bld, 'pch_tasks', None) is None:
		self.bld.pch_tasks = {}

	if getattr(self, 'headers', None) is None:
		return

	self.headers = self.to_nodes(self.headers)

	if getattr(self, 'name', None):
		try:
			task = self.bld.pch_tasks["%s.%s" % (self.name, self.idx)]
			self.bld.fatal("Duplicated 'pch' task with name %r" % "%s.%s" % (self.name, self.idx))
		except KeyError:
			pass

	out = '%s.%d%s' % (self.target, self.idx, self.env['CXXPCH_EXT'])
	out = self.path.find_or_declare(out)
	task = self.create_task('gchx', self.headers, out)

	# target should be an absolute path of `out`, but without precompiled header extension
	task.target = out.abspath()[:-len(out.suffix())]

	self.pch_task = task
	if getattr(self, 'name', None):
		self.bld.pch_tasks["%s.%s" % (self.name, self.idx)] = task

@TaskGen.feature('cxx')
@TaskGen.after_method('process_source', 'propagate_uselib_vars')
def add_pch(self):
	if not (self.env['WITH_PCH'] and getattr(self, 'use', None) and getattr(self, 'compiled_tasks', None) and getattr(self.bld, 'pch_tasks', None)):
		return

	pch = None
	# find pch task, if any

	if getattr(self, 'pch_task', None):
		pch = self.pch_task
	else:
		for use in Utils.to_list(self.use):
			try:
				pch = self.bld.pch_tasks[use]
			except KeyError:
				pass

	if pch:
		for x in self.compiled_tasks:
			x.env.append_value('CXXFLAGS', self.env['CXXPCH_F'] + [pch.target])

class gchx(Task.Task):
	run_str = '${CXX} ${ARCH_ST:ARCH} ${CXXFLAGS} ${CPPFLAGS} ${CXXPCH_FLAGS} ${FRAMEWORKPATH_ST:FRAMEWORKPATH} ${CPPPATH_ST:INCPATHS} ${DEFINES_ST:DEFINES} ${CXXPCH_F:SRC} ${CXX_SRC_F}${SRC[0].abspath()} ${CXX_TGT_F}${TGT[0].abspath()}'
	scan    = c_preproc.scan
	color   = 'BLUE'
	ext_out=['.h']

	def runnable_status(self):
		try:
			node_deps = self.generator.bld.node_deps[self.uid()]
		except KeyError:
			node_deps = []
		ret = Task.Task.runnable_status(self)
		if ret == Task.SKIP_ME and self.env.CXX_NAME == 'clang':
			t = os.stat(self.outputs[0].abspath()).st_mtime
			for n in self.inputs + node_deps:
				if os.stat(n.abspath()).st_mtime > t:
					return Task.RUN_ME
		return ret
