aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNirbheek Chauhan <nirbheek@centricular.com>2016-12-17 14:00:08 +0530
committerNirbheek Chauhan <nirbheek@centricular.com>2016-12-18 10:17:36 +0530
commit6292122a19ed765ed060c8d4aad9d0791cfef9f1 (patch)
tree9694ee52a64526251665f54ae1f070ebccc98675
parentb389f430609a4956d23beddcdaa26b3fea06bc23 (diff)
downloadmeson-6292122a19ed765ed060c8d4aad9d0791cfef9f1.zip
meson-6292122a19ed765ed060c8d4aad9d0791cfef9f1.tar.gz
meson-6292122a19ed765ed060c8d4aad9d0791cfef9f1.tar.bz2
has_header: Don't compile, only preprocess
Since we're checking for the existence of a header, just running the preprocessor is enough. According to my benchmarks, doing this makes the test roughly 2x faster. I'm sure this will be useful for other checks too in the future. This shaves off 7% on the configure time for glib on my machine. This also fixes the issue that we had earlier where you had to specify any extra headers needed to resolve symbols in the header being checked for with `prefix`.
-rw-r--r--mesonbuild/compilers.py69
-rw-r--r--test cases/common/37 has header/meson.build17
2 files changed, 52 insertions, 34 deletions
diff --git a/mesonbuild/compilers.py b/mesonbuild/compilers.py
index dcb4b69..b9256d2 100644
--- a/mesonbuild/compilers.py
+++ b/mesonbuild/compilers.py
@@ -452,11 +452,22 @@ class Compiler():
extra_flags += environment.cross_info.config['properties'].get(lang_link_args_key, [])
return extra_flags
+ def _get_compile_output(self, dirname, mode):
+ # In pre-processor mode, the output is sent to stdout and discarded
+ if mode == 'preprocess':
+ return None
+ # Extension only matters if running results; '.exe' is
+ # guaranteed to be executable on every platform.
+ if mode == 'link':
+ suffix = 'exe'
+ else:
+ suffix = 'obj'
+ return os.path.join(dirname, 'output.' + suffix)
+
@contextlib.contextmanager
- def compile(self, code, extra_args=None, compile_only=False):
+ def compile(self, code, extra_args=None, mode='link'):
if extra_args is None:
extra_args = []
-
try:
with tempfile.TemporaryDirectory() as tmpdirname:
if isinstance(code, str):
@@ -466,21 +477,19 @@ class Compiler():
ofile.write(code)
elif isinstance(code, mesonlib.File):
srcname = code.fname
+ output = self._get_compile_output(tmpdirname, mode)
- # Extension only matters if running results; '.exe' is
- # guaranteed to be executable on every platform.
- if compile_only:
- suffix = 'obj'
- else:
- suffix = 'exe'
- output = os.path.join(tmpdirname, 'output.' + suffix)
-
+ # Construct the compiler command-line
commands = self.get_exelist()
commands.append(srcname)
commands += extra_args
- commands += self.get_output_args(output)
- if compile_only:
+ if mode == 'compile':
commands += self.get_compile_only_args()
+ # Preprocess mode outputs to stdout, so no output args
+ if mode == 'preprocess':
+ commands += self.get_preprocess_only_args()
+ else:
+ commands += self.get_output_args(output)
mlog.debug('Running compile:')
mlog.debug('Working directory: ', tmpdirname)
mlog.debug('Command line: ', ' '.join(commands), '\n')
@@ -580,6 +589,9 @@ class CCompiler(Compiler):
def get_linker_exelist(self):
return self.exelist[:]
+ def get_preprocess_only_args(self):
+ return ['-E']
+
def get_compile_only_args(self):
return ['-c']
@@ -710,7 +722,7 @@ class CCompiler(Compiler):
if extra_args is None:
extra_args = []
code = '{}\n#include<{}>\nint someUselessSymbol;'.format(prefix, hname)
- return self.compiles(code, env, extra_args, dependencies)
+ return self.compiles(code, env, extra_args, dependencies, 'preprocess')
def has_header_symbol(self, hname, symbol, prefix, env, extra_args=None, dependencies=None):
if extra_args is None:
@@ -747,7 +759,7 @@ int main () {{
after_args.append(arg)
return before_args + args + after_args
- def compiles(self, code, env, extra_args=None, dependencies=None):
+ def compiles(self, code, env, extra_args=None, dependencies=None, mode='compile'):
if extra_args is None:
extra_args = []
if isinstance(extra_args, str):
@@ -771,7 +783,7 @@ int main () {{
# Append both to the compiler args such that they override them
args = self._override_args(args, extra_args)
# We only want to compile; not link
- with self.compile(code, args, compile_only=True) as p:
+ with self.compile(code, args, mode) as p:
return p.returncode == 0
def _links_wrapper(self, code, env, extra_args, dependencies):
@@ -1090,7 +1102,7 @@ void bar() {
args = self.get_cross_extra_flags(env, compile=True, link=False)
args += self.get_compiler_check_args()
n = 'symbols_have_underscore_prefix'
- with self.compile(code, args, compile_only=True) as p:
+ with self.compile(code, args, 'compile') as p:
if p.returncode != 0:
m = 'BUG: Unable to compile {!r} check: {}'
raise RuntimeError(m.format(n, p.stdo))
@@ -1433,7 +1445,7 @@ class ValaCompiler(Compiler):
def sanity_check(self, work_dir, environment):
code = 'class MesonSanityCheck : Object { }'
args = self.get_cross_extra_flags(environment, compile=True, link=False)
- with self.compile(code, args, compile_only=True) as p:
+ with self.compile(code, args, 'compile') as p:
if p.returncode != 0:
msg = 'Vala compiler {!r} can not compile programs' \
''.format(self.name_string())
@@ -1454,7 +1466,7 @@ class ValaCompiler(Compiler):
vapi_args = ['--pkg', libname]
args = self.get_cross_extra_flags(env, compile=True, link=False)
args += vapi_args
- with self.compile(code, args, compile_only=True) as p:
+ with self.compile(code, args, 'compile') as p:
if p.returncode == 0:
return vapi_args
# Not found? Try to find the vapi file itself.
@@ -1607,6 +1619,12 @@ class DCompiler(Compiler):
def get_linker_exelist(self):
return self.exelist[:]
+ def get_preprocess_only_args(self):
+ return ['-E']
+
+ def get_compile_only_args(self):
+ return ['-c']
+
def depfile_for_object(self, objfile):
return objfile + '.' + self.get_depfile_suffix()
@@ -1689,9 +1707,6 @@ class GnuDCompiler(DCompiler):
def get_output_args(self, target):
return ['-o', target]
- def get_compile_only_args(self):
- return ['-c']
-
def get_linker_output_args(self, target):
return ['-o', target]
@@ -1735,9 +1750,6 @@ class LLVMDCompiler(DCompiler):
def get_output_args(self, target):
return ['-of', target]
- def get_compile_only_args(self):
- return ['-c']
-
def get_linker_output_args(self, target):
return ['-of', target]
@@ -1793,9 +1805,6 @@ class DmdDCompiler(DCompiler):
def get_werror_args(self):
return ['-w']
- def get_compile_only_args(self):
- return ['-c']
-
def get_linker_output_args(self, target):
return ['-of' + target]
@@ -1873,6 +1882,9 @@ class VisualStudioCCompiler(CCompiler):
pchname = self.get_pch_name(header)
return ['/FI' + base, '/Yu' + base, '/Fp' + os.path.join(pch_dir, pchname)]
+ def get_preprocess_only_args(self):
+ return ['/E']
+
def get_compile_only_args(self):
return ['/c']
@@ -2436,6 +2448,9 @@ end program prog
def get_output_args(self, target):
return ['-o', target]
+ def get_preprocess_only_args(self):
+ return ['-E']
+
def get_compile_only_args(self):
return ['-c']
diff --git a/test cases/common/37 has header/meson.build b/test cases/common/37 has header/meson.build
index 4f9b94f..2f763ae 100644
--- a/test cases/common/37 has header/meson.build
+++ b/test cases/common/37 has header/meson.build
@@ -5,20 +5,23 @@ foreach comp : [meson.get_compiler('c'), meson.get_compiler('cpp')]
error('Stdio missing.')
endif
- # stdio.h doesn't actually need stdlib.h, but I don't know any headers on
- # UNIX/Linux that need other headers defined beforehand
+ # stdio.h doesn't actually need stdlib.h, but just test that setting the
+ # prefix does not result in an error.
if not comp.has_header('stdio.h', prefix : '#include <stdlib.h>')
error('Stdio missing.')
endif
- # XInput.h needs windows.h included beforehand. We only do this check on MSVC
- # because MinGW often defines its own wrappers that pre-include windows.h
+ # XInput.h should not require type definitions from windows.h, but it does
+ # require macro definitions. Specifically, it requires an arch setting for
+ # VS2015 at least.
+ # We only do this check on MSVC because MinGW often defines its own wrappers
+ # that pre-include windows.h
if comp.get_id() == 'msvc'
if not comp.has_header('XInput.h', prefix : '#include <windows.h>')
- error('XInput.h is missing on Windows')
+ error('XInput.h should not be missing on Windows')
endif
- if comp.has_header('XInput.h')
- error('XInput.h needs windows.h')
+ if not comp.has_header('XInput.h', prefix : '#define _X86_')
+ error('XInput.h should not need windows.h')
endif
endif