compilers: Tell mypy that the compiler mixins are just that

We do this by making the mixins inherit the Compiler class only when
mypy is examining the code (using some clever inheritance shenanigans).
This caught a bunch of issues, and also lets us delete a ton of code.
pull/7786/head
Dylan Baker 4 years ago
parent 2c0fbe161d
commit 682d22129c
  1. 23
      mesonbuild/compilers/compilers.py
  2. 24
      mesonbuild/compilers/mixins/arm.py
  3. 13
      mesonbuild/compilers/mixins/c2000.py
  4. 9
      mesonbuild/compilers/mixins/ccrx.py
  5. 18
      mesonbuild/compilers/mixins/clang.py
  6. 57
      mesonbuild/compilers/mixins/clike.py
  7. 12
      mesonbuild/compilers/mixins/compcert.py
  8. 3
      mesonbuild/compilers/mixins/elbrus.py
  9. 18
      mesonbuild/compilers/mixins/emscripten.py
  10. 34
      mesonbuild/compilers/mixins/gnu.py
  11. 8
      mesonbuild/compilers/mixins/intel.py
  12. 17
      mesonbuild/compilers/mixins/islinker.py
  13. 14
      mesonbuild/compilers/mixins/pgi.py
  14. 36
      mesonbuild/compilers/mixins/visualstudio.py
  15. 13
      mesonbuild/compilers/mixins/xc16.py
  16. 1
      mesonbuild/linkers.py

