compilers: move _build_wrapper out of clike into Compiler

This abstraction is really useful, and most compilers could use it
(including D). It also will allow the Gnu mixins to work properly
without the CLikeCompiler in their mro.
pull/7795/head
Dylan Baker 4 years ago
parent cd59ce98dc
commit 738e343860
  1. 88
      mesonbuild/compilers/compilers.py
  2. 42
      mesonbuild/compilers/mixins/clike.py

@ -642,20 +642,6 @@ class Compiler(metaclass=abc.ABCMeta):
dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[bool, bool]:
raise EnvironmentException('Language %s does not support header symbol checks.' % self.get_display_language())
def compiles(self, code: str, env: 'Environment', *,
extra_args: T.Union[None, T.List[str], CompilerArgs] = None,
dependencies: T.Optional[T.List['Dependency']] = None,
mode: str = 'compile',
disable_cache: bool = False) -> T.Tuple[bool, bool]:
raise EnvironmentException('Language %s does not support compile checks.' % self.get_display_language())
def links(self, code: str, env: 'Environment', *,
extra_args: T.Union[None, T.List[str], CompilerArgs] = None,
dependencies: T.Optional[T.List['Dependency']] = None,
mode: str = 'compile',
disable_cache: bool = False) -> T.Tuple[bool, bool]:
raise EnvironmentException('Language %s does not support link checks.' % self.get_display_language())
def run(self, code: str, env: 'Environment', *,
extra_args: T.Optional[T.List[str]] = None,
dependencies: T.Optional[T.List['Dependency']] = None) -> RunResult:
@ -1132,6 +1118,80 @@ class Compiler(metaclass=abc.ABCMeta):
"""Arguments to the compiler to turn off all optimizations."""
return []
def build_wrapper_args(self, env: 'Environment',
extra_args: T.Union[None, CompilerArgs, T.List[str]],
dependencies: T.Optional[T.List['Dependency']],
mode: CompileCheckMode = CompileCheckMode.COMPILE) -> CompilerArgs:
"""Arguments to pass the build_wrapper helper.
This generally needs to be set on a per-language baises. It provides
a hook for languages to handle dependencies and extra args. The base
implementation handles the most common cases, namely adding the
check_arguments, unwrapping dependencies, and appending extra args.
"""
if callable(extra_args):
extra_args = extra_args(mode)
if extra_args is None:
extra_args = []
if dependencies is None:
dependencies = []
# Collect compiler arguments
args = self.compiler_args(self.get_compiler_check_args(mode))
for d in dependencies:
# Add compile flags needed by dependencies
args += d.get_compile_args()
if mode is CompileCheckMode.LINK:
# Add link flags needed to find dependencies
args += d.get_link_args()
if mode is CompileCheckMode.COMPILE:
# Add DFLAGS from the env
args += env.coredata.get_external_args(self.for_machine, self.language)
elif mode is CompileCheckMode.LINK:
# Add LDFLAGS from the env
args += env.coredata.get_external_link_args(self.for_machine, self.language)
# extra_args must override all other arguments, so we add them last
args += extra_args
return args
@contextlib.contextmanager
def _build_wrapper(self, code: str, env: 'Environment',
extra_args: T.Union[None, CompilerArgs, T.List[str]] = None,
dependencies: T.Optional[T.List['Dependency']] = None,
mode: str = 'compile', want_output: bool = False,
disable_cache: bool = False,
temp_dir: str = None) -> T.Iterator[T.Optional[CompileResult]]:
"""Helper for getting a cacched value when possible.
This method isn't meant to be called externally, it's mean to be
wrapped by other methods like compiles() and links().
"""
args = self.build_wrapper_args(env, extra_args, dependencies, CompileCheckMode(mode))
if disable_cache or want_output:
with self.compile(code, extra_args=args, mode=mode, want_output=want_output, temp_dir=env.scratch_dir) as r:
yield r
else:
with self.cached_compile(code, env.coredata, extra_args=args, mode=mode, temp_dir=env.scratch_dir) as r:
yield r
def compiles(self, code: str, env: 'Environment', *,
extra_args: T.Union[None, T.List[str], CompilerArgs] = None,
dependencies: T.Optional[T.List['Dependency']] = None,
mode: str = 'compile',
disable_cache: bool = False) -> T.Tuple[bool, bool]:
with self._build_wrapper(code, env, extra_args, dependencies, mode, disable_cache=disable_cache) as p:
return p.returncode == 0, p.cached
def links(self, code: str, env: 'Environment', *,
extra_args: T.Union[None, T.List[str], CompilerArgs] = None,
dependencies: T.Optional[T.List['Dependency']] = None,
mode: str = 'compile',
disable_cache: bool = False) -> T.Tuple[bool, bool]:
return self.compiles(code, env, extra_args=extra_args,
dependencies=dependencies, mode='link', disable_cache=disable_cache)
def get_args_from_envvars(lang: str,
for_machine: MachineChoice,

@ -20,7 +20,6 @@ of this is to have mixin's, which are classes that are designed *not* to be
standalone, they only work through inheritance.
"""
import contextlib
import collections
import functools
import glob
@ -423,10 +422,10 @@ class CLikeCompiler(Compiler):
cargs += self.get_compiler_args_for_mode(mode)
return cargs, largs
def _get_compiler_check_args(self, env: 'Environment',
extra_args: T.Union[None, arglist.CompilerArgs, T.List[str]],
dependencies: T.Optional[T.List['Dependency']],
mode: CompileCheckMode = CompileCheckMode.COMPILE) -> arglist.CompilerArgs:
def build_wrapper_args(self, env: 'Environment',
extra_args: T.Union[None, arglist.CompilerArgs, T.List[str]],
dependencies: T.Optional[T.List['Dependency']],
mode: CompileCheckMode = CompileCheckMode.COMPILE) -> arglist.CompilerArgs:
# TODO: the caller should handle the listfing of these arguments
if extra_args is None:
extra_args = []
@ -464,37 +463,6 @@ class CLikeCompiler(Compiler):
args = cargs + extra_args + largs
return args
def compiles(self, code: str, env: 'Environment', *,
extra_args: T.Union[None, T.List[str], arglist.CompilerArgs] = None,
dependencies: T.Optional[T.List['Dependency']] = None,
mode: str = 'compile',
disable_cache: bool = False) -> T.Tuple[bool, bool]:
with self._build_wrapper(code, env, extra_args, dependencies, mode, disable_cache=disable_cache) as p:
return p.returncode == 0, p.cached
@contextlib.contextmanager
def _build_wrapper(self, code: str, env: 'Environment',
extra_args: T.Union[None, arglist.CompilerArgs, T.List[str]] = None,
dependencies: T.Optional[T.List['Dependency']] = None,
mode: str = 'compile', want_output: bool = False,
disable_cache: bool = False,
temp_dir: str = None) -> T.Iterator[T.Optional[compilers.CompileResult]]:
args = self._get_compiler_check_args(env, extra_args, dependencies, CompileCheckMode(mode))
if disable_cache or want_output:
with self.compile(code, extra_args=args, mode=mode, want_output=want_output, temp_dir=env.scratch_dir) as r:
yield r
else:
with self.cached_compile(code, env.coredata, extra_args=args, mode=mode, temp_dir=env.scratch_dir) as r:
yield r
def links(self, code: str, env: 'Environment', *,
extra_args: T.Union[None, T.List[str], arglist.CompilerArgs] = None,
dependencies: T.Optional[T.List['Dependency']] = None,
mode: str = 'compile',
disable_cache: bool = False) -> T.Tuple[bool, bool]:
return self.compiles(code, env, extra_args=extra_args,
dependencies=dependencies, mode='link', disable_cache=disable_cache)
def run(self, code: str, env: 'Environment', *,
extra_args: T.Optional[T.List[str]] = None,
dependencies: T.Optional[T.List['Dependency']] = None) -> compilers.RunResult:
@ -713,7 +681,7 @@ class CLikeCompiler(Compiler):
# define {define}
#endif
{delim}\n{define}'''
args = self._get_compiler_check_args(env, extra_args, dependencies,
args = self.build_wrapper_args(env, extra_args, dependencies,
mode=CompileCheckMode.PREPROCESS).to_native()
func = functools.partial(self.cached_compile, code.format(**fargs), env.coredata, extra_args=args, mode='preprocess')
if disable_cache:

Loading…
Cancel
Save