aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xbackends.py69
-rwxr-xr-xenvironment.py22
-rwxr-xr-xinterpreter.py38
-rw-r--r--test cases/common/13 pch/meson.build3
-rw-r--r--test cases/common/13 pch/prog.c4
5 files changed, 107 insertions, 29 deletions
diff --git a/backends.py b/backends.py
index df7a2cb..a9bb34c 100755
--- a/backends.py
+++ b/backends.py
@@ -112,6 +112,12 @@ class Backend():
self.build_to_src = os.path.relpath(self.environment.get_source_dir(),
self.environment.get_build_dir())
+ def get_compiler_for_lang(self, lang):
+ for i in self.build.compilers:
+ if i.language == lang:
+ return i
+ raise RuntimeError('No compiler for language ' + lang)
+
def get_compiler_for_source(self, src):
for i in self.build.compilers:
if i.can_compile(src):
@@ -171,10 +177,13 @@ class Backend():
args = []
pchpath = self.get_target_private_dir(target)
includearg = compiler.get_include_arg(pchpath)
- for p in target.get_pch():
- if compiler.can_compile(p):
+ for lang in ['c', 'cpp']:
+ p = target.get_pch(lang)
+ if len(p) == 0:
+ continue
+ if compiler.can_compile(p[-1]):
args.append('-include')
- args.append(os.path.split(p)[-1])
+ args.append(os.path.split(p[0])[-1])
if len(args) > 0:
args = [includearg] + args
return args
@@ -595,7 +604,7 @@ class NinjaBackend(Backend):
rel_obj = os.path.join(self.get_target_private_dir(target), os.path.basename(src_filename))
rel_obj += '.' + self.environment.get_object_suffix()
dep_file = rel_obj + '.' + compiler.get_depfile_suffix()
- pchlist = target.get_pch()
+ pchlist = target.get_pch(compiler.language)
if len(pchlist) == 0:
pch_dep = []
else:
@@ -628,22 +637,54 @@ class NinjaBackend(Backend):
element.write(outfile)
return rel_obj
+ def generate_msvc_pch_command(self, target, compiler, pch):
+ if len(pch) != 2:
+ raise RuntimeError('MSVC requires one header and one source to produce precompiled headers.')
+ header = pch[0]
+ source = pch[1]
+ chopped = os.path.split(header)[-1].split('.')[:-1]
+ chopped.append(compiler.get_pch_suffix())
+ pchname = '.'.join(chopped)
+ dst = os.path.join(self.get_target_private_dir(target), pchname)
+
+ commands = []
+ commands += self.generate_basic_compiler_flags(target, compiler)
+ commands += compiler.gen_pch_args(header, source, dst)
+
+ dep = dst + '.' + compiler.get_depfile_suffix()
+ return (commands, dep, dst)
+
+ def generate_gcc_pch_command(self, target, compiler, pch):
+ commands = []
+ commands += self.generate_basic_compiler_flags(target, compiler)
+
+ dst = os.path.join(self.get_target_private_dir(target),
+ os.path.split(pch)[-1] + '.' + compiler.get_pch_suffix())
+ dep = dst + '.' + compiler.get_depfile_suffix()
+ return (commands, dep, dst)
+
def generate_pch(self, target, outfile):
- for pch in target.get_pch():
- if '/' not in pch:
+ for lang in ['c', 'cpp']:
+ pch = target.get_pch(lang)
+ if len(pch) == 0:
+ continue
+ if '/' not in pch[0] or '/' not in pch[-1]:
raise interpreter.InvalidArguments('Precompiled header of "%s" must not be in the same direcotory as source, please put it in a subdirectory.' % target.get_basename())
- compiler = self.get_compiler_for_source(pch)
- commands = []
- commands += self.generate_basic_compiler_flags(target, compiler)
- src = os.path.join(self.build_to_src, target.get_source_subdir(), pch)
- dst = os.path.join(self.get_target_private_dir(target),
- os.path.split(pch)[-1] + '.' + compiler.get_pch_suffix())
- dep = dst + '.' + compiler.get_depfile_suffix()
+ compiler = self.get_compiler_for_lang(lang)
+ src = os.path.join(self.build_to_src, target.get_source_subdir(), pch[-1])
+ if compiler.id == 'msvc':
+ (commands, dep, dst) = self.generate_msvc_pch_command(target, compiler, pch)
+ extradep = os.path.join(self.build_to_src, target.get_source_subdir(), pch[0])
+ else:
+ (commands, dep, dst) = self.generate_gcc_pch_command(target, compiler, pch[0])
+ extradep = None
elem = NinjaBuildElement(dst, compiler.get_language() + '_COMPILER', src)
+ if extradep is not None:
+ elem.add_dep(extradep)
elem.add_item('FLAGS', commands)
elem.add_item('DEPFILE', dep)
elem.write(outfile)
-
+
def generate_shsym(self, outfile, target):
target_name = self.get_target_filename(target)
targetdir = self.get_target_private_dir(target)
diff --git a/environment.py b/environment.py
index 0212dbd..9274651 100755
--- a/environment.py
+++ b/environment.py
@@ -169,8 +169,6 @@ int main(int argc, char **argv) {
raise EnvironmentException('Could not run sizeof test binary.')
return int(so.decode())
-cpp_suffixes = ['cc', 'cpp', 'cxx', 'hh', 'hpp', 'hxx']
-
class CPPCompiler(CCompiler):
def __init__(self, exelist):
CCompiler.__init__(self, exelist)
@@ -280,6 +278,9 @@ class VisualStudioCCompiler(CCompiler):
def get_std_shared_lib_link_flags(self):
return ['/DLL']
+ def gen_pch_args(self, header, source, pchname):
+ return ['/Yc' + header, '/Fp' + pchname]
+
def sanity_check(self, work_dir):
source_name = os.path.join(work_dir, 'sanitycheckc.c')
binary_name = os.path.join(work_dir, 'sanitycheckc')
@@ -504,6 +505,17 @@ def is_windows():
return platform.system().lower() == 'windows'
header_suffixes = ['h', 'hh', 'hpp', 'hxx', 'H']
+cpp_suffixes = ['cc', 'cpp', 'cxx', 'hh', 'hpp', 'hxx']
+c_suffixes = ['c']
+clike_suffixes = c_suffixes + cpp_suffixes
+
+def is_header(fname):
+ suffix = fname.split('.')[-1]
+ return suffix in header_suffixes
+
+def is_source(fname):
+ suffix = fname.split('.')[-1]
+ return suffix in clike_suffixes
class Environment():
private_dir = 'meson-private'
@@ -573,8 +585,10 @@ class Environment():
return self.meson_script_file
def is_header(self, fname):
- suffix = fname.split('.')[-1]
- return suffix in header_suffixes
+ return is_header(fname)
+
+ def is_source(self, fname):
+ return is_source(fname)
def detect_c_compiler(self):
evar = 'CC'
diff --git a/interpreter.py b/interpreter.py
index 5469cec..da53cc2 100755
--- a/interpreter.py
+++ b/interpreter.py
@@ -348,7 +348,7 @@ class BuildTarget(InterpreterObject):
self.link_targets = []
self.filename = 'no_name'
self.need_install = False
- self.pch = []
+ self.pch = {}
self.extra_args = {}
self.generated = []
self.process_sourcelist(sources)
@@ -379,10 +379,14 @@ class BuildTarget(InterpreterObject):
llist = [llist]
for linktarget in llist:
self.link(linktarget)
- pchlist = kwargs.get('pch', [])
- if not isinstance(pchlist, list):
- pchlist = [pchlist]
- self.add_pch(pchlist)
+ c_pchlist = kwargs.get('c_pch', [])
+ if not isinstance(c_pchlist, list):
+ c_pchlist = [c_pchlist]
+ self.add_pch('c', c_pchlist)
+ cpp_pchlist = kwargs.get('cpp_pch', [])
+ if not isinstance(cpp_pchlist, list):
+ cpp_pchlist = [cpp_pchlist]
+ self.add_pch('cpp', cpp_pchlist)
clist = kwargs.get('c_args', [])
if not isinstance(clist, list):
clist = [clist]
@@ -434,8 +438,11 @@ class BuildTarget(InterpreterObject):
def has_pch(self):
return len(self.pch) > 0
- def get_pch(self):
- return self.pch
+ def get_pch(self, language):
+ try:
+ return self.pch[language]
+ except KeyError:
+ return[]
def get_include_dirs(self):
return self.include_dirs
@@ -467,9 +474,20 @@ class BuildTarget(InterpreterObject):
raise InvalidArguments('Generated source argument is not the output of a generator.')
self.generated.append(g)
- def add_pch(self, pchlist):
- for a in pchlist:
- self.pch.append(a)
+ def add_pch(self, language, pchlist):
+ if len(pchlist) == 0:
+ return
+ if len(pchlist) == 2:
+ if environment.is_header(pchlist[0]):
+ if not environment.is_source(pchlist[1]):
+ raise InterpreterException('PCH definition must contain one header and at most one source.')
+ elif environment.is_source(pchlist[0]):
+ if not environment.is_header(pchlist[1]):
+ raise InterpreterException('PCH definition must contain one header and at most one source.')
+ pchlist = [pchlist[1], pchlist[0]]
+ elif len(pchlist) > 2:
+ raise InterpreterException('PCH definition may have a maximum of 2 files.')
+ self.pch[language] = pchlist
def add_include_dirs(self, args):
for a in args:
diff --git a/test cases/common/13 pch/meson.build b/test cases/common/13 pch/meson.build
index 9632cc5..9ed6512 100644
--- a/test cases/common/13 pch/meson.build
+++ b/test cases/common/13 pch/meson.build
@@ -1,3 +1,4 @@
project('pch test', 'c')
-exe = executable('prog', 'prog.c', pch : 'pch/prog.h')
+exe = executable('prog', 'prog.c',
+c_pch : ['pch/prog_pch.c', 'pch/prog.h'])
diff --git a/test cases/common/13 pch/prog.c b/test cases/common/13 pch/prog.c
index 995bb3f..23125f5 100644
--- a/test cases/common/13 pch/prog.c
+++ b/test cases/common/13 pch/prog.c
@@ -1,3 +1,7 @@
+#if defined(_MSC_VER)
+#include"prog.pch"
+#endif
+
void func() {
fprintf(stdout, "This is a function that fails if stdio is not #included.\n");
}