@ -440,10 +440,10 @@ class CompileResult:
class Compiler(metaclass=abc.ABCMeta): class Compiler(metaclass=abc.ABCMeta):
# Libraries to ignore in find_library() since they are provided by the # Libraries to ignore in find_library() since they are provided by the
# compiler or the C library. Currently only used for MSVC. # compiler or the C library. Currently only used for MSVC.
ignore_libs = () # type: T.Tuple[str, ...] ignore_libs = [] # type: T.List[str]
# Libraries that are internal compiler implementations, and must not be # Libraries that are internal compiler implementations, and must not be
# manually searched. # manually searched.
internal_libs = () # type: T.Tuple[str, ...] internal_libs = [] # type: T.List[str]
LINKER_PREFIX = None # type: T.Union[None, str, T.List[str]] LINKER_PREFIX = None # type: T.Union[None, str, T.List[str]]
INVOKES_LINKER = True INVOKES_LINKER = True
@ -518,18 +518,18 @@ class Compiler(metaclass=abc.ABCMeta):
raise EnvironmentException('%s does not support get_define ' % self.get_id()) raise EnvironmentException('%s does not support get_define ' % self.get_id())
def compute_int(self, expression: str, low: T.Optional[int], high: T.Optional[int], def compute_int(self, expression: str, low: T.Optional[int], high: T.Optional[int],
guess: T.Optional[int], prefix: str, env: 'Environment', guess: T.Optional[int], prefix: str, env: 'Environment', *,
extra_args: T.List[str], dependencies: T.List['Dependency']) -> int: extra_args: T.Optional[T.List[str]], dependencies: T.Optional[T.List['Dependency']]) -> int:
raise EnvironmentException('%s does not support compute_int ' % self.get_id()) raise EnvironmentException('%s does not support compute_int ' % self.get_id())
def compute_parameters_with_absolute_paths(self, parameter_list: T.List[str], def compute_parameters_with_absolute_paths(self, parameter_list: T.List[str],
build_dir: str) -> T.List[str]: build_dir: str) -> T.List[str]:
raise EnvironmentException('%s does not support compute_parameters_with_absolute_paths ' % self.get_id()) raise EnvironmentException('%s does not support compute_parameters_with_absolute_paths ' % self.get_id())
def has_members(self, typename: str, membernames: T.Iterable[str], def has_members(self, typename: str, membernames: T.List[str],
prefix: str, env: 'Environment', *, prefix: str, env: 'Environment', *,
extra_args: T.Optional[T.Iterable[str]] = None, extra_args: T.Optional[T.List[str]] = None,
dependencies: T.Optional[T.Iterable['Dependency']] = None) -> T.Tuple[bool, bool]: dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[bool, bool]:
raise EnvironmentException('%s does not support has_member(s) ' % self.get_id()) raise EnvironmentException('%s does not support has_member(s) ' % self.get_id())
def has_type(self, typename: str, prefix: str, env: 'Environment', def has_type(self, typename: str, prefix: str, env: 'Environment',
@ -662,8 +662,8 @@ class Compiler(metaclass=abc.ABCMeta):
raise EnvironmentException('Language %s does not support alignment checks.' % self.get_display_language()) raise EnvironmentException('Language %s does not support alignment checks.' % self.get_display_language())
def has_function(self, funcname: str, prefix: str, env: 'Environment', *, def has_function(self, funcname: str, prefix: str, env: 'Environment', *,
extra_args: T.Optional[T.Iterable[str]] = None, extra_args: T.Optional[T.List[str]] = None,
dependencies: T.Optional[T.Iterable['Dependency']] = None) -> T.Tuple[bool, bool]: dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[bool, bool]:
"""See if a function exists. """See if a function exists.
Returns a two item tuple of bools. The first bool is whether the Returns a two item tuple of bools. The first bool is whether the
@ -672,8 +672,7 @@ class Compiler(metaclass=abc.ABCMeta):
""" """
raise EnvironmentException('Language %s does not support function checks.' % self.get_display_language()) raise EnvironmentException('Language %s does not support function checks.' % self.get_display_language())
@classmethod def unix_args_to_native(self, args: T.List[str]) -> T.List[str]:
def unix_args_to_native(cls, args: T.List[str]) -> T.List[str]:
"Always returns a copy that can be independently mutated" "Always returns a copy that can be independently mutated"
return args.copy() return args.copy()
@ -878,7 +877,7 @@ class Compiler(metaclass=abc.ABCMeta):
def get_gui_app_args(self, value: bool) -> T.List[str]: def get_gui_app_args(self, value: bool) -> T.List[str]:
return [] return []
def has_func_attribute(self, name: str, env: 'Environment') -> T.List[str]: def has_func_attribute(self, name: str, env: 'Environment') -> T.Tuple[bool, bool]:
raise EnvironmentException( raise EnvironmentException(
'Language {} does not support function attributes.'.format(self.get_display_language())) 'Language {} does not support function attributes.'.format(self.get_display_language()))

@ -23,8 +23,14 @@ from ..compilers import clike_debug_args
from .clang import clang_color_args from .clang import clang_color_args
if T.TYPE_CHECKING: if T.TYPE_CHECKING:
from ...envconfig import MachineChoice
from ...environment import Environment from ...environment import Environment
from ...compilers.compilers import Compiler
else:
# This is a bit clever, for mypy we pretend that these mixins descend from
# Compiler, so we get all of the methods and attributes defined for us, but
# for runtime we make them descend from object (which all classes normally
# do). This gives up DRYer type checking, with no runtime impact
Compiler = object
arm_buildtype_args = { arm_buildtype_args = {
'plain': [], 'plain': [],
@ -63,14 +69,10 @@ armclang_optimization_args = {
} # type: T.Dict[str, T.List[str]] } # type: T.Dict[str, T.List[str]]
class ArmCompiler: class ArmCompiler(Compiler):
"""Functionality that is common to all ARM family compilers.""" """Functionality that is common to all ARM family compilers."""
if T.TYPE_CHECKING:
is_cross = True
can_compile_suffixes = set() # type: T.Set[str]
def __init__(self) -> None: def __init__(self) -> None:
if not self.is_cross: if not self.is_cross:
raise mesonlib.EnvironmentException('armcc supports only cross-compilation.') raise mesonlib.EnvironmentException('armcc supports only cross-compilation.')
@ -133,15 +135,7 @@ class ArmCompiler:
return parameter_list return parameter_list
class ArmclangCompiler: class ArmclangCompiler(Compiler):
if T.TYPE_CHECKING:
can_compile_suffixes = set() # type: T.Set[str]
is_cross = True
version = '0'
linker = ArmClangDynamicLinker(MachineChoice.HOST, version='1.2.3')
def get_pch_name(self, name: str) -> str: ...
def __init__(self) -> None: def __init__(self) -> None:
if not self.is_cross: if not self.is_cross:

@ -21,6 +21,13 @@ from ...mesonlib import EnvironmentException
if T.TYPE_CHECKING: if T.TYPE_CHECKING:
from ...environment import Environment from ...environment import Environment
from ...compilers.compilers import Compiler
else:
# This is a bit clever, for mypy we pretend that these mixins descend from
# Compiler, so we get all of the methods and attributes defined for us, but
# for runtime we make them descend from object (which all classes normally
# do). This gives up DRYer type checking, with no runtime impact
Compiler = object
c2000_buildtype_args = { c2000_buildtype_args = {
'plain': [], 'plain': [],
@ -46,11 +53,7 @@ c2000_debug_args = {
} # type: T.Dict[bool, T.List[str]] } # type: T.Dict[bool, T.List[str]]
class C2000Compiler: class C2000Compiler(Compiler):
if T.TYPE_CHECKING:
is_cross = True
can_compile_suffixes = set() # type: T.Set[str]
def __init__(self) -> None: def __init__(self) -> None:
if not self.is_cross: if not self.is_cross:

@ -21,6 +21,13 @@ from ...mesonlib import EnvironmentException
if T.TYPE_CHECKING: if T.TYPE_CHECKING:
from ...environment import Environment from ...environment import Environment
from ...compilers.compilers import Compiler
else:
# This is a bit clever, for mypy we pretend that these mixins descend from
# Compiler, so we get all of the methods and attributes defined for us, but
# for runtime we make them descend from object (which all classes normally
# do). This gives up DRYer type checking, with no runtime impact
Compiler = object
ccrx_buildtype_args = { ccrx_buildtype_args = {
'plain': [], 'plain': [],
@ -46,7 +53,7 @@ ccrx_debug_args = {
} # type: T.Dict[bool, T.List[str]] } # type: T.Dict[bool, T.List[str]]
class CcrxCompiler: class CcrxCompiler(Compiler):
if T.TYPE_CHECKING: if T.TYPE_CHECKING:
is_cross = True is_cross = True

@ -23,10 +23,8 @@ from ...linkers import AppleDynamicLinker
from .gnu import GnuLikeCompiler from .gnu import GnuLikeCompiler
if T.TYPE_CHECKING: if T.TYPE_CHECKING:
from ...envconfig import MachineChoice
from ...environment import Environment from ...environment import Environment
from ...dependencies import Dependency # noqa: F401 from ...dependencies import Dependency # noqa: F401
from ...linkers import AppleDynamicLinker
clang_color_args = { clang_color_args = {
'auto': ['-Xclang', '-fcolor-diagnostics'], 'auto': ['-Xclang', '-fcolor-diagnostics'],
@ -45,11 +43,6 @@ clang_optimization_args = {
class ClangCompiler(GnuLikeCompiler): class ClangCompiler(GnuLikeCompiler):
if T.TYPE_CHECKING:
linker = AppleDynamicLinker([], MachineChoice.HOST, '', [])
def get_pch_name(self, name: str) -> str: ...
def __init__(self, defines: T.Optional[T.Dict[str, str]]): def __init__(self, defines: T.Optional[T.Dict[str, str]]):
super().__init__() super().__init__()
self.id = 'clang' self.id = 'clang'
@ -83,14 +76,11 @@ class ClangCompiler(GnuLikeCompiler):
# so it might change semantics at any time. # so it might change semantics at any time.
return ['-include-pch', os.path.join(pch_dir, self.get_pch_name(header))] return ['-include-pch', os.path.join(pch_dir, self.get_pch_name(header))]
def has_multi_arguments(self, args: T.List[str], env: 'Environment') -> T.List[str]: def has_multi_arguments(self, args: T.List[str], env: 'Environment') -> T.Tuple[bool, bool]:
myargs = ['-Werror=unknown-warning-option', '-Werror=unused-command-line-argument'] myargs = ['-Werror=unknown-warning-option', '-Werror=unused-command-line-argument']
if mesonlib.version_compare(self.version, '>=3.6.0'): if mesonlib.version_compare(self.version, '>=3.6.0'):
myargs.append('-Werror=ignored-optimization-argument') myargs.append('-Werror=ignored-optimization-argument')
# Mypy doesn't understand co-coperative inheritance return super().has_multi_arguments(myargs + args, env)
return super().has_multi_arguments( # type: ignore
myargs + args,
env)
def has_function(self, funcname: str, prefix: str, env: 'Environment', *, def has_function(self, funcname: str, prefix: str, env: 'Environment', *,
extra_args: T.Optional[T.List[str]] = None, extra_args: T.Optional[T.List[str]] = None,
@ -104,10 +94,8 @@ class ClangCompiler(GnuLikeCompiler):
# TODO: this really should be communicated by the linker # TODO: this really should be communicated by the linker
if isinstance(self.linker, AppleDynamicLinker) and mesonlib.version_compare(self.version, '>=8.0'): if isinstance(self.linker, AppleDynamicLinker) and mesonlib.version_compare(self.version, '>=8.0'):
extra_args.append('-Wl,-no_weak_imports') extra_args.append('-Wl,-no_weak_imports')
# Mypy doesn't understand co-coperative inheritance return super().has_function(funcname, prefix, env, extra_args=extra_args,
ret = super().has_function(funcname, prefix, env, extra_args=extra_args, # type: ignore
dependencies=dependencies) dependencies=dependencies)
return T.cast(T.Tuple[bool, bool], ret)
def openmp_flags(self) -> T.List[str]: def openmp_flags(self) -> T.List[str]:
if mesonlib.version_compare(self.version, '>=3.8.0'): if mesonlib.version_compare(self.version, '>=3.8.0'):

@ -40,10 +40,15 @@ from .. import compilers
from .visualstudio import VisualStudioLikeCompiler from .visualstudio import VisualStudioLikeCompiler
if T.TYPE_CHECKING: if T.TYPE_CHECKING:
from ...coredata import CoreData
from ...dependencies import Dependency, ExternalProgram from ...dependencies import Dependency, ExternalProgram
from ...environment import Environment from ...environment import Environment
from ...linkers import DynamicLinker from ...compilers.compilers import Compiler
else:
# This is a bit clever, for mypy we pretend that these mixins descend from
# Compiler, so we get all of the methods and attributes defined for us, but
# for runtime we make them descend from object (which all classes normally
# do). This gives up DRYer type checking, with no runtime impact
Compiler = object
GROUP_FLAGS = re.compile(r'''\.so (?:\.[0-9]+)? (?:\.[0-9]+)? (?:\.[0-9]+)?$ | GROUP_FLAGS = re.compile(r'''\.so (?:\.[0-9]+)? (?:\.[0-9]+)? (?:\.[0-9]+)?$ |
^(?:-Wl,)?-l | ^(?:-Wl,)?-l |
@ -115,46 +120,13 @@ class CLikeCompilerArgs(arglist.CompilerArgs):
return 'CLikeCompilerArgs({!r}, {!r})'.format(self.compiler, self._container) return 'CLikeCompilerArgs({!r}, {!r})'.format(self.compiler, self._container)
class CLikeCompiler: class CLikeCompiler(Compiler):
"""Shared bits for the C and CPP Compilers.""" """Shared bits for the C and CPP Compilers."""
if T.TYPE_CHECKING: if T.TYPE_CHECKING:
can_compile_suffixes = set() # type: T.Set[str]
exelist = [] # type: T.List[str]
for_machine = mesonlib.MachineChoice.HOST
id = ''
ignore_libs = () # type: T.Tuple[str, ...]
language = ''
linker = SolarisDynamicLinker([], mesonlib.MachineChoice.HOST, [], []) # type: DynamicLinker
warn_args = {} # type: T.Dict[str, T.List[str]] warn_args = {} # type: T.Dict[str, T.List[str]]
@staticmethod
def attribute_check_func(name: str) -> str:...
def get_allow_undefined_link_args(self) -> T.List[str]: ...
def get_compiler_args_for_mode(self, mode: str) -> T.List[str]: ...
def get_display_language(self) -> str: ...
def get_largefile_args(self) -> T.List[str]: ...
def get_linker_always_args(self) -> T.List[str]: ...
def get_pch_suffix(self) -> str: ...
def get_id(self) -> str: ...
def name_string(self) -> str: ...
def remove_linkerlike_args(self, args: T.List[str]) -> T.List[str]: ...
@classmethod
def use_linker_args(cls, linker: str) -> T.List[str]: ...
@contextlib.contextmanager
def compile(self, code: 'mesonlib.FileOrString',
extra_args: T.Union[None, arglist.CompilerArgs, T.List[str]] = None,
*, mode: str = 'link', want_output: bool = False,
temp_dir: T.Optional[str] = None) -> T.Iterator[T.Optional[compilers.CompileResult]]: ...
@contextlib.contextmanager
def cached_compile(self, code: str, cdata: 'CoreData', *,
extra_args: T.Union[None, arglist.CompilerArgs, T.List[str]] = None,
mode: str = 'link',
temp_dir: T.Optional[str] = None) -> T.Iterator[T.Optional[compilers.CompileResult]]: ...
# TODO: Replace this manual cache with functools.lru_cache # TODO: Replace this manual cache with functools.lru_cache
find_library_cache = {} # type: T.Dict[T.Tuple[T.Tuple[str, ...], str, T.Tuple[str, ...], str, LibType], T.Optional[T.List[str]]] find_library_cache = {} # type: T.Dict[T.Tuple[T.Tuple[str, ...], str, T.Tuple[str, ...], str, LibType], T.Optional[T.List[str]]]
find_framework_cache = {} # type: T.Dict[T.Tuple[T.Tuple[str, ...], str, T.Tuple[str, ...], bool], T.Optional[T.List[str]]] find_framework_cache = {} # type: T.Dict[T.Tuple[T.Tuple[str, ...], str, T.Tuple[str, ...], bool], T.Optional[T.List[str]]]
@ -170,9 +142,9 @@ class CLikeCompiler:
else: else:
self.exe_wrapper = exe_wrapper.get_command() self.exe_wrapper = exe_wrapper.get_command()
def compiler_args(self, args: T.Optional[T.List[str]] = None) -> CLikeCompilerArgs: def compiler_args(self, args: T.Optional[T.Iterable[str]] = None) -> CLikeCompilerArgs:
# This is correct, mypy just doesn't understand co-operative inheritance # This is correct, mypy just doesn't understand co-operative inheritance
return CLikeCompilerArgs(self, args) # type: ignore return CLikeCompilerArgs(self, args)
def needs_static_linker(self) -> bool: def needs_static_linker(self) -> bool:
return True # When compiling static libraries, so yes. return True # When compiling static libraries, so yes.
@ -296,13 +268,16 @@ class CLikeCompiler:
return self._get_library_dirs(env, elf_class).copy() return self._get_library_dirs(env, elf_class).copy()
@functools.lru_cache() @functools.lru_cache()
def get_program_dirs(self, env: 'Environment') -> T.List[str]: def _get_program_dirs(self, env: 'Environment') -> T.List[str]:
''' '''
Programs used by the compiler. Also where toolchain DLLs such as Programs used by the compiler. Also where toolchain DLLs such as
libstdc++-6.dll are found with MinGW. libstdc++-6.dll are found with MinGW.
''' '''
return self.get_compiler_dirs(env, 'programs') return self.get_compiler_dirs(env, 'programs')
def get_program_dirs(self, env: 'Environment') -> T.List[str]:
return self._get_program_dirs(env).copy()
def get_pic_args(self) -> T.List[str]: def get_pic_args(self) -> T.List[str]:
return ['-fPIC'] return ['-fPIC']
@ -506,7 +481,7 @@ class CLikeCompiler:
return args return args
def compiles(self, code: str, env: 'Environment', *, def compiles(self, code: str, env: 'Environment', *,
extra_args: T.Optional[T.List[str]] = None, extra_args: T.Union[None, T.List[str], arglist.CompilerArgs] = None,
dependencies: T.Optional[T.List['Dependency']] = None, dependencies: T.Optional[T.List['Dependency']] = None,
mode: str = 'compile', mode: str = 'compile',
disable_cache: bool = False) -> T.Tuple[bool, bool]: disable_cache: bool = False) -> T.Tuple[bool, bool]:
@ -529,7 +504,7 @@ class CLikeCompiler:
yield r yield r
def links(self, code: str, env: 'Environment', *, def links(self, code: str, env: 'Environment', *,
extra_args: T.Optional[T.List[str]] = None, extra_args: T.Union[None, T.List[str], arglist.CompilerArgs] = None,
dependencies: T.Optional[T.List['Dependency']] = None, dependencies: T.Optional[T.List['Dependency']] = None,
mode: str = 'compile', mode: str = 'compile',
disable_cache: bool = False) -> T.Tuple[bool, bool]: disable_cache: bool = False) -> T.Tuple[bool, bool]:

@ -20,6 +20,13 @@ import typing as T
if T.TYPE_CHECKING: if T.TYPE_CHECKING:
from ...environment import Environment from ...environment import Environment
from ...compilers.compilers import Compiler
else:
# This is a bit clever, for mypy we pretend that these mixins descend from
# Compiler, so we get all of the methods and attributes defined for us, but
# for runtime we make them descend from object (which all classes normally
# do). This gives up DRYer type checking, with no runtime impact
Compiler = object
ccomp_buildtype_args = { ccomp_buildtype_args = {
'plain': [''], 'plain': [''],
@ -51,10 +58,7 @@ ccomp_args_to_wul = [
r"^-r$" r"^-r$"
] # type: T.List[str] ] # type: T.List[str]
class CompCertCompiler: class CompCertCompiler(Compiler):
if T.TYPE_CHECKING:
can_compile_suffixes = set() # type: T.Set[str]
def __init__(self) -> None: def __init__(self) -> None:
self.id = 'ccomp' self.id = 'ccomp'

@ -31,9 +31,6 @@ class ElbrusCompiler(GnuLikeCompiler):
# Elbrus compiler is nearly like GCC, but does not support # Elbrus compiler is nearly like GCC, but does not support
# PCH, LTO, sanitizers and color output as of version 1.21.x. # PCH, LTO, sanitizers and color output as of version 1.21.x.
if T.TYPE_CHECKING:
exelist = [] # type: T.List[str]
def __init__(self) -> None: def __init__(self) -> None:
super().__init__() super().__init__()
self.id = 'lcc' self.id = 'lcc'

@ -20,15 +20,17 @@ import typing as T
from ... import coredata from ... import coredata
if T.TYPE_CHECKING: if T.TYPE_CHECKING:
from ...envconfig import MachineChoice
from ...environment import Environment from ...environment import Environment
from ...compilers.compilers import Compiler
else:
# This is a bit clever, for mypy we pretend that these mixins descend from
# Compiler, so we get all of the methods and attributes defined for us, but
# for runtime we make them descend from object (which all classes normally
# do). This gives up DRYer type checking, with no runtime impact
Compiler = object
class EmscriptenMixin: class EmscriptenMixin(Compiler):
if T.TYPE_CHECKING:
for_machine = MachineChoice.HOST
language = ''
def _get_compile_output(self, dirname: str, mode: str) -> str: def _get_compile_output(self, dirname: str, mode: str) -> str:
# In pre-processor mode, the output is sent to stdout and discarded # In pre-processor mode, the output is sent to stdout and discarded
@ -54,9 +56,7 @@ class EmscriptenMixin:
return args return args
def get_options(self) -> 'coredata.OptionDictType': def get_options(self) -> 'coredata.OptionDictType':
# Mypy and co-operative inheritance opts = super().get_options()
_opts = super().get_options() # type: ignore
opts = T.cast('coredata.OptionDictType', _opts)
opts.update({ opts.update({
'{}_thread_count'.format(self.language): coredata.UserIntegerOption( '{}_thread_count'.format(self.language): coredata.UserIntegerOption(
'Number of threads to use in web assembly, set to 0 to disable', 'Number of threads to use in web assembly, set to 0 to disable',

@ -26,14 +26,14 @@ from ... import mesonlib
from ... import mlog from ... import mlog
if T.TYPE_CHECKING: if T.TYPE_CHECKING:
import contextlib
from .. import compilers
from ... import arglist
from ...coredata import UserOption # noqa: F401
from ...dependency import Dependency
from ...envconfig import MachineInfo
from ...environment import Environment from ...environment import Environment
from .clike import CLikeCompiler as Compiler
else:
# This is a bit clever, for mypy we pretend that these mixins descend from
# Compiler, so we get all of the methods and attributes defined for us, but
# for runtime we make them descend from object (which all classes normally
# do). This gives up DRYer type checking, with no runtime impact
Compiler = object
# XXX: prevent circular references. # XXX: prevent circular references.
# FIXME: this really is a posix interface not a c-like interface # FIXME: this really is a posix interface not a c-like interface
@ -135,7 +135,7 @@ def gnulike_default_include_dirs(compiler: T.Tuple[str], lang: str) -> T.List[st
return paths return paths
class GnuLikeCompiler(metaclass=abc.ABCMeta): class GnuLikeCompiler(Compiler, metaclass=abc.ABCMeta):
""" """
GnuLikeCompiler is a common interface to all compilers implementing GnuLikeCompiler is a common interface to all compilers implementing
the GNU-style commandline interface. This includes GCC, Clang the GNU-style commandline interface. This includes GCC, Clang
@ -143,21 +143,6 @@ class GnuLikeCompiler(metaclass=abc.ABCMeta):
that the actual concrete subclass define their own implementation. that the actual concrete subclass define their own implementation.
""" """
if T.TYPE_CHECKING:
can_compile_suffixes = set() # type: T.Set[str]
exelist = [] # type: T.List[str]
info = MachineInfo('', '', '', '')
language = ''
version = ''
@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]]: ...
LINKER_PREFIX = '-Wl,' LINKER_PREFIX = '-Wl,'
def __init__(self) -> None: def __init__(self) -> None:
@ -354,8 +339,7 @@ class GnuCompiler(GnuLikeCompiler):
def get_warn_args(self, level: str) -> T.List[str]: def get_warn_args(self, level: str) -> T.List[str]:
# Mypy doesn't understand cooperative inheritance # Mypy doesn't understand cooperative inheritance
_args = super().get_warn_args(level) # type: ignore args = super().get_warn_args(level)
args = T.cast(T.List[str], _args)
if mesonlib.version_compare(self.version, '<4.8.0') and '-Wpedantic' in args: if mesonlib.version_compare(self.version, '<4.8.0') and '-Wpedantic' in args:
# -Wpedantic was added in 4.8.0 # -Wpedantic was added in 4.8.0
# https://gcc.gnu.org/gcc-4.8/changes.html # https://gcc.gnu.org/gcc-4.8/changes.html

@ -28,8 +28,6 @@ from .gnu import GnuLikeCompiler
from .visualstudio import VisualStudioLikeCompiler from .visualstudio import VisualStudioLikeCompiler
if T.TYPE_CHECKING: if T.TYPE_CHECKING:
import subprocess # noqa: F401
from ...arglist import CompilerArgs from ...arglist import CompilerArgs
from ...dependencies import Dependency from ...dependencies import Dependency
from ...environment import Environment from ...environment import Environment
@ -115,8 +113,7 @@ class IntelGnuLikeCompiler(GnuLikeCompiler):
'-diag-error', '10157', # Ignoring argument of the wrong type '-diag-error', '10157', # Ignoring argument of the wrong type
'-diag-error', '10158', # Argument must be separate. Can be hit by trying an option like -foo-bar=foo when -foo=bar is a valid option but -foo-bar isn't '-diag-error', '10158', # Argument must be separate. Can be hit by trying an option like -foo-bar=foo when -foo=bar is a valid option but -foo-bar isn't
] ]
ret = super().compiles(code, env, extra_args=extra_args, dependencies=dependencies, mode=mode, disable_cache=disable_cache) # type: ignore return super().compiles(code, env, extra_args=extra_args, dependencies=dependencies, mode=mode, disable_cache=disable_cache)
return T.cast(T.Tuple[bool, bool], ret)
def get_profile_generate_args(self) -> T.List[str]: def get_profile_generate_args(self) -> T.List[str]:
return ['-prof-gen=threadsafe'] return ['-prof-gen=threadsafe']
@ -176,8 +173,7 @@ class IntelVisualStudioLikeCompiler(VisualStudioLikeCompiler):
'/Qdiag-error:10157', # Ignoring argument of the wrong type '/Qdiag-error:10157', # Ignoring argument of the wrong type
'/Qdiag-error:10158', # Argument must be separate. Can be hit by trying an option like -foo-bar=foo when -foo=bar is a valid option but -foo-bar isn't '/Qdiag-error:10158', # Argument must be separate. Can be hit by trying an option like -foo-bar=foo when -foo=bar is a valid option but -foo-bar isn't
]) ])
ret = super().compiles(code, env, extra_args=extra_args, dependencies=dependencies, mode=mode, disable_cache=disable_cache) # type: ignore return super().compiles(code, env, extra_args=extra_args, dependencies=dependencies, mode=mode, disable_cache=disable_cache)
return T.cast(T.Tuple[bool, bool], ret)
def get_toolset_version(self) -> T.Optional[str]: def get_toolset_version(self) -> T.Optional[str]:
# Avoid circular dependencies.... # Avoid circular dependencies....

@ -27,9 +27,16 @@ from ... import mesonlib
if T.TYPE_CHECKING: if T.TYPE_CHECKING:
from ...coredata import OptionDictType from ...coredata import OptionDictType
from ...environment import Environment from ...environment import Environment
from ...compilers.compilers import Compiler
else:
# This is a bit clever, for mypy we pretend that these mixins descend from
# Compiler, so we get all of the methods and attributes defined for us, but
# for runtime we make them descend from object (which all classes normally
# do). This gives up DRYer type checking, with no runtime impact
Compiler = object
class BasicLinkerIsCompilerMixin: class BasicLinkerIsCompilerMixin(Compiler):
"""Provides a baseline of methods that a linker would implement. """Provides a baseline of methods that a linker would implement.
@ -38,10 +45,6 @@ class BasicLinkerIsCompilerMixin:
functionality itself. functionality itself.
""" """
if T.TYPE_CHECKING:
exelist = [] # type: T.List[str]
id = ''
def sanitizer_link_args(self, value: str) -> T.List[str]: def sanitizer_link_args(self, value: str) -> T.List[str]:
return [] return []
@ -103,8 +106,8 @@ class BasicLinkerIsCompilerMixin:
def bitcode_args(self) -> T.List[str]: def bitcode_args(self) -> T.List[str]:
raise mesonlib.MesonException("This linker doesn't support bitcode bundles") raise mesonlib.MesonException("This linker doesn't support bitcode bundles")
def get_soname_args(self, for_machine: 'mesonlib.MachineChoice', def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str,
prefix: str, shlib_name: str, suffix: str, soversion: str, suffix: str, soversion: str,
darwin_versions: T.Tuple[str, str], darwin_versions: T.Tuple[str, str],
is_shared_module: bool) -> T.List[str]: is_shared_module: bool) -> T.List[str]:
raise mesonlib.MesonException("This linker doesn't support soname args") raise mesonlib.MesonException("This linker doesn't support soname args")

@ -21,8 +21,14 @@ from pathlib import Path
from ..compilers import clike_debug_args, clike_optimization_args from ..compilers import clike_debug_args, clike_optimization_args
if T.TYPE_CHECKING: if T.TYPE_CHECKING:
from ...envconfig import MachineInfo
from ...environment import Environment from ...environment import Environment
from ...compilers.compilers import Compiler
else:
# This is a bit clever, for mypy we pretend that these mixins descend from
# Compiler, so we get all of the methods and attributes defined for us, but
# for runtime we make them descend from object (which all classes normally
# do). This gives up DRYer type checking, with no runtime impact
Compiler = object
pgi_buildtype_args = { pgi_buildtype_args = {
'plain': [], 'plain': [],
@ -34,11 +40,7 @@ pgi_buildtype_args = {
} # type: T.Dict[str, T.List[str]] } # type: T.Dict[str, T.List[str]]
class PGICompiler: class PGICompiler(Compiler):
if T.TYPE_CHECKING:
info = MachineInfo('', '', '', '')
language = ''
def __init__(self) -> None: def __init__(self) -> None:
self.base_options = ['b_pch'] self.base_options = ['b_pch']

@ -20,18 +20,19 @@ import abc
import os import os
import typing as T import typing as T
from ... import arglist
from ... import mesonlib from ... import mesonlib
from ... import mlog from ... import mlog
if T.TYPE_CHECKING: if T.TYPE_CHECKING:
from contextlib import contextmanager
from ...arglist import CompilerArgs
from ...compilers.compilers import CompileResult
from ...dependencies import Dependency
from ...envconfig import MachineChoice
from ...environment import Environment from ...environment import Environment
from ...linkers import MSVCDynamicLinker from .clike import CLikeCompiler as Compiler
else:
# This is a bit clever, for mypy we pretend that these mixins descend from
# Compiler, so we get all of the methods and attributes defined for us, but
# for runtime we make them descend from object (which all classes normally
# do). This gives up DRYer type checking, with no runtime impact
Compiler = object
vs32_instruction_set_args = { vs32_instruction_set_args = {
'mmx': ['/arch:SSE'], # There does not seem to be a flag just for MMX 'mmx': ['/arch:SSE'], # There does not seem to be a flag just for MMX
@ -92,7 +93,7 @@ msvc_debug_args = {
} # type: T.Dict[bool, T.List[str]] } # type: T.Dict[bool, T.List[str]]
class VisualStudioLikeCompiler(metaclass=abc.ABCMeta): class VisualStudioLikeCompiler(Compiler, metaclass=abc.ABCMeta):
"""A common interface for all compilers implementing an MSVC-style """A common interface for all compilers implementing an MSVC-style
interface. interface.
@ -102,24 +103,10 @@ class VisualStudioLikeCompiler(metaclass=abc.ABCMeta):
This class implements as much common logic as possible. This class implements as much common logic as possible.
""" """
if T.TYPE_CHECKING:
linker = MSVCDynamicLinker(MachineChoice.HOST, [])
version = ''
@contextmanager # yes, yes, it's a half truth.
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]]: ...
std_warn_args = ['/W3'] std_warn_args = ['/W3']
std_opt_args = ['/O2'] std_opt_args = ['/O2']
# XXX: this is copied in this patch only to avoid circular dependencies ignore_libs = arglist.UNIXY_COMPILER_INTERNAL_LIBS + ['execinfo']
#ignore_libs = unixy_compiler_internal_libs internal_libs = [] # type: T.List[str]
ignore_libs = ('m', 'c', 'pthread', 'dl', 'rt', 'execinfo')
internal_libs = ()
crt_args = { crt_args = {
'none': [], 'none': [],
@ -156,6 +143,7 @@ class VisualStudioLikeCompiler(metaclass=abc.ABCMeta):
self.machine = 'arm' self.machine = 'arm'
else: else:
self.machine = target self.machine = target
assert self.linker is not None
self.linker.machine = self.machine self.linker.machine = self.machine
# Override CCompiler.get_always_args # Override CCompiler.get_always_args

@ -21,6 +21,13 @@ from ...mesonlib import EnvironmentException
if T.TYPE_CHECKING: if T.TYPE_CHECKING:
from ...environment import Environment from ...environment import Environment
from ...compilers.compilers import Compiler
else:
# This is a bit clever, for mypy we pretend that these mixins descend from
# Compiler, so we get all of the methods and attributes defined for us, but
# for runtime we make them descend from object (which all classes normally
# do). This gives up DRYer type checking, with no runtime impact
Compiler = object
xc16_buildtype_args = { xc16_buildtype_args = {
'plain': [], 'plain': [],
@ -46,11 +53,7 @@ xc16_debug_args = {
} # type: T.Dict[bool, T.List[str]] } # type: T.Dict[bool, T.List[str]]
class Xc16Compiler: class Xc16Compiler(Compiler):
if T.TYPE_CHECKING:
can_compile_suffixes = set() # type: T.Set[str]
is_cross = True
def __init__(self) -> None: def __init__(self) -> None:
if not self.is_cross: if not self.is_cross:

@ -351,6 +351,7 @@ class DynamicLinker(LinkerEnvVarsMixin, metaclass=abc.ABCMeta):
self.version = version self.version = version
self.prefix_arg = prefix_arg self.prefix_arg = prefix_arg
self.always_args = always_args self.always_args = always_args
self.machine = None # type: T.Optional[str]
def __repr__(self) -> str: def __repr__(self) -> str:
return '<{}: v{} `{}`>'.format(type(self).__name__, self.version, ' '.join(self.exelist)) return '<{}: v{} `{}`>'.format(type(self).__name__, self.version, ' '.join(self.exelist))

Loading…
Cancel
Save