aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.pylintrc12
-rw-r--r--mesonbuild/ast/introspection.py15
-rw-r--r--mesonbuild/backend/ninjabackend.py7
-rw-r--r--mesonbuild/build.py8
-rw-r--r--mesonbuild/compilers/c.py6
-rw-r--r--mesonbuild/compilers/compilers.py534
-rw-r--r--mesonbuild/compilers/cpp.py6
-rw-r--r--mesonbuild/compilers/cs.py4
-rw-r--r--mesonbuild/compilers/cuda.py7
-rw-r--r--mesonbuild/compilers/d.py29
-rw-r--r--mesonbuild/compilers/fortran.py8
-rw-r--r--mesonbuild/compilers/java.py4
-rw-r--r--mesonbuild/compilers/mixins/arm.py48
-rw-r--r--mesonbuild/compilers/mixins/c2000.py12
-rw-r--r--mesonbuild/compilers/mixins/ccrx.py16
-rw-r--r--mesonbuild/compilers/mixins/clang.py13
-rw-r--r--mesonbuild/compilers/mixins/clike.py340
-rw-r--r--mesonbuild/compilers/mixins/compcert.py14
-rw-r--r--mesonbuild/compilers/mixins/elbrus.py3
-rw-r--r--mesonbuild/compilers/mixins/emscripten.py15
-rw-r--r--mesonbuild/compilers/mixins/gnu.py38
-rw-r--r--mesonbuild/compilers/mixins/intel.py35
-rw-r--r--mesonbuild/compilers/mixins/islinker.py13
-rw-r--r--mesonbuild/compilers/mixins/pgi.py17
-rw-r--r--mesonbuild/compilers/mixins/visualstudio.py23
-rw-r--r--mesonbuild/compilers/mixins/xc16.py14
-rw-r--r--mesonbuild/compilers/objc.py43
-rw-r--r--mesonbuild/compilers/objcpp.py46
-rw-r--r--mesonbuild/compilers/rust.py11
-rw-r--r--mesonbuild/compilers/swift.py8
-rw-r--r--mesonbuild/compilers/vala.py8
-rw-r--r--mesonbuild/coredata.py7
-rw-r--r--mesonbuild/dependencies/scalapack.py8
-rw-r--r--mesonbuild/environment.py9
-rw-r--r--mesonbuild/linkers.py1
-rw-r--r--mesonbuild/mesonlib.py4
-rw-r--r--mesonbuild/minstall.py2
-rw-r--r--mesonbuild/modules/qt.py46
-rw-r--r--mesonbuild/optinterpreter.py2
-rwxr-xr-xrun_mypy.py6
-rwxr-xr-xrun_tests.py2
-rwxr-xr-xrun_unittests.py4
42 files changed, 898 insertions, 550 deletions
diff --git a/.pylintrc b/.pylintrc
index c79b83c..41adf61 100644
--- a/.pylintrc
+++ b/.pylintrc
@@ -7,9 +7,19 @@ score=no
[MESSAGES CONTROL]
disable=all
enable=
+ abstract-class-instantiated,
assert-on-tuple,
+ bad-indentation,
+ compare-to-zero,
dangerous-default-value,
deprecated-lambda,
- compare-to-zero,
len-as-condition,
+ literal-comparison,
+ missing-kwoa,
+ mixed-indentation,
+ no-value-for-parameter,
+ redundant-keyword-arg,
+ singleton-comparison,
+ too-many-function-args,
+ unexpected-keyword-arg,
unreachable
diff --git a/mesonbuild/ast/introspection.py b/mesonbuild/ast/introspection.py
index f03f7d2..9cfdded 100644
--- a/mesonbuild/ast/introspection.py
+++ b/mesonbuild/ast/introspection.py
@@ -151,14 +151,15 @@ class IntrospectionInterpreter(AstInterpreter):
for for_machine in [MachineChoice.BUILD, MachineChoice.HOST]:
self._add_languages(args, for_machine)
- def _add_languages(self, langs: T.List[TYPE_nvar], for_machine: MachineChoice) -> None:
- langs = self.flatten_args(langs)
+ def _add_languages(self, raw_langs: T.List[TYPE_nvar], for_machine: MachineChoice) -> None:
+ langs = [] # type: T.List[str]
+ for l in self.flatten_args(raw_langs):
+ if isinstance(l, str):
+ langs.append(l)
+ elif isinstance(l, StringNode):
+ langs.append(l.value)
+
for lang in sorted(langs, key=compilers.sort_clink):
- if isinstance(lang, StringNode):
- assert isinstance(lang.value, str)
- lang = lang.value
- if not isinstance(lang, str):
- continue
lang = lang.lower()
if lang not in self.coredata.compilers[for_machine]:
self.environment.detect_compiler_for(lang, for_machine)
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
index 66fc464..f89b917 100644
--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -2647,10 +2647,10 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485'''))
guessed_dependencies = []
# TODO The get_library_naming requirement currently excludes link targets that use d or fortran as their main linker
- if hasattr(linker, 'get_library_naming'):
- search_dirs = tuple(search_dirs) + tuple(linker.get_library_dirs(self.environment))
+ try:
static_patterns = linker.get_library_naming(self.environment, LibType.STATIC, strict=True)
shared_patterns = linker.get_library_naming(self.environment, LibType.SHARED, strict=True)
+ search_dirs = tuple(search_dirs) + tuple(linker.get_library_dirs(self.environment))
for libname in libs:
# be conservative and record most likely shared and static resolution, because we don't know exactly
# which one the linker will prefer
@@ -2662,6 +2662,9 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485'''))
guessed_dependencies.append(staticlibs.resolve().as_posix())
if sharedlibs:
guessed_dependencies.append(sharedlibs.resolve().as_posix())
+ except (mesonlib.MesonException, AttributeError) as e:
+ if 'get_library_naming' not in str(e):
+ raise
return guessed_dependencies + absolute_libs
diff --git a/mesonbuild/build.py b/mesonbuild/build.py
index 30fa77a..be97634 100644
--- a/mesonbuild/build.py
+++ b/mesonbuild/build.py
@@ -462,10 +462,10 @@ a hard error in the future.'''.format(name))
for k, v in option_overrides.items():
if '_' in k:
- lang, k2 = k.split('_', 1)
- if lang in all_languages:
- self.option_overrides_compiler[lang][k2] = v
- continue
+ lang, k2 = k.split('_', 1)
+ if lang in all_languages:
+ self.option_overrides_compiler[lang][k2] = v
+ continue
self.option_overrides_base[k] = v
def parse_overrides(self, kwargs) -> dict:
diff --git a/mesonbuild/compilers/c.py b/mesonbuild/compilers/c.py
index 5cfa06c..091a000 100644
--- a/mesonbuild/compilers/c.py
+++ b/mesonbuild/compilers/c.py
@@ -56,15 +56,15 @@ class CCompiler(CLikeCompiler, Compiler):
def __init__(self, exelist, version, for_machine: MachineChoice, is_cross: bool,
info: 'MachineInfo', exe_wrapper: T.Optional[str] = None, **kwargs):
# If a child ObjC or CPP class has already set it, don't set it ourselves
- Compiler.__init__(self, exelist, version, for_machine, info, **kwargs)
- CLikeCompiler.__init__(self, is_cross, exe_wrapper)
+ Compiler.__init__(self, exelist, version, for_machine, info, is_cross=is_cross, **kwargs)
+ CLikeCompiler.__init__(self, exe_wrapper)
def get_no_stdinc_args(self):
return ['-nostdinc']
def sanity_check(self, work_dir, environment):
code = 'int main(void) { int class=0; return class; }\n'
- return self.sanity_check_impl(work_dir, environment, 'sanitycheckc.c', code)
+ return self._sanity_check_impl(work_dir, environment, 'sanitycheckc.c', code)
def has_header_symbol(self, hname, symbol, prefix, env, *, extra_args=None, dependencies=None):
fargs = {'prefix': prefix, 'header': hname, 'symbol': symbol}
diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py
index c4bd7c2..12643b0 100644
--- a/mesonbuild/compilers/compilers.py
+++ b/mesonbuild/compilers/compilers.py
@@ -24,28 +24,32 @@ from .. import mesonlib
from ..linkers import LinkerEnvVarsMixin
from ..mesonlib import (
EnvironmentException, MachineChoice, MesonException,
- Popen_safe, split_args
+ Popen_safe, split_args, LibType
)
from ..envconfig import (
Properties, get_env_var
)
+
from ..arglist import CompilerArgs
if T.TYPE_CHECKING:
+ from ..build import BuildTarget
from ..coredata import OptionDictType
from ..envconfig import MachineInfo
from ..environment import Environment
from ..linkers import DynamicLinker # noqa: F401
+ from ..dependencies import Dependency
CompilerType = T.TypeVar('CompilerType', bound=Compiler)
+ _T = T.TypeVar('_T')
"""This file contains the data files of all compilers Meson knows
about. To support a new compiler, add its information below.
Also add corresponding autodetection code in environment.py."""
-header_suffixes = ('h', 'hh', 'hpp', 'hxx', 'H', 'ipp', 'moc', 'vapi', 'di')
-obj_suffixes = ('o', 'obj', 'res')
-lib_suffixes = ('a', 'lib', 'dll', 'dll.a', 'dylib', 'so')
+header_suffixes = ('h', 'hh', 'hpp', 'hxx', 'H', 'ipp', 'moc', 'vapi', 'di') # type: T.Tuple[str, ...]
+obj_suffixes = ('o', 'obj', 'res') # type: T.Tuple[str, ...]
+lib_suffixes = ('a', 'lib', 'dll', 'dll.a', 'dylib', 'so') # type: T.Tuple[str, ...]
# Mapping of language to suffixes of files that should always be in that language
# This means we can't include .h headers here since they could be C, C++, ObjC, etc.
lang_suffixes = {
@@ -63,26 +67,26 @@ lang_suffixes = {
'cs': ('cs',),
'swift': ('swift',),
'java': ('java',),
-}
+} # type: T.Dict[str, T.Tuple[str, ...]]
all_languages = lang_suffixes.keys()
-cpp_suffixes = lang_suffixes['cpp'] + ('h',)
-c_suffixes = lang_suffixes['c'] + ('h',)
+cpp_suffixes = lang_suffixes['cpp'] + ('h',) # type: T.Tuple[str, ...]
+c_suffixes = lang_suffixes['c'] + ('h',) # type: T.Tuple[str, ...]
# List of languages that by default consume and output libraries following the
# C ABI; these can generally be used interchangebly
-clib_langs = ('objcpp', 'cpp', 'objc', 'c', 'fortran',)
+clib_langs = ('objcpp', 'cpp', 'objc', 'c', 'fortran',) # type: T.Tuple[str, ...]
# List of languages that can be linked with C code directly by the linker
# used in build.py:process_compilers() and build.py:get_dynamic_linker()
-clink_langs = ('d', 'cuda') + clib_langs
-clink_suffixes = ()
+clink_langs = ('d', 'cuda') + clib_langs # type: T.Tuple[str, ...]
+clink_suffixes = tuple() # type: T.Tuple[str, ...]
for _l in clink_langs + ('vala',):
clink_suffixes += lang_suffixes[_l]
clink_suffixes += ('h', 'll', 's')
-all_suffixes = set(itertools.chain(*lang_suffixes.values(), clink_suffixes))
+all_suffixes = set(itertools.chain(*lang_suffixes.values(), clink_suffixes)) # type: T.Set[str]
# Languages that should use LDFLAGS arguments when linking.
-languages_using_ldflags = {'objcpp', 'cpp', 'objc', 'c', 'fortran', 'd', 'cuda'}
+languages_using_ldflags = {'objcpp', 'cpp', 'objc', 'c', 'fortran', 'd', 'cuda'} # type: T.Set[str]
# Languages that should use CPPFLAGS arguments when linking.
-languages_using_cppflags = {'c', 'cpp', 'objc', 'objcpp'}
+languages_using_cppflags = {'c', 'cpp', 'objc', 'objcpp'} # type: T.Set[str]
soregex = re.compile(r'.*\.so(\.[0-9]+)?(\.[0-9]+)?(\.[0-9]+)?$')
# Environment variables that each lang uses.
@@ -94,14 +98,14 @@ cflags_mapping = {'c': 'CFLAGS',
'fortran': 'FFLAGS',
'd': 'DFLAGS',
'vala': 'VALAFLAGS',
- 'rust': 'RUSTFLAGS'}
+ 'rust': 'RUSTFLAGS'} # type: T.Dict[str, str]
cexe_mapping = {'c': 'CC',
'cpp': 'CXX'}
# All these are only for C-linkable languages; see `clink_langs` above.
-def sort_clink(lang):
+def sort_clink(lang: str) -> int:
'''
Sorting function to sort the list of languages according to
reversed(compilers.clink_langs) and append the unknown langs in the end.
@@ -112,40 +116,40 @@ def sort_clink(lang):
return 1
return -clink_langs.index(lang)
-def is_header(fname):
- if hasattr(fname, 'fname'):
+def is_header(fname: 'mesonlib.FileOrString') -> bool:
+ if isinstance(fname, mesonlib.File):
fname = fname.fname
suffix = fname.split('.')[-1]
return suffix in header_suffixes
-def is_source(fname):
- if hasattr(fname, 'fname'):
+def is_source(fname: 'mesonlib.FileOrString') -> bool:
+ if isinstance(fname, mesonlib.File):
fname = fname.fname
suffix = fname.split('.')[-1].lower()
return suffix in clink_suffixes
-def is_assembly(fname):
- if hasattr(fname, 'fname'):
+def is_assembly(fname: 'mesonlib.FileOrString') -> bool:
+ if isinstance(fname, mesonlib.File):
fname = fname.fname
return fname.split('.')[-1].lower() == 's'
-def is_llvm_ir(fname):
- if hasattr(fname, 'fname'):
+def is_llvm_ir(fname: 'mesonlib.FileOrString') -> bool:
+ if isinstance(fname, mesonlib.File):
fname = fname.fname
return fname.split('.')[-1] == 'll'
@lru_cache(maxsize=None)
-def cached_by_name(fname):
+def cached_by_name(fname: 'mesonlib.FileOrString') -> bool:
suffix = fname.split('.')[-1]
return suffix in obj_suffixes
-def is_object(fname):
- if hasattr(fname, 'fname'):
+def is_object(fname: 'mesonlib.FileOrString') -> bool:
+ if isinstance(fname, mesonlib.File):
fname = fname.fname
return cached_by_name(fname)
-def is_library(fname):
- if hasattr(fname, 'fname'):
+def is_library(fname: 'mesonlib.FileOrString') -> bool:
+ if isinstance(fname, mesonlib.File):
fname = fname.fname
if soregex.match(fname):
@@ -154,8 +158,8 @@ def is_library(fname):
suffix = fname.split('.')[-1]
return suffix in lib_suffixes
-def is_known_suffix(fname):
- if hasattr(fname, 'fname'):
+def is_known_suffix(fname: 'mesonlib.FileOrString') -> bool:
+ if isinstance(fname, mesonlib.File):
fname = fname.fname
suffix = fname.split('.')[-1]
@@ -166,14 +170,14 @@ cuda_buildtype_args = {'plain': [],
'debugoptimized': [],
'release': [],
'minsize': [],
- }
+ } # type: T.Dict[str, T.List[str]]
java_buildtype_args = {'plain': [],
'debug': ['-g'],
'debugoptimized': ['-g'],
'release': [],
'minsize': [],
'custom': [],
- }
+ } # type: T.Dict[str, T.List[str]]
rust_buildtype_args = {'plain': [],
'debug': [],
@@ -181,7 +185,7 @@ rust_buildtype_args = {'plain': [],
'release': [],
'minsize': [],
'custom': [],
- }
+ } # type: T.Dict[str, T.List[str]]
d_gdc_buildtype_args = {'plain': [],
'debug': [],
@@ -189,7 +193,7 @@ d_gdc_buildtype_args = {'plain': [],
'release': ['-finline-functions'],
'minsize': [],
'custom': [],
- }
+ } # type: T.Dict[str, T.List[str]]
d_ldc_buildtype_args = {'plain': [],
'debug': [],
@@ -197,7 +201,7 @@ d_ldc_buildtype_args = {'plain': [],
'release': ['-enable-inlining', '-Hkeep-all-bodies'],
'minsize': [],
'custom': [],
- }
+ } # type: T.Dict[str, T.List[str]]
d_dmd_buildtype_args = {'plain': [],
'debug': [],
@@ -205,7 +209,7 @@ d_dmd_buildtype_args = {'plain': [],
'release': ['-inline'],
'minsize': [],
'custom': [],
- }
+ } # type: T.Dict[str, T.List[str]]
mono_buildtype_args = {'plain': [],
'debug': [],
@@ -213,7 +217,7 @@ mono_buildtype_args = {'plain': [],
'release': ['-optimize+'],
'minsize': [],
'custom': [],
- }
+ } # type: T.Dict[str, T.List[str]]
swift_buildtype_args = {'plain': [],
'debug': [],
@@ -221,14 +225,14 @@ swift_buildtype_args = {'plain': [],
'release': [],
'minsize': [],
'custom': [],
- }
+ } # type: T.Dict[str, T.List[str]]
gnu_winlibs = ['-lkernel32', '-luser32', '-lgdi32', '-lwinspool', '-lshell32',
- '-lole32', '-loleaut32', '-luuid', '-lcomdlg32', '-ladvapi32']
+ '-lole32', '-loleaut32', '-luuid', '-lcomdlg32', '-ladvapi32'] # type: T.List[str]
msvc_winlibs = ['kernel32.lib', 'user32.lib', 'gdi32.lib',
'winspool.lib', 'shell32.lib', 'ole32.lib', 'oleaut32.lib',
- 'uuid.lib', 'comdlg32.lib', 'advapi32.lib']
+ 'uuid.lib', 'comdlg32.lib', 'advapi32.lib'] # type: T.List[str]
clike_optimization_args = {'0': [],
'g': [],
@@ -236,7 +240,7 @@ clike_optimization_args = {'0': [],
'2': ['-O2'],
'3': ['-O3'],
's': ['-Os'],
- }
+ } # type: T.Dict[str, T.List[str]]
cuda_optimization_args = {'0': [],
'g': ['-O0'],
@@ -244,13 +248,13 @@ cuda_optimization_args = {'0': [],
'2': ['-O2'],
'3': ['-O3'],
's': ['-O3']
- }
+ } # type: T.Dict[str, T.List[str]]
cuda_debug_args = {False: [],
- True: ['-g']}
+ True: ['-g']} # type: T.Dict[bool, T.List[str]]
clike_debug_args = {False: [],
- True: ['-g']}
+ True: ['-g']} # type: T.Dict[bool, T.List[str]]
base_options = {'b_pch': coredata.UserBooleanOption('Use precompiled headers', True),
'b_lto': coredata.UserBooleanOption('Use link time optimization', False),
@@ -278,18 +282,21 @@ base_options = {'b_pch': coredata.UserBooleanOption('Use precompiled headers', T
'b_vscrt': coredata.UserComboOption('VS run-time library type to use.',
['none', 'md', 'mdd', 'mt', 'mtd', 'from_buildtype'],
'from_buildtype'),
- }
+ } # type: OptionDictType
-def option_enabled(boptions, options, option):
+def option_enabled(boptions: T.List[str], options: 'OptionDictType',
+ option: str) -> bool:
try:
if option not in boptions:
return False
- return options[option].value
+ ret = options[option].value
+ assert isinstance(ret, bool), 'must return bool' # could also be str
+ return ret
except KeyError:
return False
-def get_base_compile_args(options, compiler):
- args = []
+def get_base_compile_args(options: 'OptionDictType', compiler: 'Compiler') -> T.List[str]:
+ args = [] # type T.List[str]
try:
if options['b_lto'].value:
args.extend(compiler.get_lto_compile_args())
@@ -337,8 +344,9 @@ def get_base_compile_args(options, compiler):
pass
return args
-def get_base_link_args(options, linker, is_shared_module):
- args = []
+def get_base_link_args(options: 'OptionDictType', linker: 'Compiler',
+ is_shared_module: bool) -> T.List[str]:
+ args = [] # type: T.List[str]
try:
if options['b_lto'].value:
args.extend(linker.get_lto_link_args())
@@ -398,32 +406,58 @@ class CrossNoRunException(MesonException):
pass
class RunResult:
- def __init__(self, compiled, returncode=999, stdout='UNDEFINED', stderr='UNDEFINED'):
+ def __init__(self, compiled: bool, returncode: int = 999,
+ stdout: str = 'UNDEFINED', stderr: str = 'UNDEFINED'):
self.compiled = compiled
self.returncode = returncode
self.stdout = stdout
self.stderr = stderr
+class CompileResult:
+
+ """The result of Compiler.compiles (and friends)."""
+
+ def __init__(self, stdo: T.Optional[str] = None, stde: T.Optional[str] = None,
+ args: T.Optional[T.List[str]] = None,
+ returncode: int = 999, pid: int = -1,
+ text_mode: bool = True,
+ input_name: T.Optional[str] = None,
+ output_name: T.Optional[str] = None,
+ command: T.Optional[T.List[str]] = None, cached: bool = False):
+ self.stdout = stdo
+ self.stderr = stde
+ self.input_name = input_name
+ self.output_name = output_name
+ self.command = command or []
+ self.args = args or []
+ self.cached = cached
+ self.returncode = returncode
+ self.pid = pid
+ self.text_mode = text_mode
+
+
class Compiler(metaclass=abc.ABCMeta):
# Libraries to ignore in find_library() since they are provided by the
# compiler or the C library. Currently only used for MSVC.
- ignore_libs = ()
+ ignore_libs = [] # type: T.List[str]
# Libraries that are internal compiler implementations, and must not be
# manually searched.
- internal_libs = ()
+ internal_libs = [] # type: T.List[str]
LINKER_PREFIX = None # type: T.Union[None, str, T.List[str]]
INVOKES_LINKER = True
- def __init__(self, exelist, version, for_machine: MachineChoice, info: 'MachineInfo',
- linker: T.Optional['DynamicLinker'] = None, **kwargs):
- if isinstance(exelist, str):
- self.exelist = [exelist]
- elif isinstance(exelist, list):
- self.exelist = exelist
- else:
- raise TypeError('Unknown argument to Compiler')
+ # TODO: these could be forward declarations once we drop 3.5 support
+ if T.TYPE_CHECKING:
+ language = 'unset'
+ id = ''
+
+ def __init__(self, exelist: T.List[str], version: str,
+ for_machine: MachineChoice, info: 'MachineInfo',
+ linker: T.Optional['DynamicLinker'] = None,
+ full_version: T.Optional[str] = None, is_cross: bool = False):
+ self.exelist = exelist
# In case it's been overridden by a child class already
if not hasattr(self, 'file_suffixes'):
self.file_suffixes = lang_suffixes[self.language]
@@ -431,28 +465,24 @@ class Compiler(metaclass=abc.ABCMeta):
self.can_compile_suffixes = set(self.file_suffixes)
self.default_suffix = self.file_suffixes[0]
self.version = version
- if 'full_version' in kwargs:
- self.full_version = kwargs['full_version']
- else:
- self.full_version = None
+ self.full_version = full_version
self.for_machine = for_machine
- self.base_options = []
+ self.base_options = [] # type: T.List[str]
self.linker = linker
self.info = info
+ self.is_cross = is_cross
- def __repr__(self):
+ def __repr__(self) -> str:
repr_str = "<{0}: v{1} `{2}`>"
return repr_str.format(self.__class__.__name__, self.version,
' '.join(self.exelist))
@lru_cache(maxsize=None)
- def can_compile(self, src) -> bool:
- if hasattr(src, 'fname'):
+ def can_compile(self, src: 'mesonlib.FileOrString') -> bool:
+ if isinstance(src, mesonlib.File):
src = src.fname
suffix = os.path.splitext(src)[1].lower()
- if suffix and suffix[1:] in self.can_compile_suffixes:
- return True
- return False
+ return bool(suffix) and suffix[1:] in self.can_compile_suffixes
def get_id(self) -> str:
return self.id
@@ -482,42 +512,54 @@ class Compiler(metaclass=abc.ABCMeta):
def get_default_suffix(self) -> str:
return self.default_suffix
- def get_define(self, dname, prefix, env, extra_args, dependencies) -> T.Tuple[str, bool]:
+ def get_define(self, dname: str, prefix: str, env: 'Environment',
+ extra_args: T.List[str], dependencies: T.List['Dependency'],
+ disable_cache: bool = False) -> T.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:
+ def compute_int(self, expression: str, low: T.Optional[int], high: T.Optional[int],
+ guess: T.Optional[int], prefix: str, env: 'Environment', *,
+ 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())
- def compute_parameters_with_absolute_paths(self, parameter_list, build_dir):
+ def compute_parameters_with_absolute_paths(self, parameter_list: T.List[str],
+ build_dir: str) -> T.List[str]:
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) -> T.Tuple[bool, bool]:
+ def has_members(self, typename: str, membernames: T.List[str],
+ prefix: str, env: 'Environment', *,
+ extra_args: T.Optional[T.List[str]] = None,
+ dependencies: T.Optional[T.List['Dependency']] = None) -> T.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) -> T.Tuple[bool, bool]:
+ def has_type(self, typename: str, prefix: str, env: 'Environment',
+ extra_args: T.List[str], *,
+ dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[bool, bool]:
raise EnvironmentException('%s does not support has_type ' % self.get_id())
- def symbols_have_underscore_prefix(self, env) -> bool:
+ def symbols_have_underscore_prefix(self, env: 'Environment') -> bool:
raise EnvironmentException('%s does not support symbols_have_underscore_prefix ' % self.get_id())
- def get_exelist(self):
- return self.exelist[:]
+ def get_exelist(self) -> T.List[str]:
+ return self.exelist.copy()
def get_linker_exelist(self) -> T.List[str]:
return self.linker.get_exelist()
+ @abc.abstractmethod
+ def get_output_args(self, outputname: str) -> T.List[str]:
+ pass
+
def get_linker_output_args(self, outputname: str) -> T.List[str]:
return self.linker.get_output_args(outputname)
- def get_builtin_define(self, *args, **kwargs):
+ def get_builtin_define(self, define: str) -> T.Optional[str]:
raise EnvironmentException('%s does not support get_builtin_define.' % self.id)
- def has_builtin_define(self, *args, **kwargs):
+ def has_builtin_define(self, define: str) -> bool:
raise EnvironmentException('%s does not support has_builtin_define.' % self.id)
- def get_always_args(self):
+ def get_always_args(self) -> T.List[str]:
return []
def can_linker_accept_rsp(self) -> bool:
@@ -529,10 +571,10 @@ class Compiler(metaclass=abc.ABCMeta):
def get_linker_always_args(self) -> T.List[str]:
return self.linker.get_always_args()
- def get_linker_lib_prefix(self):
+ def get_linker_lib_prefix(self) -> str:
return self.linker.get_lib_prefix()
- def gen_import_library_args(self, implibname):
+ def gen_import_library_args(self, implibname: str) -> T.List[str]:
"""
Used only on Windows for libraries that need an import library.
This currently means C, C++, Fortran.
@@ -544,62 +586,115 @@ class Compiler(metaclass=abc.ABCMeta):
is_cross: bool) -> T.List[str]:
return self.linker.get_args_from_envvars(for_machine, is_cross)
- def get_options(self) -> T.Dict[str, coredata.UserOption]:
+ def get_options(self) -> 'OptionDictType':
return {}
- def get_option_compile_args(self, options):
+ def get_option_compile_args(self, options: 'OptionDictType') -> T.List[str]:
return []
def get_option_link_args(self, options: 'OptionDictType') -> T.List[str]:
return self.linker.get_option_args(options)
- def check_header(self, *args, **kwargs) -> T.Tuple[bool, bool]:
+ def check_header(self, hname: str, prefix: str, env: 'Environment', *,
+ extra_args: T.Optional[T.List[str]] = None,
+ dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[bool, bool]:
+ """Check that header is usable.
+
+ Returns a two item tuple of bools. The first bool is whether the
+ check succeeded, the second is whether the result was cached (True)
+ or run fresh (False).
+ """
raise EnvironmentException('Language %s does not support header checks.' % self.get_display_language())
- def has_header(self, *args, **kwargs) -> T.Tuple[bool, bool]:
+ def has_header(self, hname: str, prefix: str, env: 'Environment', *,
+ extra_args: T.Optional[T.List[str]] = None,
+ dependencies: T.Optional[T.List['Dependency']] = None,
+ disable_cache: bool = False) -> T.Tuple[bool, bool]:
+ """Check that header is exists.
+
+ This check will return true if the file exists, even if it contains:
+
+ ```c
+ # error "You thought you could use this, LOLZ!"
+ ```
+
+ Use check_header if your header only works in some cases.
+
+ Returns a two item tuple of bools. The first bool is whether the
+ check succeeded, the second is whether the result was cached (True)
+ or run fresh (False).
+ """
raise EnvironmentException('Language %s does not support header checks.' % self.get_display_language())
- def has_header_symbol(self, *args, **kwargs) -> T.Tuple[bool, bool]:
+ def has_header_symbol(self, hname: str, symbol: str, prefix: str,
+ env: 'Environment', *,
+ extra_args: T.Optional[T.List[str]] = None,
+ 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, *args, **kwargs) -> T.Tuple[bool, bool]:
+ 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, *args, **kwargs) -> T.Tuple[bool, bool]:
+ 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, *args, **kwargs) -> RunResult:
+ def run(self, code: str, env: 'Environment', *,
+ extra_args: T.Optional[T.List[str]] = None,
+ dependencies: T.Optional[T.List['Dependency']] = None) -> RunResult:
raise EnvironmentException('Language %s does not support run checks.' % self.get_display_language())
- def sizeof(self, *args, **kwargs) -> int:
+ def sizeof(self, typename: str, prefix: str, env: 'Environment', *,
+ extra_args: T.Optional[T.List[str]] = None,
+ dependencies: T.Optional[T.List['Dependency']] = None) -> int:
raise EnvironmentException('Language %s does not support sizeof checks.' % self.get_display_language())
- def alignment(self, *args, **kwargs) -> int:
+ def alignment(self, typename: str, prefix: str, env: 'Environment', *,
+ extra_args: T.Optional[T.List[str]] = None,
+ dependencies: T.Optional[T.List['Dependency']] = None) -> int:
raise EnvironmentException('Language %s does not support alignment checks.' % self.get_display_language())
- def has_function(self, *args, **kwargs) -> T.Tuple[bool, bool]:
+ def has_function(self, funcname: str, prefix: str, env: 'Environment', *,
+ extra_args: T.Optional[T.List[str]] = None,
+ dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[bool, bool]:
+ """See if a function exists.
+
+ Returns a two item tuple of bools. The first bool is whether the
+ check succeeded, the second is whether the result was cached (True)
+ or run fresh (False).
+ """
raise EnvironmentException('Language %s does not support function checks.' % self.get_display_language())
- @classmethod
- def unix_args_to_native(cls, args: T.List[str]) -> T.List[str]:
+ def unix_args_to_native(self, args: T.List[str]) -> T.List[str]:
"Always returns a copy that can be independently mutated"
- return args[:]
+ return args.copy()
@classmethod
def native_args_to_unix(cls, args: T.List[str]) -> T.List[str]:
"Always returns a copy that can be independently mutated"
- return args[:]
+ return args.copy()
- def find_library(self, *args, **kwargs):
+ def find_library(self, libname: str, env: 'Environment', extra_dirs: T.List[str],
+ libtype: LibType = LibType.PREFER_SHARED) -> T.Optional[T.List[str]]:
raise EnvironmentException('Language {} does not support library finding.'.format(self.get_display_language()))
- def get_library_dirs(self, *args, **kwargs):
- return ()
+ def get_library_naming(self, env: 'Environment', libtype: LibType,
+ strict: bool = False) -> T.Optional[T.Tuple[str, ...]]:
+ raise EnvironmentException(
+ 'Language {} does not support get_library_naming.'.format(
+ self.get_display_language()))
- def get_program_dirs(self, *args, **kwargs):
+ def get_program_dirs(self, env: 'Environment') -> T.List[str]:
return []
- def has_multi_arguments(self, args, env) -> T.Tuple[bool, bool]:
+ def has_multi_arguments(self, args: T.List[str], env: 'Environment') -> T.Tuple[bool, bool]:
raise EnvironmentException(
'Language {} does not support has_multi_arguments.'.format(
self.get_display_language()))
@@ -607,7 +702,8 @@ class Compiler(metaclass=abc.ABCMeta):
def has_multi_link_arguments(self, args: T.List[str], env: 'Environment') -> T.Tuple[bool, bool]:
return self.linker.has_multi_arguments(args, env)
- def _get_compile_output(self, dirname, mode):
+ def _get_compile_output(self, dirname: str, mode: str) -> str:
+ # TODO: mode should really be an enum
# In pre-processor mode, the output is sent to stdout and discarded
if mode == 'preprocess':
return None
@@ -619,8 +715,9 @@ class Compiler(metaclass=abc.ABCMeta):
suffix = 'obj'
return os.path.join(dirname, 'output.' + suffix)
- def get_compiler_args_for_mode(self, mode):
- args = []
+ def get_compiler_args_for_mode(self, mode: str) -> T.List[str]:
+ # TODO: mode should really be an enum
+ args = [] # type: T.List[str]
args += self.get_always_args()
if mode == 'compile':
args += self.get_compile_only_args()
@@ -633,7 +730,11 @@ class Compiler(metaclass=abc.ABCMeta):
return CompilerArgs(self, args)
@contextlib.contextmanager
- def compile(self, code: str, extra_args: list = None, *, mode: str = 'link', want_output: bool = False, temp_dir: str = None):
+ def compile(self, code: 'mesonlib.FileOrString',
+ extra_args: T.Union[None, CompilerArgs, T.List[str]] = None,
+ *, mode: str = 'link', want_output: bool = False,
+ temp_dir: T.Optional[str] = None) -> T.Iterator[T.Optional[CompileResult]]:
+ # TODO: there isn't really any reason for this to be a contextmanager
if extra_args is None:
extra_args = []
try:
@@ -646,8 +747,11 @@ class Compiler(metaclass=abc.ABCMeta):
ofile.write(code)
# ccache would result in a cache miss
no_ccache = True
+ contents = code
elif isinstance(code, mesonlib.File):
srcname = code.fname
+ with open(code.fname, 'r') as f:
+ contents = f.read()
# Construct the compiler command-line
commands = self.compiler_args()
@@ -662,69 +766,62 @@ class Compiler(metaclass=abc.ABCMeta):
# in the command line after '/link' is given to the linker.
commands += extra_args
# Generate full command-line with the exelist
- commands = self.get_exelist() + commands.to_native()
+ command_list = self.get_exelist() + commands.to_native()
mlog.debug('Running compile:')
mlog.debug('Working directory: ', tmpdirname)
- mlog.debug('Command line: ', ' '.join(commands), '\n')
- mlog.debug('Code:\n', code)
+ mlog.debug('Command line: ', ' '.join(command_list), '\n')
+ mlog.debug('Code:\n', contents)
os_env = os.environ.copy()
os_env['LC_ALL'] = 'C'
if no_ccache:
os_env['CCACHE_DISABLE'] = '1'
- p, p.stdo, p.stde = Popen_safe(commands, cwd=tmpdirname, env=os_env)
- mlog.debug('Compiler stdout:\n', p.stdo)
- mlog.debug('Compiler stderr:\n', p.stde)
- p.commands = commands
- p.input_name = srcname
+ p, stdo, stde = Popen_safe(command_list, cwd=tmpdirname, env=os_env)
+ mlog.debug('Compiler stdout:\n', stdo)
+ mlog.debug('Compiler stderr:\n', stde)
+
+ result = CompileResult(stdo, stde, list(commands), p.returncode, p.pid, input_name=srcname)
if want_output:
- p.output_name = output
- p.cached = False # Make sure that the cached attribute always exists
- yield p
+ result.output_name = output
+ yield result
except OSError:
# On Windows antivirus programs and the like hold on to files so
# they can't be deleted. There's not much to do in this case. Also,
# catch OSError because the directory is then no longer empty.
- pass
+ yield None
@contextlib.contextmanager
- def cached_compile(self, code, cdata: coredata.CoreData, *, extra_args=None, mode: str = 'link', temp_dir=None):
- assert(isinstance(cdata, coredata.CoreData))
+ def cached_compile(self, code: str, cdata: coredata.CoreData, *,
+ extra_args: T.Union[None, T.List[str], CompilerArgs] = None,
+ mode: str = 'link',
+ temp_dir: T.Optional[str] = None) -> T.Iterator[T.Optional[CompileResult]]:
+ # TODO: There's isn't really any reason for this to be a context manager
# 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:
+ textra_args = tuple(extra_args) if extra_args is not None else tuple() # type: T.Tuple[str, ...]
+ key = (tuple(self.exelist), self.version, code, textra_args, mode) # type: coredata.CompilerCheckCacheKey
+
+ # Check if not cached, and generate, otherwise get from the cache
+ if key in cdata.compiler_check_cache:
+ p = cdata.compiler_check_cache[key] # type: CompileResult
+ p.cached = True
+ mlog.debug('Using cached compile:')
+ mlog.debug('Cached command line: ', ' '.join(p.command), '\n')
+ mlog.debug('Code:\n', code)
+ mlog.debug('Cached compiler stdout:\n', p.stdout)
+ mlog.debug('Cached compiler stderr:\n', p.stderr)
+ yield p
+ else:
with self.compile(code, extra_args=extra_args, mode=mode, want_output=False, temp_dir=temp_dir) 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):
+
+ def get_colorout_args(self, colortype: str) -> T.List[str]:
+ # TODO: colortype can probably be an emum
return []
# Some compilers (msvc) write debug info to a separate file.
# These args specify where it should be written.
- def get_compile_debugfile_args(self, rel_obj, **kwargs):
+ def get_compile_debugfile_args(self, rel_obj: str, pch: bool = False) -> T.List[str]:
return []
def get_link_debugfile_name(self, targetfile: str) -> str:
@@ -748,10 +845,12 @@ class Compiler(metaclass=abc.ABCMeta):
def no_undefined_link_args(self) -> T.List[str]:
return self.linker.no_undefined_args()
- # Compiler arguments needed to enable the given instruction set.
- # May be [] meaning nothing needed or None meaning the given set
- # is not supported.
- def get_instruction_set_args(self, instruction_set):
+ def get_instruction_set_args(self, instruction_set: str) -> T.Optional[T.List[str]]:
+ """Compiler arguments needed to enable the given instruction set.
+
+ Return type ay be an empty list meaning nothing needed or None
+ meaning the given set is not supported.
+ """
return None
def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str,
@@ -760,40 +859,40 @@ class Compiler(metaclass=abc.ABCMeta):
return self.linker.build_rpath_args(
env, build_dir, from_dir, rpath_paths, build_rpath, install_rpath)
- def thread_flags(self, env):
+ def thread_flags(self, env: 'Environment') -> T.List[str]:
return []
- def openmp_flags(self):
+ def openmp_flags(self) -> T.List[str]:
raise EnvironmentException('Language %s does not support OpenMP flags.' % self.get_display_language())
- def openmp_link_flags(self):
+ def openmp_link_flags(self) -> T.List[str]:
return self.openmp_flags()
- def language_stdlib_only_link_flags(self):
+ def language_stdlib_only_link_flags(self) -> T.List[str]:
return []
- def gnu_symbol_visibility_args(self, vistype):
+ def gnu_symbol_visibility_args(self, vistype: str) -> T.List[str]:
return []
- def get_gui_app_args(self, value):
+ def get_gui_app_args(self, value: bool) -> T.List[str]:
return []
- def has_func_attribute(self, name, env):
+ def has_func_attribute(self, name: str, env: 'Environment') -> T.Tuple[bool, bool]:
raise EnvironmentException(
'Language {} does not support function attributes.'.format(self.get_display_language()))
- def get_pic_args(self):
+ def get_pic_args(self) -> T.List[str]:
m = 'Language {} does not support position-independent code'
raise EnvironmentException(m.format(self.get_display_language()))
- def get_pie_args(self):
+ def get_pie_args(self) -> T.List[str]:
m = 'Language {} does not support position-independent executable'
raise EnvironmentException(m.format(self.get_display_language()))
def get_pie_link_args(self) -> T.List[str]:
return self.linker.get_pie_args()
- def get_argument_syntax(self):
+ def get_argument_syntax(self) -> str:
"""Returns the argument family type.
Compilers fall into families if they try to emulate the command line
@@ -804,22 +903,19 @@ class Compiler(metaclass=abc.ABCMeta):
"""
return 'other'
- def get_profile_generate_args(self):
+ def get_profile_generate_args(self) -> T.List[str]:
raise EnvironmentException(
'%s does not support get_profile_generate_args ' % self.get_id())
- def get_profile_use_args(self):
+ def get_profile_use_args(self) -> T.List[str]:
raise EnvironmentException(
'%s does not support get_profile_use_args ' % self.get_id())
- def get_undefined_link_args(self) -> T.List[str]:
- return self.linker.get_undefined_link_args()
-
- def remove_linkerlike_args(self, args):
+ def remove_linkerlike_args(self, args: T.List[str]) -> T.List[str]:
rm_exact = ('-headerpad_max_install_names',)
rm_prefixes = ('-Wl,', '-L',)
rm_next = ('-L', '-framework',)
- ret = []
+ ret = [] # T.List[str]
iargs = iter(args)
for arg in iargs:
# Remove this argument
@@ -868,13 +964,13 @@ class Compiler(metaclass=abc.ABCMeta):
env, prefix, shlib_name, suffix, soversion,
darwin_versions, is_shared_module)
- def get_target_link_args(self, target):
+ def get_target_link_args(self, target: 'BuildTarget') -> T.List[str]:
return target.link_args
- def get_dependency_compile_args(self, dep):
+ def get_dependency_compile_args(self, dep: 'Dependency') -> T.List[str]:
return dep.get_compile_args()
- def get_dependency_link_args(self, dep):
+ def get_dependency_link_args(self, dep: 'Dependency') -> T.List[str]:
return dep.get_link_args()
@classmethod
@@ -883,33 +979,73 @@ class Compiler(metaclass=abc.ABCMeta):
"""
return []
+ def get_coverage_args(self) -> T.List[str]:
+ return []
+
def get_coverage_link_args(self) -> T.List[str]:
return self.linker.get_coverage_args()
def get_disable_assert_args(self) -> T.List[str]:
return []
+ def get_crt_compile_args(self, crt_val: str, buildtype: str) -> T.List[str]:
+ raise EnvironmentError('This compiler does not support Windows CRT selection')
-def get_largefile_args(compiler):
- '''
- Enable transparent large-file-support for 32-bit UNIX systems
- '''
- if not (compiler.get_argument_syntax() == 'msvc' or compiler.info.is_darwin()):
- # Enable large-file support unconditionally on all platforms other
- # than macOS and MSVC. macOS is now 64-bit-only so it doesn't
- # need anything special, and MSVC doesn't have automatic LFS.
- # You must use the 64-bit counterparts explicitly.
- # glibc, musl, and uclibc, and all BSD libcs support this. On Android,
- # support for transparent LFS is available depending on the version of
- # Bionic: https://github.com/android/platform_bionic#32-bit-abi-bugs
- # https://code.google.com/p/android/issues/detail?id=64613
- #
- # If this breaks your code, fix it! It's been 20+ years!
- return ['-D_FILE_OFFSET_BITS=64']
- # We don't enable -D_LARGEFILE64_SOURCE since that enables
- # transitionary features and must be enabled by programs that use
- # those features explicitly.
- return []
+ def get_crt_link_args(self, crt_val: str, buildtype: str) -> T.List[str]:
+ raise EnvironmentError('This compiler does not support Windows CRT selection')
+
+ def get_compile_only_args(self) -> T.List[str]:
+ return []
+
+ def get_preprocess_only_args(self) -> T.List[str]:
+ raise EnvironmentError('This compiler does not have a preprocessor')
+
+ def get_default_include_dirs(self) -> T.List[str]:
+ return []
+
+ def get_largefile_args(self) -> T.List[str]:
+ '''Enable transparent large-file-support for 32-bit UNIX systems'''
+ if not (self.get_argument_syntax() == 'msvc' or self.info.is_darwin()):
+ # Enable large-file support unconditionally on all platforms other
+ # than macOS and MSVC. macOS is now 64-bit-only so it doesn't
+ # need anything special, and MSVC doesn't have automatic LFS.
+ # You must use the 64-bit counterparts explicitly.
+ # glibc, musl, and uclibc, and all BSD libcs support this. On Android,
+ # support for transparent LFS is available depending on the version of
+ # Bionic: https://github.com/android/platform_bionic#32-bit-abi-bugs
+ # https://code.google.com/p/android/issues/detail?id=64613
+ #
+ # If this breaks your code, fix it! It's been 20+ years!
+ return ['-D_FILE_OFFSET_BITS=64']
+ # We don't enable -D_LARGEFILE64_SOURCE since that enables
+ # transitionary features and must be enabled by programs that use
+ # those features explicitly.
+ return []
+
+ def get_library_dirs(self, env: 'Environment',
+ elf_class: T.Optional[int] = None) -> T.List[str]:
+ return []
+
+ def find_framework_paths(self, env: 'Environment') -> T.List[str]:
+ raise EnvironmentException('{} does not support find_framework_paths'.format(self.id))
+
+ def attribute_check_func(self, name: str) -> str:
+ raise EnvironmentException('{} does not support attribute checks'.format(self.id))
+
+ def get_pch_suffix(self) -> str:
+ raise EnvironmentException('{} does not support pre compiled headers'.format(self.id))
+
+ def get_pch_name(self, name: str) -> str:
+ raise EnvironmentException('{} does not support pre compiled headers'.format(self.id))
+
+ def get_pch_use_args(self, pch_dir: str, header: str) -> T.List[str]:
+ raise EnvironmentException('{} does not support pre compiled headers'.format(self.id))
+
+ def get_has_func_attribute_extra_args(self, name: str) -> T.List[str]:
+ raise EnvironmentException('{} does not support function attributes'.format(self.id))
+
+ def name_string(self) -> str:
+ return ' '.join(self.exelist)
def get_args_from_envvars(lang: str,
@@ -953,7 +1089,7 @@ def get_global_options(lang: str,
comp: T.Type[Compiler],
for_machine: MachineChoice,
is_cross: bool,
- properties: Properties) -> T.Dict[str, coredata.UserOption]:
+ properties: Properties) -> 'OptionDictType':
"""Retreive options that apply to all compilers for a given language."""
description = 'Extra arguments passed to the {}'.format(lang)
opts = {
@@ -963,7 +1099,7 @@ def get_global_options(lang: str,
'link_args': coredata.UserArrayOption(
description + ' linker',
[], split_args=True, user_input=True, allow_dups=True),
- }
+ } # type: OptionDictType
# Get from env vars.
compile_args, link_args = get_args_from_envvars(
diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py
index 698c71a..b5dbdda 100644
--- a/mesonbuild/compilers/cpp.py
+++ b/mesonbuild/compilers/cpp.py
@@ -65,8 +65,8 @@ class CPPCompiler(CLikeCompiler, Compiler):
def __init__(self, exelist, version, for_machine: MachineChoice, is_cross: bool,
info: 'MachineInfo', exe_wrap: T.Optional[str] = None, **kwargs):
# If a child ObjCPP class has already set it, don't set it ourselves
- Compiler.__init__(self, exelist, version, for_machine, info, **kwargs)
- CLikeCompiler.__init__(self, is_cross, exe_wrap)
+ Compiler.__init__(self, exelist, version, for_machine, info, is_cross=is_cross, **kwargs)
+ CLikeCompiler.__init__(self, exe_wrap)
@staticmethod
def get_display_language():
@@ -77,7 +77,7 @@ class CPPCompiler(CLikeCompiler, Compiler):
def sanity_check(self, work_dir, environment):
code = 'class breakCCompiler;int main(void) { return 0; }\n'
- return self.sanity_check_impl(work_dir, environment, 'sanitycheckcpp.cc', code)
+ return self._sanity_check_impl(work_dir, environment, 'sanitycheckcpp.cc', code)
def get_compiler_check_args(self):
# -fpermissive allows non-conforming code to compile which is necessary
diff --git a/mesonbuild/compilers/cs.py b/mesonbuild/compilers/cs.py
index 843348e..b269aec 100644
--- a/mesonbuild/compilers/cs.py
+++ b/mesonbuild/compilers/cs.py
@@ -40,7 +40,6 @@ class CsCompiler(BasicLinkerIsCompilerMixin, Compiler):
info: 'MachineInfo', comp_id, runner=None):
super().__init__(exelist, version, for_machine, info)
self.id = comp_id
- self.is_cross = False
self.runner = runner
@classmethod
@@ -95,9 +94,6 @@ class CsCompiler(BasicLinkerIsCompilerMixin, Compiler):
return parameter_list
- def name_string(self):
- return ' '.join(self.exelist)
-
def get_pch_use_args(self, pch_dir, header):
return []
diff --git a/mesonbuild/compilers/cuda.py b/mesonbuild/compilers/cuda.py
index 934ad12..482d504 100644
--- a/mesonbuild/compilers/cuda.py
+++ b/mesonbuild/compilers/cuda.py
@@ -161,7 +161,7 @@ class CudaCompiler(Compiler):
mlog.debug('cudaGetDeviceCount() returned ' + stde)
def has_header_symbol(self, hname, symbol, prefix, env, extra_args=None, dependencies=None):
- result, cached = super().has_header_symbol(hname, symbol, prefix, env, extra_args, dependencies)
+ result, cached = super().has_header_symbol(hname, symbol, prefix, env, extra_args=extra_args, dependencies=dependencies)
if result:
return True, cached
if extra_args is None:
@@ -171,7 +171,7 @@ class CudaCompiler(Compiler):
#include <{header}>
using {symbol};
int main(void) {{ return 0; }}'''
- return self.compiles(t.format(**fargs), env, extra_args, dependencies)
+ return self.compiles(t.format(**fargs), env, extra_args=extra_args, dependencies=dependencies)
def get_options(self):
opts = super().get_options()
@@ -210,9 +210,6 @@ class CudaCompiler(Compiler):
def get_option_link_args(self, options):
return self._cook_link_args(self.host_compiler.get_option_link_args(self._to_host_compiler_options(options)))
- def name_string(self):
- return ' '.join(self.exelist)
-
def get_soname_args(self, *args):
return self._cook_link_args(self.host_compiler.get_soname_args(*args))
diff --git a/mesonbuild/compilers/d.py b/mesonbuild/compilers/d.py
index a74dc95..ca7f80d 100644
--- a/mesonbuild/compilers/d.py
+++ b/mesonbuild/compilers/d.py
@@ -30,6 +30,7 @@ from .compilers import (
from .mixins.gnu import GnuCompiler
if T.TYPE_CHECKING:
+ from ..dependencies import ExternalProgram
from ..envconfig import MachineInfo
d_feature_args = {'gcc': {'unittest': '-funittest',
@@ -442,13 +443,13 @@ class DCompiler(Compiler):
language = 'd'
- def __init__(self, exelist, version, for_machine: MachineChoice,
- info: 'MachineInfo', arch, is_cross, exe_wrapper, **kwargs):
+ def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice,
+ info: 'MachineInfo', arch: str, exe_wrapper: T.Optional['ExternalProgram'] = None,
+ **kwargs):
super().__init__(exelist, version, for_machine, info, **kwargs)
self.id = 'unknown'
self.arch = arch
self.exe_wrapper = exe_wrapper
- self.is_cross = is_cross
def sanity_check(self, work_dir, environment):
source_name = os.path.join(work_dir, 'sanity.d')
@@ -633,18 +634,16 @@ class DCompiler(Compiler):
def thread_link_flags(self, env):
return self.linker.thread_flags(env)
- def name_string(self):
- return ' '.join(self.exelist)
-
class GnuDCompiler(GnuCompiler, DCompiler):
# we mostly want DCompiler, but that gives us the Compiler.LINKER_PREFIX instead
LINKER_PREFIX = GnuCompiler.LINKER_PREFIX
- def __init__(self, exelist, version, for_machine: MachineChoice,
- info: 'MachineInfo', is_cross, exe_wrapper, arch, **kwargs):
- DCompiler.__init__(self, exelist, version, for_machine, info, is_cross, exe_wrapper, arch, **kwargs)
+ def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice,
+ info: 'MachineInfo', arch: str, *, exe_wrapper: T.Optional['ExternalProgram'] = None,
+ **kwargs):
+ DCompiler.__init__(self, exelist, version, for_machine, info, arch, exe_wrapper=exe_wrapper, **kwargs)
GnuCompiler.__init__(self, {})
self.id = 'gcc'
default_warn_args = ['-Wall', '-Wdeprecated']
@@ -698,9 +697,9 @@ class GnuDCompiler(GnuCompiler, DCompiler):
class LLVMDCompiler(DmdLikeCompilerMixin, DCompiler):
- def __init__(self, exelist, version, for_machine: MachineChoice,
- info: 'MachineInfo', arch, **kwargs):
- DCompiler.__init__(self, exelist, version, for_machine, info, arch, False, None, **kwargs)
+ def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice,
+ info: 'MachineInfo', arch: str, **kwargs):
+ DCompiler.__init__(self, exelist, version, for_machine, info, arch, **kwargs)
self.id = 'llvm'
self.base_options = ['b_coverage', 'b_colorout', 'b_vscrt', 'b_ndebug']
@@ -750,9 +749,9 @@ class LLVMDCompiler(DmdLikeCompilerMixin, DCompiler):
class DmdDCompiler(DmdLikeCompilerMixin, DCompiler):
- def __init__(self, exelist, version, for_machine: MachineChoice,
- info: 'MachineInfo', arch, **kwargs):
- DCompiler.__init__(self, exelist, version, for_machine, info, arch, False, None, **kwargs)
+ def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice,
+ info: 'MachineInfo', arch: str, **kwargs):
+ DCompiler.__init__(self, exelist, version, for_machine, info, arch, **kwargs)
self.id = 'dmd'
self.base_options = ['b_coverage', 'b_colorout', 'b_vscrt', 'b_ndebug']
diff --git a/mesonbuild/compilers/fortran.py b/mesonbuild/compilers/fortran.py
index 7ca3073..9c2f5bf 100644
--- a/mesonbuild/compilers/fortran.py
+++ b/mesonbuild/compilers/fortran.py
@@ -44,9 +44,9 @@ class FortranCompiler(CLikeCompiler, Compiler):
language = 'fortran'
def __init__(self, exelist, version, for_machine: MachineChoice,
- is_cross, info: 'MachineInfo', exe_wrapper=None, **kwargs):
- Compiler.__init__(self, exelist, version, for_machine, info, **kwargs)
- CLikeCompiler.__init__(self, is_cross, exe_wrapper)
+ is_cross: bool, info: 'MachineInfo', exe_wrapper=None, **kwargs):
+ Compiler.__init__(self, exelist, version, for_machine, info, is_cross=is_cross, **kwargs)
+ CLikeCompiler.__init__(self, exe_wrapper)
self.id = 'unknown'
def has_function(self, funcname, prefix, env, *, extra_args=None, dependencies=None):
@@ -143,7 +143,7 @@ class FortranCompiler(CLikeCompiler, Compiler):
def find_library(self, libname, env, extra_dirs, libtype: LibType = LibType.PREFER_SHARED):
code = 'stop; end program'
- return self.find_library_impl(libname, env, extra_dirs, code, libtype)
+ return self._find_library_impl(libname, env, extra_dirs, code, libtype)
def has_multi_arguments(self, args: T.Sequence[str], env):
for arg in args[:]:
diff --git a/mesonbuild/compilers/java.py b/mesonbuild/compilers/java.py
index 5aeb250..8405b43 100644
--- a/mesonbuild/compilers/java.py
+++ b/mesonbuild/compilers/java.py
@@ -32,7 +32,6 @@ class JavaCompiler(BasicLinkerIsCompilerMixin, Compiler):
info: 'MachineInfo'):
super().__init__(exelist, version, for_machine, info)
self.id = 'unknown'
- self.is_cross = False
self.javarunner = 'java'
def get_werror_args(self):
@@ -64,9 +63,6 @@ class JavaCompiler(BasicLinkerIsCompilerMixin, Compiler):
def get_pic_args(self):
return []
- def name_string(self):
- return ' '.join(self.exelist)
-
def get_pch_use_args(self, pch_dir, header):
return []
diff --git a/mesonbuild/compilers/mixins/arm.py b/mesonbuild/compilers/mixins/arm.py
index b331d8f..25fb545 100644
--- a/mesonbuild/compilers/mixins/arm.py
+++ b/mesonbuild/compilers/mixins/arm.py
@@ -1,4 +1,4 @@
-# Copyright 2012-2019 The Meson development team
+# Copyright 2012-2020 Meson development team
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -15,15 +15,22 @@
"""Representations specific to the arm family of compilers."""
import os
-import re
import typing as T
from ... import mesonlib
+from ...linkers import ArmClangDynamicLinker
from ..compilers import clike_debug_args
from .clang import clang_color_args
if T.TYPE_CHECKING:
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 = {
'plain': [],
@@ -62,9 +69,11 @@ armclang_optimization_args = {
} # type: T.Dict[str, T.List[str]]
-class ArmCompiler:
- # Functionality that is common to all ARM family compilers.
- def __init__(self):
+class ArmCompiler(Compiler):
+
+ """Functionality that is common to all ARM family compilers."""
+
+ def __init__(self) -> None:
if not self.is_cross:
raise mesonlib.EnvironmentException('armcc supports only cross-compilation.')
self.id = 'arm'
@@ -126,32 +135,15 @@ class ArmCompiler:
return parameter_list
-class ArmclangCompiler:
- def __init__(self):
+class ArmclangCompiler(Compiler):
+
+ def __init__(self) -> None:
if not self.is_cross:
raise mesonlib.EnvironmentException('armclang supports only cross-compilation.')
# Check whether 'armlink' is available in path
- self.linker_exe = 'armlink'
- args = '--vsn'
- try:
- p, stdo, stderr = mesonlib.Popen_safe(self.linker_exe, args)
- except OSError as e:
- err_msg = 'Unknown linker\nRunning "{0}" gave \n"{1}"'.format(' '.join([self.linker_exe] + [args]), e)
- raise mesonlib.EnvironmentException(err_msg)
- # Verify the armlink version
- ver_str = re.search('.*Component.*', stdo)
- if ver_str:
- ver_str = ver_str.group(0)
- else:
- raise mesonlib.EnvironmentException('armlink version string not found')
- assert ver_str # makes mypy happy
- # Using the regular expression from environment.search_version,
- # which is used for searching compiler version
- version_regex = r'(?<!(\d|\.))(\d{1,2}(\.\d+)+(-[a-zA-Z0-9]+)?)'
- linker_ver = re.search(version_regex, ver_str)
- if linker_ver:
- linker_ver = linker_ver.group(0)
- if not mesonlib.version_compare(self.version, '==' + linker_ver):
+ if not isinstance(self.linker, ArmClangDynamicLinker):
+ raise mesonlib.EnvironmentException('Unsupported Linker {}, must be armlink'.format(self.linker.exelist))
+ if not mesonlib.version_compare(self.version, '==' + self.linker.version):
raise mesonlib.EnvironmentException('armlink version does not match with compiler version')
self.id = 'armclang'
self.base_options = ['b_pch', 'b_lto', 'b_pgo', 'b_sanitize', 'b_coverage',
diff --git a/mesonbuild/compilers/mixins/c2000.py b/mesonbuild/compilers/mixins/c2000.py
index 65a2cea..aca1ee8 100644
--- a/mesonbuild/compilers/mixins/c2000.py
+++ b/mesonbuild/compilers/mixins/c2000.py
@@ -21,6 +21,13 @@ from ...mesonlib import EnvironmentException
if T.TYPE_CHECKING:
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 = {
'plain': [],
@@ -46,8 +53,9 @@ c2000_debug_args = {
} # type: T.Dict[bool, T.List[str]]
-class C2000Compiler:
- def __init__(self):
+class C2000Compiler(Compiler):
+
+ def __init__(self) -> None:
if not self.is_cross:
raise EnvironmentException('c2000 supports only cross-compilation.')
self.id = 'c2000'
diff --git a/mesonbuild/compilers/mixins/ccrx.py b/mesonbuild/compilers/mixins/ccrx.py
index b859215..fb82797 100644
--- a/mesonbuild/compilers/mixins/ccrx.py
+++ b/mesonbuild/compilers/mixins/ccrx.py
@@ -21,6 +21,13 @@ from ...mesonlib import EnvironmentException
if T.TYPE_CHECKING:
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 = {
'plain': [],
@@ -46,8 +53,13 @@ ccrx_debug_args = {
} # type: T.Dict[bool, T.List[str]]
-class CcrxCompiler:
- def __init__(self):
+class CcrxCompiler(Compiler):
+
+ if T.TYPE_CHECKING:
+ is_cross = True
+ can_compile_suffixes = set() # type: T.Set[str]
+
+ def __init__(self) -> None:
if not self.is_cross:
raise EnvironmentException('ccrx supports only cross-compilation.')
self.id = 'ccrx'
diff --git a/mesonbuild/compilers/mixins/clang.py b/mesonbuild/compilers/mixins/clang.py
index 7525c12..8c85944 100644
--- a/mesonbuild/compilers/mixins/clang.py
+++ b/mesonbuild/compilers/mixins/clang.py
@@ -42,6 +42,7 @@ clang_optimization_args = {
} # type: T.Dict[str, T.List[str]]
class ClangCompiler(GnuLikeCompiler):
+
def __init__(self, defines: T.Optional[T.Dict[str, str]]):
super().__init__()
self.id = 'clang'
@@ -75,17 +76,15 @@ class ClangCompiler(GnuLikeCompiler):
# so it might change semantics at any time.
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']
if mesonlib.version_compare(self.version, '>=3.6.0'):
myargs.append('-Werror=ignored-optimization-argument')
- return super().has_multi_arguments(
- myargs + args,
- env)
+ return super().has_multi_arguments(myargs + args, env)
def has_function(self, funcname: str, prefix: str, env: 'Environment', *,
extra_args: T.Optional[T.List[str]] = None,
- dependencies: T.Optional[T.List['Dependency']] = None) -> bool:
+ dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[bool, bool]:
if extra_args is None:
extra_args = []
# Starting with XCode 8, we need to pass this to force linker
@@ -96,7 +95,7 @@ class ClangCompiler(GnuLikeCompiler):
if isinstance(self.linker, AppleDynamicLinker) and mesonlib.version_compare(self.version, '>=8.0'):
extra_args.append('-Wl,-no_weak_imports')
return super().has_function(funcname, prefix, env, extra_args=extra_args,
- dependencies=dependencies)
+ dependencies=dependencies)
def openmp_flags(self) -> T.List[str]:
if mesonlib.version_compare(self.version, '>=3.8.0'):
@@ -125,7 +124,7 @@ class ClangCompiler(GnuLikeCompiler):
return ['-fuse-ld={}'.format(linker)]
return super().use_linker_args(linker)
- def get_has_func_attribute_extra_args(self, name):
+ def get_has_func_attribute_extra_args(self, name: str) -> T.List[str]:
# Clang only warns about unknown or ignored attributes, so force an
# error.
return ['-Werror=attributes']
diff --git a/mesonbuild/compilers/mixins/clike.py b/mesonbuild/compilers/mixins/clike.py
index b2942d3..e146f5f 100644
--- a/mesonbuild/compilers/mixins/clike.py
+++ b/mesonbuild/compilers/mixins/clike.py
@@ -20,6 +20,8 @@ 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
import itertools
@@ -38,7 +40,15 @@ from .. import compilers
from .visualstudio import VisualStudioLikeCompiler
if T.TYPE_CHECKING:
+ from ...dependencies import Dependency, ExternalProgram
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
GROUP_FLAGS = re.compile(r'''\.so (?:\.[0-9]+)? (?:\.[0-9]+)? (?:\.[0-9]+)?$ |
^(?:-Wl,)?-l |
@@ -55,6 +65,9 @@ class CLikeCompilerArgs(arglist.CompilerArgs):
dedup1_args = ('-c', '-S', '-E', '-pipe', '-pthread')
def to_native(self, copy: bool = False) -> T.List[str]:
+ # This seems to be allowed, but could never work?
+ assert isinstance(self.compiler, compilers.Compiler), 'How did you get here'
+
# Check if we need to add --start/end-group for circular dependencies
# between static libraries, and for recursively searching for symbols
# needed by static libraries that are provided by object files or
@@ -82,8 +95,8 @@ class CLikeCompilerArgs(arglist.CompilerArgs):
new.insert(group_end + 1, '-Wl,--end-group')
new.insert(group_start, '-Wl,--start-group')
# Remove system/default include paths added with -isystem
- if hasattr(self.compiler, 'get_default_include_dirs'):
- default_dirs = self.compiler.get_default_include_dirs()
+ default_dirs = self.compiler.get_default_include_dirs()
+ if default_dirs:
bad_idx_list = [] # type: T.List[int]
for i, each in enumerate(new):
if not each.startswith('-isystem'):
@@ -107,20 +120,20 @@ class CLikeCompilerArgs(arglist.CompilerArgs):
return 'CLikeCompilerArgs({!r}, {!r})'.format(self.compiler, self._container)
-class CLikeCompiler:
+class CLikeCompiler(Compiler):
"""Shared bits for the C and CPP Compilers."""
+ if T.TYPE_CHECKING:
+ warn_args = {} # type: T.Dict[str, T.List[str]]
+
# TODO: Replace this manual cache with functools.lru_cache
- library_dirs_cache = {}
- program_dirs_cache = {}
- find_library_cache = {}
- find_framework_cache = {}
+ 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]]]
internal_libs = arglist.UNIXY_COMPILER_INTERNAL_LIBS
- def __init__(self, is_cross: bool, exe_wrapper: T.Optional[str] = None):
+ def __init__(self, exe_wrapper: T.Optional['ExternalProgram'] = None):
# If a child ObjC or CPP class has already set it, don't set it ourselves
- self.is_cross = is_cross
self.can_compile_suffixes.add('h')
# If the exe wrapper was not found, pretend it wasn't set so that the
# sanity check is skipped and compiler checks use fallbacks.
@@ -130,69 +143,71 @@ class CLikeCompiler:
self.exe_wrapper = exe_wrapper.get_command()
def compiler_args(self, args: T.Optional[T.Iterable[str]] = None) -> CLikeCompilerArgs:
+ # This is correct, mypy just doesn't understand co-operative inheritance
return CLikeCompilerArgs(self, args)
- def needs_static_linker(self):
+ def needs_static_linker(self) -> bool:
return True # When compiling static libraries, so yes.
- def get_always_args(self):
+ def get_always_args(self) -> T.List[str]:
'''
Args that are always-on for all C compilers other than MSVC
'''
- return ['-pipe'] + compilers.get_largefile_args(self)
+ return ['-pipe'] + self.get_largefile_args()
- def get_no_stdinc_args(self):
+ def get_no_stdinc_args(self) -> T.List[str]:
return ['-nostdinc']
- def get_no_stdlib_link_args(self):
+ def get_no_stdlib_link_args(self) -> T.List[str]:
return ['-nostdlib']
- def get_warn_args(self, level):
+ def get_warn_args(self, level: str) -> T.List[str]:
+ # TODO: this should be an enum
return self.warn_args[level]
- def get_no_warn_args(self):
+ def get_no_warn_args(self) -> T.List[str]:
# Almost every compiler uses this for disabling warnings
return ['-w']
- def split_shlib_to_parts(self, fname):
+ def split_shlib_to_parts(self, fname: str) -> T.Tuple[T.Optional[str], str]:
return None, fname
- def depfile_for_object(self, objfile):
+ def depfile_for_object(self, objfile: str) -> str:
return objfile + '.' + self.get_depfile_suffix()
- def get_depfile_suffix(self):
+ def get_depfile_suffix(self) -> str:
return 'd'
- def get_exelist(self):
- return self.exelist[:]
+ def get_exelist(self) -> T.List[str]:
+ return self.exelist.copy()
- def get_preprocess_only_args(self):
+ def get_preprocess_only_args(self) -> T.List[str]:
return ['-E', '-P']
- def get_compile_only_args(self):
+ def get_compile_only_args(self) -> T.List[str]:
return ['-c']
- def get_no_optimization_args(self):
+ def get_no_optimization_args(self) -> T.List[str]:
return ['-O0']
- def get_compiler_check_args(self):
+ def get_compiler_check_args(self) -> T.List[str]:
'''
Get arguments useful for compiler checks such as being permissive in
the code quality and not doing any optimization.
'''
return self.get_no_optimization_args()
- def get_output_args(self, target):
+ def get_output_args(self, target: str) -> T.List[str]:
return ['-o', target]
- def get_werror_args(self):
+ def get_werror_args(self) -> T.List[str]:
return ['-Werror']
- def get_std_exe_link_args(self):
+ def get_std_exe_link_args(self) -> T.List[str]:
# TODO: is this a linker property?
return []
- def get_include_args(self, path, is_system):
+ def get_include_args(self, path: str, is_system: bool) -> T.List[str]:
if path == '':
path = '.'
if is_system:
@@ -206,7 +221,9 @@ class CLikeCompiler:
return []
@functools.lru_cache()
- def get_library_dirs(self, env, elf_class = None):
+ def _get_library_dirs(self, env: 'Environment',
+ elf_class: T.Optional[int] = None) -> T.List[str]:
+ # TODO: replace elf_class with enum
dirs = self.get_compiler_dirs(env, 'libraries')
if elf_class is None or elf_class == 0:
return dirs
@@ -241,22 +258,29 @@ class CLikeCompiler:
# Skip the file if we can't read it
pass
- return tuple(retval)
+ return retval
+
+ def get_library_dirs(self, env: 'Environment',
+ elf_class: T.Optional[int] = None) -> T.List[str]:
+ """Wrap the lru_cache so that we return a new copy and don't allow
+ mutation of the cached value.
+ """
+ return self._get_library_dirs(env, elf_class).copy()
@functools.lru_cache()
- def get_program_dirs(self, env):
+ def _get_program_dirs(self, env: 'Environment') -> T.List[str]:
'''
Programs used by the compiler. Also where toolchain DLLs such as
libstdc++-6.dll are found with MinGW.
'''
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]:
return ['-fPIC']
- def name_string(self) -> str:
- return ' '.join(self.exelist)
-
def get_pch_use_args(self, pch_dir: str, header: str) -> T.List[str]:
return ['-include', os.path.basename(header)]
@@ -266,7 +290,7 @@ class CLikeCompiler:
def get_linker_search_args(self, dirname: str) -> T.List[str]:
return self.linker.get_search_args(dirname)
- def get_default_include_dirs(self):
+ def get_default_include_dirs(self) -> T.List[str]:
return []
def gen_export_dynamic_link_args(self, env: 'Environment') -> T.List[str]:
@@ -275,7 +299,8 @@ class CLikeCompiler:
def gen_import_library_args(self, implibname: str) -> T.List[str]:
return self.linker.import_library_args(implibname)
- def sanity_check_impl(self, work_dir, environment, sname, code):
+ def _sanity_check_impl(self, work_dir: str, environment: 'Environment',
+ sname: str, code: str) -> None:
mlog.debug('Sanity testing ' + self.get_display_language() + ' compiler:', ' '.join(self.exelist))
mlog.debug('Is cross compiler: %s.' % str(self.is_cross))
@@ -330,18 +355,23 @@ class CLikeCompiler:
if pe.returncode != 0:
raise mesonlib.EnvironmentException('Executables created by {0} compiler {1} are not runnable.'.format(self.language, self.name_string()))
- def sanity_check(self, work_dir, environment):
+ def sanity_check(self, work_dir: str, environment: 'Environment') -> None:
code = 'int main(void) { int class=0; return class; }\n'
- return self.sanity_check_impl(work_dir, environment, 'sanitycheckc.c', code)
+ return self._sanity_check_impl(work_dir, environment, 'sanitycheckc.c', code)
- def check_header(self, hname: str, prefix: str, env, *, extra_args=None, dependencies=None):
+ def check_header(self, hname: str, prefix: str, env: 'Environment', *,
+ extra_args: T.Optional[T.List[str]] = None,
+ dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[bool, bool]:
fargs = {'prefix': prefix, 'header': hname}
code = '''{prefix}
#include <{header}>'''
return self.compiles(code.format(**fargs), env, extra_args=extra_args,
dependencies=dependencies)
- def has_header(self, hname: str, prefix: str, env, *, extra_args=None, dependencies=None, disable_cache: bool = False):
+ def has_header(self, hname: str, prefix: str, env: 'Environment', *,
+ extra_args: T.Optional[T.List[str]] = None,
+ dependencies: T.Optional[T.List['Dependency']] = None,
+ disable_cache: bool = False) -> T.Tuple[bool, bool]:
fargs = {'prefix': prefix, 'header': hname}
code = '''{prefix}
#ifdef __has_include
@@ -354,7 +384,10 @@ class CLikeCompiler:
return self.compiles(code.format(**fargs), env, extra_args=extra_args,
dependencies=dependencies, mode='preprocess', disable_cache=disable_cache)
- def has_header_symbol(self, hname: str, symbol: str, prefix: str, env, *, extra_args=None, dependencies=None):
+ def has_header_symbol(self, hname: str, symbol: str, prefix: str,
+ env: 'Environment', *,
+ extra_args: T.Optional[T.List[str]] = None,
+ dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[bool, bool]:
fargs = {'prefix': prefix, 'header': hname, 'symbol': symbol}
t = '''{prefix}
#include <{header}>
@@ -368,8 +401,9 @@ class CLikeCompiler:
return self.compiles(t.format(**fargs), env, extra_args=extra_args,
dependencies=dependencies)
- def _get_basic_compiler_args(self, env, mode: str):
- cargs, largs = [], []
+ def _get_basic_compiler_args(self, env: 'Environment', mode: str) -> T.Tuple[T.List[str], T.List[str]]:
+ cargs = [] # type: T.List[str]
+ largs = [] # type: T.List[str]
if mode == 'link':
# Sometimes we need to manually select the CRT to use with MSVC.
# One example is when trying to do a compiler check that involves
@@ -405,20 +439,26 @@ class CLikeCompiler:
cargs += self.get_compiler_args_for_mode(mode)
return cargs, largs
- def _get_compiler_check_args(self, env, extra_args: list, dependencies, mode: str = 'compile') -> T.List[str]:
+ 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: str = 'compile') -> arglist.CompilerArgs:
+ # TODO: the caller should handle the listfing of these arguments
if extra_args is None:
extra_args = []
else:
+ # TODO: we want to do this in the caller
extra_args = mesonlib.listify(extra_args)
extra_args = mesonlib.listify([e(mode) if callable(e) else e for e in extra_args])
if dependencies is None:
dependencies = []
- elif not isinstance(dependencies, list):
- dependencies = [dependencies]
+ elif not isinstance(dependencies, collections.abc.Iterable):
+ # TODO: we want to ensure the front end does the listifing here
+ dependencies = [dependencies] # type: ignore
# Collect compiler arguments
- cargs = self.compiler_args()
- largs = []
+ cargs = self.compiler_args() # type: arglist.CompilerArgs
+ largs = [] # type: T.List[str]
for d in dependencies:
# Add compile flags needed by dependencies
cargs += d.get_compile_args()
@@ -440,23 +480,40 @@ class CLikeCompiler:
args = cargs + extra_args + largs
return args
- def compiles(self, code: str, env, *,
- extra_args: T.Sequence[T.Union[T.Sequence[str], str]] = None,
- dependencies=None, mode: str = 'compile', disable_cache: bool = False) -> T.Tuple[bool, bool]:
+ 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
- def _build_wrapper(self, code: str, env, extra_args, dependencies=None, mode: str = 'compile', want_output: bool = False, disable_cache: bool = False, temp_dir: str = None) -> T.Tuple[bool, bool]:
+ @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, mode)
if disable_cache or want_output:
- return self.compile(code, extra_args=args, mode=mode, want_output=want_output, temp_dir=env.scratch_dir)
- return self.cached_compile(code, env.coredata, extra_args=args, mode=mode, temp_dir=env.scratch_dir)
-
- def links(self, code, env, *, extra_args=None, dependencies=None, disable_cache=False):
+ 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, *, extra_args=None, dependencies=None):
+ def run(self, code: str, env: 'Environment', *,
+ extra_args: T.Optional[T.List[str]] = None,
+ dependencies: T.Optional[T.List['Dependency']] = None) -> compilers.RunResult:
need_exe_wrapper = env.need_exe_wrapper(self.for_machine)
if need_exe_wrapper and self.exe_wrapper is None:
raise compilers.CrossNoRunException('Can not run test applications in this cross environment.')
@@ -469,7 +526,7 @@ class CLikeCompiler:
if need_exe_wrapper:
cmdlist = self.exe_wrapper + [p.output_name]
else:
- cmdlist = p.output_name
+ cmdlist = [p.output_name]
try:
pe, so, se = mesonlib.Popen_safe(cmdlist)
except Exception as e:
@@ -482,7 +539,9 @@ class CLikeCompiler:
mlog.debug(se)
return compilers.RunResult(True, pe.returncode, so, se)
- def _compile_int(self, expression, prefix, env, extra_args, dependencies):
+ def _compile_int(self, expression: str, prefix: str, env: 'Environment',
+ extra_args: T.Optional[T.List[str]],
+ dependencies: T.Optional[T.List['Dependency']]) -> bool:
fargs = {'prefix': prefix, 'expression': expression}
t = '''#include <stdio.h>
{prefix}
@@ -490,7 +549,10 @@ class CLikeCompiler:
return self.compiles(t.format(**fargs), env, extra_args=extra_args,
dependencies=dependencies)[0]
- def cross_compute_int(self, expression, low, high, guess, prefix, env, extra_args, dependencies):
+ def cross_compute_int(self, expression: str, low: T.Optional[int], high: T.Optional[int],
+ guess: T.Optional[int], prefix: str, env: 'Environment',
+ extra_args: T.Optional[T.List[str]] = None,
+ dependencies: T.Optional[T.List['Dependency']] = None) -> int:
# Try user's guess first
if isinstance(guess, int):
if self._compile_int('%s == %d' % (expression, guess), prefix, env, extra_args, dependencies):
@@ -538,7 +600,10 @@ class CLikeCompiler:
return low
- def compute_int(self, expression, low, high, guess, prefix, env, *, extra_args=None, dependencies=None):
+ def compute_int(self, expression: str, low: T.Optional[int], high: T.Optional[int],
+ guess: T.Optional[int], prefix: str, env: 'Environment', *,
+ extra_args: T.Optional[T.List[str]] = None,
+ dependencies: T.Optional[T.List['Dependency']] = None) -> int:
if extra_args is None:
extra_args = []
if self.is_cross:
@@ -558,7 +623,9 @@ class CLikeCompiler:
raise mesonlib.EnvironmentException('Could not run compute_int test binary.')
return int(res.stdout)
- def cross_sizeof(self, typename, prefix, env, *, extra_args=None, dependencies=None):
+ def cross_sizeof(self, typename: str, prefix: str, env: 'Environment', *,
+ extra_args: T.Optional[T.List[str]] = None,
+ dependencies: T.Optional[T.List['Dependency']] = None) -> int:
if extra_args is None:
extra_args = []
fargs = {'prefix': prefix, 'type': typename}
@@ -573,7 +640,9 @@ class CLikeCompiler:
return -1
return self.cross_compute_int('sizeof(%s)' % typename, None, None, None, prefix, env, extra_args, dependencies)
- def sizeof(self, typename, prefix, env, *, extra_args=None, dependencies=None):
+ def sizeof(self, typename: str, prefix: str, env: 'Environment', *,
+ extra_args: T.Optional[T.List[str]] = None,
+ dependencies: T.Optional[T.List['Dependency']] = None) -> int:
if extra_args is None:
extra_args = []
fargs = {'prefix': prefix, 'type': typename}
@@ -594,7 +663,9 @@ class CLikeCompiler:
raise mesonlib.EnvironmentException('Could not run sizeof test binary.')
return int(res.stdout)
- def cross_alignment(self, typename, prefix, env, *, extra_args=None, dependencies=None):
+ def cross_alignment(self, typename: str, prefix: str, env: 'Environment', *,
+ extra_args: T.Optional[T.List[str]] = None,
+ dependencies: T.Optional[T.List['Dependency']] = None) -> int:
if extra_args is None:
extra_args = []
fargs = {'prefix': prefix, 'type': typename}
@@ -615,7 +686,9 @@ class CLikeCompiler:
}};'''
return self.cross_compute_int('offsetof(struct tmp, target)', None, None, None, t.format(**fargs), env, extra_args, dependencies)
- def alignment(self, typename, prefix, env, *, extra_args=None, dependencies=None):
+ def alignment(self, typename: str, prefix: str, env: 'Environment', *,
+ extra_args: T.Optional[T.List[str]] = None,
+ dependencies: T.Optional[T.List['Dependency']] = None) -> int:
if extra_args is None:
extra_args = []
if self.is_cross:
@@ -644,7 +717,10 @@ class CLikeCompiler:
raise mesonlib.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, disable_cache=False):
+ def get_define(self, dname: str, prefix: str, env: 'Environment',
+ extra_args: T.Optional[T.List[str]],
+ dependencies: T.Optional[T.List['Dependency']],
+ disable_cache: bool = False) -> T.Tuple[str, bool]:
delim = '"MESON_GET_DEFINE_DELIMITER"'
fargs = {'prefix': prefix, 'define': dname, 'delim': delim}
code = '''
@@ -655,9 +731,9 @@ class CLikeCompiler:
{delim}\n{define}'''
args = self._get_compiler_check_args(env, extra_args, dependencies,
mode='preprocess').to_native()
- func = lambda: self.cached_compile(code.format(**fargs), env.coredata, extra_args=args, mode='preprocess')
+ func = functools.partial(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', temp_dir=env.scratch_dir)
+ func = functools.partial(self.compile, code.format(**fargs), extra_args=args, mode='preprocess', temp_dir=env.scratch_dir)
with func() as p:
cached = p.cached
if p.returncode != 0:
@@ -665,9 +741,13 @@ class CLikeCompiler:
# Get the preprocessed value after the delimiter,
# minus the extra newline at the end and
# merge string literals.
- return self.concatenate_string_literals(p.stdo.split(delim + '\n')[-1][:-1]), cached
+ return self._concatenate_string_literals(p.stdout.split(delim + '\n')[-1][:-1]), cached
- def get_return_value(self, fname, rtype, prefix, env, extra_args, dependencies):
+ def get_return_value(self, fname: str, rtype: str, prefix: str,
+ env: 'Environment', extra_args: T.Optional[T.List[str]],
+ dependencies: T.Optional[T.List['Dependency']]) -> T.Union[str, int]:
+ # TODO: rtype should be an enum.
+ # TODO: maybe we can use overload to tell mypy when this will return int vs str?
if rtype == 'string':
fmt = '%s'
cast = '(char*)'
@@ -695,9 +775,10 @@ class CLikeCompiler:
except ValueError:
m = 'Return value of {}() is not an int'
raise mesonlib.EnvironmentException(m.format(fname))
+ assert False, 'Unreachable'
@staticmethod
- def _no_prototype_templ():
+ def _no_prototype_templ() -> T.Tuple[str, str]:
"""
Try to find the function without a prototype from a header by defining
our own dummy prototype and trying to link with the C library (and
@@ -732,7 +813,7 @@ class CLikeCompiler:
return head, main
@staticmethod
- def _have_prototype_templ():
+ def _have_prototype_templ() -> T.Tuple[str, str]:
"""
Returns a head-er and main() call that uses the headers listed by the
user for the function prototype while checking if a function exists.
@@ -752,8 +833,11 @@ class CLikeCompiler:
}}'''
return head, main
- def has_function(self, funcname, prefix, env, *, extra_args=None, dependencies=None):
- """
+ def has_function(self, funcname: str, prefix: str, env: 'Environment', *,
+ extra_args: T.Optional[T.List[str]] = None,
+ dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[bool, bool]:
+ """Determine if a function exists.
+
First, this function looks for the symbol in the default libraries
provided by the compiler (stdlib + a few others usually). If that
fails, it checks if any of the headers specified in the prefix provide
@@ -773,7 +857,11 @@ class CLikeCompiler:
return val, False
raise mesonlib.EnvironmentException('Cross variable {0} is not a boolean.'.format(varname))
- fargs = {'prefix': prefix, 'func': funcname}
+ # TODO: we really need a protocol for this,
+ #
+ # class StrProto(typing.Protocol):
+ # def __str__(self) -> str: ...
+ fargs = {'prefix': prefix, 'func': funcname} # type: T.Dict[str, T.Union[str, bool, int]]
# glibc defines functions that are not available on Linux as stubs that
# fail with ENOSYS (such as e.g. lchmod). In this case we want to fail
@@ -845,7 +933,10 @@ class CLikeCompiler:
return self.links(t.format(**fargs), env, extra_args=extra_args,
dependencies=dependencies)
- def has_members(self, typename, membernames, prefix, env, *, extra_args=None, dependencies=None):
+ def has_members(self, typename: str, membernames: T.List[str],
+ prefix: str, env: 'Environment', *,
+ extra_args: T.Optional[T.List[str]] = None,
+ dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[bool, bool]:
if extra_args is None:
extra_args = []
fargs = {'prefix': prefix, 'type': typename, 'name': 'foo'}
@@ -862,7 +953,8 @@ class CLikeCompiler:
return self.compiles(t.format(**fargs), env, extra_args=extra_args,
dependencies=dependencies)
- def has_type(self, typename, prefix, env, extra_args, dependencies=None):
+ def has_type(self, typename: str, prefix: str, env: 'Environment', extra_args: T.List[str],
+ dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[bool, bool]:
fargs = {'prefix': prefix, 'type': typename}
t = '''{prefix}
void bar(void) {{
@@ -871,7 +963,7 @@ class CLikeCompiler:
return self.compiles(t.format(**fargs), env, extra_args=extra_args,
dependencies=dependencies)
- def symbols_have_underscore_prefix(self, env):
+ def symbols_have_underscore_prefix(self, env: 'Environment') -> bool:
'''
Check if the compiler prefixes an underscore to global C symbols
'''
@@ -889,7 +981,7 @@ class CLikeCompiler:
with self._build_wrapper(code, env, extra_args=args, mode='compile', want_output=True, temp_dir=env.scratch_dir) as p:
if p.returncode != 0:
m = 'BUG: Unable to compile {!r} check: {}'
- raise RuntimeError(m.format(n, p.stdo))
+ raise RuntimeError(m.format(n, p.stdout))
if not os.path.isfile(p.output_name):
m = 'BUG: Can\'t find compiled test code for {!r} check'
raise RuntimeError(m.format(n))
@@ -906,8 +998,8 @@ class CLikeCompiler:
return False
raise RuntimeError('BUG: {!r} check failed unexpectedly'.format(n))
- def _get_patterns(self, env, prefixes, suffixes, shared=False):
- patterns = []
+ def _get_patterns(self, env: 'Environment', prefixes: T.List[str], suffixes: T.List[str], shared: bool = False) -> T.List[str]:
+ patterns = [] # type: T.List[str]
for p in prefixes:
for s in suffixes:
patterns.append(p + '{}.' + s)
@@ -923,7 +1015,7 @@ class CLikeCompiler:
patterns.append(p + '{}.so.[0-9]*.[0-9]*')
return patterns
- def get_library_naming(self, env, libtype: LibType, strict=False):
+ def get_library_naming(self, env: 'Environment', libtype: LibType, strict: bool = False) -> T.Tuple[str, ...]:
'''
Get library prefixes and suffixes for the target platform ordered by
priority
@@ -970,8 +1062,8 @@ class CLikeCompiler:
return tuple(patterns)
@staticmethod
- def _sort_shlibs_openbsd(libs):
- filtered = []
+ def _sort_shlibs_openbsd(libs: T.List[str]) -> T.List[str]:
+ filtered = [] # type: T.List[str]
for lib in libs:
# Validate file as a shared library of type libfoo.so.X.Y
ret = lib.rsplit('.so.', maxsplit=1)
@@ -986,7 +1078,7 @@ class CLikeCompiler:
return sorted(filtered, key=float_cmp, reverse=True)
@classmethod
- def _get_trials_from_pattern(cls, pattern, directory, libname):
+ def _get_trials_from_pattern(cls, pattern: str, directory: str, libname: str) -> T.List[Path]:
f = Path(directory) / pattern.format(libname)
# Globbing for OpenBSD
if '*' in pattern:
@@ -996,7 +1088,7 @@ class CLikeCompiler:
return [f]
@staticmethod
- def _get_file_from_list(env, files: T.List[str]) -> Path:
+ def _get_file_from_list(env: 'Environment', paths: T.List[Path]) -> Path:
'''
We just check whether the library exists. We can't do a link check
because the library might have unresolved symbols that require other
@@ -1004,7 +1096,6 @@ class CLikeCompiler:
architecture.
'''
# If not building on macOS for Darwin, do a simple file check
- paths = [Path(f) for f in files]
if not env.machines.host.is_darwin() or not env.machines.build.is_darwin():
for p in paths:
if p.is_file():
@@ -1022,13 +1113,13 @@ class CLikeCompiler:
return None
@functools.lru_cache()
- def output_is_64bit(self, env):
+ def output_is_64bit(self, env: 'Environment') -> bool:
'''
returns true if the output produced is 64-bit, false if 32-bit
'''
return self.sizeof('void *', '', env) == 8
- def find_library_real(self, libname, env, extra_dirs, code, libtype: LibType):
+ def _find_library_real(self, libname: str, env: 'Environment', extra_dirs: T.List[str], code: str, libtype: LibType) -> T.Optional[T.List[str]]:
# First try if we can just add the library as -l.
# Gcc + co seem to prefer builtin lib dirs to -L dirs.
# Only try to find std libs if no extra dirs specified.
@@ -1061,16 +1152,17 @@ class CLikeCompiler:
# Search in the specified dirs, and then in the system libraries
for d in itertools.chain(extra_dirs, self.get_library_dirs(env, elf_class)):
for p in patterns:
- trial = self._get_trials_from_pattern(p, d, libname)
- if not trial:
+ trials = self._get_trials_from_pattern(p, d, libname)
+ if not trials:
continue
- trial = self._get_file_from_list(env, trial)
+ trial = self._get_file_from_list(env, trials)
if not trial:
continue
return [trial.as_posix()]
return None
- def find_library_impl(self, libname, env, extra_dirs, code, libtype: LibType):
+ def _find_library_impl(self, libname: str, env: 'Environment', extra_dirs: T.List[str],
+ code: str, libtype: LibType) -> T.Optional[T.List[str]]:
# These libraries are either built-in or invalid
if libname in self.ignore_libs:
return []
@@ -1078,24 +1170,26 @@ class CLikeCompiler:
extra_dirs = [extra_dirs]
key = (tuple(self.exelist), libname, tuple(extra_dirs), code, libtype)
if key not in self.find_library_cache:
- value = self.find_library_real(libname, env, extra_dirs, code, libtype)
+ value = self._find_library_real(libname, env, extra_dirs, code, libtype)
self.find_library_cache[key] = value
else:
value = self.find_library_cache[key]
if value is None:
return None
- return value[:]
+ return value.copy()
- def find_library(self, libname, env, extra_dirs, libtype: LibType = LibType.PREFER_SHARED):
+ def find_library(self, libname: str, env: 'Environment', extra_dirs: T.List[str],
+ libtype: LibType = LibType.PREFER_SHARED) -> T.Optional[T.List[str]]:
code = 'int main(void) { return 0; }\n'
- return self.find_library_impl(libname, env, extra_dirs, code, libtype)
+ return self._find_library_impl(libname, env, extra_dirs, code, libtype)
- def find_framework_paths(self, env):
+ def find_framework_paths(self, env: 'Environment') -> T.List[str]:
'''
These are usually /Library/Frameworks and /System/Library/Frameworks,
unless you select a particular macOS SDK with the -isysroot flag.
You can also add to this by setting -F in CFLAGS.
'''
+ # TODO: this really needs to be *AppleClang*, not just any clang.
if self.id != 'clang':
raise mesonlib.MesonException('Cannot find framework path with non-clang compiler')
# Construct the compiler command-line
@@ -1107,7 +1201,7 @@ class CLikeCompiler:
os_env = os.environ.copy()
os_env['LC_ALL'] = 'C'
_, _, stde = mesonlib.Popen_safe(commands, env=os_env, stdin=subprocess.PIPE)
- paths = []
+ paths = [] # T.List[str]
for line in stde.split('\n'):
if '(framework directory)' not in line:
continue
@@ -1116,7 +1210,7 @@ class CLikeCompiler:
paths.append(line[:-21].strip())
return paths
- def find_framework_real(self, name, env, extra_dirs, allow_system):
+ def _find_framework_real(self, name: str, env: 'Environment', extra_dirs: T.List[str], allow_system: bool) -> T.Optional[T.List[str]]:
code = 'int main(void) { return 0; }'
link_args = []
for d in extra_dirs:
@@ -1127,36 +1221,43 @@ class CLikeCompiler:
link_args += ['-framework', name]
if self.links(code, env, extra_args=(extra_args + link_args), disable_cache=True)[0]:
return link_args
+ return None
- def find_framework_impl(self, name, env, extra_dirs, allow_system):
+ def _find_framework_impl(self, name: str, env: 'Environment', extra_dirs: T.List[str],
+ allow_system: bool) -> T.Optional[T.List[str]]:
if isinstance(extra_dirs, str):
extra_dirs = [extra_dirs]
key = (tuple(self.exelist), name, tuple(extra_dirs), allow_system)
if key in self.find_framework_cache:
value = self.find_framework_cache[key]
else:
- value = self.find_framework_real(name, env, extra_dirs, allow_system)
+ value = self._find_framework_real(name, env, extra_dirs, allow_system)
self.find_framework_cache[key] = value
if value is None:
return None
- return value[:]
+ return value.copy()
- def find_framework(self, name, env, extra_dirs, allow_system=True):
+ def find_framework(self, name: str, env: 'Environment', extra_dirs: T.List[str],
+ allow_system: bool = True) -> T.Optional[T.List[str]]:
'''
Finds the framework with the specified name, and returns link args for
the same or returns None when the framework is not found.
'''
+ # TODO: maybe this belongs in clang? also, should probably check for macOS?
if self.id != 'clang':
raise mesonlib.MesonException('Cannot find frameworks with non-clang compiler')
- return self.find_framework_impl(name, env, extra_dirs, allow_system)
+ return self._find_framework_impl(name, env, extra_dirs, allow_system)
def get_crt_compile_args(self, crt_val: str, buildtype: str) -> T.List[str]:
+ # TODO: does this belong here or in GnuLike or maybe PosixLike?
return []
def get_crt_link_args(self, crt_val: str, buildtype: str) -> T.List[str]:
+ # TODO: does this belong here or in GnuLike or maybe PosixLike?
return []
- def thread_flags(self, env):
+ def thread_flags(self, env: 'Environment') -> T.List[str]:
+ # TODO: does this belong here or in GnuLike or maybe PosixLike?
host_m = env.machines[self.for_machine]
if host_m.is_haiku() or host_m.is_darwin():
return []
@@ -1165,19 +1266,21 @@ class CLikeCompiler:
def thread_link_flags(self, env: 'Environment') -> T.List[str]:
return self.linker.thread_flags(env)
- def linker_to_compiler_args(self, args):
- return args
+ def linker_to_compiler_args(self, args: T.List[str]) -> T.List[str]:
+ return args.copy()
- def has_arguments(self, args: T.Sequence[str], env, code: str, mode: str) -> T.Tuple[bool, bool]:
+ def has_arguments(self, args: T.List[str], env: 'Environment', code: str,
+ mode: str) -> T.Tuple[bool, bool]:
return self.compiles(code, env, extra_args=args, mode=mode)
- def has_multi_arguments(self, args, env):
- for arg in args[:]:
+ def has_multi_arguments(self, args: T.List[str], env: 'Environment') -> T.Tuple[bool, bool]:
+ new_args = [] # type: T.List[str]
+ for arg in args:
# some compilers, e.g. GCC, don't warn for unsupported warning-disable
# flags, so when we are testing a flag like "-Wno-forgotten-towel", also
# check the equivalent enable flag too "-Wforgotten-towel"
if arg.startswith('-Wno-'):
- args.append('-W' + arg[5:])
+ new_args.append('-W' + arg[5:])
if arg.startswith('-Wl,'):
mlog.warning('{} looks like a linker argument, '
'but has_argument and other similar methods only '
@@ -1187,10 +1290,11 @@ class CLikeCompiler:
'the compiler you are using. has_link_argument or '
'other similar method can be used instead.'
.format(arg))
+ new_args.append(arg)
code = 'extern int i;\nint i;\n'
- return self.has_arguments(args, env, code, mode='compile')
+ return self.has_arguments(new_args, env, code, mode='compile')
- def has_multi_link_arguments(self, args, env):
+ def has_multi_link_arguments(self, args: T.List[str], env: 'Environment') -> T.Tuple[bool, bool]:
# First time we check for link flags we need to first check if we have
# --fatal-warnings, otherwise some linker checks could give some
# false positive.
@@ -1200,7 +1304,7 @@ class CLikeCompiler:
return self.has_arguments(args, env, code, mode='link')
@staticmethod
- def concatenate_string_literals(s):
+ def _concatenate_string_literals(s: str) -> str:
pattern = re.compile(r'(?P<pre>.*([^\\]")|^")(?P<str1>([^\\"]|\\.)*)"\s+"(?P<str2>([^\\"]|\\.)*)(?P<post>".*)')
ret = s
m = pattern.match(ret)
@@ -1209,13 +1313,13 @@ class CLikeCompiler:
m = pattern.match(ret)
return ret
- def get_has_func_attribute_extra_args(self, name):
+ def get_has_func_attribute_extra_args(self, name: str) -> T.List[str]:
# Most compilers (such as GCC and Clang) only warn about unknown or
# ignored attributes, so force an error. Overriden in GCC and Clang
# mixins.
return ['-Werror']
- def has_func_attribute(self, name, env):
+ def has_func_attribute(self, name: str, env: 'Environment') -> T.Tuple[bool, bool]:
# Just assume that if we're not on windows that dllimport and dllexport
# don't work
m = env.machines[self.for_machine]
diff --git a/mesonbuild/compilers/mixins/compcert.py b/mesonbuild/compilers/mixins/compcert.py
index ebcccf5..0f816a8 100644
--- a/mesonbuild/compilers/mixins/compcert.py
+++ b/mesonbuild/compilers/mixins/compcert.py
@@ -20,6 +20,13 @@ import typing as T
if T.TYPE_CHECKING:
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 = {
'plain': [''],
@@ -51,7 +58,8 @@ ccomp_args_to_wul = [
r"^-r$"
] # type: T.List[str]
-class CompCertCompiler:
+class CompCertCompiler(Compiler):
+
def __init__(self) -> None:
self.id = 'ccomp'
# Assembly
@@ -78,9 +86,9 @@ class CompCertCompiler:
def get_pch_use_args(self, pch_dir: str, header: str) -> T.List[str]:
return []
- def unix_args_to_native(self, args):
+ def unix_args_to_native(self, args: T.List[str]) -> T.List[str]:
"Always returns a copy that can be independently mutated"
- patched_args = []
+ patched_args = [] # type: T.List[str]
for arg in args:
added = 0
for ptrn in ccomp_args_to_wul:
diff --git a/mesonbuild/compilers/mixins/elbrus.py b/mesonbuild/compilers/mixins/elbrus.py
index db743d8..2ea3599 100644
--- a/mesonbuild/compilers/mixins/elbrus.py
+++ b/mesonbuild/compilers/mixins/elbrus.py
@@ -30,7 +30,8 @@ if T.TYPE_CHECKING:
class ElbrusCompiler(GnuLikeCompiler):
# Elbrus compiler is nearly like GCC, but does not support
# PCH, LTO, sanitizers and color output as of version 1.21.x.
- def __init__(self):
+
+ def __init__(self) -> None:
super().__init__()
self.id = 'lcc'
self.base_options = ['b_pgo', 'b_coverage',
diff --git a/mesonbuild/compilers/mixins/emscripten.py b/mesonbuild/compilers/mixins/emscripten.py
index 08b2205..87bc40c 100644
--- a/mesonbuild/compilers/mixins/emscripten.py
+++ b/mesonbuild/compilers/mixins/emscripten.py
@@ -20,12 +20,19 @@ import typing as T
from ... import coredata
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
-class EmscriptenMixin:
+class EmscriptenMixin(Compiler):
- def _get_compile_output(self, dirname, mode):
+ def _get_compile_output(self, dirname: str, mode: str) -> str:
# In pre-processor mode, the output is sent to stdout and discarded
if mode == 'preprocess':
return None
@@ -48,7 +55,7 @@ class EmscriptenMixin:
args.extend(['-s', 'PTHREAD_POOL_SIZE={}'.format(count)])
return args
- def get_options(self):
+ def get_options(self) -> 'coredata.OptionDictType':
opts = super().get_options()
opts.update({
'{}_thread_count'.format(self.language): coredata.UserIntegerOption(
diff --git a/mesonbuild/compilers/mixins/gnu.py b/mesonbuild/compilers/mixins/gnu.py
index 83f7047..9c60fcb 100644
--- a/mesonbuild/compilers/mixins/gnu.py
+++ b/mesonbuild/compilers/mixins/gnu.py
@@ -26,8 +26,14 @@ from ... import mesonlib
from ... import mlog
if T.TYPE_CHECKING:
- from ...coredata import UserOption # noqa: F401
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.
# FIXME: this really is a posix interface not a c-like interface
@@ -106,7 +112,7 @@ def gnulike_default_include_dirs(compiler: T.Tuple[str], lang: str) -> T.List[st
)
stdout = p.stdout.read().decode('utf-8', errors='replace')
parse_state = 0
- paths = []
+ paths = [] # type: T.List[str]
for line in stdout.split('\n'):
line = line.strip(' \n\r\t')
if parse_state == 0:
@@ -129,7 +135,7 @@ def gnulike_default_include_dirs(compiler: T.Tuple[str], lang: str) -> T.List[st
return paths
-class GnuLikeCompiler(metaclass=abc.ABCMeta):
+class GnuLikeCompiler(Compiler, metaclass=abc.ABCMeta):
"""
GnuLikeCompiler is a common interface to all compilers implementing
the GNU-style commandline interface. This includes GCC, Clang
@@ -139,7 +145,7 @@ class GnuLikeCompiler(metaclass=abc.ABCMeta):
LINKER_PREFIX = '-Wl,'
- def __init__(self):
+ def __init__(self) -> None:
self.base_options = ['b_pch', 'b_lto', 'b_pgo', 'b_coverage',
'b_ndebug', 'b_staticpic', 'b_pie']
if not (self.info.is_windows() or self.info.is_cygwin() or self.info.is_openbsd()):
@@ -164,14 +170,14 @@ class GnuLikeCompiler(metaclass=abc.ABCMeta):
@abc.abstractmethod
def get_optimization_args(self, optimization_level: str) -> T.List[str]:
- raise NotImplementedError("get_optimization_args not implemented")
+ pass
def get_debug_args(self, is_debug: bool) -> T.List[str]:
return clike_debug_args[is_debug]
@abc.abstractmethod
def get_pch_suffix(self) -> str:
- raise NotImplementedError("get_pch_suffix not implemented")
+ pass
def split_shlib_to_parts(self, fname: str) -> T.Tuple[str, str]:
return os.path.dirname(fname), fname
@@ -184,7 +190,7 @@ class GnuLikeCompiler(metaclass=abc.ABCMeta):
@abc.abstractmethod
def openmp_flags(self) -> T.List[str]:
- raise NotImplementedError("openmp_flags not implemented")
+ pass
def gnu_symbol_visibility_args(self, vistype: str) -> T.List[str]:
return gnu_symbol_visibility_args[vistype]
@@ -223,12 +229,10 @@ class GnuLikeCompiler(metaclass=abc.ABCMeta):
@functools.lru_cache()
def _get_search_dirs(self, env: 'Environment') -> str:
extra_args = ['--print-search-dirs']
- stdo = None
with self._build_wrapper('', env, extra_args=extra_args,
dependencies=None, mode='compile',
want_output=True) as p:
- stdo = p.stdo
- return stdo
+ return p.stdout
def _split_fetch_real_dirs(self, pathstr: str) -> T.List[str]:
# We need to use the path separator used by the compiler for printing
@@ -291,7 +295,7 @@ class GnuLikeCompiler(metaclass=abc.ABCMeta):
def get_output_args(self, target: str) -> T.List[str]:
return ['-o', target]
- def get_dependency_gen_args(self, outtarget, outfile):
+ def get_dependency_gen_args(self, outtarget: str, outfile: str) -> T.List[str]:
return ['-MD', '-MQ', outtarget, '-MF', outfile]
def get_compile_only_args(self) -> T.List[str]:
@@ -322,7 +326,7 @@ class GnuCompiler(GnuLikeCompiler):
Compilers imitating GCC (Clang/Intel) should use the GnuLikeCompiler ABC.
"""
- def __init__(self, defines: T.Dict[str, str]):
+ def __init__(self, defines: T.Optional[T.Dict[str, str]]):
super().__init__()
self.id = 'gcc'
self.defines = defines or {}
@@ -334,6 +338,7 @@ class GnuCompiler(GnuLikeCompiler):
return []
def get_warn_args(self, level: str) -> T.List[str]:
+ # Mypy doesn't understand cooperative inheritance
args = super().get_warn_args(level)
if mesonlib.version_compare(self.version, '<4.8.0') and '-Wpedantic' in args:
# -Wpedantic was added in 4.8.0
@@ -358,19 +363,20 @@ class GnuCompiler(GnuLikeCompiler):
def openmp_flags(self) -> T.List[str]:
return ['-fopenmp']
- def has_arguments(self, args, env, code, mode):
+ def has_arguments(self, args: T.List[str], env: 'Environment', code: str,
+ mode: str) -> T.Tuple[bool, bool]:
# For some compiler command line arguments, the GNU compilers will
# emit a warning on stderr indicating that an option is valid for a
# another language, but still complete with exit_success
with self._build_wrapper(code, env, args, None, mode) as p:
result = p.returncode == 0
- if self.language in {'cpp', 'objcpp'} and 'is valid for C/ObjC' in p.stde:
+ if self.language in {'cpp', 'objcpp'} and 'is valid for C/ObjC' in p.stderr:
result = False
- if self.language in {'c', 'objc'} and 'is valid for C++/ObjC++' in p.stde:
+ if self.language in {'c', 'objc'} and 'is valid for C++/ObjC++' in p.stderr:
result = False
return result, p.cached
- def get_has_func_attribute_extra_args(self, name):
+ def get_has_func_attribute_extra_args(self, name: str) -> T.List[str]:
# GCC only warns about unknown or ignored attributes, so force an
# error.
return ['-Werror=attributes']
diff --git a/mesonbuild/compilers/mixins/intel.py b/mesonbuild/compilers/mixins/intel.py
index eb4b10d..b83e5c4 100644
--- a/mesonbuild/compilers/mixins/intel.py
+++ b/mesonbuild/compilers/mixins/intel.py
@@ -28,7 +28,9 @@ from .gnu import GnuLikeCompiler
from .visualstudio import VisualStudioLikeCompiler
if T.TYPE_CHECKING:
- import subprocess # noqa: F401
+ from ...arglist import CompilerArgs
+ from ...dependencies import Dependency
+ from ...environment import Environment
# XXX: avoid circular dependencies
# TODO: this belongs in a posix compiler class
@@ -97,21 +99,21 @@ class IntelGnuLikeCompiler(GnuLikeCompiler):
else:
return ['-openmp']
- def compiles(self, *args, **kwargs) -> T.Tuple[bool, bool]:
- # This covers a case that .get('foo', []) doesn't, that extra_args is
- # defined and is None
- extra_args = kwargs.get('extra_args') or []
- kwargs['extra_args'] = [
- extra_args,
+ 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]:
+ extra_args = extra_args.copy() if extra_args is not None else []
+ extra_args += [
'-diag-error', '10006', # ignoring unknown option
'-diag-error', '10148', # Option not supported
'-diag-error', '10155', # ignoring argument required
'-diag-error', '10156', # ignoring not argument allowed
'-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', '1292', # unknown __attribute__
]
- return super().compiles(*args, **kwargs)
+ return super().compiles(code, env, extra_args=extra_args, dependencies=dependencies, mode=mode, disable_cache=disable_cache)
def get_profile_generate_args(self) -> T.List[str]:
return ['-prof-gen=threadsafe']
@@ -125,6 +127,9 @@ class IntelGnuLikeCompiler(GnuLikeCompiler):
def get_optimization_args(self, optimization_level: str) -> T.List[str]:
return self.OPTIM_ARGS[optimization_level]
+ def get_has_func_attribute_extra_args(self, name: str) -> T.List[str]:
+ return ['-diag-error', '1292']
+
class IntelVisualStudioLikeCompiler(VisualStudioLikeCompiler):
@@ -148,13 +153,17 @@ class IntelVisualStudioLikeCompiler(VisualStudioLikeCompiler):
's': ['/Os'],
}
- def __init__(self, target: str):
+ def __init__(self, target: str) -> None:
super().__init__(target)
self.id = 'intel-cl'
- def compile(self, code: str, *, extra_args: T.Optional[T.List[str]] = None, **kwargs) -> T.Iterator['subprocess.Popen']:
+ 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]:
# This covers a case that .get('foo', []) doesn't, that extra_args is
- if kwargs.get('mode', 'compile') != 'link':
+ if mode != 'link':
extra_args = extra_args.copy() if extra_args is not None else []
extra_args.extend([
'/Qdiag-error:10006', # ignoring unknown option
@@ -164,7 +173,7 @@ class IntelVisualStudioLikeCompiler(VisualStudioLikeCompiler):
'/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
])
- return super().compile(code, extra_args, **kwargs)
+ return super().compiles(code, env, extra_args=extra_args, dependencies=dependencies, mode=mode, disable_cache=disable_cache)
def get_toolset_version(self) -> T.Optional[str]:
# Avoid circular dependencies....
diff --git a/mesonbuild/compilers/mixins/islinker.py b/mesonbuild/compilers/mixins/islinker.py
index a9967d6..ce7a8af 100644
--- a/mesonbuild/compilers/mixins/islinker.py
+++ b/mesonbuild/compilers/mixins/islinker.py
@@ -27,9 +27,16 @@ from ... import mesonlib
if T.TYPE_CHECKING:
from ...coredata import OptionDictType
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.
@@ -99,8 +106,8 @@ class BasicLinkerIsCompilerMixin:
def bitcode_args(self) -> T.List[str]:
raise mesonlib.MesonException("This linker doesn't support bitcode bundles")
- def get_soname_args(self, for_machine: 'mesonlib.MachineChoice',
- prefix: str, shlib_name: str, suffix: str, soversion: str,
+ def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str,
+ suffix: str, soversion: str,
darwin_versions: T.Tuple[str, str],
is_shared_module: bool) -> T.List[str]:
raise mesonlib.MesonException("This linker doesn't support soname args")
diff --git a/mesonbuild/compilers/mixins/pgi.py b/mesonbuild/compilers/mixins/pgi.py
index 77a7a28..f6ad279 100644
--- a/mesonbuild/compilers/mixins/pgi.py
+++ b/mesonbuild/compilers/mixins/pgi.py
@@ -20,6 +20,16 @@ from pathlib import Path
from ..compilers import clike_debug_args, clike_optimization_args
+if T.TYPE_CHECKING:
+ 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 = {
'plain': [],
'debug': [],
@@ -30,8 +40,9 @@ pgi_buildtype_args = {
} # type: T.Dict[str, T.List[str]]
-class PGICompiler:
- def __init__(self):
+class PGICompiler(Compiler):
+
+ def __init__(self) -> None:
self.base_options = ['b_pch']
self.id = 'pgi'
@@ -94,6 +105,6 @@ class PGICompiler:
else:
return []
- def thread_flags(self, env):
+ def thread_flags(self, env: 'Environment') -> T.List[str]:
# PGI cannot accept -pthread, it's already threaded
return []
diff --git a/mesonbuild/compilers/mixins/visualstudio.py b/mesonbuild/compilers/mixins/visualstudio.py
index 0ea03f0..d9abb95 100644
--- a/mesonbuild/compilers/mixins/visualstudio.py
+++ b/mesonbuild/compilers/mixins/visualstudio.py
@@ -20,11 +20,19 @@ import abc
import os
import typing as T
+from ... import arglist
from ... import mesonlib
from ... import mlog
if T.TYPE_CHECKING:
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
vs32_instruction_set_args = {
'mmx': ['/arch:SSE'], # There does not seem to be a flag just for MMX
@@ -85,7 +93,7 @@ msvc_debug_args = {
} # 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
interface.
@@ -97,10 +105,8 @@ class VisualStudioLikeCompiler(metaclass=abc.ABCMeta):
std_warn_args = ['/W3']
std_opt_args = ['/O2']
- # XXX: this is copied in this patch only to avoid circular dependencies
- #ignore_libs = unixy_compiler_internal_libs
- ignore_libs = ('m', 'c', 'pthread', 'dl', 'rt', 'execinfo')
- internal_libs = ()
+ ignore_libs = arglist.UNIXY_COMPILER_INTERNAL_LIBS + ['execinfo']
+ internal_libs = [] # type: T.List[str]
crt_args = {
'none': [],
@@ -137,6 +143,7 @@ class VisualStudioLikeCompiler(metaclass=abc.ABCMeta):
self.machine = 'arm'
else:
self.machine = target
+ assert self.linker is not None
self.linker.machine = self.machine
# Override CCompiler.get_always_args
@@ -291,12 +298,12 @@ class VisualStudioLikeCompiler(metaclass=abc.ABCMeta):
# Visual Studio is special. It ignores some arguments it does not
# understand and you can't tell it to error out on those.
# http://stackoverflow.com/questions/15259720/how-can-i-make-the-microsoft-c-compiler-treat-unknown-flags-as-errors-rather-t
- def has_arguments(self, args: T.List[str], env: 'Environment', code, mode: str) -> T.Tuple[bool, bool]:
+ def has_arguments(self, args: T.List[str], env: 'Environment', code: str, mode: str) -> T.Tuple[bool, bool]:
warning_text = '4044' if mode == 'link' else '9002'
with self._build_wrapper(code, env, extra_args=args, mode=mode) as p:
if p.returncode != 0:
return False, p.cached
- return not(warning_text in p.stde or warning_text in p.stdo), p.cached
+ return not(warning_text in p.stderr or warning_text in p.stdout), p.cached
def get_compile_debugfile_args(self, rel_obj: str, pch: bool = False) -> T.List[str]:
pdbarr = rel_obj.split('.')[:-1]
@@ -420,7 +427,7 @@ class ClangClCompiler(VisualStudioLikeCompiler):
super().__init__(target)
self.id = 'clang-cl'
- def has_arguments(self, args: T.List[str], env: 'Environment', code, mode: str) -> T.Tuple[bool, bool]:
+ def has_arguments(self, args: T.List[str], env: 'Environment', code: str, mode: str) -> T.Tuple[bool, bool]:
if mode != 'link':
args = args + ['-Werror=unknown-argument']
return super().has_arguments(args, env, code, mode)
diff --git a/mesonbuild/compilers/mixins/xc16.py b/mesonbuild/compilers/mixins/xc16.py
index f12cccc..edc5f2c 100644
--- a/mesonbuild/compilers/mixins/xc16.py
+++ b/mesonbuild/compilers/mixins/xc16.py
@@ -21,6 +21,13 @@ from ...mesonlib import EnvironmentException
if T.TYPE_CHECKING:
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 = {
'plain': [],
@@ -46,8 +53,9 @@ xc16_debug_args = {
} # type: T.Dict[bool, T.List[str]]
-class Xc16Compiler:
- def __init__(self):
+class Xc16Compiler(Compiler):
+
+ def __init__(self) -> None:
if not self.is_cross:
raise EnvironmentException('xc16 supports only cross-compilation.')
self.id = 'xc16'
@@ -85,7 +93,7 @@ class Xc16Compiler:
def get_coverage_args(self) -> T.List[str]:
return []
-
+
def get_no_stdinc_args(self) -> T.List[str]:
return ['-nostdinc']
diff --git a/mesonbuild/compilers/objc.py b/mesonbuild/compilers/objc.py
index 254a609..1b280eb 100644
--- a/mesonbuild/compilers/objc.py
+++ b/mesonbuild/compilers/objc.py
@@ -23,24 +23,31 @@ from .mixins.gnu import GnuCompiler
from .mixins.clang import ClangCompiler
if T.TYPE_CHECKING:
+ from ..dependencies import ExternalProgram
from ..envconfig import MachineInfo
+ from ..environment import Environment
+ from ..linkers import DynamicLinker
class ObjCCompiler(CLikeCompiler, Compiler):
language = 'objc'
- def __init__(self, exelist, version, for_machine: MachineChoice,
+ def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice,
is_cross: bool, info: 'MachineInfo',
- exe_wrap: T.Optional[str], **kwargs):
- Compiler.__init__(self, exelist, version, for_machine, info, **kwargs)
- CLikeCompiler.__init__(self, is_cross, exe_wrap)
+ exe_wrap: T.Optional['ExternalProgram'],
+ linker: T.Optional['DynamicLinker'] = None,
+ full_version: T.Optional[str] = None):
+ Compiler.__init__(self, exelist, version, for_machine, info,
+ is_cross=is_cross, full_version=full_version,
+ linker=linker)
+ CLikeCompiler.__init__(self, exe_wrap)
@staticmethod
- def get_display_language():
+ def get_display_language() -> str:
return 'Objective-C'
- def sanity_check(self, work_dir, environment):
+ def sanity_check(self, work_dir: str, environment: 'Environment') -> None:
# TODO try to use sanity_check_impl instead of duplicated code
source_name = os.path.join(work_dir, 'sanitycheckobjc.m')
binary_name = os.path.join(work_dir, 'sanitycheckobjc')
@@ -67,11 +74,14 @@ class ObjCCompiler(CLikeCompiler, Compiler):
class GnuObjCCompiler(GnuCompiler, ObjCCompiler):
- def __init__(self, exelist, version, for_machine: MachineChoice,
- is_cross, info: 'MachineInfo', exe_wrapper=None,
- defines=None, **kwargs):
+ def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice,
+ is_cross: bool, info: 'MachineInfo',
+ exe_wrapper: T.Optional['ExternalProgram'] = None,
+ defines: T.Optional[T.Dict[str, str]] = None,
+ linker: T.Optional['DynamicLinker'] = None,
+ full_version: T.Optional[str] = None):
ObjCCompiler.__init__(self, exelist, version, for_machine, is_cross,
- info, exe_wrapper, **kwargs)
+ info, exe_wrapper, linker=linker, full_version=full_version)
GnuCompiler.__init__(self, defines)
default_warn_args = ['-Wall', '-Winvalid-pch']
self.warn_args = {'0': [],
@@ -81,12 +91,15 @@ class GnuObjCCompiler(GnuCompiler, ObjCCompiler):
class ClangObjCCompiler(ClangCompiler, ObjCCompiler):
- def __init__(self, exelist, version, for_machine: MachineChoice,
- is_cross, info: 'MachineInfo', exe_wrapper=None,
- **kwargs):
+ def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice,
+ is_cross: bool, info: 'MachineInfo',
+ exe_wrapper: T.Optional['ExternalProgram'] = None,
+ defines: T.Optional[T.Dict[str, str]] = None,
+ linker: T.Optional['DynamicLinker'] = None,
+ full_version: T.Optional[str] = None):
ObjCCompiler.__init__(self, exelist, version, for_machine, is_cross,
- info, exe_wrapper, **kwargs)
- ClangCompiler.__init__(self, [])
+ info, exe_wrapper, linker=linker, full_version=full_version)
+ ClangCompiler.__init__(self, defines)
default_warn_args = ['-Wall', '-Winvalid-pch']
self.warn_args = {'0': [],
'1': default_warn_args,
diff --git a/mesonbuild/compilers/objcpp.py b/mesonbuild/compilers/objcpp.py
index 3197abc..16ba77e 100644
--- a/mesonbuild/compilers/objcpp.py
+++ b/mesonbuild/compilers/objcpp.py
@@ -23,23 +23,30 @@ from .mixins.gnu import GnuCompiler
from .mixins.clang import ClangCompiler
if T.TYPE_CHECKING:
+ from ..dependencies import ExternalProgram
from ..envconfig import MachineInfo
+ from ..environment import Environment
+ from ..linkers import DynamicLinker
class ObjCPPCompiler(CLikeCompiler, Compiler):
language = 'objcpp'
- def __init__(self, exelist, version, for_machine: MachineChoice,
+ def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice,
is_cross: bool, info: 'MachineInfo',
- exe_wrap: T.Optional[str], **kwargs):
- Compiler.__init__(self, exelist, version, for_machine, info, **kwargs)
- CLikeCompiler.__init__(self, is_cross, exe_wrap)
+ exe_wrap: T.Optional['ExternalProgram'],
+ linker: T.Optional['DynamicLinker'] = None,
+ full_version: T.Optional[str] = None):
+ Compiler.__init__(self, exelist, version, for_machine, info,
+ is_cross=is_cross, full_version=full_version,
+ linker=linker)
+ CLikeCompiler.__init__(self, exe_wrap)
@staticmethod
- def get_display_language():
+ def get_display_language() -> str:
return 'Objective-C++'
- def sanity_check(self, work_dir, environment):
+ def sanity_check(self, work_dir: str, environment: 'Environment') -> None:
# TODO try to use sanity_check_impl instead of duplicated code
source_name = os.path.join(work_dir, 'sanitycheckobjcpp.mm')
binary_name = os.path.join(work_dir, 'sanitycheckobjcpp')
@@ -67,10 +74,14 @@ class ObjCPPCompiler(CLikeCompiler, Compiler):
class GnuObjCPPCompiler(GnuCompiler, ObjCPPCompiler):
- def __init__(self, exelist, version, for_machine: MachineChoice,
- is_cross, info: 'MachineInfo', exe_wrapper=None,
- defines=None, **kwargs):
- ObjCPPCompiler.__init__(self, exelist, version, for_machine, is_cross, info, exe_wrapper, **kwargs)
+ def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice,
+ is_cross: bool, info: 'MachineInfo',
+ exe_wrapper: T.Optional['ExternalProgram'] = None,
+ defines: T.Optional[T.Dict[str, str]] = None,
+ linker: T.Optional['DynamicLinker'] = None,
+ full_version: T.Optional[str] = None):
+ ObjCPPCompiler.__init__(self, exelist, version, for_machine, is_cross,
+ info, exe_wrapper, linker=linker, full_version=full_version)
GnuCompiler.__init__(self, defines)
default_warn_args = ['-Wall', '-Winvalid-pch', '-Wnon-virtual-dtor']
self.warn_args = {'0': [],
@@ -80,11 +91,16 @@ class GnuObjCPPCompiler(GnuCompiler, ObjCPPCompiler):
class ClangObjCPPCompiler(ClangCompiler, ObjCPPCompiler):
- def __init__(self, exelist, version, for_machine: MachineChoice,
- is_cross, info: 'MachineInfo', exe_wrapper=None,
- **kwargs):
- ObjCPPCompiler.__init__(self, exelist, version, for_machine, is_cross, info, exe_wrapper, **kwargs)
- ClangCompiler.__init__(self, [])
+
+ def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice,
+ is_cross: bool, info: 'MachineInfo',
+ exe_wrapper: T.Optional['ExternalProgram'] = None,
+ defines: T.Optional[T.Dict[str, str]] = None,
+ linker: T.Optional['DynamicLinker'] = None,
+ full_version: T.Optional[str] = None):
+ ObjCPPCompiler.__init__(self, exelist, version, for_machine, is_cross,
+ info, exe_wrapper, linker=linker, full_version=full_version)
+ ClangCompiler.__init__(self, defines)
default_warn_args = ['-Wall', '-Winvalid-pch', '-Wnon-virtual-dtor']
self.warn_args = {'0': [],
'1': default_warn_args,
diff --git a/mesonbuild/compilers/rust.py b/mesonbuild/compilers/rust.py
index c2e21c4..baa7272 100644
--- a/mesonbuild/compilers/rust.py
+++ b/mesonbuild/compilers/rust.py
@@ -36,18 +36,14 @@ class RustCompiler(Compiler):
language = 'rust'
def __init__(self, exelist, version, for_machine: MachineChoice,
- is_cross, info: 'MachineInfo', exe_wrapper=None, **kwargs):
- super().__init__(exelist, version, for_machine, info, **kwargs)
+ is_cross: bool, info: 'MachineInfo', exe_wrapper=None, **kwargs):
+ super().__init__(exelist, version, for_machine, info, is_cross=is_cross, **kwargs)
self.exe_wrapper = exe_wrapper
self.id = 'rustc'
- self.is_cross = is_cross
def needs_static_linker(self):
return False
- def name_string(self):
- return ' '.join(self.exelist)
-
def sanity_check(self, work_dir, environment):
source_name = os.path.join(work_dir, 'sanity.rs')
output_name = os.path.join(work_dir, 'rusttest')
@@ -110,6 +106,9 @@ class RustCompiler(Compiler):
def get_std_exe_link_args(self):
return []
+ def get_output_args(self, outputname: str) -> T.List[str]:
+ return ['-o', outputname]
+
# Rust does not have a use_linker_args because it dispatches to a gcc-like
# C compiler for dynamic linking, as such we invoke the C compiler's
# use_linker_args method instead.
diff --git a/mesonbuild/compilers/swift.py b/mesonbuild/compilers/swift.py
index 1942120..55f2761 100644
--- a/mesonbuild/compilers/swift.py
+++ b/mesonbuild/compilers/swift.py
@@ -36,14 +36,10 @@ class SwiftCompiler(Compiler):
language = 'swift'
def __init__(self, exelist, version, for_machine: MachineChoice,
- is_cross, info: 'MachineInfo', **kwargs):
- super().__init__(exelist, version, for_machine, info, **kwargs)
+ is_cross: bool, info: 'MachineInfo', **kwargs):
+ super().__init__(exelist, version, for_machine, info, is_cross=is_cross, **kwargs)
self.version = version
self.id = 'llvm'
- self.is_cross = is_cross
-
- def name_string(self):
- return ' '.join(self.exelist)
def needs_static_linker(self):
return True
diff --git a/mesonbuild/compilers/vala.py b/mesonbuild/compilers/vala.py
index a5d49b6..f31a294 100644
--- a/mesonbuild/compilers/vala.py
+++ b/mesonbuild/compilers/vala.py
@@ -28,16 +28,12 @@ class ValaCompiler(Compiler):
language = 'vala'
def __init__(self, exelist, version, for_machine: MachineChoice,
- is_cross, info: 'MachineInfo'):
- super().__init__(exelist, version, for_machine, info)
+ is_cross: bool, info: 'MachineInfo'):
+ super().__init__(exelist, version, for_machine, info, is_cross=is_cross)
self.version = version
- self.is_cross = is_cross
self.id = 'valac'
self.base_options = ['b_colorout']
- def name_string(self):
- return ' '.join(self.exelist)
-
def needs_static_linker(self):
return False # Because compiles into C.
diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py
index bba3942..5827a4e 100644
--- a/mesonbuild/coredata.py
+++ b/mesonbuild/coredata.py
@@ -32,10 +32,11 @@ import typing as T
if T.TYPE_CHECKING:
from . import dependencies
- from .compilers import Compiler # noqa: F401
+ from .compilers.compilers import Compiler, CompileResult # noqa: F401
from .environment import Environment
OptionDictType = T.Dict[str, 'UserOption[T.Any]']
+ CompilerCheckCacheKey = T.Tuple[T.Tuple[str, ...], str, str, T.Tuple[str, ...], str]
version = '0.55.999'
backendlist = ['ninja', 'vs', 'vs2010', 'vs2015', 'vs2017', 'vs2019', 'xcode']
@@ -394,7 +395,7 @@ class CoreData:
build_cache = DependencyCache(self.builtins_per_machine, MachineChoice.BUILD)
host_cache = DependencyCache(self.builtins_per_machine, MachineChoice.BUILD)
self.deps = PerMachine(build_cache, host_cache) # type: PerMachine[DependencyCache]
- self.compiler_check_cache = OrderedDict()
+ self.compiler_check_cache = OrderedDict() # type: T.Dict[CompilerCheckCacheKey, compiler.CompileResult]
# Only to print a warning if it changes between Meson invocations.
self.config_files = self.__load_config_files(options, scratch_dir, 'native')
@@ -771,7 +772,7 @@ class CoreData:
lang, key = k.split('_', 1)
for machine in MachineChoice:
if key not in env.compiler_options[machine][lang]:
- env.compiler_options[machine][lang][key] = v
+ env.compiler_options[machine][lang][key] = v
elif k in base_options:
if not subproject and k not in env.base_options:
env.base_options[k] = v
diff --git a/mesonbuild/dependencies/scalapack.py b/mesonbuild/dependencies/scalapack.py
index 8774746..0147e0b 100644
--- a/mesonbuild/dependencies/scalapack.py
+++ b/mesonbuild/dependencies/scalapack.py
@@ -109,10 +109,10 @@ class MKLPkgConfigDependency(PkgConfigDependency):
if self.clib_compiler.id == 'gcc':
for i, a in enumerate(self.link_args):
# only replace in filename, not in directory names
- parts = list(os.path.split(a))
- if 'mkl_intel_lp64' in parts[-1]:
- parts[-1] = parts[-1].replace('intel', 'gf')
- self.link_args[i] = '/' + os.path.join(*parts)
+ dirname, basename = os.path.split(a)
+ if 'mkl_intel_lp64' in basename:
+ basename = basename.replace('intel', 'gf')
+ self.link_args[i] = '/' + os.path.join(dirname, basename)
# MKL pkg-config omits scalapack
# be sure "-L" and "-Wl" are first if present
i = 0
diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py
index 4623049..513a03c 100644
--- a/mesonbuild/environment.py
+++ b/mesonbuild/environment.py
@@ -1588,6 +1588,10 @@ class Environment:
exe_wrap, defines, linker=linker)
if 'clang' in out:
linker = None
+ defines = self.get_clang_compiler_defines(compiler)
+ if not defines:
+ popen_exceptions[' '.join(compiler)] = 'no pre-processor defines'
+ continue
if 'Apple' in out:
comp = AppleClangObjCCompiler if objc else AppleClangObjCPPCompiler
else:
@@ -1604,7 +1608,7 @@ class Environment:
compiler, comp, for_machine)
return comp(
ccache + compiler, version, for_machine,
- is_cross, info, exe_wrap, linker=linker)
+ is_cross, info, exe_wrap, linker=linker, defines=defines)
self._handle_exceptions(popen_exceptions, compilers)
def detect_java_compiler(self, for_machine):
@@ -1821,7 +1825,8 @@ class Environment:
elif 'gdc' in out:
linker = self._guess_nix_linker(exelist, compilers.GnuDCompiler, for_machine)
return compilers.GnuDCompiler(
- exelist, version, for_machine, info, arch, is_cross, exe_wrap,
+ exelist, version, for_machine, info, arch,
+ exe_wrapper=exe_wrap, is_cross=is_cross,
full_version=full_version, linker=linker)
elif 'The D Language Foundation' in out or 'Digital Mars' in out:
# DMD seems to require a file
diff --git a/mesonbuild/linkers.py b/mesonbuild/linkers.py
index d85c88e..ed28fa3 100644
--- a/mesonbuild/linkers.py
+++ b/mesonbuild/linkers.py
@@ -351,6 +351,7 @@ class DynamicLinker(LinkerEnvVarsMixin, metaclass=abc.ABCMeta):
self.version = version
self.prefix_arg = prefix_arg
self.always_args = always_args
+ self.machine = None # type: T.Optional[str]
def __repr__(self) -> str:
return '<{}: v{} `{}`>'.format(type(self).__name__, self.version, ' '.join(self.exelist))
diff --git a/mesonbuild/mesonlib.py b/mesonbuild/mesonlib.py
index c6cbbd6..17d2733 100644
--- a/mesonbuild/mesonlib.py
+++ b/mesonbuild/mesonlib.py
@@ -34,6 +34,8 @@ if T.TYPE_CHECKING:
from .compilers.compilers import CompilerType
from .interpreterbase import ObjectHolder
+ FileOrString = T.Union['File', str]
+
_T = T.TypeVar('_T')
_U = T.TypeVar('_U')
@@ -946,7 +948,7 @@ def do_define(regex: T.Pattern[str], line: str, confdata: 'ConfigurationData', v
arr = line.split()
if variable_format == 'meson' and len(arr) != 2:
- raise MesonException('#mesondefine does not contain exactly two tokens: %s' % line.strip())
+ raise MesonException('#mesondefine does not contain exactly two tokens: %s' % line.strip())
varname = arr[1]
try:
diff --git a/mesonbuild/minstall.py b/mesonbuild/minstall.py
index 7a56275..0eaa54f 100644
--- a/mesonbuild/minstall.py
+++ b/mesonbuild/minstall.py
@@ -483,7 +483,7 @@ class Installer:
set_mode(outname, install_mode, d.install_umask)
if should_strip and d.strip_bin is not None:
if fname.endswith('.jar'):
- self.log('Not stripping jar target:', os.path.basename(fname))
+ self.log('Not stripping jar target: {}'.format(os.path.basename(fname)))
continue
self.log('Stripping target {!r} using {}.'.format(fname, d.strip_bin[0]))
ps, stdo, stde = Popen_safe(d.strip_bin + [outname])
diff --git a/mesonbuild/modules/qt.py b/mesonbuild/modules/qt.py
index c7a1c46..32ff6af 100644
--- a/mesonbuild/modules/qt.py
+++ b/mesonbuild/modules/qt.py
@@ -87,29 +87,29 @@ class QtBaseModule(ExtensionModule):
rcc_dirname, nodes = self.qrc_nodes(state, rcc_file)
result = []
for resource_path in nodes:
- # We need to guess if the pointed resource is:
- # a) in build directory -> implies a generated file
- # b) in source directory
- # c) somewhere else external dependency file to bundle
- #
- # Also from qrc documentation: relative path are always from qrc file
- # So relative path must always be computed from qrc file !
- if os.path.isabs(resource_path):
- # a)
- if resource_path.startswith(os.path.abspath(state.environment.build_dir)):
- resource_relpath = os.path.relpath(resource_path, state.environment.build_dir)
- result.append(File(is_built=True, subdir='', fname=resource_relpath))
- # either b) or c)
- else:
- result.append(File(is_built=False, subdir=state.subdir, fname=resource_path))
- else:
- path_from_rcc = os.path.normpath(os.path.join(rcc_dirname, resource_path))
- # a)
- if path_from_rcc.startswith(state.environment.build_dir):
- result.append(File(is_built=True, subdir=state.subdir, fname=resource_path))
- # b)
- else:
- result.append(File(is_built=False, subdir=state.subdir, fname=path_from_rcc))
+ # We need to guess if the pointed resource is:
+ # a) in build directory -> implies a generated file
+ # b) in source directory
+ # c) somewhere else external dependency file to bundle
+ #
+ # Also from qrc documentation: relative path are always from qrc file
+ # So relative path must always be computed from qrc file !
+ if os.path.isabs(resource_path):
+ # a)
+ if resource_path.startswith(os.path.abspath(state.environment.build_dir)):
+ resource_relpath = os.path.relpath(resource_path, state.environment.build_dir)
+ result.append(File(is_built=True, subdir='', fname=resource_relpath))
+ # either b) or c)
+ else:
+ result.append(File(is_built=False, subdir=state.subdir, fname=resource_path))
+ else:
+ path_from_rcc = os.path.normpath(os.path.join(rcc_dirname, resource_path))
+ # a)
+ if path_from_rcc.startswith(state.environment.build_dir):
+ result.append(File(is_built=True, subdir=state.subdir, fname=resource_path))
+ # b)
+ else:
+ result.append(File(is_built=False, subdir=state.subdir, fname=path_from_rcc))
return result
@noPosargs
diff --git a/mesonbuild/optinterpreter.py b/mesonbuild/optinterpreter.py
index 75011e7..ec329a8 100644
--- a/mesonbuild/optinterpreter.py
+++ b/mesonbuild/optinterpreter.py
@@ -210,7 +210,7 @@ class OptionInterpreter:
(posargs, kwargs) = self.reduce_arguments(node.args)
if 'yield' in kwargs:
- FeatureNew.single_use('option yield', '0.45.0', self.subproject)
+ FeatureNew.single_use('option yield', '0.45.0', self.subproject)
if 'type' not in kwargs:
raise OptionException('Option call missing mandatory "type" keyword argument')
diff --git a/run_mypy.py b/run_mypy.py
index 953c20d..db38112 100755
--- a/run_mypy.py
+++ b/run_mypy.py
@@ -9,12 +9,16 @@ import typing as T
modules = [
# fully typed submodules
'mesonbuild/ast',
+ 'mesonbuild/compilers/mixins',
'mesonbuild/scripts',
'mesonbuild/wrap',
# specific files
'mesonbuild/arglist.py',
- # 'mesonbuild/compilers/mixins/intel.py',
+ 'mesonbuild/compilers/compilers.py',
+ 'mesonbuild/compilers/c_function_attributes.py',
+ 'mesonbuild/compilers/objc.py',
+ 'mesonbuild/compilers/objcpp.py',
# 'mesonbuild/coredata.py',
'mesonbuild/dependencies/boost.py',
'mesonbuild/dependencies/hdf5.py',
diff --git a/run_tests.py b/run_tests.py
index 6e9c6ce..0f02636 100755
--- a/run_tests.py
+++ b/run_tests.py
@@ -263,8 +263,6 @@ def run_mtest_inprocess(commandlist):
return returncode, stdout.getvalue(), stderr.getvalue()
def clear_meson_configure_class_caches():
- compilers.CCompiler.library_dirs_cache = {}
- compilers.CCompiler.program_dirs_cache = {}
compilers.CCompiler.find_library_cache = {}
compilers.CCompiler.find_framework_cache = {}
dependencies.PkgConfigDependency.pkgbin_cache = {}
diff --git a/run_unittests.py b/run_unittests.py
index 6b817bb..db61ca6 100755
--- a/run_unittests.py
+++ b/run_unittests.py
@@ -377,7 +377,7 @@ class InternalTests(unittest.TestCase):
self.assertEqual(a, ['-I.', '-I./tests2/', '-I./tests/', '-I..'])
def test_compiler_args_class_d(self):
- d = mesonbuild.compilers.DCompiler([], 'fake', MachineChoice.HOST, 'info', 'arch', False, None)
+ d = mesonbuild.compilers.DmdDCompiler([], 'fake', MachineChoice.HOST, 'info', 'arch')
# check include order is kept when deduplicating
a = d.compiler_args(['-Ifirst', '-Isecond', '-Ithird'])
a += ['-Ifirst']
@@ -792,7 +792,7 @@ class InternalTests(unittest.TestCase):
f.write('')
with open(os.path.join(tmpdir, 'libfoo.so.70.0.so.1'), 'w') as f:
f.write('')
- found = cc.find_library_real('foo', env, [tmpdir], '', LibType.PREFER_SHARED)
+ found = cc._find_library_real('foo', env, [tmpdir], '', LibType.PREFER_SHARED)
self.assertEqual(os.path.basename(found[0]), 'libfoo.so.54.0')
def test_find_library_patterns(self):