From c9bd84fd25dd24999ac2d20b616e91efb9038905 Mon Sep 17 00:00:00 2001 From: Daniel Mensinger Date: Tue, 19 Feb 2019 19:34:20 +0100 Subject: [PATCH 01/11] Cache compile results in coredata --- mesonbuild/compilers/c.py | 4 ++-- mesonbuild/compilers/compilers.py | 21 +++++++++++++-------- mesonbuild/compilers/d.py | 2 +- mesonbuild/compilers/vala.py | 2 +- mesonbuild/coredata.py | 1 + 5 files changed, 18 insertions(+), 12 deletions(-) diff --git a/mesonbuild/compilers/c.py b/mesonbuild/compilers/c.py index 94ef33601..f0dc20191 100644 --- a/mesonbuild/compilers/c.py +++ b/mesonbuild/compilers/c.py @@ -450,7 +450,7 @@ class CCompiler(Compiler): def _build_wrapper(self, code, env, extra_args, dependencies=None, mode='compile', want_output=False): args = self._get_compiler_check_args(env, extra_args, dependencies, mode) - return self.compile(code, args, mode, want_output=want_output) + return self.compile(code, args, mode, want_output=want_output, cdata=env.coredata) def links(self, code, env, *, extra_args=None, dependencies=None): return self.compiles(code, env, extra_args=extra_args, @@ -652,7 +652,7 @@ class CCompiler(Compiler): {delim}\n{define}''' args = self._get_compiler_check_args(env, extra_args, dependencies, mode='preprocess').to_native() - with self.compile(code.format(**fargs), args, 'preprocess') as p: + with self.compile(code.format(**fargs), args, 'preprocess', cdata=env.coredata) as p: if p.returncode != 0: raise EnvironmentException('Could not get define {!r}'.format(dname)) # Get the preprocessed value after the delimiter, diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py index 87a83e5dd..169a973a9 100644 --- a/mesonbuild/compilers/compilers.py +++ b/mesonbuild/compilers/compilers.py @@ -875,8 +875,6 @@ class Compiler: # Libraries that are internal compiler implementations, and must not be # manually searched. internal_libs = () - # Cache for the result of compiler checks which can be cached - compiler_check_cache = {} def __init__(self, exelist, version, **kwargs): if isinstance(exelist, str): @@ -1148,16 +1146,16 @@ class Compiler: return os.path.join(dirname, 'output.' + suffix) @contextlib.contextmanager - def compile(self, code, extra_args=None, mode='link', want_output=False): + def compile(self, code, extra_args=None, mode='link', want_output=False, cdata: coredata.CoreData = None): if extra_args is None: textra_args = None extra_args = [] else: textra_args = tuple(extra_args) - key = (code, textra_args, mode) + key = (tuple(self.exelist), self.version, code, textra_args, mode) if not want_output: - if key in self.compiler_check_cache: - p = self.compiler_check_cache[key] + if cdata is not None and key in cdata.compiler_check_cache: + p = cdata.compiler_check_cache[key] mlog.debug('Using cached compile:') mlog.debug('Cached command line: ', ' '.join(p.commands), '\n') mlog.debug('Code:\n', code) @@ -1206,8 +1204,15 @@ class Compiler: p.input_name = srcname if want_output: p.output_name = output - else: - self.compiler_check_cache[key] = p + elif cdata is not None: + # Remove all attributes except the following + # This way the object can be serialized + tokeep = ['args', 'commands', 'input_name', 'output_name', + 'pid', 'returncode', 'stdo', 'stde', 'text_mode'] + todel = [x for x in vars(p).keys() if x not in tokeep] + for i in todel: + delattr(p, i) + cdata.compiler_check_cache[key] = p yield p except (PermissionError, OSError): # On Windows antivirus programs and the like hold on to files so diff --git a/mesonbuild/compilers/d.py b/mesonbuild/compilers/d.py index 529919b7d..e8257d345 100644 --- a/mesonbuild/compilers/d.py +++ b/mesonbuild/compilers/d.py @@ -326,7 +326,7 @@ class DCompiler(Compiler): def compiles(self, code, env, *, extra_args=None, dependencies=None, mode='compile'): args = self._get_compiler_check_args(env, extra_args, dependencies, mode) - with self.compile(code, args, mode) as p: + with self.compile(code, args, mode, cdata=env.coredata) as p: return p.returncode == 0 def has_multi_arguments(self, args, env): diff --git a/mesonbuild/compilers/vala.py b/mesonbuild/compilers/vala.py index 98b8b42da..789e00bb8 100644 --- a/mesonbuild/compilers/vala.py +++ b/mesonbuild/compilers/vala.py @@ -121,7 +121,7 @@ class ValaCompiler(Compiler): args = env.coredata.get_external_args(for_machine, self.language) vapi_args = ['--pkg', libname] args += vapi_args - with self.compile(code, args, 'compile') as p: + with self.compile(code, args, 'compile', cdata=env.coredata) as p: if p.returncode == 0: return vapi_args # Not found? Try to find the vapi file itself. diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index 9281019c8..a2c5ff909 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -247,6 +247,7 @@ class CoreData: self.compilers = OrderedDict() self.cross_compilers = OrderedDict() self.deps = OrderedDict() + self.compiler_check_cache = OrderedDict() # Only to print a warning if it changes between Meson invocations. self.config_files = self.__load_config_files(options.native_file, 'native') self.libdir_cross_fixup() From dfe3d56bfd28eb7b960f1beb09f502f9902b45fa Mon Sep 17 00:00:00 2001 From: Daniel Mensinger Date: Tue, 19 Feb 2019 21:04:23 +0100 Subject: [PATCH 02/11] Print '(cached)' when compiler result was cached --- mesonbuild/compilers/c.py | 31 +++++----- mesonbuild/compilers/compilers.py | 2 + mesonbuild/compilers/cpp.py | 11 ++-- mesonbuild/dependencies/misc.py | 2 +- mesonbuild/dependencies/ui.py | 2 +- mesonbuild/interpreter.py | 92 ++++++++++++++++------------- mesonbuild/modules/unstable_simd.py | 2 +- 7 files changed, 79 insertions(+), 63 deletions(-) diff --git a/mesonbuild/compilers/c.py b/mesonbuild/compilers/c.py index f0dc20191..fe5a9ca14 100644 --- a/mesonbuild/compilers/c.py +++ b/mesonbuild/compilers/c.py @@ -446,7 +446,7 @@ class CCompiler(Compiler): def compiles(self, code, env, *, extra_args=None, dependencies=None, mode='compile'): with self._build_wrapper(code, env, extra_args, dependencies, mode) as p: - return p.returncode == 0 + return p.returncode == 0, p.cached def _build_wrapper(self, code, env, extra_args, dependencies=None, mode='compile', want_output=False): args = self._get_compiler_check_args(env, extra_args, dependencies, mode) @@ -487,7 +487,7 @@ class CCompiler(Compiler): {prefix} int main() {{ static int a[1-2*!({expression})]; a[0]=0; return 0; }}''' return self.compiles(t.format(**fargs), env, extra_args=extra_args, - dependencies=dependencies) + dependencies=dependencies)[0] def cross_compute_int(self, expression, low, high, guess, prefix, env, extra_args, dependencies): # Try user's guess first @@ -567,7 +567,7 @@ class CCompiler(Compiler): {type} something; }}''' if not self.compiles(t.format(**fargs), env, extra_args=extra_args, - dependencies=dependencies): + dependencies=dependencies)[0]: return -1 return self.cross_compute_int('sizeof(%s)' % typename, None, None, None, prefix, env, extra_args, dependencies) @@ -602,7 +602,7 @@ class CCompiler(Compiler): {type} something; }}''' if not self.compiles(t.format(**fargs), env, extra_args=extra_args, - dependencies=dependencies): + dependencies=dependencies)[0]: return -1 t = '''#include {prefix} @@ -762,7 +762,7 @@ class CCompiler(Compiler): val = env.properties.host.get(varname, None) if val is not None: if isinstance(val, bool): - return val + return val, True raise EnvironmentException('Cross variable {0} is not a boolean.'.format(varname)) fargs = {'prefix': prefix, 'func': funcname} @@ -792,13 +792,14 @@ class CCompiler(Compiler): head, main = self._no_prototype_templ() templ = head + stubs_fail + main - if self.links(templ.format(**fargs), env, extra_args=extra_args, - dependencies=dependencies): - return True + res, cached = self.links(templ.format(**fargs), env, extra_args=extra_args, + dependencies=dependencies) + if res: + return True, cached # MSVC does not have compiler __builtin_-s. if self.get_id() == 'msvc': - return False + return False, False # Detect function as a built-in # @@ -1020,7 +1021,7 @@ class CCompiler(Compiler): libname in self.internal_libs): args = ['-l' + libname] largs = self.linker_to_compiler_args(self.get_allow_undefined_link_args()) - if self.links(code, env, extra_args=(args + largs)): + if self.links(code, env, extra_args=(args + largs))[0]: return args # Don't do a manual search for internal libs if libname in self.internal_libs: @@ -1109,7 +1110,7 @@ class CCompiler(Compiler): # then we must also pass -L/usr/lib to pick up libSystem.dylib extra_args = [] if allow_system else ['-Z', '-L/usr/lib'] link_args += ['-framework', name] - if self.links(code, env, extra_args=(extra_args + link_args)): + if self.links(code, env, extra_args=(extra_args + link_args))[0]: return link_args def find_framework_impl(self, name, env, extra_dirs, allow_system): @@ -1176,7 +1177,7 @@ class CCompiler(Compiler): fatal_warnings_args = ['-Wl,--fatal-warnings'] if self.has_fatal_warnings_link_arg is None: self.has_fatal_warnings_link_arg = False - self.has_fatal_warnings_link_arg = self.has_multi_link_arguments(fatal_warnings_args, env) + self.has_fatal_warnings_link_arg = self.has_multi_link_arguments(fatal_warnings_args, env)[0] if self.has_fatal_warnings_link_arg: args = fatal_warnings_args + args @@ -1348,7 +1349,7 @@ class ElbrusCCompiler(GnuCCompiler, ElbrusCompiler): # So we should explicitly fail at this case. def has_function(self, funcname, prefix, env, *, extra_args=None, dependencies=None): if funcname == 'lchmod': - return False + return False, False else: return super().has_function(funcname, prefix, env, extra_args=extra_args, @@ -1609,8 +1610,8 @@ class VisualStudioCCompiler(CCompiler): args = args + ['-Werror=unknown-argument'] with self._build_wrapper(code, env, extra_args=args, mode=mode) as p: if p.returncode != 0: - return False - return not(warning_text in p.stde or warning_text in p.stdo) + return False, p.cached + return not(warning_text in p.stde or warning_text in p.stdo), p.cached def get_compile_debugfile_args(self, rel_obj, pch=False): pdbarr = rel_obj.split('.')[:-1] diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py index 169a973a9..e8d8358aa 100644 --- a/mesonbuild/compilers/compilers.py +++ b/mesonbuild/compilers/compilers.py @@ -1156,6 +1156,7 @@ class Compiler: if not want_output: if cdata is not None and key in cdata.compiler_check_cache: p = cdata.compiler_check_cache[key] + p.cached = True mlog.debug('Using cached compile:') mlog.debug('Cached command line: ', ' '.join(p.commands), '\n') mlog.debug('Code:\n', code) @@ -1213,6 +1214,7 @@ class Compiler: for i in todel: delattr(p, i) cdata.compiler_check_cache[key] = p + p.cached = False yield p except (PermissionError, OSError): # On Windows antivirus programs and the like hold on to files so diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py index 87e6ffc65..3e0942db0 100644 --- a/mesonbuild/compilers/cpp.py +++ b/mesonbuild/compilers/cpp.py @@ -65,10 +65,11 @@ class CPPCompiler(CCompiler): def has_header_symbol(self, hname, symbol, prefix, env, *, extra_args=None, dependencies=None): # Check if it's a C-like symbol - if super().has_header_symbol(hname, symbol, prefix, env, - extra_args=extra_args, - dependencies=dependencies): - return True + found, cached = super().has_header_symbol(hname, symbol, prefix, env, + extra_args=extra_args, + dependencies=dependencies) + if found: + return True, cached # Check if it's a class or a template if extra_args is None: extra_args = [] @@ -264,7 +265,7 @@ class ElbrusCPPCompiler(GnuCPPCompiler, ElbrusCompiler): # So we should explicitly fail at this case. def has_function(self, funcname, prefix, env, *, extra_args=None, dependencies=None): if funcname == 'lchmod': - return False + return False, False else: return super().has_function(funcname, prefix, env, extra_args=extra_args, diff --git a/mesonbuild/dependencies/misc.py b/mesonbuild/dependencies/misc.py index 55cb56939..d266a3737 100644 --- a/mesonbuild/dependencies/misc.py +++ b/mesonbuild/dependencies/misc.py @@ -376,7 +376,7 @@ class OpenMPDependency(ExternalDependency): if openmp_date: self.version = self.VERSIONS[openmp_date] - if self.clib_compiler.has_header('omp.h', '', self.env, dependencies=[self]): + if self.clib_compiler.has_header('omp.h', '', self.env, dependencies=[self])[0]: self.is_found = True self.compile_args = self.link_args = self.clib_compiler.openmp_flags() else: diff --git a/mesonbuild/dependencies/ui.py b/mesonbuild/dependencies/ui.py index ce1ca6834..0a01ac46e 100644 --- a/mesonbuild/dependencies/ui.py +++ b/mesonbuild/dependencies/ui.py @@ -641,7 +641,7 @@ class VulkanDependency(ExternalDependency): else: # simply try to guess it, usually works on linux libs = self.clib_compiler.find_library('vulkan', environment, []) - if libs is not None and self.clib_compiler.has_header('vulkan/vulkan.h', '', environment): + if libs is not None and self.clib_compiler.has_header('vulkan/vulkan.h', '', environment)[0]: self.type_name = 'system' self.is_found = True for lib in libs: diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index 8ca7758f5..b0311a4b9 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -1134,16 +1134,17 @@ class CompilerHolder(InterpreterObject): raise InterpreterException('Prefix argument of has_member must be a string.') extra_args = functools.partial(self.determine_args, kwargs) deps, msg = self.determine_dependencies(kwargs) - had = self.compiler.has_members(typename, [membername], prefix, - self.environment, - extra_args=extra_args, - dependencies=deps) + had, cached = self.compiler.has_members(typename, [membername], prefix, + self.environment, + extra_args=extra_args, + dependencies=deps) + cached = '(cached)' if cached else '' if had: hadtxt = mlog.green('YES') else: hadtxt = mlog.red('NO') mlog.log('Checking whether type', mlog.bold(typename, True), - 'has member', mlog.bold(membername, True), msg, hadtxt) + 'has member', mlog.bold(membername, True), msg, hadtxt, cached) return had @permittedKwargs({ @@ -1163,17 +1164,18 @@ class CompilerHolder(InterpreterObject): raise InterpreterException('Prefix argument of has_members must be a string.') extra_args = functools.partial(self.determine_args, kwargs) deps, msg = self.determine_dependencies(kwargs) - had = self.compiler.has_members(typename, membernames, prefix, - self.environment, - extra_args=extra_args, - dependencies=deps) + had, cached = self.compiler.has_members(typename, membernames, prefix, + self.environment, + extra_args=extra_args, + dependencies=deps) + cached = '(cached)' if cached else '' if had: hadtxt = mlog.green('YES') else: hadtxt = mlog.red('NO') members = mlog.bold(', '.join(['"{}"'.format(m) for m in membernames])) mlog.log('Checking whether type', mlog.bold(typename, True), - 'has members', members, msg, hadtxt) + 'has members', members, msg, hadtxt, cached) return had @permittedKwargs({ @@ -1193,14 +1195,15 @@ class CompilerHolder(InterpreterObject): raise InterpreterException('Prefix argument of has_function must be a string.') extra_args = self.determine_args(kwargs) deps, msg = self.determine_dependencies(kwargs) - had = self.compiler.has_function(funcname, prefix, self.environment, + had, cached = self.compiler.has_function(funcname, prefix, self.environment, extra_args=extra_args, dependencies=deps) + cached = '(cached)' if cached else '' if had: hadtxt = mlog.green('YES') else: hadtxt = mlog.red('NO') - mlog.log('Checking for function', mlog.bold(funcname, True), msg, hadtxt) + mlog.log('Checking for function', mlog.bold(funcname, True), msg, hadtxt, cached) return had @permittedKwargs({ @@ -1220,13 +1223,14 @@ class CompilerHolder(InterpreterObject): raise InterpreterException('Prefix argument of has_type must be a string.') extra_args = functools.partial(self.determine_args, kwargs) deps, msg = self.determine_dependencies(kwargs) - had = self.compiler.has_type(typename, prefix, self.environment, - extra_args=extra_args, dependencies=deps) + had, cached = self.compiler.has_type(typename, prefix, self.environment, + extra_args=extra_args, dependencies=deps) + cached = '(cached)' if cached else '' if had: hadtxt = mlog.green('YES') else: hadtxt = mlog.red('NO') - mlog.log('Checking for type', mlog.bold(typename, True), msg, hadtxt) + mlog.log('Checking for type', mlog.bold(typename, True), msg, hadtxt, cached) return had @FeatureNew('compiler.compute_int', '0.40.0') @@ -1332,15 +1336,16 @@ class CompilerHolder(InterpreterObject): raise InterpreterException('Testname argument must be a string.') extra_args = functools.partial(self.determine_args, kwargs) deps, msg = self.determine_dependencies(kwargs, endl=None) - result = self.compiler.compiles(code, self.environment, - extra_args=extra_args, - dependencies=deps) + result, cached = self.compiler.compiles(code, self.environment, + extra_args=extra_args, + dependencies=deps) if len(testname) > 0: if result: h = mlog.green('YES') else: h = mlog.red('NO') - mlog.log('Checking if', mlog.bold(testname, True), msg, 'compiles:', h) + cached = '(cached)' if cached else '' + mlog.log('Checking if', mlog.bold(testname, True), msg, 'compiles:', h, cached) return result @permittedKwargs({ @@ -1364,15 +1369,16 @@ class CompilerHolder(InterpreterObject): raise InterpreterException('Testname argument must be a string.') extra_args = functools.partial(self.determine_args, kwargs) deps, msg = self.determine_dependencies(kwargs, endl=None) - result = self.compiler.links(code, self.environment, - extra_args=extra_args, - dependencies=deps) + result, cached = self.compiler.links(code, self.environment, + extra_args=extra_args, + dependencies=deps) + cached = '(cached)' if cached else '' if len(testname) > 0: if result: h = mlog.green('YES') else: h = mlog.red('NO') - mlog.log('Checking if', mlog.bold(testname, True), msg, 'links:', h) + mlog.log('Checking if', mlog.bold(testname, True), msg, 'links:', h, cached) return result @FeatureNew('compiler.check_header', '0.47.0') @@ -1392,16 +1398,17 @@ class CompilerHolder(InterpreterObject): return False extra_args = functools.partial(self.determine_args, kwargs) deps, msg = self.determine_dependencies(kwargs) - haz = self.compiler.check_header(hname, prefix, self.environment, - extra_args=extra_args, - dependencies=deps) + haz, cached = self.compiler.check_header(hname, prefix, self.environment, + extra_args=extra_args, + dependencies=deps) + cached = '(cached)' if cached else '' if required and not haz: raise InterpreterException('{} header {!r} not usable'.format(self.compiler.get_display_language(), hname)) elif haz: h = mlog.green('YES') else: h = mlog.red('NO') - mlog.log('Check usable header', mlog.bold(hname, True), msg, h) + mlog.log('Check usable header', mlog.bold(hname, True), msg, h, cached) return haz @FeatureNewKwargs('compiler.has_header', '0.50.0', ['required']) @@ -1420,15 +1427,16 @@ class CompilerHolder(InterpreterObject): return False extra_args = functools.partial(self.determine_args, kwargs) deps, msg = self.determine_dependencies(kwargs) - haz = self.compiler.has_header(hname, prefix, self.environment, - extra_args=extra_args, dependencies=deps) + haz, cached = self.compiler.has_header(hname, prefix, self.environment, + extra_args=extra_args, dependencies=deps) + cached = '(cached)' if cached else '' if required and not haz: raise InterpreterException('{} header {!r} not found'.format(self.compiler.get_display_language(), hname)) elif haz: h = mlog.green('YES') else: h = mlog.red('NO') - mlog.log('Has header', mlog.bold(hname, True), msg, h) + mlog.log('Has header', mlog.bold(hname, True), msg, h, cached) return haz @FeatureNewKwargs('compiler.has_header_symbol', '0.50.0', ['required']) @@ -1447,16 +1455,17 @@ class CompilerHolder(InterpreterObject): return False extra_args = functools.partial(self.determine_args, kwargs) deps, msg = self.determine_dependencies(kwargs) - haz = self.compiler.has_header_symbol(hname, symbol, prefix, self.environment, - extra_args=extra_args, - dependencies=deps) + haz, cached = self.compiler.has_header_symbol(hname, symbol, prefix, self.environment, + extra_args=extra_args, + dependencies=deps) if required and not haz: raise InterpreterException('{} symbol {} not found in header {}'.format(self.compiler.get_display_language(), symbol, hname)) elif haz: h = mlog.green('YES') else: h = mlog.red('NO') - mlog.log('Header <{0}> has symbol'.format(hname), mlog.bold(symbol, True), msg, h) + cached = '(cached)' if cached else '' + mlog.log('Header <{0}> has symbol'.format(hname), mlog.bold(symbol, True), msg, h, cached) return haz def notfound_library(self, libname): @@ -1518,15 +1527,16 @@ class CompilerHolder(InterpreterObject): @permittedKwargs({}) def has_multi_arguments_method(self, args, kwargs): args = mesonlib.stringlistify(args) - result = self.compiler.has_multi_arguments(args, self.environment) + result, cached = self.compiler.has_multi_arguments(args, self.environment) if result: h = mlog.green('YES') else: h = mlog.red('NO') + cached = '(cached)' if cached else '' mlog.log( 'Compiler for {} supports arguments {}:'.format( self.compiler.get_display_language(), ' '.join(args)), - h) + h, cached) return result @FeatureNew('compiler.get_supported_arguments', '0.43.0') @@ -1560,7 +1570,8 @@ class CompilerHolder(InterpreterObject): @permittedKwargs({}) def has_multi_link_arguments_method(self, args, kwargs): args = mesonlib.stringlistify(args) - result = self.compiler.has_multi_link_arguments(args, self.environment) + result, cached = self.compiler.has_multi_link_arguments(args, self.environment) + cached = '(cached)' if cached else '' if result: h = mlog.green('YES') else: @@ -1568,7 +1579,7 @@ class CompilerHolder(InterpreterObject): mlog.log( 'Compiler for {} supports link arguments {}:'.format( self.compiler.get_display_language(), ' '.join(args)), - h) + h, cached) return result @FeatureNew('compiler.get_supported_link_arguments_method', '0.46.0') @@ -1597,9 +1608,10 @@ class CompilerHolder(InterpreterObject): args = mesonlib.stringlistify(args) if len(args) != 1: raise InterpreterException('has_func_attribute takes exactly one argument.') - result = self.compiler.has_func_attribute(args[0], self.environment) + result, cached = self.compiler.has_func_attribute(args[0], self.environment) + cached = '(cached)' if cached else '' h = mlog.green('YES') if result else mlog.red('NO') - mlog.log('Compiler for {} supports function attribute {}:'.format(self.compiler.get_display_language(), args[0]), h) + mlog.log('Compiler for {} supports function attribute {}:'.format(self.compiler.get_display_language(), args[0]), h, cached) return result @FeatureNew('compiler.get_supported_function_attributes', '0.48.0') diff --git a/mesonbuild/modules/unstable_simd.py b/mesonbuild/modules/unstable_simd.py index 18a1099c4..2f2f67f79 100644 --- a/mesonbuild/modules/unstable_simd.py +++ b/mesonbuild/modules/unstable_simd.py @@ -66,7 +66,7 @@ class SimdModule(ExtensionModule): mlog.log('Compiler supports %s:' % iset, mlog.red('NO')) continue if args: - if not compiler.has_multi_arguments(args, state.environment): + if not compiler.has_multi_arguments(args, state.environment)[0]: mlog.log('Compiler supports %s:' % iset, mlog.red('NO')) continue mlog.log('Compiler supports %s:' % iset, mlog.green('YES')) From 971dfd664b7ca6532e8e368b66a956ef5a0abaae Mon Sep 17 00:00:00 2001 From: Daniel Mensinger Date: Tue, 19 Feb 2019 21:46:10 +0100 Subject: [PATCH 03/11] Added some cahced values --- mesonbuild/compilers/c.py | 7 ++++--- mesonbuild/compilers/cuda.py | 5 +++-- mesonbuild/compilers/d.py | 2 +- mesonbuild/dependencies/boost.py | 2 +- mesonbuild/dependencies/misc.py | 2 +- mesonbuild/interpreter.py | 9 +++++---- 6 files changed, 15 insertions(+), 12 deletions(-) diff --git a/mesonbuild/compilers/c.py b/mesonbuild/compilers/c.py index fe5a9ca14..2d70d7279 100644 --- a/mesonbuild/compilers/c.py +++ b/mesonbuild/compilers/c.py @@ -653,12 +653,13 @@ class CCompiler(Compiler): args = self._get_compiler_check_args(env, extra_args, dependencies, mode='preprocess').to_native() with self.compile(code.format(**fargs), args, 'preprocess', cdata=env.coredata) as p: + cached = p.cached if p.returncode != 0: raise EnvironmentException('Could not get define {!r}'.format(dname)) # Get the preprocessed value after the delimiter, # minus the extra newline at the end and # merge string literals. - return CCompiler.concatenate_string_literals(p.stdo.split(delim + '\n')[-1][:-1]) + return CCompiler.concatenate_string_literals(p.stdo.split(delim + '\n')[-1][:-1]), cached def get_return_value(self, fname, rtype, prefix, env, extra_args, dependencies): if rtype == 'string': @@ -1202,7 +1203,7 @@ class CCompiler(Compiler): if not (for_windows(env.is_cross_build(), env) or for_cygwin(env.is_cross_build(), env)): if name in ['dllimport', 'dllexport']: - return False + return False, False # Clang and GCC both return warnings if the __attribute__ is undefined, # so set -Werror @@ -1707,7 +1708,7 @@ class VisualStudioCCompiler(CCompiler): def has_func_attribute(self, name, env): # MSVC doesn't have __attribute__ like Clang and GCC do, so just return # false without compiling anything - return name in ['dllimport', 'dllexport'] + return name in ['dllimport', 'dllexport'], False def get_argument_syntax(self): return 'msvc' diff --git a/mesonbuild/compilers/cuda.py b/mesonbuild/compilers/cuda.py index 21fa4984f..51a1300f9 100644 --- a/mesonbuild/compilers/cuda.py +++ b/mesonbuild/compilers/cuda.py @@ -146,8 +146,9 @@ class CudaCompiler(Compiler): return super().get_compiler_check_args() + [] def has_header_symbol(self, hname, symbol, prefix, env, extra_args=None, dependencies=None): - if super().has_header_symbol(hname, symbol, prefix, env, extra_args, dependencies): - return True + result, cached = super().has_header_symbol(hname, symbol, prefix, env, extra_args, dependencies) + if result: + return True, cached if extra_args is None: extra_args = [] fargs = {'prefix': prefix, 'header': hname, 'symbol': symbol} diff --git a/mesonbuild/compilers/d.py b/mesonbuild/compilers/d.py index e8257d345..a5f72d856 100644 --- a/mesonbuild/compilers/d.py +++ b/mesonbuild/compilers/d.py @@ -327,7 +327,7 @@ class DCompiler(Compiler): args = self._get_compiler_check_args(env, extra_args, dependencies, mode) with self.compile(code, args, mode, cdata=env.coredata) as p: - return p.returncode == 0 + return p.returncode == 0, p.cached def has_multi_arguments(self, args, env): return self.compiles('int i;\n', env, extra_args=args) diff --git a/mesonbuild/dependencies/boost.py b/mesonbuild/dependencies/boost.py index 381824c79..6e06847e3 100644 --- a/mesonbuild/dependencies/boost.py +++ b/mesonbuild/dependencies/boost.py @@ -250,7 +250,7 @@ class BoostDependency(ExternalDependency): def detect_headers_and_version(self): try: - version = self.clib_compiler.get_define('BOOST_LIB_VERSION', '#include ', self.env, self.get_compile_args(), []) + version = self.clib_compiler.get_define('BOOST_LIB_VERSION', '#include ', self.env, self.get_compile_args(), [])[0] except mesonlib.EnvironmentException: return except TypeError: diff --git a/mesonbuild/dependencies/misc.py b/mesonbuild/dependencies/misc.py index d266a3737..77ea6ef05 100644 --- a/mesonbuild/dependencies/misc.py +++ b/mesonbuild/dependencies/misc.py @@ -368,7 +368,7 @@ class OpenMPDependency(ExternalDependency): self.is_found = False try: openmp_date = self.clib_compiler.get_define( - '_OPENMP', '', self.env, self.clib_compiler.openmp_flags(), [self]) + '_OPENMP', '', self.env, self.clib_compiler.openmp_flags(), [self])[0] except mesonlib.EnvironmentException as e: mlog.debug('OpenMP support not available in the compiler') mlog.debug(e) diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index b0311a4b9..c4092f224 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -1309,10 +1309,11 @@ class CompilerHolder(InterpreterObject): raise InterpreterException('Prefix argument of get_define() must be a string.') extra_args = functools.partial(self.determine_args, kwargs) deps, msg = self.determine_dependencies(kwargs) - value = self.compiler.get_define(element, prefix, self.environment, - extra_args=extra_args, - dependencies=deps) - mlog.log('Fetching value of define', mlog.bold(element, True), msg, value) + value, cached = self.compiler.get_define(element, prefix, self.environment, + extra_args=extra_args, + dependencies=deps) + cached = '(cached)' if cached else '' + mlog.log('Fetching value of define', mlog.bold(element, True), msg, value, cached) return value @permittedKwargs({ From a351e0d64ec3907695a12c0999cd72c07f9b7a62 Mon Sep 17 00:00:00 2001 From: Daniel Mensinger Date: Tue, 19 Feb 2019 22:02:13 +0100 Subject: [PATCH 04/11] Annotaded return types in the base compiler class --- mesonbuild/compilers/compilers.py | 44 +++++++++++++++---------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py index e8d8358aa..9c9b61f86 100644 --- a/mesonbuild/compilers/compilers.py +++ b/mesonbuild/compilers/compilers.py @@ -901,7 +901,7 @@ class Compiler: return repr_str.format(self.__class__.__name__, self.version, ' '.join(self.exelist)) - def can_compile(self, src): + def can_compile(self, src) -> bool: if hasattr(src, 'fname'): src = src.fname suffix = os.path.splitext(src)[1].lower() @@ -909,40 +909,40 @@ class Compiler: return True return False - def get_id(self): + def get_id(self) -> str: return self.id - def get_version_string(self): + def get_version_string(self) -> str: details = [self.id, self.version] if self.full_version: details += ['"%s"' % (self.full_version)] return '(%s)' % (' '.join(details)) - def get_language(self): + def get_language(self) -> str: return self.language - def get_display_language(self): + def get_display_language(self) -> str: return self.language.capitalize() - def get_default_suffix(self): + def get_default_suffix(self) -> str: return self.default_suffix - def get_define(self, dname, prefix, env, extra_args, dependencies): + def get_define(self, dname, prefix, env, extra_args, dependencies) -> (str, bool): raise EnvironmentException('%s does not support get_define ' % self.get_id()) - def compute_int(self, expression, low, high, guess, prefix, env, extra_args, dependencies): + def compute_int(self, expression, low, high, guess, prefix, env, extra_args, dependencies) -> int: raise EnvironmentException('%s does not support compute_int ' % self.get_id()) def compute_parameters_with_absolute_paths(self, parameter_list, build_dir): raise EnvironmentException('%s does not support compute_parameters_with_absolute_paths ' % self.get_id()) - def has_members(self, typename, membernames, prefix, env, *, extra_args=None, dependencies=None): + def has_members(self, typename, membernames, prefix, env, *, extra_args=None, dependencies=None) -> (bool, bool): raise EnvironmentException('%s does not support has_member(s) ' % self.get_id()) - def has_type(self, typename, prefix, env, extra_args, *, dependencies=None): + def has_type(self, typename, prefix, env, extra_args, *, dependencies=None) -> (bool, bool): raise EnvironmentException('%s does not support has_type ' % self.get_id()) - def symbols_have_underscore_prefix(self, env): + def symbols_have_underscore_prefix(self, env) -> bool: raise EnvironmentException('%s does not support symbols_have_underscore_prefix ' % self.get_id()) def get_exelist(self): @@ -1085,31 +1085,31 @@ class Compiler: def get_option_link_args(self, options): return [] - def check_header(self, *args, **kwargs): + def check_header(self, *args, **kwargs) -> (bool, bool): raise EnvironmentException('Language %s does not support header checks.' % self.get_display_language()) - def has_header(self, *args, **kwargs): + def has_header(self, *args, **kwargs) -> (bool, bool): raise EnvironmentException('Language %s does not support header checks.' % self.get_display_language()) - def has_header_symbol(self, *args, **kwargs): + def has_header_symbol(self, *args, **kwargs) -> (bool, bool): raise EnvironmentException('Language %s does not support header symbol checks.' % self.get_display_language()) - def compiles(self, *args, **kwargs): + def compiles(self, *args, **kwargs) -> (bool, bool): raise EnvironmentException('Language %s does not support compile checks.' % self.get_display_language()) - def links(self, *args, **kwargs): + def links(self, *args, **kwargs) -> (bool, bool): raise EnvironmentException('Language %s does not support link checks.' % self.get_display_language()) - def run(self, *args, **kwargs): + def run(self, *args, **kwargs) -> RunResult: raise EnvironmentException('Language %s does not support run checks.' % self.get_display_language()) - def sizeof(self, *args, **kwargs): + def sizeof(self, *args, **kwargs) -> int: raise EnvironmentException('Language %s does not support sizeof checks.' % self.get_display_language()) - def alignment(self, *args, **kwargs): + def alignment(self, *args, **kwargs) -> int: raise EnvironmentException('Language %s does not support alignment checks.' % self.get_display_language()) - def has_function(self, *args, **kwargs): + def has_function(self, *args, **kwargs) -> (bool, bool): raise EnvironmentException('Language %s does not support function checks.' % self.get_display_language()) @classmethod @@ -1123,12 +1123,12 @@ class Compiler: def get_library_dirs(self, *args, **kwargs): return () - def has_multi_arguments(self, args, env): + def has_multi_arguments(self, args, env) -> (bool, bool): raise EnvironmentException( 'Language {} does not support has_multi_arguments.'.format( self.get_display_language())) - def has_multi_link_arguments(self, args, env): + def has_multi_link_arguments(self, args, env) -> (bool, bool): raise EnvironmentException( 'Language {} does not support has_multi_link_arguments.'.format( self.get_display_language())) From c9e2d22eef07a87005640a4a8d8ebc78fc5bdf75 Mon Sep 17 00:00:00 2001 From: Daniel Mensinger Date: Tue, 19 Feb 2019 22:04:21 +0100 Subject: [PATCH 05/11] Make flake8 happy --- mesonbuild/interpreter.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index c4092f224..a6e34fc77 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -1196,8 +1196,8 @@ class CompilerHolder(InterpreterObject): extra_args = self.determine_args(kwargs) deps, msg = self.determine_dependencies(kwargs) had, cached = self.compiler.has_function(funcname, prefix, self.environment, - extra_args=extra_args, - dependencies=deps) + extra_args=extra_args, + dependencies=deps) cached = '(cached)' if cached else '' if had: hadtxt = mlog.green('YES') From 0e91e4bdd12cf9a7362cf82bcf7e25ffc763a675 Mon Sep 17 00:00:00 2001 From: Daniel Mensinger Date: Wed, 20 Feb 2019 23:41:34 +0100 Subject: [PATCH 06/11] Fixed typeing --- mesonbuild/compilers/compilers.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py index 9c9b61f86..e705a75d6 100644 --- a/mesonbuild/compilers/compilers.py +++ b/mesonbuild/compilers/compilers.py @@ -927,7 +927,7 @@ class Compiler: def get_default_suffix(self) -> str: return self.default_suffix - def get_define(self, dname, prefix, env, extra_args, dependencies) -> (str, bool): + def get_define(self, dname, prefix, env, extra_args, dependencies) -> Tuple[str, bool]: raise EnvironmentException('%s does not support get_define ' % self.get_id()) def compute_int(self, expression, low, high, guess, prefix, env, extra_args, dependencies) -> int: @@ -936,10 +936,10 @@ class Compiler: def compute_parameters_with_absolute_paths(self, parameter_list, build_dir): raise EnvironmentException('%s does not support compute_parameters_with_absolute_paths ' % self.get_id()) - def has_members(self, typename, membernames, prefix, env, *, extra_args=None, dependencies=None) -> (bool, bool): + def has_members(self, typename, membernames, prefix, env, *, extra_args=None, dependencies=None) -> Tuple[bool, bool]: raise EnvironmentException('%s does not support has_member(s) ' % self.get_id()) - def has_type(self, typename, prefix, env, extra_args, *, dependencies=None) -> (bool, bool): + def has_type(self, typename, prefix, env, extra_args, *, dependencies=None) -> Tuple[bool, bool]: raise EnvironmentException('%s does not support has_type ' % self.get_id()) def symbols_have_underscore_prefix(self, env) -> bool: @@ -1085,19 +1085,19 @@ class Compiler: def get_option_link_args(self, options): return [] - def check_header(self, *args, **kwargs) -> (bool, bool): + def check_header(self, *args, **kwargs) -> Tuple[bool, bool]: raise EnvironmentException('Language %s does not support header checks.' % self.get_display_language()) - def has_header(self, *args, **kwargs) -> (bool, bool): + def has_header(self, *args, **kwargs) -> Tuple[bool, bool]: raise EnvironmentException('Language %s does not support header checks.' % self.get_display_language()) - def has_header_symbol(self, *args, **kwargs) -> (bool, bool): + def has_header_symbol(self, *args, **kwargs) -> Tuple[bool, bool]: raise EnvironmentException('Language %s does not support header symbol checks.' % self.get_display_language()) - def compiles(self, *args, **kwargs) -> (bool, bool): + def compiles(self, *args, **kwargs) -> Tuple[bool, bool]: raise EnvironmentException('Language %s does not support compile checks.' % self.get_display_language()) - def links(self, *args, **kwargs) -> (bool, bool): + def links(self, *args, **kwargs) -> Tuple[bool, bool]: raise EnvironmentException('Language %s does not support link checks.' % self.get_display_language()) def run(self, *args, **kwargs) -> RunResult: @@ -1109,7 +1109,7 @@ class Compiler: def alignment(self, *args, **kwargs) -> int: raise EnvironmentException('Language %s does not support alignment checks.' % self.get_display_language()) - def has_function(self, *args, **kwargs) -> (bool, bool): + def has_function(self, *args, **kwargs) -> Tuple[bool, bool]: raise EnvironmentException('Language %s does not support function checks.' % self.get_display_language()) @classmethod @@ -1123,12 +1123,12 @@ class Compiler: def get_library_dirs(self, *args, **kwargs): return () - def has_multi_arguments(self, args, env) -> (bool, bool): + def has_multi_arguments(self, args, env) -> Tuple[bool, bool]: raise EnvironmentException( 'Language {} does not support has_multi_arguments.'.format( self.get_display_language())) - def has_multi_link_arguments(self, args, env) -> (bool, bool): + def has_multi_link_arguments(self, args, env) -> Tuple[bool, bool]: raise EnvironmentException( 'Language {} does not support has_multi_link_arguments.'.format( self.get_display_language())) @@ -1146,7 +1146,7 @@ class Compiler: return os.path.join(dirname, 'output.' + suffix) @contextlib.contextmanager - def compile(self, code, extra_args=None, mode='link', want_output=False, cdata: coredata.CoreData = None): + def compile(self, code, extra_args=None, mode='link', want_output=False, cdata: Optional[coredata.CoreData] = None): if extra_args is None: textra_args = None extra_args = [] From 6969772a3e915e3a6cd577ec7b54bf2d2ed604c8 Mon Sep 17 00:00:00 2001 From: Daniel Mensinger Date: Sun, 3 Mar 2019 22:15:49 +0100 Subject: [PATCH 07/11] Changing cached flag from True to False --- mesonbuild/compilers/c.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/compilers/c.py b/mesonbuild/compilers/c.py index 2d70d7279..7df31b6b5 100644 --- a/mesonbuild/compilers/c.py +++ b/mesonbuild/compilers/c.py @@ -763,7 +763,7 @@ class CCompiler(Compiler): val = env.properties.host.get(varname, None) if val is not None: if isinstance(val, bool): - return val, True + return val, False raise EnvironmentException('Cross variable {0} is not a boolean.'.format(varname)) fargs = {'prefix': prefix, 'func': funcname} From 210fe5bf40f596e50da9c39f15e101459deac9eb Mon Sep 17 00:00:00 2001 From: Daniel Mensinger Date: Sun, 3 Mar 2019 22:59:38 +0100 Subject: [PATCH 08/11] Add option to disable the cache --- mesonbuild/compilers/c.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/mesonbuild/compilers/c.py b/mesonbuild/compilers/c.py index 7df31b6b5..2e796aed8 100644 --- a/mesonbuild/compilers/c.py +++ b/mesonbuild/compilers/c.py @@ -444,17 +444,17 @@ class CCompiler(Compiler): args += extra_args return args - def compiles(self, code, env, *, extra_args=None, dependencies=None, mode='compile'): - with self._build_wrapper(code, env, extra_args, dependencies, mode) as p: + def compiles(self, code, env, *, extra_args=None, dependencies=None, mode='compile', disable_cache=False): + with self._build_wrapper(code, env, extra_args, dependencies, mode, disable_cache=disable_cache) as p: return p.returncode == 0, p.cached - def _build_wrapper(self, code, env, extra_args, dependencies=None, mode='compile', want_output=False): + def _build_wrapper(self, code, env, extra_args, dependencies=None, mode='compile', want_output=False, disable_cache=False): args = self._get_compiler_check_args(env, extra_args, dependencies, mode) - return self.compile(code, args, mode, want_output=want_output, cdata=env.coredata) + return self.compile(code, args, mode, want_output=want_output, cdata=env.coredata if not disable_cache else None) - def links(self, code, env, *, extra_args=None, dependencies=None): + def links(self, code, env, *, extra_args=None, dependencies=None, disable_cache=False): return self.compiles(code, env, extra_args=extra_args, - dependencies=dependencies, mode='link') + dependencies=dependencies, mode='link', disable_cache=disable_cache) def run(self, code: str, env, *, extra_args=None, dependencies=None): if self.is_cross and self.exe_wrapper is None: @@ -1022,7 +1022,7 @@ class CCompiler(Compiler): libname in self.internal_libs): args = ['-l' + libname] largs = self.linker_to_compiler_args(self.get_allow_undefined_link_args()) - if self.links(code, env, extra_args=(args + largs))[0]: + if self.links(code, env, extra_args=(args + largs), disable_cache=True)[0]: return args # Don't do a manual search for internal libs if libname in self.internal_libs: @@ -1111,7 +1111,7 @@ class CCompiler(Compiler): # then we must also pass -L/usr/lib to pick up libSystem.dylib extra_args = [] if allow_system else ['-Z', '-L/usr/lib'] link_args += ['-framework', name] - if self.links(code, env, extra_args=(extra_args + link_args))[0]: + if self.links(code, env, extra_args=(extra_args + link_args), disable_cache=True)[0]: return link_args def find_framework_impl(self, name, env, extra_dirs, allow_system): From 47c06a787504dd9635a0bd5a9e2013aa4bf85b12 Mon Sep 17 00:00:00 2001 From: Daniel Mensinger Date: Sun, 3 Mar 2019 23:32:21 +0100 Subject: [PATCH 09/11] Add disable_cache to the fortran compiler --- mesonbuild/compilers/fortran.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/mesonbuild/compilers/fortran.py b/mesonbuild/compilers/fortran.py index 0f7c38e0a..7e27f1ac4 100644 --- a/mesonbuild/compilers/fortran.py +++ b/mesonbuild/compilers/fortran.py @@ -250,16 +250,16 @@ class FortranCompiler(Compiler): def _get_compiler_check_args(self, env, extra_args, dependencies, mode='compile'): return CCompiler._get_compiler_check_args(self, env, extra_args, dependencies, mode=mode) - def compiles(self, code, env, *, extra_args=None, dependencies=None, mode='compile'): + def compiles(self, code, env, *, extra_args=None, dependencies=None, mode='compile', disable_cache=False): return CCompiler.compiles(self, code, env, extra_args=extra_args, - dependencies=dependencies, mode=mode) + dependencies=dependencies, mode=mode, disable_cache=disable_cache) - def _build_wrapper(self, code, env, extra_args, dependencies=None, mode='compile', want_output=False): - return CCompiler._build_wrapper(self, code, env, extra_args, dependencies, mode, want_output) + def _build_wrapper(self, code, env, extra_args, dependencies=None, mode='compile', want_output=False, disable_cache=False): + return CCompiler._build_wrapper(self, code, env, extra_args, dependencies, mode, want_output, disable_cache=disable_cache) - def links(self, code, env, *, extra_args=None, dependencies=None): + def links(self, code, env, *, extra_args=None, dependencies=None, disable_cache=False): return CCompiler.links(self, code, env, extra_args=extra_args, - dependencies=dependencies) + dependencies=dependencies, disable_cache=disable_cache) def run(self, code, env, *, extra_args=None, dependencies=None): return CCompiler.run(self, code, env, extra_args=extra_args, dependencies=dependencies) From 8a32fc8dbeb6d0fb5666f2af694d70fa6b575e03 Mon Sep 17 00:00:00 2001 From: Daniel Mensinger Date: Sun, 3 Mar 2019 23:43:54 +0100 Subject: [PATCH 10/11] Disable cache for dependencies --- mesonbuild/compilers/c.py | 8 ++++---- mesonbuild/compilers/fortran.py | 8 ++++---- mesonbuild/dependencies/boost.py | 2 +- mesonbuild/dependencies/misc.py | 4 ++-- mesonbuild/dependencies/ui.py | 2 +- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/mesonbuild/compilers/c.py b/mesonbuild/compilers/c.py index 2e796aed8..e1001e7d3 100644 --- a/mesonbuild/compilers/c.py +++ b/mesonbuild/compilers/c.py @@ -368,7 +368,7 @@ class CCompiler(Compiler): return self.compiles(code.format(**fargs), env, extra_args=extra_args, dependencies=dependencies) - def has_header(self, hname, prefix, env, *, extra_args=None, dependencies=None): + def has_header(self, hname, prefix, env, *, extra_args=None, dependencies=None, disable_cache=False): fargs = {'prefix': prefix, 'header': hname} code = '''{prefix} #ifdef __has_include @@ -379,7 +379,7 @@ class CCompiler(Compiler): #include <{header}> #endif''' return self.compiles(code.format(**fargs), env, extra_args=extra_args, - dependencies=dependencies, mode='preprocess') + dependencies=dependencies, mode='preprocess', disable_cache=disable_cache) def has_header_symbol(self, hname, symbol, prefix, env, *, extra_args=None, dependencies=None): fargs = {'prefix': prefix, 'header': hname, 'symbol': symbol} @@ -641,7 +641,7 @@ class CCompiler(Compiler): raise EnvironmentException('Could not determine alignment of %s. Sorry. You might want to file a bug.' % typename) return align - def get_define(self, dname, prefix, env, extra_args, dependencies): + def get_define(self, dname, prefix, env, extra_args, dependencies, disable_cache=False): delim = '"MESON_GET_DEFINE_DELIMITER"' fargs = {'prefix': prefix, 'define': dname, 'delim': delim} code = ''' @@ -652,7 +652,7 @@ class CCompiler(Compiler): {delim}\n{define}''' args = self._get_compiler_check_args(env, extra_args, dependencies, mode='preprocess').to_native() - with self.compile(code.format(**fargs), args, 'preprocess', cdata=env.coredata) as p: + with self.compile(code.format(**fargs), args, 'preprocess', cdata=env.coredata if not disable_cache else None) as p: cached = p.cached if p.returncode != 0: raise EnvironmentException('Could not get define {!r}'.format(dname)) diff --git a/mesonbuild/compilers/fortran.py b/mesonbuild/compilers/fortran.py index 7e27f1ac4..acfb506cc 100644 --- a/mesonbuild/compilers/fortran.py +++ b/mesonbuild/compilers/fortran.py @@ -297,11 +297,11 @@ class FortranCompiler(Compiler): def has_multi_arguments(self, args, env): return CCompiler.has_multi_arguments(self, args, env) - def has_header(self, hname, prefix, env, *, extra_args=None, dependencies=None): - return CCompiler.has_header(self, hname, prefix, env, extra_args=extra_args, dependencies=dependencies) + def has_header(self, hname, prefix, env, *, extra_args=None, dependencies=None, disable_cache=False): + return CCompiler.has_header(self, hname, prefix, env, extra_args=extra_args, dependencies=dependencies, disable_cache=disable_cache) - def get_define(self, dname, prefix, env, extra_args, dependencies): - return CCompiler.get_define(self, dname, prefix, env, extra_args, dependencies) + def get_define(self, dname, prefix, env, extra_args, dependencies, disable_cache=False): + return CCompiler.get_define(self, dname, prefix, env, extra_args, dependencies, disable_cache=disable_cache) @classmethod def _get_trials_from_pattern(cls, pattern, directory, libname): diff --git a/mesonbuild/dependencies/boost.py b/mesonbuild/dependencies/boost.py index 6e06847e3..f5b95f5b3 100644 --- a/mesonbuild/dependencies/boost.py +++ b/mesonbuild/dependencies/boost.py @@ -250,7 +250,7 @@ class BoostDependency(ExternalDependency): def detect_headers_and_version(self): try: - version = self.clib_compiler.get_define('BOOST_LIB_VERSION', '#include ', self.env, self.get_compile_args(), [])[0] + version = self.clib_compiler.get_define('BOOST_LIB_VERSION', '#include ', self.env, self.get_compile_args(), [], disable_cache=True)[0] except mesonlib.EnvironmentException: return except TypeError: diff --git a/mesonbuild/dependencies/misc.py b/mesonbuild/dependencies/misc.py index 77ea6ef05..72ba7b3bf 100644 --- a/mesonbuild/dependencies/misc.py +++ b/mesonbuild/dependencies/misc.py @@ -368,7 +368,7 @@ class OpenMPDependency(ExternalDependency): self.is_found = False try: openmp_date = self.clib_compiler.get_define( - '_OPENMP', '', self.env, self.clib_compiler.openmp_flags(), [self])[0] + '_OPENMP', '', self.env, self.clib_compiler.openmp_flags(), [self], disable_cache=True)[0] except mesonlib.EnvironmentException as e: mlog.debug('OpenMP support not available in the compiler') mlog.debug(e) @@ -376,7 +376,7 @@ class OpenMPDependency(ExternalDependency): if openmp_date: self.version = self.VERSIONS[openmp_date] - if self.clib_compiler.has_header('omp.h', '', self.env, dependencies=[self])[0]: + if self.clib_compiler.has_header('omp.h', '', self.env, dependencies=[self], disable_cache=True)[0]: self.is_found = True self.compile_args = self.link_args = self.clib_compiler.openmp_flags() else: diff --git a/mesonbuild/dependencies/ui.py b/mesonbuild/dependencies/ui.py index 0a01ac46e..4b3fb705b 100644 --- a/mesonbuild/dependencies/ui.py +++ b/mesonbuild/dependencies/ui.py @@ -641,7 +641,7 @@ class VulkanDependency(ExternalDependency): else: # simply try to guess it, usually works on linux libs = self.clib_compiler.find_library('vulkan', environment, []) - if libs is not None and self.clib_compiler.has_header('vulkan/vulkan.h', '', environment)[0]: + if libs is not None and self.clib_compiler.has_header('vulkan/vulkan.h', '', environment, disable_cache=True)[0]: self.type_name = 'system' self.is_found = True for lib in libs: From c61ae46461bf9f4c7afef2381032ac0cb2d26043 Mon Sep 17 00:00:00 2001 From: Daniel Mensinger Date: Sun, 28 Apr 2019 14:30:52 +0200 Subject: [PATCH 11/11] Moved caching into a seperate function --- mesonbuild/compilers/c.py | 9 ++++- mesonbuild/compilers/compilers.py | 61 ++++++++++++++++++------------- mesonbuild/compilers/d.py | 2 +- mesonbuild/compilers/vala.py | 4 +- 4 files changed, 45 insertions(+), 31 deletions(-) diff --git a/mesonbuild/compilers/c.py b/mesonbuild/compilers/c.py index e1001e7d3..da51ce23f 100644 --- a/mesonbuild/compilers/c.py +++ b/mesonbuild/compilers/c.py @@ -450,7 +450,9 @@ class CCompiler(Compiler): def _build_wrapper(self, code, env, extra_args, dependencies=None, mode='compile', want_output=False, disable_cache=False): args = self._get_compiler_check_args(env, extra_args, dependencies, mode) - return self.compile(code, args, mode, want_output=want_output, cdata=env.coredata if not disable_cache else None) + if disable_cache or want_output: + return self.compile(code, extra_args=args, mode=mode, want_output=want_output) + return self.cached_compile(code, env.coredata, extra_args=args, mode=mode) def links(self, code, env, *, extra_args=None, dependencies=None, disable_cache=False): return self.compiles(code, env, extra_args=extra_args, @@ -652,7 +654,10 @@ class CCompiler(Compiler): {delim}\n{define}''' args = self._get_compiler_check_args(env, extra_args, dependencies, mode='preprocess').to_native() - with self.compile(code.format(**fargs), args, 'preprocess', cdata=env.coredata if not disable_cache else None) as p: + func = lambda: self.cached_compile(code.format(**fargs), env.coredata, extra_args=args, mode='preprocess') + if disable_cache: + func = lambda: self.compile(code.format(**fargs), extra_args=args, mode='preprocess') + with func() as p: cached = p.cached if p.returncode != 0: raise EnvironmentException('Could not get define {!r}'.format(dname)) diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py index e705a75d6..b03458aee 100644 --- a/mesonbuild/compilers/compilers.py +++ b/mesonbuild/compilers/compilers.py @@ -1146,24 +1146,9 @@ class Compiler: return os.path.join(dirname, 'output.' + suffix) @contextlib.contextmanager - def compile(self, code, extra_args=None, mode='link', want_output=False, cdata: Optional[coredata.CoreData] = None): + def compile(self, code, extra_args=None, mode='link', want_output=False): if extra_args is None: - textra_args = None extra_args = [] - else: - textra_args = tuple(extra_args) - key = (tuple(self.exelist), self.version, code, textra_args, mode) - if not want_output: - if cdata is not None and key in cdata.compiler_check_cache: - p = cdata.compiler_check_cache[key] - p.cached = True - mlog.debug('Using cached compile:') - mlog.debug('Cached command line: ', ' '.join(p.commands), '\n') - mlog.debug('Code:\n', code) - mlog.debug('Cached compiler stdout:\n', p.stdo) - mlog.debug('Cached compiler stderr:\n', p.stde) - yield p - return try: with tempfile.TemporaryDirectory() as tmpdirname: if isinstance(code, str): @@ -1205,16 +1190,7 @@ class Compiler: p.input_name = srcname if want_output: p.output_name = output - elif cdata is not None: - # Remove all attributes except the following - # This way the object can be serialized - tokeep = ['args', 'commands', 'input_name', 'output_name', - 'pid', 'returncode', 'stdo', 'stde', 'text_mode'] - todel = [x for x in vars(p).keys() if x not in tokeep] - for i in todel: - delattr(p, i) - cdata.compiler_check_cache[key] = p - p.cached = False + p.cached = False # Make sure that the cached attribute always exists yield p except (PermissionError, OSError): # On Windows antivirus programs and the like hold on to files so @@ -1222,6 +1198,39 @@ class Compiler: # catch OSError because the directory is then no longer empty. pass + @contextlib.contextmanager + def cached_compile(self, code, cdata: coredata.CoreData, extra_args=None, mode: str = 'link'): + assert(isinstance(cdata, coredata.CoreData)) + + # Calculate the key + textra_args = tuple(extra_args) if extra_args is not None else None + key = (tuple(self.exelist), self.version, code, textra_args, mode) + + # Check if not cached + if key not in cdata.compiler_check_cache: + with self.compile(code, extra_args=extra_args, mode=mode, want_output=False) as p: + # Remove all attributes except the following + # This way the object can be serialized + tokeep = ['args', 'commands', 'input_name', 'output_name', + 'pid', 'returncode', 'stdo', 'stde', 'text_mode'] + todel = [x for x in vars(p).keys() if x not in tokeep] + for i in todel: + delattr(p, i) + p.cached = False + cdata.compiler_check_cache[key] = p + yield p + return + + # Return cached + p = cdata.compiler_check_cache[key] + p.cached = True + mlog.debug('Using cached compile:') + mlog.debug('Cached command line: ', ' '.join(p.commands), '\n') + mlog.debug('Code:\n', code) + mlog.debug('Cached compiler stdout:\n', p.stdo) + mlog.debug('Cached compiler stderr:\n', p.stde) + yield p + def get_colorout_args(self, colortype): return [] diff --git a/mesonbuild/compilers/d.py b/mesonbuild/compilers/d.py index a5f72d856..46cc0541e 100644 --- a/mesonbuild/compilers/d.py +++ b/mesonbuild/compilers/d.py @@ -326,7 +326,7 @@ class DCompiler(Compiler): def compiles(self, code, env, *, extra_args=None, dependencies=None, mode='compile'): args = self._get_compiler_check_args(env, extra_args, dependencies, mode) - with self.compile(code, args, mode, cdata=env.coredata) as p: + with self.cached_compile(code, env.coredata, extra_args=args, mode=mode) as p: return p.returncode == 0, p.cached def has_multi_arguments(self, args, env): diff --git a/mesonbuild/compilers/vala.py b/mesonbuild/compilers/vala.py index 789e00bb8..c0b2a6824 100644 --- a/mesonbuild/compilers/vala.py +++ b/mesonbuild/compilers/vala.py @@ -96,7 +96,7 @@ class ValaCompiler(Compiler): extra_flags += self.get_compile_only_args() else: extra_flags += environment.coredata.get_external_link_args(for_machine, self.language) - with self.compile(code, extra_flags, 'compile') as p: + with self.cached_compile(code, environment.coredata, extra_args=extra_flags, mode='compile') as p: if p.returncode != 0: msg = 'Vala compiler {!r} can not compile programs' \ ''.format(self.name_string()) @@ -121,7 +121,7 @@ class ValaCompiler(Compiler): args = env.coredata.get_external_args(for_machine, self.language) vapi_args = ['--pkg', libname] args += vapi_args - with self.compile(code, args, 'compile', cdata=env.coredata) as p: + with self.cached_compile(code, env.coredata, extra_args=args, mode='compile') as p: if p.returncode == 0: return vapi_args # Not found? Try to find the vapi file itself.