types: import typing as T (fixes #6333)

pull/6529/head
Daniel Mensinger 5 years ago committed by Nirbheek Chauhan
parent 00c1779bf3
commit 2e5268e94e
  1. 10
      mesonbuild/ast/interpreter.py
  2. 14
      mesonbuild/backend/backends.py
  3. 6
      mesonbuild/backend/ninjabackend.py
  4. 30
      mesonbuild/build.py
  5. 14
      mesonbuild/cmake/client.py
  6. 4
      mesonbuild/cmake/common.py
  7. 18
      mesonbuild/cmake/executor.py
  8. 14
      mesonbuild/cmake/fileapi.py
  9. 62
      mesonbuild/cmake/interpreter.py
  10. 28
      mesonbuild/cmake/traceparser.py
  11. 6
      mesonbuild/compilers/c.py
  12. 138
      mesonbuild/compilers/compilers.py
  13. 8
      mesonbuild/compilers/cpp.py
  14. 4
      mesonbuild/compilers/cs.py
  15. 16
      mesonbuild/compilers/cuda.py
  16. 10
      mesonbuild/compilers/d.py
  17. 18
      mesonbuild/compilers/fortran.py
  18. 4
      mesonbuild/compilers/java.py
  19. 50
      mesonbuild/compilers/mixins/arm.py
  20. 32
      mesonbuild/compilers/mixins/ccrx.py
  21. 20
      mesonbuild/compilers/mixins/clang.py
  22. 28
      mesonbuild/compilers/mixins/clike.py
  23. 12
      mesonbuild/compilers/mixins/elbrus.py
  24. 6
      mesonbuild/compilers/mixins/emscripten.py
  25. 76
      mesonbuild/compilers/mixins/gnu.py
  26. 32
      mesonbuild/compilers/mixins/intel.py
  27. 52
      mesonbuild/compilers/mixins/islinker.py
  28. 28
      mesonbuild/compilers/mixins/pgi.py
  29. 82
      mesonbuild/compilers/mixins/visualstudio.py
  30. 6
      mesonbuild/compilers/objc.py
  31. 6
      mesonbuild/compilers/objcpp.py
  32. 4
      mesonbuild/compilers/rust.py
  33. 4
      mesonbuild/compilers/swift.py
  34. 4
      mesonbuild/compilers/vala.py
  35. 99
      mesonbuild/coredata.py
  36. 64
      mesonbuild/dependencies/base.py
  37. 6
      mesonbuild/dependencies/dev.py
  38. 10
      mesonbuild/dependencies/mpi.py
  39. 64
      mesonbuild/envconfig.py
  40. 25
      mesonbuild/environment.py
  41. 16
      mesonbuild/interpreter.py
  42. 312
      mesonbuild/linkers.py
  43. 66
      mesonbuild/mesonlib.py
  44. 88
      mesonbuild/mintro.py
  45. 67
      mesonbuild/mlog.py
  46. 26
      mesonbuild/modules/fs.py
  47. 8
      mesonbuild/modules/python.py
  48. 6
      mesonbuild/msetup.py
  49. 84
      mesonbuild/mtest.py
  50. 4
      mesonbuild/optinterpreter.py
  51. 30
      mesonbuild/rewriter.py
  52. 10
      mesonbuild/wrap/wrap.py
  53. 22
      run_project_tests.py
  54. 12
      tools/cmake2meson.py
  55. 6
      tools/dircondenser.py

@ -35,7 +35,7 @@ from ..mparser import (
) )
import os, sys import os, sys
from typing import List, Any, Optional import typing as T
class DontCareObject(interpreterbase.InterpreterObject): class DontCareObject(interpreterbase.InterpreterObject):
pass pass
@ -59,7 +59,7 @@ ADD_SOURCE = 0
REMOVE_SOURCE = 1 REMOVE_SOURCE = 1
class AstInterpreter(interpreterbase.InterpreterBase): class AstInterpreter(interpreterbase.InterpreterBase):
def __init__(self, source_root: str, subdir: str, visitors: Optional[List[AstVisitor]] = None): def __init__(self, source_root: str, subdir: str, visitors: T.Optional[T.List[AstVisitor]] = None):
super().__init__(source_root, subdir) super().__init__(source_root, subdir)
self.visitors = visitors if visitors is not None else [] self.visitors = visitors if visitors is not None else []
self.visited_subdirs = {} self.visited_subdirs = {}
@ -246,8 +246,8 @@ class AstInterpreter(interpreterbase.InterpreterBase):
self.reverse_assignment[node.value.ast_id] = node self.reverse_assignment[node.value.ast_id] = node
self.assign_vals[node.var_name] = [self.evaluate_statement(node.value)] # Evaluate the value just in case self.assign_vals[node.var_name] = [self.evaluate_statement(node.value)] # Evaluate the value just in case
def resolve_node(self, node: BaseNode, include_unknown_args: bool = False, id_loop_detect: Optional[List[str]] = None) -> Optional[Any]: def resolve_node(self, node: BaseNode, include_unknown_args: bool = False, id_loop_detect: T.Optional[T.List[str]] = None) -> T.Optional[T.Any]:
def quick_resolve(n: BaseNode, loop_detect: Optional[List[str]] = None) -> Any: def quick_resolve(n: BaseNode, loop_detect: T.Optional[T.List[str]] = None) -> T.Any:
if loop_detect is None: if loop_detect is None:
loop_detect = [] loop_detect = []
if isinstance(n, IdNode): if isinstance(n, IdNode):
@ -327,7 +327,7 @@ class AstInterpreter(interpreterbase.InterpreterBase):
return result return result
def flatten_args(self, args: Any, include_unknown_args: bool = False, id_loop_detect: Optional[List[str]] = None) -> List[Any]: def flatten_args(self, args: T.Any, include_unknown_args: bool = False, id_loop_detect: T.Optional[T.List[str]] = None) -> T.List[T.Any]:
# Make sure we are always dealing with lists # Make sure we are always dealing with lists
if not isinstance(args, list): if not isinstance(args, list):
args = [args] args = [args]

@ -27,7 +27,7 @@ from ..compilers import CompilerArgs, VisualStudioLikeCompiler
from collections import OrderedDict from collections import OrderedDict
import shlex import shlex
from functools import lru_cache from functools import lru_cache
import typing import typing as T
class CleanTrees: class CleanTrees:
@ -81,12 +81,12 @@ class ExecutableSerialisation:
self.capture = capture self.capture = capture
class TestSerialisation: class TestSerialisation:
def __init__(self, name: str, project: str, suite: str, fname: typing.List[str], def __init__(self, name: str, project: str, suite: str, fname: T.List[str],
is_cross_built: bool, exe_wrapper: typing.Optional[build.Executable], is_cross_built: bool, exe_wrapper: T.Optional[build.Executable],
needs_exe_wrapper: bool, is_parallel: bool, cmd_args: typing.List[str], needs_exe_wrapper: bool, is_parallel: bool, cmd_args: T.List[str],
env: build.EnvironmentVariables, should_fail: bool, env: build.EnvironmentVariables, should_fail: bool,
timeout: typing.Optional[int], workdir: typing.Optional[str], timeout: T.Optional[int], workdir: T.Optional[str],
extra_paths: typing.List[str], protocol: str, priority: int): extra_paths: T.List[str], protocol: str, priority: int):
self.name = name self.name = name
self.project_name = project self.project_name = project
self.suite = suite self.suite = suite
@ -676,7 +676,7 @@ class Backend:
paths.update(cc.get_library_dirs(self.environment)) paths.update(cc.get_library_dirs(self.environment))
return list(paths) return list(paths)
def determine_windows_extra_paths(self, target: typing.Union[build.BuildTarget, str], extra_bdeps): def determine_windows_extra_paths(self, target: T.Union[build.BuildTarget, str], extra_bdeps):
'''On Windows there is no such thing as an rpath. '''On Windows there is no such thing as an rpath.
We must determine all locations of DLLs that this exe We must determine all locations of DLLs that this exe
links to and return them so they can be used in unit links to and return them so they can be used in unit

@ -11,7 +11,7 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
from typing import List import typing as T
import os import os
import re import re
import pickle import pickle
@ -1872,7 +1872,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485'''))
self.fortran_deps[target.get_basename()] = {**module_files, **submodule_files} self.fortran_deps[target.get_basename()] = {**module_files, **submodule_files}
def get_fortran_deps(self, compiler: FortranCompiler, src: Path, target) -> List[str]: def get_fortran_deps(self, compiler: FortranCompiler, src: Path, target) -> T.List[str]:
""" """
Find all module and submodule needed by a Fortran target Find all module and submodule needed by a Fortran target
""" """
@ -2795,7 +2795,7 @@ def load(build_dir):
return obj return obj
def _scan_fortran_file_deps(src: Path, srcdir: Path, dirname: Path, tdeps, compiler) -> List[str]: def _scan_fortran_file_deps(src: Path, srcdir: Path, dirname: Path, tdeps, compiler) -> T.List[str]:
""" """
scan a Fortran file for dependencies. Needs to be distinct from target scan a Fortran file for dependencies. Needs to be distinct from target
to allow for recursion induced by `include` statements.er to allow for recursion induced by `include` statements.er

@ -18,7 +18,7 @@ import itertools, pathlib
import hashlib import hashlib
import pickle import pickle
from functools import lru_cache from functools import lru_cache
import typing import typing as T
from . import environment from . import environment
from . import dependencies from . import dependencies
@ -117,11 +117,11 @@ class Build:
self.environment = environment self.environment = environment
self.projects = {} self.projects = {}
self.targets = OrderedDict() self.targets = OrderedDict()
self.run_target_names = set() # type: typing.Set[typing.Tuple[str, str]] self.run_target_names = set() # type: T.Set[T.Tuple[str, str]]
self.global_args = PerMachine({}, {}) # type: PerMachine[typing.Dict[str, typing.List[str]]] self.global_args = PerMachine({}, {}) # type: PerMachine[T.Dict[str, T.List[str]]]
self.projects_args = PerMachine({}, {}) # type: PerMachine[typing.Dict[str, typing.List[str]]] self.projects_args = PerMachine({}, {}) # type: PerMachine[T.Dict[str, T.List[str]]]
self.global_link_args = PerMachine({}, {}) # type: PerMachine[typing.Dict[str, typing.List[str]]] self.global_link_args = PerMachine({}, {}) # type: PerMachine[T.Dict[str, T.List[str]]]
self.projects_link_args = PerMachine({}, {}) # type: PerMachine[typing.Dict[str, typing.List[str]]] self.projects_link_args = PerMachine({}, {}) # type: PerMachine[T.Dict[str, T.List[str]]]
self.tests = [] self.tests = []
self.benchmarks = [] self.benchmarks = []
self.headers = [] self.headers = []
@ -137,7 +137,7 @@ class Build:
self.dep_manifest_name = None self.dep_manifest_name = None
self.dep_manifest = {} self.dep_manifest = {}
self.stdlibs = PerMachine({}, {}) self.stdlibs = PerMachine({}, {})
self.test_setups = {} # type: typing.Dict[str, TestSetup] self.test_setups = {} # type: T.Dict[str, TestSetup]
self.test_setup_default_name = None self.test_setup_default_name = None
self.find_overrides = {} self.find_overrides = {}
self.searched_programs = set() # The list of all programs that have been searched for. self.searched_programs = set() # The list of all programs that have been searched for.
@ -331,7 +331,7 @@ class EnvironmentVariables:
return value return value
def get_env(self, full_env: typing.Dict[str, str]) -> typing.Dict[str, str]: def get_env(self, full_env: T.Dict[str, str]) -> T.Dict[str, str]:
env = full_env.copy() env = full_env.copy()
for method, name, values, kwargs in self.envvars: for method, name, values, kwargs in self.envvars:
env[name] = method(full_env, name, values, kwargs) env[name] = method(full_env, name, values, kwargs)
@ -355,22 +355,22 @@ a hard error in the future.''' % name)
if not hasattr(self, 'typename'): if not hasattr(self, 'typename'):
raise RuntimeError('Target type is not set for target class "{}". This is a bug'.format(type(self).__name__)) raise RuntimeError('Target type is not set for target class "{}". This is a bug'.format(type(self).__name__))
def __lt__(self, other: typing.Any) -> typing.Union[bool, 'NotImplemented']: def __lt__(self, other: T.Any) -> T.Union[bool, 'NotImplemented']:
if not hasattr(other, 'get_id') and not callable(other.get_id): if not hasattr(other, 'get_id') and not callable(other.get_id):
return NotImplemented return NotImplemented
return self.get_id() < other.get_id() return self.get_id() < other.get_id()
def __le__(self, other: typing.Any) -> typing.Union[bool, 'NotImplemented']: def __le__(self, other: T.Any) -> T.Union[bool, 'NotImplemented']:
if not hasattr(other, 'get_id') and not callable(other.get_id): if not hasattr(other, 'get_id') and not callable(other.get_id):
return NotImplemented return NotImplemented
return self.get_id() <= other.get_id() return self.get_id() <= other.get_id()
def __gt__(self, other: typing.Any) -> typing.Union[bool, 'NotImplemented']: def __gt__(self, other: T.Any) -> T.Union[bool, 'NotImplemented']:
if not hasattr(other, 'get_id') and not callable(other.get_id): if not hasattr(other, 'get_id') and not callable(other.get_id):
return NotImplemented return NotImplemented
return self.get_id() > other.get_id() return self.get_id() > other.get_id()
def __ge__(self, other: typing.Any) -> typing.Union[bool, 'NotImplemented']: def __ge__(self, other: T.Any) -> T.Union[bool, 'NotImplemented']:
if not hasattr(other, 'get_id') and not callable(other.get_id): if not hasattr(other, 'get_id') and not callable(other.get_id):
return NotImplemented return NotImplemented
return self.get_id() >= other.get_id() return self.get_id() >= other.get_id()
@ -1171,7 +1171,7 @@ You probably should put it in link_with instead.''')
raise MesonException('File %s does not exist.' % f) raise MesonException('File %s does not exist.' % f)
self.pch[language] = pchlist self.pch[language] = pchlist
def add_include_dirs(self, args, set_is_system: typing.Optional[str] = None): def add_include_dirs(self, args, set_is_system: T.Optional[str] = None):
ids = [] ids = []
for a in args: for a in args:
# FIXME same hack, forcibly unpack from holder. # FIXME same hack, forcibly unpack from holder.
@ -1200,7 +1200,7 @@ You probably should put it in link_with instead.''')
def get_aliases(self): def get_aliases(self):
return {} return {}
def get_langs_used_by_deps(self) -> typing.List[str]: def get_langs_used_by_deps(self) -> T.List[str]:
''' '''
Sometimes you want to link to a C++ library that exports C API, which Sometimes you want to link to a C++ library that exports C API, which
means the linker must link in the C++ stdlib, and we must use a C++ means the linker must link in the C++ stdlib, and we must use a C++
@ -2448,7 +2448,7 @@ class RunScript(dict):
self['args'] = args self['args'] = args
class TestSetup: class TestSetup:
def __init__(self, exe_wrapper: typing.Optional[typing.List[str]], gdb: bool, def __init__(self, exe_wrapper: T.Optional[T.List[str]], gdb: bool,
timeout_multiplier: int, env: EnvironmentVariables): timeout_multiplier: int, env: EnvironmentVariables):
self.exe_wrapper = exe_wrapper self.exe_wrapper = exe_wrapper
self.gdb = gdb self.gdb = gdb

@ -22,7 +22,7 @@ from ..mesonlib import MachineChoice
from .. import mlog from .. import mlog
from contextlib import contextmanager from contextlib import contextmanager
from subprocess import Popen, PIPE, TimeoutExpired from subprocess import Popen, PIPE, TimeoutExpired
from typing import List, Optional import typing as T
import json import json
import os import os
@ -110,11 +110,11 @@ class Progress(MessageBase):
pass pass
class MessageHello(MessageBase): class MessageHello(MessageBase):
def __init__(self, supported_protocol_versions: List[dict]): def __init__(self, supported_protocol_versions: T.List[dict]):
super().__init__('hello', '') super().__init__('hello', '')
self.supported_protocol_versions = supported_protocol_versions self.supported_protocol_versions = supported_protocol_versions
def supports(self, major: int, minor: Optional[int] = None) -> bool: def supports(self, major: int, minor: T.Optional[int] = None) -> bool:
for i in self.supported_protocol_versions: for i in self.supported_protocol_versions:
if major == i['major']: if major == i['major']:
if minor is None or minor == i['minor']: if minor is None or minor == i['minor']:
@ -124,7 +124,7 @@ class MessageHello(MessageBase):
# Request classes # Request classes
class RequestHandShake(RequestBase): class RequestHandShake(RequestBase):
def __init__(self, src_dir: str, build_dir: str, generator: str, vers_major: int, vers_minor: Optional[int] = None): def __init__(self, src_dir: str, build_dir: str, generator: str, vers_major: int, vers_minor: T.Optional[int] = None):
super().__init__('handshake') super().__init__('handshake')
self.src_dir = src_dir self.src_dir = src_dir
self.build_dir = build_dir self.build_dir = build_dir
@ -150,7 +150,7 @@ class RequestHandShake(RequestBase):
} }
class RequestConfigure(RequestBase): class RequestConfigure(RequestBase):
def __init__(self, args: Optional[List[str]] = None): def __init__(self, args: T.Optional[T.List[str]] = None):
super().__init__('configure') super().__init__('configure')
self.args = args self.args = args
@ -187,7 +187,7 @@ class ReplyCompute(ReplyBase):
super().__init__(cookie, 'compute') super().__init__(cookie, 'compute')
class ReplyCMakeInputs(ReplyBase): class ReplyCMakeInputs(ReplyBase):
def __init__(self, cookie: str, cmake_root: str, src_dir: str, build_files: List[CMakeBuildFile]): def __init__(self, cookie: str, cmake_root: str, src_dir: str, build_files: T.List[CMakeBuildFile]):
super().__init__(cookie, 'cmakeInputs') super().__init__(cookie, 'cmakeInputs')
self.cmake_root = cmake_root self.cmake_root = cmake_root
self.src_dir = src_dir self.src_dir = src_dir
@ -296,7 +296,7 @@ class CMakeClient:
raise CMakeException('CMake server query failed') raise CMakeException('CMake server query failed')
return reply return reply
def do_handshake(self, src_dir: str, build_dir: str, generator: str, vers_major: int, vers_minor: Optional[int] = None) -> None: def do_handshake(self, src_dir: str, build_dir: str, generator: str, vers_major: int, vers_minor: T.Optional[int] = None) -> None:
# CMake prints the hello message on startup # CMake prints the hello message on startup
msg = self.readMessage() msg = self.readMessage()
if not isinstance(msg, MessageHello): if not isinstance(msg, MessageHello):

@ -17,7 +17,7 @@
from ..mesonlib import MesonException from ..mesonlib import MesonException
from .. import mlog from .. import mlog
from typing import List import typing as T
class CMakeException(MesonException): class CMakeException(MesonException):
pass pass
@ -31,7 +31,7 @@ class CMakeBuildFile:
def __repr__(self): def __repr__(self):
return '<{}: {}; cmake={}; temp={}>'.format(self.__class__.__name__, self.file, self.is_cmake, self.is_temp) return '<{}: {}; cmake={}; temp={}>'.format(self.__class__.__name__, self.file, self.is_cmake, self.is_temp)
def _flags_to_list(raw: str) -> List[str]: def _flags_to_list(raw: str) -> T.List[str]:
# Convert a raw commandline string into a list of strings # Convert a raw commandline string into a list of strings
res = [] res = []
curr = '' curr = ''

@ -17,7 +17,7 @@
import subprocess import subprocess
from pathlib import Path from pathlib import Path
from typing import List, Tuple, Optional, TYPE_CHECKING import typing as T
import re import re
import os import os
import shutil import shutil
@ -27,7 +27,7 @@ from .. import mlog, mesonlib
from ..mesonlib import PerMachine, Popen_safe, version_compare, MachineChoice from ..mesonlib import PerMachine, Popen_safe, version_compare, MachineChoice
from ..environment import Environment from ..environment import Environment
if TYPE_CHECKING: if T.TYPE_CHECKING:
from ..dependencies.base import ExternalProgram from ..dependencies.base import ExternalProgram
@ -55,7 +55,7 @@ class CMakeExecutor:
self.cmakebin = None self.cmakebin = None
return return
def find_cmake_binary(self, environment: Environment, silent: bool = False) -> Tuple['ExternalProgram', str]: def find_cmake_binary(self, environment: Environment, silent: bool = False) -> T.Tuple['ExternalProgram', str]:
from ..dependencies.base import ExternalProgram from ..dependencies.base import ExternalProgram
# Create an iterator of options # Create an iterator of options
@ -107,7 +107,7 @@ class CMakeExecutor:
return CMakeExecutor.class_cmakebin[self.for_machine], CMakeExecutor.class_cmakevers[self.for_machine] return CMakeExecutor.class_cmakebin[self.for_machine], CMakeExecutor.class_cmakevers[self.for_machine]
def check_cmake(self, cmakebin: 'ExternalProgram') -> Optional[str]: def check_cmake(self, cmakebin: 'ExternalProgram') -> T.Optional[str]:
if not cmakebin.found(): if not cmakebin.found():
mlog.log('Did not find CMake {!r}'.format(cmakebin.name)) mlog.log('Did not find CMake {!r}'.format(cmakebin.name))
return None return None
@ -130,12 +130,12 @@ class CMakeExecutor:
cmvers = re.sub(r'\s*cmake version\s*', '', out.split('\n')[0]).strip() cmvers = re.sub(r'\s*cmake version\s*', '', out.split('\n')[0]).strip()
return cmvers return cmvers
def _cache_key(self, args: List[str], build_dir: str, env): def _cache_key(self, args: T.List[str], build_dir: str, env):
fenv = frozenset(env.items()) if env is not None else None fenv = frozenset(env.items()) if env is not None else None
targs = tuple(args) targs = tuple(args)
return (self.cmakebin, targs, build_dir, fenv) return (self.cmakebin, targs, build_dir, fenv)
def _call_real(self, args: List[str], build_dir: str, env) -> Tuple[int, str, str]: def _call_real(self, args: T.List[str], build_dir: str, env) -> T.Tuple[int, str, str]:
os.makedirs(build_dir, exist_ok=True) os.makedirs(build_dir, exist_ok=True)
cmd = self.cmakebin.get_command() + args cmd = self.cmakebin.get_command() + args
ret = subprocess.run(cmd, env=env, cwd=build_dir, close_fds=False, ret = subprocess.run(cmd, env=env, cwd=build_dir, close_fds=False,
@ -148,7 +148,7 @@ class CMakeExecutor:
mlog.debug("Called `{}` in {} -> {}".format(call, build_dir, rc)) mlog.debug("Called `{}` in {} -> {}".format(call, build_dir, rc))
return rc, out, err return rc, out, err
def call(self, args: List[str], build_dir: str, env=None, disable_cache: bool = False): def call(self, args: T.List[str], build_dir: str, env=None, disable_cache: bool = False):
if env is None: if env is None:
env = os.environ env = os.environ
@ -162,7 +162,7 @@ class CMakeExecutor:
cache[key] = self._call_real(args, build_dir, env) cache[key] = self._call_real(args, build_dir, env)
return cache[key] return cache[key]
def call_with_fake_build(self, args: List[str], build_dir: str, env=None): def call_with_fake_build(self, args: T.List[str], build_dir: str, env=None):
# First check the cache # First check the cache
cache = CMakeExecutor.class_cmake_cache cache = CMakeExecutor.class_cmake_cache
key = self._cache_key(args, build_dir, env) key = self._cache_key(args, build_dir, env)
@ -186,7 +186,7 @@ class CMakeExecutor:
p = fallback p = fallback
return p return p
def choose_compiler(lang: str) -> Tuple[str, str]: def choose_compiler(lang: str) -> T.Tuple[str, str]:
exe_list = [] exe_list = []
if lang in compilers: if lang in compilers:
exe_list = compilers[lang].get_exelist() exe_list = compilers[lang].get_exelist()

@ -13,7 +13,7 @@
# limitations under the License. # limitations under the License.
from .common import CMakeException, CMakeBuildFile, CMakeConfiguration from .common import CMakeException, CMakeBuildFile, CMakeConfiguration
from typing import Any, List, Tuple import typing as T
from .. import mlog from .. import mlog
import os import os
import json import json
@ -34,10 +34,10 @@ class CMakeFileAPI:
'cmakeFiles': self._parse_cmakeFiles, 'cmakeFiles': self._parse_cmakeFiles,
} }
def get_cmake_sources(self) -> List[CMakeBuildFile]: def get_cmake_sources(self) -> T.List[CMakeBuildFile]:
return self.cmake_sources return self.cmake_sources
def get_cmake_configurations(self) -> List[CMakeConfiguration]: def get_cmake_configurations(self) -> T.List[CMakeConfiguration]:
return self.cmake_configurations return self.cmake_configurations
def setup_request(self) -> None: def setup_request(self) -> None:
@ -100,7 +100,7 @@ class CMakeFileAPI:
# resolved and the resulting data structure is identical # resolved and the resulting data structure is identical
# to the CMake serve output. # to the CMake serve output.
def helper_parse_dir(dir_entry: dict) -> Tuple[str, str]: def helper_parse_dir(dir_entry: dict) -> T.Tuple[str, str]:
src_dir = dir_entry.get('source', '.') src_dir = dir_entry.get('source', '.')
bld_dir = dir_entry.get('build', '.') bld_dir = dir_entry.get('build', '.')
src_dir = src_dir if os.path.isabs(src_dir) else os.path.join(source_dir, src_dir) src_dir = src_dir if os.path.isabs(src_dir) else os.path.join(source_dir, src_dir)
@ -110,7 +110,7 @@ class CMakeFileAPI:
return src_dir, bld_dir return src_dir, bld_dir
def parse_sources(comp_group: dict, tgt: dict) -> Tuple[List[str], List[str], List[int]]: def parse_sources(comp_group: dict, tgt: dict) -> T.Tuple[T.List[str], T.List[str], T.List[int]]:
gen = [] gen = []
src = [] src = []
idx = [] idx = []
@ -279,7 +279,7 @@ class CMakeFileAPI:
path = path if os.path.isabs(path) else os.path.join(src_dir, path) path = path if os.path.isabs(path) else os.path.join(src_dir, path)
self.cmake_sources += [CMakeBuildFile(path, i.get('isCMake', False), i.get('isGenerated', False))] self.cmake_sources += [CMakeBuildFile(path, i.get('isCMake', False), i.get('isGenerated', False))]
def _strip_data(self, data: Any) -> Any: def _strip_data(self, data: T.Any) -> T.Any:
if isinstance(data, list): if isinstance(data, list):
for idx, i in enumerate(data): for idx, i in enumerate(data):
data[idx] = self._strip_data(i) data[idx] = self._strip_data(i)
@ -293,7 +293,7 @@ class CMakeFileAPI:
return data return data
def _resolve_references(self, data: Any) -> Any: def _resolve_references(self, data: T.Any) -> T.Any:
if isinstance(data, list): if isinstance(data, list):
for idx, i in enumerate(data): for idx, i in enumerate(data):
data[idx] = self._resolve_references(i) data[idx] = self._resolve_references(i)

@ -25,10 +25,10 @@ from ..environment import Environment
from ..mesonlib import MachineChoice, version_compare from ..mesonlib import MachineChoice, version_compare
from ..compilers.compilers import lang_suffixes, header_suffixes, obj_suffixes, lib_suffixes, is_header from ..compilers.compilers import lang_suffixes, header_suffixes, obj_suffixes, lib_suffixes, is_header
from subprocess import Popen, PIPE from subprocess import Popen, PIPE
from typing import Any, List, Dict, Optional, Set, Union, TYPE_CHECKING
from threading import Thread from threading import Thread
from enum import Enum from enum import Enum
from functools import lru_cache from functools import lru_cache
import typing as T
import os, re import os, re
from ..mparser import ( from ..mparser import (
@ -48,7 +48,7 @@ from ..mparser import (
) )
if TYPE_CHECKING: if T.TYPE_CHECKING:
from ..build import Build from ..build import Build
from ..backend.backends import Backend from ..backend.backends import Backend
@ -136,8 +136,8 @@ class OutputTargetMap:
self.tgt_map = {} self.tgt_map = {}
self.build_dir = build_dir self.build_dir = build_dir
def add(self, tgt: Union['ConverterTarget', 'ConverterCustomTarget']) -> None: def add(self, tgt: T.Union['ConverterTarget', 'ConverterCustomTarget']) -> None:
def assign_keys(keys: List[str]) -> None: def assign_keys(keys: T.List[str]) -> None:
for i in [x for x in keys if x]: for i in [x for x in keys if x]:
self.tgt_map[i] = tgt self.tgt_map[i] = tgt
keys = [self._target_key(tgt.cmake_name)] keys = [self._target_key(tgt.cmake_name)]
@ -150,16 +150,16 @@ class OutputTargetMap:
keys += [self._base_generated_file_key(x) for x in tgt.original_outputs] keys += [self._base_generated_file_key(x) for x in tgt.original_outputs]
assign_keys(keys) assign_keys(keys)
def _return_first_valid_key(self, keys: List[str]) -> Optional[Union['ConverterTarget', 'ConverterCustomTarget']]: def _return_first_valid_key(self, keys: T.List[str]) -> T.Optional[T.Union['ConverterTarget', 'ConverterCustomTarget']]:
for i in keys: for i in keys:
if i and i in self.tgt_map: if i and i in self.tgt_map:
return self.tgt_map[i] return self.tgt_map[i]
return None return None
def target(self, name: str) -> Optional[Union['ConverterTarget', 'ConverterCustomTarget']]: def target(self, name: str) -> T.Optional[T.Union['ConverterTarget', 'ConverterCustomTarget']]:
return self._return_first_valid_key([self._target_key(name)]) return self._return_first_valid_key([self._target_key(name)])
def artifact(self, name: str) -> Optional[Union['ConverterTarget', 'ConverterCustomTarget']]: def artifact(self, name: str) -> T.Optional[T.Union['ConverterTarget', 'ConverterCustomTarget']]:
keys = [] keys = []
candidates = [name, OutputTargetMap.rm_so_version.sub('', name)] candidates = [name, OutputTargetMap.rm_so_version.sub('', name)]
for i in lib_suffixes: for i in lib_suffixes:
@ -172,11 +172,11 @@ class OutputTargetMap:
keys += [self._rel_artifact_key(i), os.path.basename(i), self._base_artifact_key(i)] keys += [self._rel_artifact_key(i), os.path.basename(i), self._base_artifact_key(i)]
return self._return_first_valid_key(keys) return self._return_first_valid_key(keys)
def generated(self, name: str) -> Optional[Union['ConverterTarget', 'ConverterCustomTarget']]: def generated(self, name: str) -> T.Optional[T.Union['ConverterTarget', 'ConverterCustomTarget']]:
return self._return_first_valid_key([self._rel_generated_file_key(name), self._base_generated_file_key(name)]) return self._return_first_valid_key([self._rel_generated_file_key(name), self._base_generated_file_key(name)])
# Utility functions to generate local keys # Utility functions to generate local keys
def _rel_path(self, fname: str) -> Optional[str]: def _rel_path(self, fname: str) -> T.Optional[str]:
fname = os.path.normpath(os.path.join(self.build_dir, fname)) fname = os.path.normpath(os.path.join(self.build_dir, fname))
if os.path.commonpath([self.build_dir, fname]) != self.build_dir: if os.path.commonpath([self.build_dir, fname]) != self.build_dir:
return None return None
@ -185,14 +185,14 @@ class OutputTargetMap:
def _target_key(self, tgt_name: str) -> str: def _target_key(self, tgt_name: str) -> str:
return '__tgt_{}__'.format(tgt_name) return '__tgt_{}__'.format(tgt_name)
def _rel_generated_file_key(self, fname: str) -> Optional[str]: def _rel_generated_file_key(self, fname: str) -> T.Optional[str]:
path = self._rel_path(fname) path = self._rel_path(fname)
return '__relgen_{}__'.format(path) if path else None return '__relgen_{}__'.format(path) if path else None
def _base_generated_file_key(self, fname: str) -> str: def _base_generated_file_key(self, fname: str) -> str:
return '__gen_{}__'.format(os.path.basename(fname)) return '__gen_{}__'.format(os.path.basename(fname))
def _rel_artifact_key(self, fname: str) -> Optional[str]: def _rel_artifact_key(self, fname: str) -> T.Optional[str]:
path = self._rel_path(fname) path = self._rel_path(fname)
return '__relart_{}__'.format(path) if path else None return '__relart_{}__'.format(path) if path else None
@ -393,7 +393,7 @@ class ConverterTarget:
self.generated = [x for x in self.generated if any([x.endswith(y) for y in supported])] self.generated = [x for x in self.generated if any([x.endswith(y) for y in supported])]
# Make paths relative # Make paths relative
def rel_path(x: str, is_header: bool, is_generated: bool) -> Optional[str]: def rel_path(x: str, is_header: bool, is_generated: bool) -> T.Optional[str]:
if not os.path.isabs(x): if not os.path.isabs(x):
x = os.path.normpath(os.path.join(self.src_dir, x)) x = os.path.normpath(os.path.join(self.src_dir, x))
if not os.path.exists(x) and not any([x.endswith(y) for y in obj_suffixes]) and not is_generated: if not os.path.exists(x) and not any([x.endswith(y) for y in obj_suffixes]) and not is_generated:
@ -458,7 +458,7 @@ class ConverterTarget:
if tgt: if tgt:
self.depends.append(tgt) self.depends.append(tgt)
def process_object_libs(self, obj_target_list: List['ConverterTarget'], linker_workaround: bool): def process_object_libs(self, obj_target_list: T.List['ConverterTarget'], linker_workaround: bool):
# Try to detect the object library(s) from the generated input sources # Try to detect the object library(s) from the generated input sources
temp = [x for x in self.generated if isinstance(x, str)] temp = [x for x in self.generated if isinstance(x, str)]
temp = [os.path.basename(x) for x in temp] temp = [os.path.basename(x) for x in temp]
@ -475,7 +475,7 @@ class ConverterTarget:
# suffix and just produces object files like `foo.obj`. Thus we have to do our best to # suffix and just produces object files like `foo.obj`. Thus we have to do our best to
# undo this step and guess the correct language suffix of the object file. This is done # undo this step and guess the correct language suffix of the object file. This is done
# by trying all language suffixes meson knows and checking if one of them fits. # by trying all language suffixes meson knows and checking if one of them fits.
candidates = [j] # type: List[str] candidates = [j] # type: T.List[str]
if not any([j.endswith('.' + x) for x in exts]): if not any([j.endswith('.' + x) for x in exts]):
mlog.warning('Object files do not contain source file extensions, thus falling back to guessing them.', once=True) mlog.warning('Object files do not contain source file extensions, thus falling back to guessing them.', once=True)
candidates += ['{}.{}'.format(j, x) for x in exts] candidates += ['{}.{}'.format(j, x) for x in exts]
@ -506,8 +506,8 @@ class ConverterTarget:
self.compile_opts[lang] += [x for x in opts if x not in self.compile_opts[lang]] self.compile_opts[lang] += [x for x in opts if x not in self.compile_opts[lang]]
@lru_cache(maxsize=None) @lru_cache(maxsize=None)
def _all_source_suffixes(self) -> List[str]: def _all_source_suffixes(self) -> T.List[str]:
suffixes = [] # type: List[str] suffixes = [] # type: T.List[str]
for exts in lang_suffixes.values(): for exts in lang_suffixes.values():
suffixes += [x for x in exts] suffixes += [x for x in exts]
return suffixes return suffixes
@ -599,7 +599,7 @@ class ConverterCustomTarget:
def __repr__(self) -> str: def __repr__(self) -> str:
return '<{}: {} {}>'.format(self.__class__.__name__, self.name, self.outputs) return '<{}: {} {}>'.format(self.__class__.__name__, self.name, self.outputs)
def postprocess(self, output_target_map: OutputTargetMap, root_src_dir: str, subdir: str, build_dir: str, all_outputs: List[str]) -> None: def postprocess(self, output_target_map: OutputTargetMap, root_src_dir: str, subdir: str, build_dir: str, all_outputs: T.List[str]) -> None:
# Default the working directory to the CMake build dir. This # Default the working directory to the CMake build dir. This
# is not 100% correct, since it should be the value of # is not 100% correct, since it should be the value of
# ${CMAKE_CURRENT_BINARY_DIR} when add_custom_command is # ${CMAKE_CURRENT_BINARY_DIR} when add_custom_command is
@ -626,7 +626,7 @@ class ConverterCustomTarget:
# Ensure that there is no duplicate output in the project so # Ensure that there is no duplicate output in the project so
# that meson can handle cases where the same filename is # that meson can handle cases where the same filename is
# generated in multiple directories # generated in multiple directories
temp_outputs = [] # type: List[str] temp_outputs = [] # type: T.List[str]
for i in self.outputs: for i in self.outputs:
if i in all_outputs: if i in all_outputs:
old = str(i) old = str(i)
@ -689,7 +689,7 @@ class ConverterCustomTarget:
new_deps += [i] new_deps += [i]
self.depends = list(set(new_deps)) self.depends = list(set(new_deps))
def get_ref(self, fname: str) -> Optional[CustomTargetReference]: def get_ref(self, fname: str) -> T.Optional[CustomTargetReference]:
fname = os.path.basename(fname) fname = os.path.basename(fname)
try: try:
if fname in self.conflict_map: if fname in self.conflict_map:
@ -724,7 +724,7 @@ class CMakeInterpreter:
self.install_prefix = install_prefix self.install_prefix = install_prefix
self.env = env self.env = env
self.backend_name = backend.name self.backend_name = backend.name
self.linkers = set() # type: Set[str] self.linkers = set() # type: T.Set[str]
self.cmake_api = CMakeAPI.SERVER self.cmake_api = CMakeAPI.SERVER
self.client = CMakeClient(self.env) self.client = CMakeClient(self.env)
self.fileapi = CMakeFileAPI(self.build_dir) self.fileapi = CMakeFileAPI(self.build_dir)
@ -738,7 +738,7 @@ class CMakeInterpreter:
self.project_name = '' self.project_name = ''
self.languages = [] self.languages = []
self.targets = [] self.targets = []
self.custom_targets = [] # type: List[ConverterCustomTarget] self.custom_targets = [] # type: T.List[ConverterCustomTarget]
self.trace = CMakeTraceParser() self.trace = CMakeTraceParser()
self.output_target_map = OutputTargetMap(self.build_dir) self.output_target_map = OutputTargetMap(self.build_dir)
@ -746,7 +746,7 @@ class CMakeInterpreter:
self.generated_targets = {} self.generated_targets = {}
self.internal_name_map = {} self.internal_name_map = {}
def configure(self, extra_cmake_options: List[str]) -> None: def configure(self, extra_cmake_options: T.List[str]) -> None:
for_machine = MachineChoice.HOST # TODO make parameter for_machine = MachineChoice.HOST # TODO make parameter
# Find CMake # Find CMake
cmake_exe = CMakeExecutor(self.env, '>=3.7', for_machine) cmake_exe = CMakeExecutor(self.env, '>=3.7', for_machine)
@ -835,7 +835,7 @@ class CMakeInterpreter:
if proc.returncode != 0: if proc.returncode != 0:
raise CMakeException('Failed to configure the CMake subproject') raise CMakeException('Failed to configure the CMake subproject')
def initialise(self, extra_cmake_options: List[str]) -> None: def initialise(self, extra_cmake_options: T.List[str]) -> None:
# Run configure the old way because doing it # Run configure the old way because doing it
# with the server doesn't work for some reason # with the server doesn't work for some reason
# Additionally, the File API requires a configure anyway # Additionally, the File API requires a configure anyway
@ -893,7 +893,7 @@ class CMakeInterpreter:
self.trace.parse(self.raw_trace) self.trace.parse(self.raw_trace)
# Find all targets # Find all targets
added_target_names = [] # type: List[str] added_target_names = [] # type: T.List[str]
for i in self.codemodel_configs: for i in self.codemodel_configs:
for j in i.projects: for j in i.projects:
if not self.project_name: if not self.project_name:
@ -929,7 +929,7 @@ class CMakeInterpreter:
# First pass: Basic target cleanup # First pass: Basic target cleanup
object_libs = [] object_libs = []
custom_target_outputs = [] # type: List[str] custom_target_outputs = [] # type: T.List[str]
for i in self.custom_targets: for i in self.custom_targets:
i.postprocess(self.output_target_map, self.src_dir, self.subdir, self.build_dir, custom_target_outputs) i.postprocess(self.output_target_map, self.src_dir, self.subdir, self.build_dir, custom_target_outputs)
for i in self.targets: for i in self.targets:
@ -1029,7 +1029,7 @@ class CMakeInterpreter:
processed = {} processed = {}
name_map = {} name_map = {}
def extract_tgt(tgt: Union[ConverterTarget, ConverterCustomTarget, CustomTargetReference]) -> IdNode: def extract_tgt(tgt: T.Union[ConverterTarget, ConverterCustomTarget, CustomTargetReference]) -> IdNode:
tgt_name = None tgt_name = None
if isinstance(tgt, (ConverterTarget, ConverterCustomTarget)): if isinstance(tgt, (ConverterTarget, ConverterCustomTarget)):
tgt_name = tgt.name tgt_name = tgt.name
@ -1039,7 +1039,7 @@ class CMakeInterpreter:
res_var = processed[tgt_name]['tgt'] res_var = processed[tgt_name]['tgt']
return id_node(res_var) if res_var else None return id_node(res_var) if res_var else None
def detect_cycle(tgt: Union[ConverterTarget, ConverterCustomTarget]) -> None: def detect_cycle(tgt: T.Union[ConverterTarget, ConverterCustomTarget]) -> None:
if tgt.name in processing: if tgt.name in processing:
raise CMakeException('Cycle in CMake inputs/dependencies detected') raise CMakeException('Cycle in CMake inputs/dependencies detected')
processing.append(tgt.name) processing.append(tgt.name)
@ -1056,7 +1056,7 @@ class CMakeInterpreter:
# First handle inter target dependencies # First handle inter target dependencies
link_with = [] link_with = []
objec_libs = [] # type: List[IdNode] objec_libs = [] # type: T.List[IdNode]
sources = [] sources = []
generated = [] generated = []
generated_filenames = [] generated_filenames = []
@ -1186,7 +1186,7 @@ class CMakeInterpreter:
detect_cycle(tgt) detect_cycle(tgt)
tgt_var = tgt.name # type: str tgt_var = tgt.name # type: str
def resolve_source(x: Any) -> Any: def resolve_source(x: T.Any) -> T.Any:
if isinstance(x, ConverterTarget): if isinstance(x, ConverterTarget):
if x.name not in processed: if x.name not in processed:
process_target(x) process_target(x)
@ -1236,7 +1236,7 @@ class CMakeInterpreter:
self.internal_name_map = name_map self.internal_name_map = name_map
return root_cb return root_cb
def target_info(self, target: str) -> Optional[Dict[str, str]]: def target_info(self, target: str) -> T.Optional[T.Dict[str, str]]:
# Try resolving the target name # Try resolving the target name
# start by checking if there is a 100% match (excluding the name prefix) # start by checking if there is a 100% match (excluding the name prefix)
prx_tgt = generated_target_name_prefix + target prx_tgt = generated_target_name_prefix + target
@ -1249,7 +1249,7 @@ class CMakeInterpreter:
return self.generated_targets[target] return self.generated_targets[target]
return None return None
def target_list(self) -> List[str]: def target_list(self) -> T.List[str]:
prx_str = generated_target_name_prefix prx_str = generated_target_name_prefix
prx_len = len(prx_str) prx_len = len(prx_str)
res = [x for x in self.generated_targets.keys()] res = [x for x in self.generated_targets.keys()]

@ -19,7 +19,7 @@ from .common import CMakeException
from .generator import parse_generator_expressions from .generator import parse_generator_expressions
from .. import mlog from .. import mlog
from typing import List, Tuple, Optional import typing as T
import re import re
import os import os
@ -35,7 +35,7 @@ class CMakeTraceLine:
return s.format(self.file, self.line, self.func, self.args) return s.format(self.file, self.line, self.func, self.args)
class CMakeTarget: class CMakeTarget:
def __init__(self, name, target_type, properties=None, imported: bool = False, tline: Optional[CMakeTraceLine] = None): def __init__(self, name, target_type, properties=None, imported: bool = False, tline: T.Optional[CMakeTraceLine] = None):
if properties is None: if properties is None:
properties = {} properties = {}
self.name = name self.name = name
@ -55,9 +55,9 @@ class CMakeTarget:
class CMakeGeneratorTarget(CMakeTarget): class CMakeGeneratorTarget(CMakeTarget):
def __init__(self, name): def __init__(self, name):
super().__init__(name, 'CUSTOM', {}) super().__init__(name, 'CUSTOM', {})
self.outputs = [] # type: List[str] self.outputs = [] # type: T.List[str]
self.command = [] # type: List[List[str]] self.command = [] # type: T.List[T.List[str]]
self.working_dir = None # type: Optional[str] self.working_dir = None # type: T.Optional[str]
class CMakeTraceParser: class CMakeTraceParser:
def __init__(self, permissive: bool = False): def __init__(self, permissive: bool = False):
@ -67,8 +67,8 @@ class CMakeTraceParser:
# Dict of CMakeTarget # Dict of CMakeTarget
self.targets = {} self.targets = {}
# List of targes that were added with add_custom_command to generate files # T.List of targes that were added with add_custom_command to generate files
self.custom_targets = [] # type: List[CMakeGeneratorTarget] self.custom_targets = [] # type: T.List[CMakeGeneratorTarget]
self.permissive = permissive # type: bool self.permissive = permissive # type: bool
@ -101,7 +101,7 @@ class CMakeTraceParser:
if(fn): if(fn):
fn(l) fn(l)
def get_first_cmake_var_of(self, var_list: List[str]) -> List[str]: def get_first_cmake_var_of(self, var_list: T.List[str]) -> T.List[str]:
# Return the first found CMake variable in list var_list # Return the first found CMake variable in list var_list
for i in var_list: for i in var_list:
if i in self.vars: if i in self.vars:
@ -109,7 +109,7 @@ class CMakeTraceParser:
return [] return []
def get_cmake_var(self, var: str) -> List[str]: def get_cmake_var(self, var: str) -> T.List[str]:
# Return the value of the CMake variable var or an empty list if var does not exist # Return the value of the CMake variable var or an empty list if var does not exist
if var in self.vars: if var in self.vars:
return self.vars[var] return self.vars[var]
@ -382,7 +382,7 @@ class CMakeTraceParser:
# option 1 first and fall back to 2, as 1 requires less code and less # option 1 first and fall back to 2, as 1 requires less code and less
# synchroniztion for cmake changes. # synchroniztion for cmake changes.
arglist = [] # type: List[Tuple[str, List[str]]] arglist = [] # type: T.List[T.Tuple[str, T.List[str]]]
name = args.pop(0) name = args.pop(0)
values = [] values = []
prop_regex = re.compile(r'^[A-Z_]+$') prop_regex = re.compile(r'^[A-Z_]+$')
@ -437,7 +437,7 @@ class CMakeTraceParser:
# DOC: https://cmake.org/cmake/help/latest/command/target_link_libraries.html # DOC: https://cmake.org/cmake/help/latest/command/target_link_libraries.html
self._parse_common_target_options('target_link_options', 'LINK_LIBRARIES', 'INTERFACE_LINK_LIBRARIES', tline) self._parse_common_target_options('target_link_options', 'LINK_LIBRARIES', 'INTERFACE_LINK_LIBRARIES', tline)
def _parse_common_target_options(self, func: str, private_prop: str, interface_prop: str, tline: CMakeTraceLine, ignore: Optional[List[str]] = None, paths: bool = False): def _parse_common_target_options(self, func: str, private_prop: str, interface_prop: str, tline: CMakeTraceLine, ignore: T.Optional[T.List[str]] = None, paths: bool = False):
if ignore is None: if ignore is None:
ignore = ['BEFORE'] ignore = ['BEFORE']
@ -509,14 +509,14 @@ class CMakeTraceParser:
yield CMakeTraceLine(file, line, func, args) yield CMakeTraceLine(file, line, func, args)
def _guess_files(self, broken_list: List[str]) -> List[str]: def _guess_files(self, broken_list: T.List[str]) -> T.List[str]:
#Try joining file paths that contain spaces #Try joining file paths that contain spaces
reg_start = re.compile(r'^([A-Za-z]:)?/.*/[^./]+$') reg_start = re.compile(r'^([A-Za-z]:)?/.*/[^./]+$')
reg_end = re.compile(r'^.*\.[a-zA-Z]+$') reg_end = re.compile(r'^.*\.[a-zA-Z]+$')
fixed_list = [] # type: List[str] fixed_list = [] # type: T.List[str]
curr_str = None # type: Optional[str] curr_str = None # type: T.Optional[str]
for i in broken_list: for i in broken_list:
if curr_str is None: if curr_str is None:

@ -13,7 +13,7 @@
# limitations under the License. # limitations under the License.
import os.path import os.path
import typing import typing as T
from .. import coredata from .. import coredata
from ..mesonlib import MachineChoice, MesonException, mlog, version_compare from ..mesonlib import MachineChoice, MesonException, mlog, version_compare
@ -35,7 +35,7 @@ from .compilers import (
Compiler, Compiler,
) )
if typing.TYPE_CHECKING: if T.TYPE_CHECKING:
from ..envconfig import MachineInfo from ..envconfig import MachineInfo
@ -51,7 +51,7 @@ class CCompiler(CLikeCompiler, Compiler):
language = 'c' language = 'c'
def __init__(self, exelist, version, for_machine: MachineChoice, is_cross: bool, def __init__(self, exelist, version, for_machine: MachineChoice, is_cross: bool,
info: 'MachineInfo', exe_wrapper: typing.Optional[str] = None, **kwargs): 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 # 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) Compiler.__init__(self, exelist, version, for_machine, info, **kwargs)
CLikeCompiler.__init__(self, is_cross, exe_wrapper) CLikeCompiler.__init__(self, is_cross, exe_wrapper)

@ -14,7 +14,7 @@
import contextlib, os.path, re, tempfile import contextlib, os.path, re, tempfile
import collections.abc import collections.abc
import typing import typing as T
from ..linkers import StaticLinker, GnuLikeDynamicLinkerMixin, SolarisDynamicLinker from ..linkers import StaticLinker, GnuLikeDynamicLinkerMixin, SolarisDynamicLinker
from .. import coredata from .. import coredata
@ -28,7 +28,7 @@ from ..envconfig import (
Properties, Properties,
) )
if typing.TYPE_CHECKING: if T.TYPE_CHECKING:
from ..coredata import OptionDictType from ..coredata import OptionDictType
from ..envconfig import MachineInfo from ..envconfig import MachineInfo
from ..environment import Environment from ..environment import Environment
@ -386,7 +386,7 @@ class RunResult:
self.stdout = stdout self.stdout = stdout
self.stderr = stderr self.stderr = stderr
class CompilerArgs(typing.MutableSequence[str]): class CompilerArgs(T.MutableSequence[str]):
''' '''
List-like class that manages a list of compiler arguments. Should be used List-like class that manages a list of compiler arguments. Should be used
while constructing compiler arguments from various sources. Can be while constructing compiler arguments from various sources. Can be
@ -441,34 +441,34 @@ class CompilerArgs(typing.MutableSequence[str]):
# *always* de-dup these because they're special arguments to the linker # *always* de-dup these because they're special arguments to the linker
always_dedup_args = tuple('-l' + lib for lib in unixy_compiler_internal_libs) always_dedup_args = tuple('-l' + lib for lib in unixy_compiler_internal_libs)
def __init__(self, compiler: typing.Union['Compiler', StaticLinker], def __init__(self, compiler: T.Union['Compiler', StaticLinker],
iterable: typing.Optional[typing.Iterable[str]] = None): iterable: T.Optional[T.Iterable[str]] = None):
self.compiler = compiler self.compiler = compiler
self.__container = list(iterable) if iterable is not None else [] # type: typing.List[str] self.__container = list(iterable) if iterable is not None else [] # type: T.List[str]
@typing.overload @T.overload
def __getitem__(self, index: int) -> str: def __getitem__(self, index: int) -> str:
pass pass
@typing.overload @T.overload
def __getitem__(self, index: slice) -> typing.List[str]: def __getitem__(self, index: slice) -> T.List[str]:
pass pass
def __getitem__(self, index): def __getitem__(self, index):
return self.__container[index] return self.__container[index]
@typing.overload @T.overload
def __setitem__(self, index: int, value: str) -> None: def __setitem__(self, index: int, value: str) -> None:
pass pass
@typing.overload @T.overload
def __setitem__(self, index: slice, value: typing.List[str]) -> None: def __setitem__(self, index: slice, value: T.List[str]) -> None:
pass pass
def __setitem__(self, index, value) -> None: def __setitem__(self, index, value) -> None:
self.__container[index] = value self.__container[index] = value
def __delitem__(self, index: typing.Union[int, slice]) -> None: def __delitem__(self, index: T.Union[int, slice]) -> None:
del self.__container[index] del self.__container[index]
def __len__(self) -> int: def __len__(self) -> int:
@ -531,7 +531,7 @@ class CompilerArgs(typing.MutableSequence[str]):
return True return True
return False return False
def to_native(self, copy: bool = False) -> typing.List[str]: def to_native(self, copy: bool = False) -> T.List[str]:
# Check if we need to add --start/end-group for circular dependencies # Check if we need to add --start/end-group for circular dependencies
# between static libraries, and for recursively searching for symbols # between static libraries, and for recursively searching for symbols
# needed by static libraries that are provided by object files or # needed by static libraries that are provided by object files or
@ -563,7 +563,7 @@ class CompilerArgs(typing.MutableSequence[str]):
# Remove system/default include paths added with -isystem # Remove system/default include paths added with -isystem
if hasattr(self.compiler, 'get_default_include_dirs'): if hasattr(self.compiler, 'get_default_include_dirs'):
default_dirs = self.compiler.get_default_include_dirs() default_dirs = self.compiler.get_default_include_dirs()
bad_idx_list = [] # type: typing.List[int] bad_idx_list = [] # type: T.List[int]
for i, each in enumerate(new): for i, each in enumerate(new):
# Remove the -isystem and the path if the path is a default path # Remove the -isystem and the path if the path is a default path
if (each == '-isystem' and if (each == '-isystem' and
@ -589,7 +589,7 @@ class CompilerArgs(typing.MutableSequence[str]):
else: else:
self.__container.append(arg) self.__container.append(arg)
def extend_direct(self, iterable: typing.Iterable[str]) -> None: def extend_direct(self, iterable: T.Iterable[str]) -> None:
''' '''
Extend using the elements in the specified iterable without any Extend using the elements in the specified iterable without any
reordering or de-dup except for absolute paths where the order of reordering or de-dup except for absolute paths where the order of
@ -598,7 +598,7 @@ class CompilerArgs(typing.MutableSequence[str]):
for elem in iterable: for elem in iterable:
self.append_direct(elem) self.append_direct(elem)
def extend_preserving_lflags(self, iterable: typing.Iterable[str]) -> None: def extend_preserving_lflags(self, iterable: T.Iterable[str]) -> None:
normal_flags = [] normal_flags = []
lflags = [] lflags = []
for i in iterable: for i in iterable:
@ -609,18 +609,18 @@ class CompilerArgs(typing.MutableSequence[str]):
self.extend(normal_flags) self.extend(normal_flags)
self.extend_direct(lflags) self.extend_direct(lflags)
def __add__(self, args: typing.Iterable[str]) -> 'CompilerArgs': def __add__(self, args: T.Iterable[str]) -> 'CompilerArgs':
new = self.copy() new = self.copy()
new += args new += args
return new return new
def __iadd__(self, args: typing.Iterable[str]) -> 'CompilerArgs': def __iadd__(self, args: T.Iterable[str]) -> 'CompilerArgs':
''' '''
Add two CompilerArgs while taking into account overriding of arguments Add two CompilerArgs while taking into account overriding of arguments
and while preserving the order of arguments as much as possible and while preserving the order of arguments as much as possible
''' '''
pre = [] # type: typing.List[str] pre = [] # type: T.List[str]
post = [] # type: typing.List[str] post = [] # type: T.List[str]
if not isinstance(args, collections.abc.Iterable): if not isinstance(args, collections.abc.Iterable):
raise TypeError('can only concatenate Iterable[str] (not "{}") to CompilerArgs'.format(args)) raise TypeError('can only concatenate Iterable[str] (not "{}") to CompilerArgs'.format(args))
for arg in args: for arg in args:
@ -650,12 +650,12 @@ class CompilerArgs(typing.MutableSequence[str]):
self.__container += post self.__container += post
return self return self
def __radd__(self, args: typing.Iterable[str]): def __radd__(self, args: T.Iterable[str]):
new = CompilerArgs(self.compiler, args) new = CompilerArgs(self.compiler, args)
new += self new += self
return new return new
def __eq__(self, other: typing.Any) -> typing.Union[bool, 'NotImplemented']: def __eq__(self, other: T.Any) -> T.Union[bool, 'NotImplemented']:
# Only allow equality checks against other CompilerArgs and lists instances # Only allow equality checks against other CompilerArgs and lists instances
if isinstance(other, CompilerArgs): if isinstance(other, CompilerArgs):
return self.compiler == other.compiler and self.__container == other.__container return self.compiler == other.compiler and self.__container == other.__container
@ -666,7 +666,7 @@ class CompilerArgs(typing.MutableSequence[str]):
def append(self, arg: str) -> None: def append(self, arg: str) -> None:
self.__iadd__([arg]) self.__iadd__([arg])
def extend(self, args: typing.Iterable[str]) -> None: def extend(self, args: T.Iterable[str]) -> None:
self.__iadd__(args) self.__iadd__(args)
def __repr__(self) -> str: def __repr__(self) -> str:
@ -680,11 +680,11 @@ class Compiler:
# manually searched. # manually searched.
internal_libs = () internal_libs = ()
LINKER_PREFIX = None # type: typing.Union[None, str, typing.List[str]] LINKER_PREFIX = None # type: T.Union[None, str, T.List[str]]
INVOKES_LINKER = True INVOKES_LINKER = True
def __init__(self, exelist, version, for_machine: MachineChoice, info: 'MachineInfo', def __init__(self, exelist, version, for_machine: MachineChoice, info: 'MachineInfo',
linker: typing.Optional['DynamicLinker'] = None, **kwargs): linker: T.Optional['DynamicLinker'] = None, **kwargs):
if isinstance(exelist, str): if isinstance(exelist, str):
self.exelist = [exelist] self.exelist = [exelist]
elif isinstance(exelist, list): elif isinstance(exelist, list):
@ -742,7 +742,7 @@ class Compiler:
def get_default_suffix(self) -> str: def get_default_suffix(self) -> str:
return self.default_suffix return self.default_suffix
def get_define(self, dname, prefix, env, extra_args, dependencies) -> typing.Tuple[str, bool]: def get_define(self, dname, prefix, env, extra_args, dependencies) -> T.Tuple[str, bool]:
raise EnvironmentException('%s does not support get_define ' % self.get_id()) raise EnvironmentException('%s does not support get_define ' % self.get_id())
def compute_int(self, expression, low, high, guess, prefix, env, extra_args, dependencies) -> int: def compute_int(self, expression, low, high, guess, prefix, env, extra_args, dependencies) -> int:
@ -752,11 +752,11 @@ class Compiler:
raise EnvironmentException('%s does not support compute_parameters_with_absolute_paths ' % self.get_id()) raise EnvironmentException('%s does not support compute_parameters_with_absolute_paths ' % self.get_id())
def has_members(self, typename, membernames, prefix, env, *, def has_members(self, typename, membernames, prefix, env, *,
extra_args=None, dependencies=None) -> typing.Tuple[bool, bool]: extra_args=None, dependencies=None) -> T.Tuple[bool, bool]:
raise EnvironmentException('%s does not support has_member(s) ' % self.get_id()) raise EnvironmentException('%s does not support has_member(s) ' % self.get_id())
def has_type(self, typename, prefix, env, extra_args, *, def has_type(self, typename, prefix, env, extra_args, *,
dependencies=None) -> typing.Tuple[bool, bool]: dependencies=None) -> T.Tuple[bool, bool]:
raise EnvironmentException('%s does not support has_type ' % self.get_id()) 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) -> bool:
@ -765,10 +765,10 @@ class Compiler:
def get_exelist(self): def get_exelist(self):
return self.exelist[:] return self.exelist[:]
def get_linker_exelist(self) -> typing.List[str]: def get_linker_exelist(self) -> T.List[str]:
return self.linker.get_exelist() return self.linker.get_exelist()
def get_linker_output_args(self, outputname: str) -> typing.List[str]: def get_linker_output_args(self, outputname: str) -> T.List[str]:
return self.linker.get_output_args(outputname) return self.linker.get_output_args(outputname)
def get_builtin_define(self, *args, **kwargs): def get_builtin_define(self, *args, **kwargs):
@ -799,31 +799,31 @@ class Compiler:
""" """
return [] return []
def get_linker_args_from_envvars(self) -> typing.List[str]: def get_linker_args_from_envvars(self) -> T.List[str]:
return self.linker.get_args_from_envvars() return self.linker.get_args_from_envvars()
def get_options(self) -> typing.Dict[str, coredata.UserOption]: def get_options(self) -> T.Dict[str, coredata.UserOption]:
return {} return {}
def get_option_compile_args(self, options): def get_option_compile_args(self, options):
return [] return []
def get_option_link_args(self, options: 'OptionDictType') -> typing.List[str]: def get_option_link_args(self, options: 'OptionDictType') -> T.List[str]:
return self.linker.get_option_args(options) return self.linker.get_option_args(options)
def check_header(self, *args, **kwargs) -> typing.Tuple[bool, bool]: def check_header(self, *args, **kwargs) -> T.Tuple[bool, bool]:
raise EnvironmentException('Language %s does not support header checks.' % self.get_display_language()) raise EnvironmentException('Language %s does not support header checks.' % self.get_display_language())
def has_header(self, *args, **kwargs) -> typing.Tuple[bool, bool]: def has_header(self, *args, **kwargs) -> T.Tuple[bool, bool]:
raise EnvironmentException('Language %s does not support header checks.' % self.get_display_language()) raise EnvironmentException('Language %s does not support header checks.' % self.get_display_language())
def has_header_symbol(self, *args, **kwargs) -> typing.Tuple[bool, bool]: def has_header_symbol(self, *args, **kwargs) -> T.Tuple[bool, bool]:
raise EnvironmentException('Language %s does not support header symbol checks.' % self.get_display_language()) raise EnvironmentException('Language %s does not support header symbol checks.' % self.get_display_language())
def compiles(self, *args, **kwargs) -> typing.Tuple[bool, bool]: def compiles(self, *args, **kwargs) -> T.Tuple[bool, bool]:
raise EnvironmentException('Language %s does not support compile checks.' % self.get_display_language()) raise EnvironmentException('Language %s does not support compile checks.' % self.get_display_language())
def links(self, *args, **kwargs) -> typing.Tuple[bool, bool]: def links(self, *args, **kwargs) -> T.Tuple[bool, bool]:
raise EnvironmentException('Language %s does not support link checks.' % self.get_display_language()) raise EnvironmentException('Language %s does not support link checks.' % self.get_display_language())
def run(self, *args, **kwargs) -> RunResult: def run(self, *args, **kwargs) -> RunResult:
@ -835,7 +835,7 @@ class Compiler:
def alignment(self, *args, **kwargs) -> int: def alignment(self, *args, **kwargs) -> int:
raise EnvironmentException('Language %s does not support alignment checks.' % self.get_display_language()) raise EnvironmentException('Language %s does not support alignment checks.' % self.get_display_language())
def has_function(self, *args, **kwargs) -> typing.Tuple[bool, bool]: def has_function(self, *args, **kwargs) -> T.Tuple[bool, bool]:
raise EnvironmentException('Language %s does not support function checks.' % self.get_display_language()) raise EnvironmentException('Language %s does not support function checks.' % self.get_display_language())
@classmethod @classmethod
@ -844,7 +844,7 @@ class Compiler:
return args[:] return args[:]
@classmethod @classmethod
def native_args_to_unix(cls, args: typing.List[str]) -> typing.List[str]: def native_args_to_unix(cls, args: T.List[str]) -> T.List[str]:
"Always returns a copy that can be independently mutated" "Always returns a copy that can be independently mutated"
return args[:] return args[:]
@ -857,12 +857,12 @@ class Compiler:
def get_program_dirs(self, *args, **kwargs): def get_program_dirs(self, *args, **kwargs):
return [] return []
def has_multi_arguments(self, args, env) -> typing.Tuple[bool, bool]: def has_multi_arguments(self, args, env) -> T.Tuple[bool, bool]:
raise EnvironmentException( raise EnvironmentException(
'Language {} does not support has_multi_arguments.'.format( 'Language {} does not support has_multi_arguments.'.format(
self.get_display_language())) self.get_display_language()))
def has_multi_link_arguments(self, args: typing.List[str], env: 'Environment') -> typing.Tuple[bool, bool]: def has_multi_link_arguments(self, args: T.List[str], env: 'Environment') -> T.Tuple[bool, bool]:
return self.linker.has_multi_arguments(args, env) return self.linker.has_multi_arguments(args, env)
def _get_compile_output(self, dirname, mode): def _get_compile_output(self, dirname, mode):
@ -976,22 +976,22 @@ class Compiler:
def get_compile_debugfile_args(self, rel_obj, **kwargs): def get_compile_debugfile_args(self, rel_obj, **kwargs):
return [] return []
def get_link_debugfile_args(self, targetfile: str) -> typing.List[str]: def get_link_debugfile_args(self, targetfile: str) -> T.List[str]:
return self.linker.get_debugfile_args(targetfile) return self.linker.get_debugfile_args(targetfile)
def get_std_shared_lib_link_args(self) -> typing.List[str]: def get_std_shared_lib_link_args(self) -> T.List[str]:
return self.linker.get_std_shared_lib_args() return self.linker.get_std_shared_lib_args()
def get_std_shared_module_link_args(self, options: 'OptionDictType') -> typing.List[str]: def get_std_shared_module_link_args(self, options: 'OptionDictType') -> T.List[str]:
return self.linker.get_std_shared_module_args(options) return self.linker.get_std_shared_module_args(options)
def get_link_whole_for(self, args: typing.List[str]) -> typing.List[str]: def get_link_whole_for(self, args: T.List[str]) -> T.List[str]:
return self.linker.get_link_whole_for(args) return self.linker.get_link_whole_for(args)
def get_allow_undefined_link_args(self) -> typing.List[str]: def get_allow_undefined_link_args(self) -> T.List[str]:
return self.linker.get_allow_undefined_args() return self.linker.get_allow_undefined_args()
def no_undefined_link_args(self) -> typing.List[str]: def no_undefined_link_args(self) -> T.List[str]:
return self.linker.no_undefined_args() return self.linker.no_undefined_args()
# Compiler arguments needed to enable the given instruction set. # Compiler arguments needed to enable the given instruction set.
@ -1002,7 +1002,7 @@ class Compiler:
def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str, def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str,
rpath_paths: str, build_rpath: str, rpath_paths: str, build_rpath: str,
install_rpath: str) -> typing.List[str]: install_rpath: str) -> T.List[str]:
return self.linker.build_rpath_args( return self.linker.build_rpath_args(
env, build_dir, from_dir, rpath_paths, build_rpath, install_rpath) env, build_dir, from_dir, rpath_paths, build_rpath, install_rpath)
@ -1033,7 +1033,7 @@ class Compiler:
m = 'Language {} does not support position-independent executable' m = 'Language {} does not support position-independent executable'
raise EnvironmentException(m.format(self.get_display_language())) raise EnvironmentException(m.format(self.get_display_language()))
def get_pie_link_args(self) -> typing.List[str]: def get_pie_link_args(self) -> T.List[str]:
return self.linker.get_pie_args() return self.linker.get_pie_args()
def get_argument_syntax(self): def get_argument_syntax(self):
@ -1055,40 +1055,40 @@ class Compiler:
raise EnvironmentException( raise EnvironmentException(
'%s does not support get_profile_use_args ' % self.get_id()) '%s does not support get_profile_use_args ' % self.get_id())
def get_undefined_link_args(self) -> typing.List[str]: def get_undefined_link_args(self) -> T.List[str]:
return self.linker.get_undefined_link_args() return self.linker.get_undefined_link_args()
def remove_linkerlike_args(self, args): def remove_linkerlike_args(self, args):
return [x for x in args if not x.startswith('-Wl')] return [x for x in args if not x.startswith('-Wl')]
def get_lto_compile_args(self) -> typing.List[str]: def get_lto_compile_args(self) -> T.List[str]:
return [] return []
def get_lto_link_args(self) -> typing.List[str]: def get_lto_link_args(self) -> T.List[str]:
return self.linker.get_lto_args() return self.linker.get_lto_args()
def sanitizer_compile_args(self, value: str) -> typing.List[str]: def sanitizer_compile_args(self, value: str) -> T.List[str]:
return [] return []
def sanitizer_link_args(self, value: str) -> typing.List[str]: def sanitizer_link_args(self, value: str) -> T.List[str]:
return self.linker.sanitizer_args(value) return self.linker.sanitizer_args(value)
def get_asneeded_args(self) -> typing.List[str]: def get_asneeded_args(self) -> T.List[str]:
return self.linker.get_asneeded_args() return self.linker.get_asneeded_args()
def bitcode_args(self) -> typing.List[str]: def bitcode_args(self) -> T.List[str]:
return self.linker.bitcode_args() return self.linker.bitcode_args()
def get_linker_debug_crt_args(self) -> typing.List[str]: def get_linker_debug_crt_args(self) -> T.List[str]:
return self.linker.get_debug_crt_args() return self.linker.get_debug_crt_args()
def get_buildtype_linker_args(self, buildtype: str) -> typing.List[str]: def get_buildtype_linker_args(self, buildtype: str) -> T.List[str]:
return self.linker.get_buildtype_args(buildtype) return self.linker.get_buildtype_args(buildtype)
def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str, def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str,
suffix: str, soversion: str, suffix: str, soversion: str,
darwin_versions: typing.Tuple[str, str], darwin_versions: T.Tuple[str, str],
is_shared_module: bool) -> typing.List[str]: is_shared_module: bool) -> T.List[str]:
return self.linker.get_soname_args( return self.linker.get_soname_args(
env, prefix, shlib_name, suffix, soversion, env, prefix, shlib_name, suffix, soversion,
darwin_versions, is_shared_module) darwin_versions, is_shared_module)
@ -1103,7 +1103,7 @@ class Compiler:
return dep.get_link_args() return dep.get_link_args()
@classmethod @classmethod
def use_linker_args(cls, linker: str) -> typing.List[str]: def use_linker_args(cls, linker: str) -> T.List[str]:
"""Get a list of arguments to pass to the compiler to set the linker. """Get a list of arguments to pass to the compiler to set the linker.
""" """
return [] return []
@ -1131,12 +1131,12 @@ def get_largefile_args(compiler):
return [] return []
def get_args_from_envvars(lang: str, use_linker_args: bool) -> typing.Tuple[typing.List[str], typing.List[str]]: def get_args_from_envvars(lang: str, use_linker_args: bool) -> T.Tuple[T.List[str], T.List[str]]:
""" """
Returns a tuple of (compile_flags, link_flags) for the specified language Returns a tuple of (compile_flags, link_flags) for the specified language
from the inherited environment from the inherited environment
""" """
def log_var(var, val: typing.Optional[str]): def log_var(var, val: T.Optional[str]):
if val: if val:
mlog.log('Appending {} from environment: {!r}'.format(var, val)) mlog.log('Appending {} from environment: {!r}'.format(var, val))
else: else:
@ -1145,8 +1145,8 @@ def get_args_from_envvars(lang: str, use_linker_args: bool) -> typing.Tuple[typi
if lang not in cflags_mapping: if lang not in cflags_mapping:
return [], [] return [], []
compile_flags = [] # type: typing.List[str] compile_flags = [] # type: T.List[str]
link_flags = [] # type: typing.List[str] link_flags = [] # type: T.List[str]
env_compile_flags = os.environ.get(cflags_mapping[lang]) env_compile_flags = os.environ.get(cflags_mapping[lang])
log_var(cflags_mapping[lang], env_compile_flags) log_var(cflags_mapping[lang], env_compile_flags)
@ -1179,8 +1179,8 @@ def get_args_from_envvars(lang: str, use_linker_args: bool) -> typing.Tuple[typi
return compile_flags, link_flags return compile_flags, link_flags
def get_global_options(lang: str, comp: typing.Type[Compiler], def get_global_options(lang: str, comp: T.Type[Compiler],
properties: Properties) -> typing.Dict[str, coredata.UserOption]: properties: Properties) -> T.Dict[str, coredata.UserOption]:
"""Retreive options that apply to all compilers for a given language.""" """Retreive options that apply to all compilers for a given language."""
description = 'Extra arguments passed to the {}'.format(lang) description = 'Extra arguments passed to the {}'.format(lang)
opts = { opts = {

@ -15,7 +15,7 @@
import copy import copy
import functools import functools
import os.path import os.path
import typing import typing as T
from .. import coredata from .. import coredata
from .. import mlog from .. import mlog
@ -39,7 +39,7 @@ from .mixins.pgi import PGICompiler
from .mixins.islinker import BasicLinkerIsCompilerMixin, LinkerEnvVarsMixin from .mixins.islinker import BasicLinkerIsCompilerMixin, LinkerEnvVarsMixin
from .mixins.emscripten import EmscriptenMixin from .mixins.emscripten import EmscriptenMixin
if typing.TYPE_CHECKING: if T.TYPE_CHECKING:
from ..envconfig import MachineInfo from ..envconfig import MachineInfo
@ -62,7 +62,7 @@ class CPPCompiler(CLikeCompiler, Compiler):
language = 'cpp' language = 'cpp'
def __init__(self, exelist, version, for_machine: MachineChoice, is_cross: bool, def __init__(self, exelist, version, for_machine: MachineChoice, is_cross: bool,
info: 'MachineInfo', exe_wrap: typing.Optional[str] = None, **kwargs): info: 'MachineInfo', exe_wrap: T.Optional[str] = None, **kwargs):
# If a child ObjCPP class has already set it, don't set it ourselves # If a child ObjCPP class has already set it, don't set it ourselves
Compiler.__init__(self, exelist, version, for_machine, info, **kwargs) Compiler.__init__(self, exelist, version, for_machine, info, **kwargs)
CLikeCompiler.__init__(self, is_cross, exe_wrap) CLikeCompiler.__init__(self, is_cross, exe_wrap)
@ -431,7 +431,7 @@ class VisualStudioLikeCPPCompilerMixin:
def get_option_link_args(self, options): def get_option_link_args(self, options):
return options['cpp_winlibs'].value[:] return options['cpp_winlibs'].value[:]
def _get_options_impl(self, opts, cpp_stds: typing.List[str]): def _get_options_impl(self, opts, cpp_stds: T.List[str]):
opts.update({'cpp_eh': coredata.UserComboOption('C++ exception handling type.', opts.update({'cpp_eh': coredata.UserComboOption('C++ exception handling type.',
['none', 'default', 'a', 's', 'sc'], ['none', 'default', 'a', 's', 'sc'],
'default'), 'default'),

@ -13,14 +13,14 @@
# limitations under the License. # limitations under the License.
import os.path, subprocess import os.path, subprocess
import typing import typing as T
from ..mesonlib import EnvironmentException from ..mesonlib import EnvironmentException
from .compilers import Compiler, MachineChoice, mono_buildtype_args from .compilers import Compiler, MachineChoice, mono_buildtype_args
from .mixins.islinker import BasicLinkerIsCompilerMixin from .mixins.islinker import BasicLinkerIsCompilerMixin
if typing.TYPE_CHECKING: if T.TYPE_CHECKING:
from ..envconfig import MachineInfo from ..envconfig import MachineInfo
cs_optimization_args = {'0': [], cs_optimization_args = {'0': [],

@ -13,7 +13,7 @@
# limitations under the License. # limitations under the License.
import os.path import os.path
import typing import typing as T
from functools import partial from functools import partial
from .. import coredata from .. import coredata
@ -22,7 +22,7 @@ from ..mesonlib import EnvironmentException, MachineChoice, Popen_safe, OptionOv
from .compilers import (Compiler, cuda_buildtype_args, cuda_optimization_args, from .compilers import (Compiler, cuda_buildtype_args, cuda_optimization_args,
cuda_debug_args) cuda_debug_args)
if typing.TYPE_CHECKING: if T.TYPE_CHECKING:
from ..environment import Environment # noqa: F401 from ..environment import Environment # noqa: F401
from ..envconfig import MachineInfo from ..envconfig import MachineInfo
@ -197,9 +197,9 @@ class CudaCompiler(Compiler):
return args + self._to_host_flags(self.host_compiler.get_option_compile_args(self._to_host_compiler_options(options))) return args + self._to_host_flags(self.host_compiler.get_option_compile_args(self._to_host_compiler_options(options)))
@classmethod @classmethod
def _cook_link_args(cls, args: typing.List[str]) -> typing.List[str]: def _cook_link_args(cls, args: T.List[str]) -> T.List[str]:
# Prepare link args for nvcc # Prepare link args for nvcc
cooked = [] # type: typing.List[str] cooked = [] # type: T.List[str]
for arg in args: for arg in args:
if arg.startswith('-Wl,'): # strip GNU-style -Wl prefix if arg.startswith('-Wl,'): # strip GNU-style -Wl prefix
arg = arg.replace('-Wl,', '', 1) arg = arg.replace('-Wl,', '', 1)
@ -263,7 +263,7 @@ class CudaCompiler(Compiler):
def get_depfile_suffix(self): def get_depfile_suffix(self):
return 'd' return 'd'
def get_linker_debug_crt_args(self) -> typing.List[str]: def get_linker_debug_crt_args(self) -> T.List[str]:
return self._cook_link_args(self.host_compiler.get_linker_debug_crt_args()) return self._cook_link_args(self.host_compiler.get_linker_debug_crt_args())
def get_buildtype_linker_args(self, buildtype): def get_buildtype_linker_args(self, buildtype):
@ -271,7 +271,7 @@ class CudaCompiler(Compiler):
def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str, def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str,
rpath_paths: str, build_rpath: str, rpath_paths: str, build_rpath: str,
install_rpath: str) -> typing.List[str]: install_rpath: str) -> T.List[str]:
return self._cook_link_args(self.host_compiler.build_rpath_args( return self._cook_link_args(self.host_compiler.build_rpath_args(
env, build_dir, from_dir, rpath_paths, build_rpath, install_rpath)) env, build_dir, from_dir, rpath_paths, build_rpath, install_rpath))
@ -284,10 +284,10 @@ class CudaCompiler(Compiler):
def compute_parameters_with_absolute_paths(self, parameter_list, build_dir): def compute_parameters_with_absolute_paths(self, parameter_list, build_dir):
return [] return []
def get_output_args(self, target: str) -> typing.List[str]: def get_output_args(self, target: str) -> T.List[str]:
return ['-o', target] return ['-o', target]
def get_std_exe_link_args(self) -> typing.List[str]: def get_std_exe_link_args(self) -> T.List[str]:
return self._cook_link_args(self.host_compiler.get_std_exe_link_args()) return self._cook_link_args(self.host_compiler.get_std_exe_link_args())
def find_library(self, libname, env, extra_dirs, libtype: LibType = LibType.PREFER_SHARED): def find_library(self, libname, env, extra_dirs, libtype: LibType = LibType.PREFER_SHARED):

@ -13,7 +13,7 @@
# limitations under the License. # limitations under the License.
import os.path, subprocess import os.path, subprocess
import typing import typing as T
from ..mesonlib import ( from ..mesonlib import (
EnvironmentException, MachineChoice, version_compare, EnvironmentException, MachineChoice, version_compare,
@ -30,7 +30,7 @@ from .compilers import (
from .mixins.gnu import GnuCompiler from .mixins.gnu import GnuCompiler
from .mixins.islinker import LinkerEnvVarsMixin, BasicLinkerIsCompilerMixin from .mixins.islinker import LinkerEnvVarsMixin, BasicLinkerIsCompilerMixin
if typing.TYPE_CHECKING: if T.TYPE_CHECKING:
from ..envconfig import MachineInfo from ..envconfig import MachineInfo
d_feature_args = {'gcc': {'unittest': '-funittest', d_feature_args = {'gcc': {'unittest': '-funittest',
@ -388,7 +388,7 @@ class DmdLikeCompilerMixin:
assert(buildtype == 'custom') assert(buildtype == 'custom')
raise EnvironmentException('Requested C runtime based on buildtype, but buildtype is "custom".') raise EnvironmentException('Requested C runtime based on buildtype, but buildtype is "custom".')
def get_soname_args(self, *args, **kwargs) -> typing.List[str]: def get_soname_args(self, *args, **kwargs) -> T.List[str]:
# LDC and DMD actually do use a linker, but they proxy all of that with # LDC and DMD actually do use a linker, but they proxy all of that with
# their own arguments # their own arguments
soargs = [] soargs = []
@ -396,7 +396,7 @@ class DmdLikeCompilerMixin:
soargs.append('-L=' + arg) soargs.append('-L=' + arg)
return soargs return soargs
def get_allow_undefined_link_args(self) -> typing.List[str]: def get_allow_undefined_link_args(self) -> T.List[str]:
args = [] args = []
for arg in self.linker.get_allow_undefined_args(): for arg in self.linker.get_allow_undefined_args():
args.append('-L=' + arg) args.append('-L=' + arg)
@ -654,7 +654,7 @@ class GnuDCompiler(DCompiler, GnuCompiler):
return parameter_list return parameter_list
def get_allow_undefined_link_args(self) -> typing.List[str]: def get_allow_undefined_link_args(self) -> T.List[str]:
return self.linker.get_allow_undefined_args() return self.linker.get_allow_undefined_args()

@ -13,7 +13,7 @@
# limitations under the License. # limitations under the License.
from pathlib import Path from pathlib import Path
from typing import TYPE_CHECKING, List import typing as T
import subprocess, os import subprocess, os
from .. import coredata from .. import coredata
@ -35,7 +35,7 @@ from mesonbuild.mesonlib import (
version_compare, EnvironmentException, MesonException, MachineChoice, LibType version_compare, EnvironmentException, MesonException, MachineChoice, LibType
) )
if TYPE_CHECKING: if T.TYPE_CHECKING:
from ..envconfig import MachineInfo from ..envconfig import MachineInfo
@ -189,7 +189,7 @@ class GnuFortranCompiler(GnuCompiler, FortranCompiler):
'none')}) 'none')})
return opts return opts
def get_option_compile_args(self, options) -> List[str]: def get_option_compile_args(self, options) -> T.List[str]:
args = [] args = []
std = options['fortran_std'] std = options['fortran_std']
if std.value != 'none': if std.value != 'none':
@ -295,7 +295,7 @@ class IntelFortranCompiler(IntelGnuLikeCompiler, FortranCompiler):
'none')}) 'none')})
return opts return opts
def get_option_compile_args(self, options) -> List[str]: def get_option_compile_args(self, options) -> T.List[str]:
args = [] args = []
std = options['fortran_std'] std = options['fortran_std']
stds = {'legacy': 'none', 'f95': 'f95', 'f2003': 'f03', 'f2008': 'f08', 'f2018': 'f18'} stds = {'legacy': 'none', 'f95': 'f95', 'f2003': 'f03', 'f2008': 'f08', 'f2018': 'f18'}
@ -315,7 +315,7 @@ class IntelFortranCompiler(IntelGnuLikeCompiler, FortranCompiler):
def language_stdlib_only_link_flags(self): def language_stdlib_only_link_flags(self):
return ['-lifcore', '-limf'] return ['-lifcore', '-limf']
def get_dependency_gen_args(self, outtarget: str, outfile: str) -> List[str]: def get_dependency_gen_args(self, outtarget: str, outfile: str) -> T.List[str]:
return ['-gen-dep=' + outtarget, '-gen-depformat=make'] return ['-gen-dep=' + outtarget, '-gen-depformat=make']
@ -345,7 +345,7 @@ class IntelClFortranCompiler(IntelVisualStudioLikeCompiler, FortranCompiler):
'none')}) 'none')})
return opts return opts
def get_option_compile_args(self, options) -> List[str]: def get_option_compile_args(self, options) -> T.List[str]:
args = [] args = []
std = options['fortran_std'] std = options['fortran_std']
stds = {'legacy': 'none', 'f95': 'f95', 'f2003': 'f03', 'f2008': 'f08', 'f2018': 'f18'} stds = {'legacy': 'none', 'f95': 'f95', 'f2003': 'f03', 'f2008': 'f08', 'f2018': 'f18'}
@ -353,7 +353,7 @@ class IntelClFortranCompiler(IntelVisualStudioLikeCompiler, FortranCompiler):
args.append('/stand:' + stds[std.value]) args.append('/stand:' + stds[std.value])
return args return args
def get_module_outdir_args(self, path) -> List[str]: def get_module_outdir_args(self, path) -> T.List[str]:
return ['/module:' + path] return ['/module:' + path]
@ -388,7 +388,7 @@ class PGIFortranCompiler(PGICompiler, FortranCompiler):
'2': default_warn_args, '2': default_warn_args,
'3': default_warn_args + ['-Mdclchk']} '3': default_warn_args + ['-Mdclchk']}
def language_stdlib_only_link_flags(self) -> List[str]: def language_stdlib_only_link_flags(self) -> T.List[str]:
return ['-lpgf90rtl', '-lpgf90', '-lpgf90_rpm1', '-lpgf902', return ['-lpgf90rtl', '-lpgf90', '-lpgf90_rpm1', '-lpgf902',
'-lpgf90rtl', '-lpgftnrtl', '-lrt'] '-lpgf90rtl', '-lpgftnrtl', '-lrt']
@ -406,7 +406,7 @@ class FlangFortranCompiler(ClangCompiler, FortranCompiler):
'2': default_warn_args, '2': default_warn_args,
'3': default_warn_args} '3': default_warn_args}
def language_stdlib_only_link_flags(self) -> List[str]: def language_stdlib_only_link_flags(self) -> T.List[str]:
return ['-lflang', '-lpgmath'] return ['-lflang', '-lpgmath']
class Open64FortranCompiler(FortranCompiler): class Open64FortranCompiler(FortranCompiler):

@ -15,13 +15,13 @@
import os.path import os.path
import shutil import shutil
import subprocess import subprocess
import typing import typing as T
from ..mesonlib import EnvironmentException, MachineChoice from ..mesonlib import EnvironmentException, MachineChoice
from .compilers import Compiler, java_buildtype_args from .compilers import Compiler, java_buildtype_args
from .mixins.islinker import BasicLinkerIsCompilerMixin from .mixins.islinker import BasicLinkerIsCompilerMixin
if typing.TYPE_CHECKING: if T.TYPE_CHECKING:
from ..envconfig import MachineInfo from ..envconfig import MachineInfo
class JavaCompiler(BasicLinkerIsCompilerMixin, Compiler): class JavaCompiler(BasicLinkerIsCompilerMixin, Compiler):

@ -16,13 +16,13 @@
import os import os
import re import re
import typing import typing as T
from ... import mesonlib from ... import mesonlib
from ..compilers import clike_debug_args from ..compilers import clike_debug_args
from .clang import clang_color_args from .clang import clang_color_args
if typing.TYPE_CHECKING: if T.TYPE_CHECKING:
from ...environment import Environment from ...environment import Environment
arm_buildtype_args = { arm_buildtype_args = {
@ -32,7 +32,7 @@ arm_buildtype_args = {
'release': ['-O3', '-Otime'], 'release': ['-O3', '-Otime'],
'minsize': ['-O3', '-Ospace'], 'minsize': ['-O3', '-Ospace'],
'custom': [], 'custom': [],
} # type: typing.Dict[str, typing.List[str]] } # type: T.Dict[str, T.List[str]]
arm_optimization_args = { arm_optimization_args = {
'0': ['-O0'], '0': ['-O0'],
@ -41,7 +41,7 @@ arm_optimization_args = {
'2': ['-O2'], '2': ['-O2'],
'3': ['-O3'], '3': ['-O3'],
's': [], 's': [],
} # type: typing.Dict[str, typing.List[str]] } # type: T.Dict[str, T.List[str]]
armclang_buildtype_args = { armclang_buildtype_args = {
'plain': [], 'plain': [],
@ -50,7 +50,7 @@ armclang_buildtype_args = {
'release': ['-Os'], 'release': ['-Os'],
'minsize': ['-Oz'], 'minsize': ['-Oz'],
'custom': [], 'custom': [],
} # type: typing.Dict[str, typing.List[str]] } # type: T.Dict[str, T.List[str]]
armclang_optimization_args = { armclang_optimization_args = {
'0': ['-O0'], '0': ['-O0'],
@ -59,7 +59,7 @@ armclang_optimization_args = {
'2': ['-O2'], '2': ['-O2'],
'3': ['-O3'], '3': ['-O3'],
's': ['-Os'] 's': ['-Os']
} # type: typing.Dict[str, typing.List[str]] } # type: T.Dict[str, T.List[str]]
class ArmCompiler: class ArmCompiler:
@ -68,7 +68,7 @@ class ArmCompiler:
if not self.is_cross: if not self.is_cross:
raise mesonlib.EnvironmentException('armcc supports only cross-compilation.') raise mesonlib.EnvironmentException('armcc supports only cross-compilation.')
self.id = 'arm' self.id = 'arm'
default_warn_args = [] # type: typing.List[str] default_warn_args = [] # type: T.List[str]
self.warn_args = {'0': [], self.warn_args = {'0': [],
'1': default_warn_args, '1': default_warn_args,
'2': default_warn_args + [], '2': default_warn_args + [],
@ -76,22 +76,22 @@ class ArmCompiler:
# Assembly # Assembly
self.can_compile_suffixes.add('s') self.can_compile_suffixes.add('s')
def get_pic_args(self) -> typing.List[str]: def get_pic_args(self) -> T.List[str]:
# FIXME: Add /ropi, /rwpi, /fpic etc. qualifiers to --apcs # FIXME: Add /ropi, /rwpi, /fpic etc. qualifiers to --apcs
return [] return []
def get_buildtype_args(self, buildtype: str) -> typing.List[str]: def get_buildtype_args(self, buildtype: str) -> T.List[str]:
return arm_buildtype_args[buildtype] return arm_buildtype_args[buildtype]
# Override CCompiler.get_always_args # Override CCompiler.get_always_args
def get_always_args(self) -> typing.List[str]: def get_always_args(self) -> T.List[str]:
return [] return []
# Override CCompiler.get_dependency_gen_args # Override CCompiler.get_dependency_gen_args
def get_dependency_gen_args(self, outtarget: str, outfile: str) -> typing.List[str]: def get_dependency_gen_args(self, outtarget: str, outfile: str) -> T.List[str]:
return [] return []
def get_pch_use_args(self, pch_dir: str, header: str) -> typing.List[str]: def get_pch_use_args(self, pch_dir: str, header: str) -> T.List[str]:
# FIXME: Add required arguments # FIXME: Add required arguments
# NOTE from armcc user guide: # NOTE from armcc user guide:
# "Support for Precompiled Header (PCH) files is deprecated from ARM Compiler 5.05 # "Support for Precompiled Header (PCH) files is deprecated from ARM Compiler 5.05
@ -106,19 +106,19 @@ class ArmCompiler:
# PCH files." # PCH files."
return 'pch' return 'pch'
def thread_flags(self, env: 'Environment') -> typing.List[str]: def thread_flags(self, env: 'Environment') -> T.List[str]:
return [] return []
def get_coverage_args(self) -> typing.List[str]: def get_coverage_args(self) -> T.List[str]:
return [] return []
def get_optimization_args(self, optimization_level: str) -> typing.List[str]: def get_optimization_args(self, optimization_level: str) -> T.List[str]:
return arm_optimization_args[optimization_level] return arm_optimization_args[optimization_level]
def get_debug_args(self, is_debug: bool) -> typing.List[str]: def get_debug_args(self, is_debug: bool) -> T.List[str]:
return clike_debug_args[is_debug] return clike_debug_args[is_debug]
def compute_parameters_with_absolute_paths(self, parameter_list: typing.List[str], build_dir: str) -> typing.List[str]: def compute_parameters_with_absolute_paths(self, parameter_list: T.List[str], build_dir: str) -> T.List[str]:
for idx, i in enumerate(parameter_list): for idx, i in enumerate(parameter_list):
if i[:2] == '-I' or i[:2] == '-L': if i[:2] == '-I' or i[:2] == '-L':
parameter_list[idx] = i[:2] + os.path.normpath(os.path.join(build_dir, i[2:])) parameter_list[idx] = i[:2] + os.path.normpath(os.path.join(build_dir, i[2:]))
@ -159,37 +159,37 @@ class ArmclangCompiler:
# Assembly # Assembly
self.can_compile_suffixes.update('s') self.can_compile_suffixes.update('s')
def get_pic_args(self) -> typing.List[str]: def get_pic_args(self) -> T.List[str]:
# PIC support is not enabled by default for ARM, # PIC support is not enabled by default for ARM,
# if users want to use it, they need to add the required arguments explicitly # if users want to use it, they need to add the required arguments explicitly
return [] return []
def get_colorout_args(self, colortype: str) -> typing.List[str]: def get_colorout_args(self, colortype: str) -> T.List[str]:
return clang_color_args[colortype][:] return clang_color_args[colortype][:]
def get_buildtype_args(self, buildtype: str) -> typing.List[str]: def get_buildtype_args(self, buildtype: str) -> T.List[str]:
return armclang_buildtype_args[buildtype] return armclang_buildtype_args[buildtype]
def get_pch_suffix(self) -> str: def get_pch_suffix(self) -> str:
return 'gch' return 'gch'
def get_pch_use_args(self, pch_dir: str, header: str) -> typing.List[str]: def get_pch_use_args(self, pch_dir: str, header: str) -> T.List[str]:
# Workaround for Clang bug http://llvm.org/bugs/show_bug.cgi?id=15136 # Workaround for Clang bug http://llvm.org/bugs/show_bug.cgi?id=15136
# This flag is internal to Clang (or at least not documented on the man page) # This flag is internal to Clang (or at least not documented on the man page)
# so it might change semantics at any time. # so it might change semantics at any time.
return ['-include-pch', os.path.join(pch_dir, self.get_pch_name(header))] return ['-include-pch', os.path.join(pch_dir, self.get_pch_name(header))]
# Override CCompiler.get_dependency_gen_args # Override CCompiler.get_dependency_gen_args
def get_dependency_gen_args(self, outtarget: str, outfile: str) -> typing.List[str]: def get_dependency_gen_args(self, outtarget: str, outfile: str) -> T.List[str]:
return [] return []
def get_optimization_args(self, optimization_level: str) -> typing.List[str]: def get_optimization_args(self, optimization_level: str) -> T.List[str]:
return armclang_optimization_args[optimization_level] return armclang_optimization_args[optimization_level]
def get_debug_args(self, is_debug: bool) -> typing.List[str]: def get_debug_args(self, is_debug: bool) -> T.List[str]:
return clike_debug_args[is_debug] return clike_debug_args[is_debug]
def compute_parameters_with_absolute_paths(self, parameter_list: typing.List[str], build_dir: str) -> typing.List[str]: def compute_parameters_with_absolute_paths(self, parameter_list: T.List[str], build_dir: str) -> T.List[str]:
for idx, i in enumerate(parameter_list): for idx, i in enumerate(parameter_list):
if i[:2] == '-I' or i[:2] == '-L': if i[:2] == '-I' or i[:2] == '-L':
parameter_list[idx] = i[:2] + os.path.normpath(os.path.join(build_dir, i[2:])) parameter_list[idx] = i[:2] + os.path.normpath(os.path.join(build_dir, i[2:]))

@ -15,11 +15,11 @@
"""Representations specific to the Renesas CC-RX compiler family.""" """Representations specific to the Renesas CC-RX compiler family."""
import os import os
import typing import typing as T
from ...mesonlib import EnvironmentException from ...mesonlib import EnvironmentException
if typing.TYPE_CHECKING: if T.TYPE_CHECKING:
from ...environment import Environment from ...environment import Environment
ccrx_buildtype_args = { ccrx_buildtype_args = {
@ -29,7 +29,7 @@ ccrx_buildtype_args = {
'release': [], 'release': [],
'minsize': [], 'minsize': [],
'custom': [], 'custom': [],
} # type: typing.Dict[str, typing.List[str]] } # type: T.Dict[str, T.List[str]]
ccrx_optimization_args = { ccrx_optimization_args = {
'0': ['-optimize=0'], '0': ['-optimize=0'],
@ -38,12 +38,12 @@ ccrx_optimization_args = {
'2': ['-optimize=2'], '2': ['-optimize=2'],
'3': ['-optimize=max'], '3': ['-optimize=max'],
's': ['-optimize=2', '-size'] 's': ['-optimize=2', '-size']
} # type: typing.Dict[str, typing.List[str]] } # type: T.Dict[str, T.List[str]]
ccrx_debug_args = { ccrx_debug_args = {
False: [], False: [],
True: ['-debug'] True: ['-debug']
} # type: typing.Dict[bool, typing.List[str]] } # type: T.Dict[bool, T.List[str]]
class CcrxCompiler: class CcrxCompiler:
@ -53,44 +53,44 @@ class CcrxCompiler:
self.id = 'ccrx' self.id = 'ccrx'
# Assembly # Assembly
self.can_compile_suffixes.update('s') self.can_compile_suffixes.update('s')
default_warn_args = [] # type: typing.List[str] default_warn_args = [] # type: T.List[str]
self.warn_args = {'0': [], self.warn_args = {'0': [],
'1': default_warn_args, '1': default_warn_args,
'2': default_warn_args + [], '2': default_warn_args + [],
'3': default_warn_args + []} '3': default_warn_args + []}
def get_pic_args(self) -> typing.List[str]: def get_pic_args(self) -> T.List[str]:
# PIC support is not enabled by default for CCRX, # PIC support is not enabled by default for CCRX,
# if users want to use it, they need to add the required arguments explicitly # if users want to use it, they need to add the required arguments explicitly
return [] return []
def get_buildtype_args(self, buildtype: str) -> typing.List[str]: def get_buildtype_args(self, buildtype: str) -> T.List[str]:
return ccrx_buildtype_args[buildtype] return ccrx_buildtype_args[buildtype]
def get_pch_suffix(self) -> str: def get_pch_suffix(self) -> str:
return 'pch' return 'pch'
def get_pch_use_args(self, pch_dir: str, header: str) -> typing.List[str]: def get_pch_use_args(self, pch_dir: str, header: str) -> T.List[str]:
return [] return []
# Override CCompiler.get_dependency_gen_args # Override CCompiler.get_dependency_gen_args
def get_dependency_gen_args(self, outtarget: str, outfile: str) -> typing.List[str]: def get_dependency_gen_args(self, outtarget: str, outfile: str) -> T.List[str]:
return [] return []
def thread_flags(self, env: 'Environment') -> typing.List[str]: def thread_flags(self, env: 'Environment') -> T.List[str]:
return [] return []
def get_coverage_args(self) -> typing.List[str]: def get_coverage_args(self) -> T.List[str]:
return [] return []
def get_optimization_args(self, optimization_level: str) -> typing.List[str]: def get_optimization_args(self, optimization_level: str) -> T.List[str]:
return ccrx_optimization_args[optimization_level] return ccrx_optimization_args[optimization_level]
def get_debug_args(self, is_debug: bool) -> typing.List[str]: def get_debug_args(self, is_debug: bool) -> T.List[str]:
return ccrx_debug_args[is_debug] return ccrx_debug_args[is_debug]
@classmethod @classmethod
def unix_args_to_native(cls, args: typing.List[str]) -> typing.List[str]: def unix_args_to_native(cls, args: T.List[str]) -> T.List[str]:
result = [] result = []
for i in args: for i in args:
if i.startswith('-D'): if i.startswith('-D'):
@ -108,7 +108,7 @@ class CcrxCompiler:
result.append(i) result.append(i)
return result return result
def compute_parameters_with_absolute_paths(self, parameter_list: typing.List[str], build_dir: str) -> typing.List[str]: def compute_parameters_with_absolute_paths(self, parameter_list: T.List[str], build_dir: str) -> T.List[str]:
for idx, i in enumerate(parameter_list): for idx, i in enumerate(parameter_list):
if i[:9] == '-include=': if i[:9] == '-include=':
parameter_list[idx] = i[:9] + os.path.normpath(os.path.join(build_dir, i[9:])) parameter_list[idx] = i[:9] + os.path.normpath(os.path.join(build_dir, i[9:]))

@ -15,14 +15,14 @@
"""Abstractions for the LLVM/Clang compiler family.""" """Abstractions for the LLVM/Clang compiler family."""
import os import os
import typing import typing as T
from ... import mesonlib from ... import mesonlib
from ...linkers import AppleDynamicLinker from ...linkers import AppleDynamicLinker
from ..compilers import clike_optimization_args from ..compilers import clike_optimization_args
from .gnu import GnuLikeCompiler from .gnu import GnuLikeCompiler
if typing.TYPE_CHECKING: if T.TYPE_CHECKING:
from ...environment import Environment from ...environment import Environment
from ...dependencies import Dependency # noqa: F401 from ...dependencies import Dependency # noqa: F401
@ -30,7 +30,7 @@ clang_color_args = {
'auto': ['-Xclang', '-fcolor-diagnostics'], 'auto': ['-Xclang', '-fcolor-diagnostics'],
'always': ['-Xclang', '-fcolor-diagnostics'], 'always': ['-Xclang', '-fcolor-diagnostics'],
'never': ['-Xclang', '-fno-color-diagnostics'], 'never': ['-Xclang', '-fno-color-diagnostics'],
} # type: typing.Dict[str, typing.List[str]] } # type: T.Dict[str, T.List[str]]
class ClangCompiler(GnuLikeCompiler): class ClangCompiler(GnuLikeCompiler):
@ -45,22 +45,22 @@ class ClangCompiler(GnuLikeCompiler):
# All Clang backends can also do LLVM IR # All Clang backends can also do LLVM IR
self.can_compile_suffixes.add('ll') self.can_compile_suffixes.add('ll')
def get_colorout_args(self, colortype: str) -> typing.List[str]: def get_colorout_args(self, colortype: str) -> T.List[str]:
return clang_color_args[colortype][:] return clang_color_args[colortype][:]
def get_optimization_args(self, optimization_level: str) -> typing.List[str]: def get_optimization_args(self, optimization_level: str) -> T.List[str]:
return clike_optimization_args[optimization_level] return clike_optimization_args[optimization_level]
def get_pch_suffix(self) -> str: def get_pch_suffix(self) -> str:
return 'pch' return 'pch'
def get_pch_use_args(self, pch_dir: str, header: str) -> typing.List[str]: def get_pch_use_args(self, pch_dir: str, header: str) -> T.List[str]:
# Workaround for Clang bug http://llvm.org/bugs/show_bug.cgi?id=15136 # Workaround for Clang bug http://llvm.org/bugs/show_bug.cgi?id=15136
# This flag is internal to Clang (or at least not documented on the man page) # This flag is internal to Clang (or at least not documented on the man page)
# so it might change semantics at any time. # so it might change semantics at any time.
return ['-include-pch', os.path.join(pch_dir, self.get_pch_name(header))] return ['-include-pch', os.path.join(pch_dir, self.get_pch_name(header))]
def has_multi_arguments(self, args: typing.List[str], env: 'Environment') -> typing.List[str]: def has_multi_arguments(self, args: T.List[str], env: 'Environment') -> T.List[str]:
myargs = ['-Werror=unknown-warning-option', '-Werror=unused-command-line-argument'] myargs = ['-Werror=unknown-warning-option', '-Werror=unused-command-line-argument']
if mesonlib.version_compare(self.version, '>=3.6.0'): if mesonlib.version_compare(self.version, '>=3.6.0'):
myargs.append('-Werror=ignored-optimization-argument') myargs.append('-Werror=ignored-optimization-argument')
@ -69,8 +69,8 @@ class ClangCompiler(GnuLikeCompiler):
env) env)
def has_function(self, funcname: str, prefix: str, env: 'Environment', *, def has_function(self, funcname: str, prefix: str, env: 'Environment', *,
extra_args: typing.Optional[typing.List[str]] = None, extra_args: T.Optional[T.List[str]] = None,
dependencies: typing.Optional[typing.List['Dependency']] = None) -> bool: dependencies: T.Optional[T.List['Dependency']] = None) -> bool:
if extra_args is None: if extra_args is None:
extra_args = [] extra_args = []
# Starting with XCode 8, we need to pass this to force linker # Starting with XCode 8, we need to pass this to force linker
@ -83,7 +83,7 @@ class ClangCompiler(GnuLikeCompiler):
return super().has_function(funcname, prefix, env, extra_args=extra_args, return super().has_function(funcname, prefix, env, extra_args=extra_args,
dependencies=dependencies) dependencies=dependencies)
def openmp_flags(self) -> typing.List[str]: def openmp_flags(self) -> T.List[str]:
if mesonlib.version_compare(self.version, '>=3.8.0'): if mesonlib.version_compare(self.version, '>=3.8.0'):
return ['-fopenmp'] return ['-fopenmp']
elif mesonlib.version_compare(self.version, '>=3.7.0'): elif mesonlib.version_compare(self.version, '>=3.7.0'):

@ -26,7 +26,7 @@ import itertools
import os import os
import re import re
import subprocess import subprocess
import typing import typing as T
from pathlib import Path from pathlib import Path
from ... import mesonlib from ... import mesonlib
@ -35,7 +35,7 @@ from ... import mlog
from .. import compilers from .. import compilers
from .visualstudio import VisualStudioLikeCompiler from .visualstudio import VisualStudioLikeCompiler
if typing.TYPE_CHECKING: if T.TYPE_CHECKING:
from ...environment import Environment from ...environment import Environment
@ -50,7 +50,7 @@ class CLikeCompiler:
find_framework_cache = {} find_framework_cache = {}
internal_libs = compilers.unixy_compiler_internal_libs internal_libs = compilers.unixy_compiler_internal_libs
def __init__(self, is_cross: bool, exe_wrapper: typing.Optional[str] = None): def __init__(self, is_cross: bool, exe_wrapper: T.Optional[str] = None):
# If a child ObjC or CPP class has already set it, don't set it ourselves # If a child ObjC or CPP class has already set it, don't set it ourselves
self.is_cross = is_cross self.is_cross = is_cross
self.can_compile_suffixes.add('h') self.can_compile_suffixes.add('h')
@ -117,7 +117,7 @@ class CLikeCompiler:
def get_coverage_args(self): def get_coverage_args(self):
return ['--coverage'] return ['--coverage']
def get_coverage_link_args(self) -> typing.List[str]: def get_coverage_link_args(self) -> T.List[str]:
return self.linker.get_coverage_args() return self.linker.get_coverage_args()
def get_werror_args(self): def get_werror_args(self):
@ -134,7 +134,7 @@ class CLikeCompiler:
return ['-isystem', path] return ['-isystem', path]
return ['-I' + path] return ['-I' + path]
def get_compiler_dirs(self, env: 'Environment', name: str) -> typing.List[str]: def get_compiler_dirs(self, env: 'Environment', name: str) -> T.List[str]:
''' '''
Get dirs from the compiler, either `libraries:` or `programs:` Get dirs from the compiler, either `libraries:` or `programs:`
''' '''
@ -177,28 +177,28 @@ class CLikeCompiler:
''' '''
return self.get_compiler_dirs(env, 'programs') return self.get_compiler_dirs(env, 'programs')
def get_pic_args(self) -> typing.List[str]: def get_pic_args(self) -> T.List[str]:
return ['-fPIC'] return ['-fPIC']
def name_string(self) -> str: def name_string(self) -> str:
return ' '.join(self.exelist) return ' '.join(self.exelist)
def get_pch_use_args(self, pch_dir: str, header: str) -> typing.List[str]: def get_pch_use_args(self, pch_dir: str, header: str) -> T.List[str]:
return ['-include', os.path.basename(header)] return ['-include', os.path.basename(header)]
def get_pch_name(self, header_name: str) -> str: def get_pch_name(self, header_name: str) -> str:
return os.path.basename(header_name) + '.' + self.get_pch_suffix() return os.path.basename(header_name) + '.' + self.get_pch_suffix()
def get_linker_search_args(self, dirname: str) -> typing.List[str]: def get_linker_search_args(self, dirname: str) -> T.List[str]:
return self.linker.get_search_args(dirname) return self.linker.get_search_args(dirname)
def get_default_include_dirs(self): def get_default_include_dirs(self):
return [] return []
def gen_export_dynamic_link_args(self, env: 'Environment') -> typing.List[str]: def gen_export_dynamic_link_args(self, env: 'Environment') -> T.List[str]:
return self.linker.export_dynamic_args(env) return self.linker.export_dynamic_args(env)
def gen_import_library_args(self, implibname: str) -> typing.List[str]: def gen_import_library_args(self, implibname: str) -> T.List[str]:
return self.linker.import_library_args(implibname) return self.linker.import_library_args(implibname)
def sanity_check_impl(self, work_dir, environment, sname, code): def sanity_check_impl(self, work_dir, environment, sname, code):
@ -901,7 +901,7 @@ class CLikeCompiler:
return [f] return [f]
@staticmethod @staticmethod
def _get_file_from_list(env, files: typing.List[str]) -> Path: def _get_file_from_list(env, files: T.List[str]) -> Path:
''' '''
We just check whether the library exists. We can't do a link check We just check whether the library exists. We can't do a link check
because the library might have unresolved symbols that require other because the library might have unresolved symbols that require other
@ -1055,10 +1055,10 @@ class CLikeCompiler:
raise mesonlib.MesonException('Cannot find frameworks with non-clang compiler') 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) -> typing.List[str]: def get_crt_compile_args(self, crt_val: str, buildtype: str) -> T.List[str]:
return [] return []
def get_crt_link_args(self, crt_val: str, buildtype: str) -> typing.List[str]: def get_crt_link_args(self, crt_val: str, buildtype: str) -> T.List[str]:
return [] return []
def thread_flags(self, env): def thread_flags(self, env):
@ -1067,7 +1067,7 @@ class CLikeCompiler:
return [] return []
return ['-pthread'] return ['-pthread']
def thread_link_flags(self, env: 'Environment') -> typing.List[str]: def thread_link_flags(self, env: 'Environment') -> T.List[str]:
return self.linker.thread_flags(env) return self.linker.thread_flags(env)
def linker_to_compiler_args(self, args): def linker_to_compiler_args(self, args):

@ -15,21 +15,21 @@
"""Abstractions for the Elbrus family of compilers.""" """Abstractions for the Elbrus family of compilers."""
import os import os
import typing import typing as T
import subprocess import subprocess
import re import re
from .gnu import GnuLikeCompiler from .gnu import GnuLikeCompiler
from ...mesonlib import Popen_safe from ...mesonlib import Popen_safe
if typing.TYPE_CHECKING: if T.TYPE_CHECKING:
from ...environment import Environment from ...environment import Environment
class ElbrusCompiler(GnuLikeCompiler): class ElbrusCompiler(GnuLikeCompiler):
# Elbrus compiler is nearly like GCC, but does not support # Elbrus compiler is nearly like GCC, but does not support
# PCH, LTO, sanitizers and color output as of version 1.21.x. # PCH, LTO, sanitizers and color output as of version 1.21.x.
def __init__(self, defines: typing.Dict[str, str]): def __init__(self, defines: T.Dict[str, str]):
super().__init__() super().__init__()
self.id = 'lcc' self.id = 'lcc'
self.base_options = ['b_pgo', 'b_coverage', self.base_options = ['b_pgo', 'b_coverage',
@ -38,7 +38,7 @@ class ElbrusCompiler(GnuLikeCompiler):
# FIXME: use _build_wrapper to call this so that linker flags from the env # FIXME: use _build_wrapper to call this so that linker flags from the env
# get applied # get applied
def get_library_dirs(self, env: 'Environment', elf_class: typing.Optional[int] = None) -> typing.List[str]: def get_library_dirs(self, env: 'Environment', elf_class: T.Optional[int] = None) -> T.List[str]:
os_env = os.environ.copy() os_env = os.environ.copy()
os_env['LC_ALL'] = 'C' os_env['LC_ALL'] = 'C'
stdo = Popen_safe(self.exelist + ['--print-search-dirs'], env=os_env)[1] stdo = Popen_safe(self.exelist + ['--print-search-dirs'], env=os_env)[1]
@ -49,7 +49,7 @@ class ElbrusCompiler(GnuLikeCompiler):
return [os.path.realpath(p) for p in libstr.split(':') if os.path.exists(p)] return [os.path.realpath(p) for p in libstr.split(':') if os.path.exists(p)]
return [] return []
def get_program_dirs(self, env: 'Environment') -> typing.List[str]: def get_program_dirs(self, env: 'Environment') -> T.List[str]:
os_env = os.environ.copy() os_env = os.environ.copy()
os_env['LC_ALL'] = 'C' os_env['LC_ALL'] = 'C'
stdo = Popen_safe(self.exelist + ['--print-search-dirs'], env=os_env)[1] stdo = Popen_safe(self.exelist + ['--print-search-dirs'], env=os_env)[1]
@ -60,7 +60,7 @@ class ElbrusCompiler(GnuLikeCompiler):
return [os.path.realpath(p) for p in libstr.split(':')] return [os.path.realpath(p) for p in libstr.split(':')]
return [] return []
def get_default_include_dirs(self) -> typing.List[str]: def get_default_include_dirs(self) -> T.List[str]:
os_env = os.environ.copy() os_env = os.environ.copy()
os_env['LC_ALL'] = 'C' os_env['LC_ALL'] = 'C'
p = subprocess.Popen(self.exelist + ['-xc', '-E', '-v', '-'], env=os_env, stdin=subprocess.DEVNULL, stdout=subprocess.PIPE, stderr=subprocess.PIPE) p = subprocess.Popen(self.exelist + ['-xc', '-E', '-v', '-'], env=os_env, stdin=subprocess.DEVNULL, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

@ -15,7 +15,7 @@
"""Provides a mixin for shared code between C and C++ Emscripten compilers.""" """Provides a mixin for shared code between C and C++ Emscripten compilers."""
import os.path import os.path
import typing import typing as T
from ...mesonlib import MesonException from ...mesonlib import MesonException
@ -26,10 +26,10 @@ class EmscriptenMixin:
def get_soname_args(self, *args, **kwargs): def get_soname_args(self, *args, **kwargs):
raise MesonException('Emscripten does not support shared libraries.') raise MesonException('Emscripten does not support shared libraries.')
def get_allow_undefined_link_args(self) -> typing.List[str]: def get_allow_undefined_link_args(self) -> T.List[str]:
return ['-s', 'ERROR_ON_UNDEFINED_SYMBOLS=0'] return ['-s', 'ERROR_ON_UNDEFINED_SYMBOLS=0']
def get_linker_output_args(self, output: str) -> typing.List[str]: def get_linker_output_args(self, output: str) -> T.List[str]:
return ['-o', output] return ['-o', output]
def _get_compile_output(self, dirname, mode): def _get_compile_output(self, dirname, mode):

@ -20,12 +20,12 @@ import os
import pathlib import pathlib
import re import re
import subprocess import subprocess
import typing import typing as T
from ... import mesonlib from ... import mesonlib
from ... import mlog from ... import mlog
if typing.TYPE_CHECKING: if T.TYPE_CHECKING:
from ...coredata import UserOption # noqa: F401 from ...coredata import UserOption # noqa: F401
from ...environment import Environment from ...environment import Environment
@ -34,7 +34,7 @@ if typing.TYPE_CHECKING:
clike_debug_args = { clike_debug_args = {
False: [], False: [],
True: ['-g'], True: ['-g'],
} # type: typing.Dict[bool, typing.List[str]] } # type: T.Dict[bool, T.List[str]]
gnulike_buildtype_args = { gnulike_buildtype_args = {
'plain': [], 'plain': [],
@ -43,7 +43,7 @@ gnulike_buildtype_args = {
'release': [], 'release': [],
'minsize': [], 'minsize': [],
'custom': [], 'custom': [],
} # type: typing.Dict[str, typing.List[str]] } # type: T.Dict[str, T.List[str]]
gnu_optimization_args = { gnu_optimization_args = {
'0': [], '0': [],
@ -52,7 +52,7 @@ gnu_optimization_args = {
'2': ['-O2'], '2': ['-O2'],
'3': ['-O3'], '3': ['-O3'],
's': ['-Os'], 's': ['-Os'],
} # type: typing.Dict[str, typing.List[str]] } # type: T.Dict[str, T.List[str]]
gnulike_instruction_set_args = { gnulike_instruction_set_args = {
'mmx': ['-mmmx'], 'mmx': ['-mmmx'],
@ -65,7 +65,7 @@ gnulike_instruction_set_args = {
'avx': ['-mavx'], 'avx': ['-mavx'],
'avx2': ['-mavx2'], 'avx2': ['-mavx2'],
'neon': ['-mfpu=neon'], 'neon': ['-mfpu=neon'],
} # type: typing.Dict[str, typing.List[str]] } # type: T.Dict[str, T.List[str]]
gnu_symbol_visibility_args = { gnu_symbol_visibility_args = {
'': [], '': [],
@ -74,17 +74,17 @@ gnu_symbol_visibility_args = {
'hidden': ['-fvisibility=hidden'], 'hidden': ['-fvisibility=hidden'],
'protected': ['-fvisibility=protected'], 'protected': ['-fvisibility=protected'],
'inlineshidden': ['-fvisibility=hidden', '-fvisibility-inlines-hidden'], 'inlineshidden': ['-fvisibility=hidden', '-fvisibility-inlines-hidden'],
} # type: typing.Dict[str, typing.List[str]] } # type: T.Dict[str, T.List[str]]
gnu_color_args = { gnu_color_args = {
'auto': ['-fdiagnostics-color=auto'], 'auto': ['-fdiagnostics-color=auto'],
'always': ['-fdiagnostics-color=always'], 'always': ['-fdiagnostics-color=always'],
'never': ['-fdiagnostics-color=never'], 'never': ['-fdiagnostics-color=never'],
} # type: typing.Dict[str, typing.List[str]] } # type: T.Dict[str, T.List[str]]
@functools.lru_cache(maxsize=None) @functools.lru_cache(maxsize=None)
def gnulike_default_include_dirs(compiler: typing.Tuple[str], lang: str) -> typing.List[str]: def gnulike_default_include_dirs(compiler: T.Tuple[str], lang: str) -> T.List[str]:
lang_map = { lang_map = {
'c': 'c', 'c': 'c',
'cpp': 'c++', 'cpp': 'c++',
@ -149,45 +149,45 @@ class GnuLikeCompiler(metaclass=abc.ABCMeta):
# All GCC-like backends can do assembly # All GCC-like backends can do assembly
self.can_compile_suffixes.add('s') self.can_compile_suffixes.add('s')
def get_pic_args(self) -> typing.List[str]: def get_pic_args(self) -> T.List[str]:
if self.info.is_windows() or self.info.is_cygwin() or self.info.is_darwin(): if self.info.is_windows() or self.info.is_cygwin() or self.info.is_darwin():
return [] # On Window and OS X, pic is always on. return [] # On Window and OS X, pic is always on.
return ['-fPIC'] return ['-fPIC']
def get_pie_args(self) -> typing.List[str]: def get_pie_args(self) -> T.List[str]:
return ['-fPIE'] return ['-fPIE']
def get_buildtype_args(self, buildtype: str) -> typing.List[str]: def get_buildtype_args(self, buildtype: str) -> T.List[str]:
return gnulike_buildtype_args[buildtype] return gnulike_buildtype_args[buildtype]
@abc.abstractmethod @abc.abstractmethod
def get_optimization_args(self, optimization_level: str) -> typing.List[str]: def get_optimization_args(self, optimization_level: str) -> T.List[str]:
raise NotImplementedError("get_optimization_args not implemented") raise NotImplementedError("get_optimization_args not implemented")
def get_debug_args(self, is_debug: bool) -> typing.List[str]: def get_debug_args(self, is_debug: bool) -> T.List[str]:
return clike_debug_args[is_debug] return clike_debug_args[is_debug]
@abc.abstractmethod @abc.abstractmethod
def get_pch_suffix(self) -> str: def get_pch_suffix(self) -> str:
raise NotImplementedError("get_pch_suffix not implemented") raise NotImplementedError("get_pch_suffix not implemented")
def split_shlib_to_parts(self, fname: str) -> typing.Tuple[str, str]: def split_shlib_to_parts(self, fname: str) -> T.Tuple[str, str]:
return os.path.dirname(fname), fname return os.path.dirname(fname), fname
def get_instruction_set_args(self, instruction_set: str) -> typing.Optional[typing.List[str]]: def get_instruction_set_args(self, instruction_set: str) -> T.Optional[T.List[str]]:
return gnulike_instruction_set_args.get(instruction_set, None) return gnulike_instruction_set_args.get(instruction_set, None)
def get_default_include_dirs(self) -> typing.List[str]: def get_default_include_dirs(self) -> T.List[str]:
return gnulike_default_include_dirs(tuple(self.exelist), self.language) return gnulike_default_include_dirs(tuple(self.exelist), self.language)
@abc.abstractmethod @abc.abstractmethod
def openmp_flags(self) -> typing.List[str]: def openmp_flags(self) -> T.List[str]:
raise NotImplementedError("openmp_flags not implemented") raise NotImplementedError("openmp_flags not implemented")
def gnu_symbol_visibility_args(self, vistype: str) -> typing.List[str]: def gnu_symbol_visibility_args(self, vistype: str) -> T.List[str]:
return gnu_symbol_visibility_args[vistype] return gnu_symbol_visibility_args[vistype]
def gen_vs_module_defs_args(self, defsfile: str) -> typing.List[str]: def gen_vs_module_defs_args(self, defsfile: str) -> T.List[str]:
if not isinstance(defsfile, str): if not isinstance(defsfile, str):
raise RuntimeError('Module definitions file should be str') raise RuntimeError('Module definitions file should be str')
# On Windows targets, .def files may be specified on the linker command # On Windows targets, .def files may be specified on the linker command
@ -200,18 +200,18 @@ class GnuLikeCompiler(metaclass=abc.ABCMeta):
def get_argument_syntax(self) -> str: def get_argument_syntax(self) -> str:
return 'gcc' return 'gcc'
def get_profile_generate_args(self) -> typing.List[str]: def get_profile_generate_args(self) -> T.List[str]:
return ['-fprofile-generate'] return ['-fprofile-generate']
def get_profile_use_args(self) -> typing.List[str]: def get_profile_use_args(self) -> T.List[str]:
return ['-fprofile-use', '-fprofile-correction'] return ['-fprofile-use', '-fprofile-correction']
def get_gui_app_args(self, value: bool) -> typing.List[str]: def get_gui_app_args(self, value: bool) -> T.List[str]:
if self.info.is_windows() or self.info.is_cygwin(): if self.info.is_windows() or self.info.is_cygwin():
return ['-mwindows' if value else '-mconsole'] return ['-mwindows' if value else '-mconsole']
return [] return []
def compute_parameters_with_absolute_paths(self, parameter_list: typing.List[str], build_dir: str) -> typing.List[str]: def compute_parameters_with_absolute_paths(self, parameter_list: T.List[str], build_dir: str) -> T.List[str]:
for idx, i in enumerate(parameter_list): for idx, i in enumerate(parameter_list):
if i[:2] == '-I' or i[:2] == '-L': if i[:2] == '-I' or i[:2] == '-L':
parameter_list[idx] = i[:2] + os.path.normpath(os.path.join(build_dir, i[2:])) parameter_list[idx] = i[:2] + os.path.normpath(os.path.join(build_dir, i[2:]))
@ -228,7 +228,7 @@ class GnuLikeCompiler(metaclass=abc.ABCMeta):
stdo = p.stdo stdo = p.stdo
return stdo return stdo
def _split_fetch_real_dirs(self, pathstr: str) -> typing.List[str]: def _split_fetch_real_dirs(self, pathstr: str) -> T.List[str]:
# We need to use the path separator used by the compiler for printing # We need to use the path separator used by the compiler for printing
# lists of paths ("gcc --print-search-dirs"). By default # lists of paths ("gcc --print-search-dirs"). By default
# we assume it uses the platform native separator. # we assume it uses the platform native separator.
@ -265,7 +265,7 @@ class GnuLikeCompiler(metaclass=abc.ABCMeta):
pass pass
return result return result
def get_compiler_dirs(self, env: 'Environment', name: str) -> typing.List[str]: def get_compiler_dirs(self, env: 'Environment', name: str) -> T.List[str]:
''' '''
Get dirs from the compiler, either `libraries:` or `programs:` Get dirs from the compiler, either `libraries:` or `programs:`
''' '''
@ -275,10 +275,10 @@ class GnuLikeCompiler(metaclass=abc.ABCMeta):
return self._split_fetch_real_dirs(line.split('=', 1)[1]) return self._split_fetch_real_dirs(line.split('=', 1)[1])
return [] return []
def get_lto_compile_args(self) -> typing.List[str]: def get_lto_compile_args(self) -> T.List[str]:
return ['-flto'] return ['-flto']
def sanitizer_compile_args(self, value: str) -> typing.List[str]: def sanitizer_compile_args(self, value: str) -> T.List[str]:
if value == 'none': if value == 'none':
return [] return []
args = ['-fsanitize=' + value] args = ['-fsanitize=' + value]
@ -286,16 +286,16 @@ class GnuLikeCompiler(metaclass=abc.ABCMeta):
args.append('-fno-omit-frame-pointer') args.append('-fno-omit-frame-pointer')
return args return args
def get_output_args(self, target: str) -> typing.List[str]: def get_output_args(self, target: str) -> T.List[str]:
return ['-o', target] return ['-o', target]
def get_dependency_gen_args(self, outtarget, outfile): def get_dependency_gen_args(self, outtarget, outfile):
return ['-MD', '-MQ', outtarget, '-MF', outfile] return ['-MD', '-MQ', outtarget, '-MF', outfile]
def get_compile_only_args(self) -> typing.List[str]: def get_compile_only_args(self) -> T.List[str]:
return ['-c'] return ['-c']
def get_include_args(self, path: str, is_system: bool) -> typing.List[str]: def get_include_args(self, path: str, is_system: bool) -> T.List[str]:
if not path: if not path:
path = '.' path = '.'
if is_system: if is_system:
@ -303,7 +303,7 @@ class GnuLikeCompiler(metaclass=abc.ABCMeta):
return ['-I' + path] return ['-I' + path]
@classmethod @classmethod
def use_linker_args(cls, linker: str) -> typing.List[str]: def use_linker_args(cls, linker: str) -> T.List[str]:
return ['-fuse-ld={}'.format(linker)] return ['-fuse-ld={}'.format(linker)]
@ -313,18 +313,18 @@ class GnuCompiler(GnuLikeCompiler):
Compilers imitating GCC (Clang/Intel) should use the GnuLikeCompiler ABC. Compilers imitating GCC (Clang/Intel) should use the GnuLikeCompiler ABC.
""" """
def __init__(self, defines: typing.Dict[str, str]): def __init__(self, defines: T.Dict[str, str]):
super().__init__() super().__init__()
self.id = 'gcc' self.id = 'gcc'
self.defines = defines or {} self.defines = defines or {}
self.base_options.append('b_colorout') self.base_options.append('b_colorout')
def get_colorout_args(self, colortype: str) -> typing.List[str]: def get_colorout_args(self, colortype: str) -> T.List[str]:
if mesonlib.version_compare(self.version, '>=4.9.0'): if mesonlib.version_compare(self.version, '>=4.9.0'):
return gnu_color_args[colortype][:] return gnu_color_args[colortype][:]
return [] return []
def get_warn_args(self, level: str) -> typing.List[str]: def get_warn_args(self, level: str) -> T.List[str]:
args = super().get_warn_args(level) args = super().get_warn_args(level)
if mesonlib.version_compare(self.version, '<4.8.0') and '-Wpedantic' in args: if mesonlib.version_compare(self.version, '<4.8.0') and '-Wpedantic' in args:
# -Wpedantic was added in 4.8.0 # -Wpedantic was added in 4.8.0
@ -335,18 +335,18 @@ class GnuCompiler(GnuLikeCompiler):
def has_builtin_define(self, define: str) -> bool: def has_builtin_define(self, define: str) -> bool:
return define in self.defines return define in self.defines
def get_builtin_define(self, define: str) -> typing.Optional[str]: def get_builtin_define(self, define: str) -> T.Optional[str]:
if define in self.defines: if define in self.defines:
return self.defines[define] return self.defines[define]
return None return None
def get_optimization_args(self, optimization_level: str) -> typing.List[str]: def get_optimization_args(self, optimization_level: str) -> T.List[str]:
return gnu_optimization_args[optimization_level] return gnu_optimization_args[optimization_level]
def get_pch_suffix(self) -> str: def get_pch_suffix(self) -> str:
return 'gch' return 'gch'
def openmp_flags(self) -> typing.List[str]: def openmp_flags(self) -> T.List[str]:
return ['-fopenmp'] return ['-fopenmp']
def has_arguments(self, args, env, code, mode): def has_arguments(self, args, env, code, mode):

@ -21,13 +21,13 @@ is IntelVisualStudioLikeCompiler.
""" """
import os import os
import typing import typing as T
from ... import mesonlib from ... import mesonlib
from .gnu import GnuLikeCompiler from .gnu import GnuLikeCompiler
from .visualstudio import VisualStudioLikeCompiler from .visualstudio import VisualStudioLikeCompiler
if typing.TYPE_CHECKING: if T.TYPE_CHECKING:
import subprocess # noqa: F401 import subprocess # noqa: F401
# XXX: avoid circular dependencies # XXX: avoid circular dependencies
@ -58,7 +58,7 @@ class IntelGnuLikeCompiler(GnuLikeCompiler):
'release': [], 'release': [],
'minsize': [], 'minsize': [],
'custom': [], 'custom': [],
} # type: typing.Dict[str, typing.List[str]] } # type: T.Dict[str, T.List[str]]
OPTIM_ARGS = { OPTIM_ARGS = {
'0': ['-O0'], '0': ['-O0'],
@ -84,20 +84,20 @@ class IntelGnuLikeCompiler(GnuLikeCompiler):
def get_pch_suffix(self) -> str: def get_pch_suffix(self) -> str:
return 'pchi' return 'pchi'
def get_pch_use_args(self, pch_dir: str, header: str) -> typing.List[str]: def get_pch_use_args(self, pch_dir: str, header: str) -> T.List[str]:
return ['-pch', '-pch_dir', os.path.join(pch_dir), '-x', return ['-pch', '-pch_dir', os.path.join(pch_dir), '-x',
self.lang_header, '-include', header, '-x', 'none'] self.lang_header, '-include', header, '-x', 'none']
def get_pch_name(self, header_name: str) -> str: def get_pch_name(self, header_name: str) -> str:
return os.path.basename(header_name) + '.' + self.get_pch_suffix() return os.path.basename(header_name) + '.' + self.get_pch_suffix()
def openmp_flags(self) -> typing.List[str]: def openmp_flags(self) -> T.List[str]:
if mesonlib.version_compare(self.version, '>=15.0.0'): if mesonlib.version_compare(self.version, '>=15.0.0'):
return ['-qopenmp'] return ['-qopenmp']
else: else:
return ['-openmp'] return ['-openmp']
def compiles(self, *args, **kwargs) -> typing.Tuple[bool, bool]: def compiles(self, *args, **kwargs) -> T.Tuple[bool, bool]:
# This covers a case that .get('foo', []) doesn't, that extra_args is # This covers a case that .get('foo', []) doesn't, that extra_args is
# defined and is None # defined and is None
extra_args = kwargs.get('extra_args') or [] extra_args = kwargs.get('extra_args') or []
@ -113,16 +113,16 @@ class IntelGnuLikeCompiler(GnuLikeCompiler):
] ]
return super().compiles(*args, **kwargs) return super().compiles(*args, **kwargs)
def get_profile_generate_args(self) -> typing.List[str]: def get_profile_generate_args(self) -> T.List[str]:
return ['-prof-gen=threadsafe'] return ['-prof-gen=threadsafe']
def get_profile_use_args(self) -> typing.List[str]: def get_profile_use_args(self) -> T.List[str]:
return ['-prof-use'] return ['-prof-use']
def get_buildtype_args(self, buildtype: str) -> typing.List[str]: def get_buildtype_args(self, buildtype: str) -> T.List[str]:
return self.BUILD_ARGS[buildtype] return self.BUILD_ARGS[buildtype]
def get_optimization_args(self, optimization_level: str) -> typing.List[str]: def get_optimization_args(self, optimization_level: str) -> T.List[str]:
return self.OPTIM_ARGS[optimization_level] return self.OPTIM_ARGS[optimization_level]
@ -137,7 +137,7 @@ class IntelVisualStudioLikeCompiler(VisualStudioLikeCompiler):
'release': [], 'release': [],
'minsize': [], 'minsize': [],
'custom': [], 'custom': [],
} # type: typing.Dict[str, typing.List[str]] } # type: T.Dict[str, T.List[str]]
OPTIM_ARGS = { OPTIM_ARGS = {
'0': ['/O0'], '0': ['/O0'],
@ -152,7 +152,7 @@ class IntelVisualStudioLikeCompiler(VisualStudioLikeCompiler):
super().__init__(target) super().__init__(target)
self.id = 'intel-cl' self.id = 'intel-cl'
def compile(self, code, *, extra_args: typing.Optional[typing.List[str]] = None, **kwargs) -> typing.Iterator['subprocess.Popen']: def compile(self, code, *, extra_args: T.Optional[T.List[str]] = None, **kwargs) -> T.Iterator['subprocess.Popen']:
# This covers a case that .get('foo', []) doesn't, that extra_args is # This covers a case that .get('foo', []) doesn't, that extra_args is
if kwargs.get('mode', 'compile') != 'link': if kwargs.get('mode', 'compile') != 'link':
extra_args = extra_args.copy() if extra_args is not None else [] extra_args = extra_args.copy() if extra_args is not None else []
@ -166,7 +166,7 @@ class IntelVisualStudioLikeCompiler(VisualStudioLikeCompiler):
]) ])
return super().compile(code, extra_args, **kwargs) return super().compile(code, extra_args, **kwargs)
def get_toolset_version(self) -> typing.Optional[str]: def get_toolset_version(self) -> T.Optional[str]:
# Avoid circular dependencies.... # Avoid circular dependencies....
from ...environment import search_version from ...environment import search_version
@ -178,11 +178,11 @@ class IntelVisualStudioLikeCompiler(VisualStudioLikeCompiler):
version = int(v1 + v2) version = int(v1 + v2)
return self._calculate_toolset_version(version) return self._calculate_toolset_version(version)
def openmp_flags(self) -> typing.List[str]: def openmp_flags(self) -> T.List[str]:
return ['/Qopenmp'] return ['/Qopenmp']
def get_buildtype_args(self, buildtype: str) -> typing.List[str]: def get_buildtype_args(self, buildtype: str) -> T.List[str]:
return self.BUILD_ARGS[buildtype] return self.BUILD_ARGS[buildtype]
def get_optimization_args(self, optimization_level: str) -> typing.List[str]: def get_optimization_args(self, optimization_level: str) -> T.List[str]:
return self.OPTIM_ARGS[optimization_level] return self.OPTIM_ARGS[optimization_level]

@ -21,11 +21,11 @@ classes for those cases.
""" """
import os import os
import typing import typing as T
from ... import mesonlib from ... import mesonlib
if typing.TYPE_CHECKING: if T.TYPE_CHECKING:
from ...coredata import OptionDictType from ...coredata import OptionDictType
from ...environment import Environment from ...environment import Environment
@ -34,7 +34,7 @@ class LinkerEnvVarsMixin:
"""Mixin reading LDFLAGS from the environment.""" """Mixin reading LDFLAGS from the environment."""
def get_linker_args_from_envvars(self) -> typing.List[str]: def get_linker_args_from_envvars(self) -> T.List[str]:
flags = os.environ.get('LDFLAGS') flags = os.environ.get('LDFLAGS')
if not flags: if not flags:
return [] return []
@ -50,83 +50,83 @@ class BasicLinkerIsCompilerMixin:
functionality itself. functionality itself.
""" """
def sanitizer_link_args(self, value: str) -> typing.List[str]: def sanitizer_link_args(self, value: str) -> T.List[str]:
return [] return []
def get_lto_link_args(self) -> typing.List[str]: def get_lto_link_args(self) -> T.List[str]:
return [] return []
def can_linker_accept_rsp(self) -> bool: def can_linker_accept_rsp(self) -> bool:
return mesonlib.is_windows() return mesonlib.is_windows()
def get_linker_exelist(self) -> typing.List[str]: def get_linker_exelist(self) -> T.List[str]:
return self.exelist.copy() return self.exelist.copy()
def get_linker_output_args(self, output: str) -> typing.List[str]: def get_linker_output_args(self, output: str) -> T.List[str]:
return [] return []
def get_linker_always_args(self) -> typing.List[str]: def get_linker_always_args(self) -> T.List[str]:
return [] return []
def get_linker_lib_prefix(self) -> str: def get_linker_lib_prefix(self) -> str:
return '' return ''
def get_option_link_args(self, options: 'OptionDictType') -> typing.List[str]: def get_option_link_args(self, options: 'OptionDictType') -> T.List[str]:
return [] return []
def has_multi_link_args(self, args: typing.List[str], env: 'Environment') -> typing.Tuple[bool, bool]: def has_multi_link_args(self, args: T.List[str], env: 'Environment') -> T.Tuple[bool, bool]:
return False, False return False, False
def get_link_debugfile_args(self, targetfile: str) -> typing.List[str]: def get_link_debugfile_args(self, targetfile: str) -> T.List[str]:
return [] return []
def get_std_shared_lib_link_args(self) -> typing.List[str]: def get_std_shared_lib_link_args(self) -> T.List[str]:
return [] return []
def get_std_shared_module_args(self, options: 'OptionDictType') -> typing.List[str]: def get_std_shared_module_args(self, options: 'OptionDictType') -> T.List[str]:
return self.get_std_shared_lib_link_args() return self.get_std_shared_lib_link_args()
def get_link_whole_for(self, args: typing.List[str]) -> typing.List[str]: def get_link_whole_for(self, args: T.List[str]) -> T.List[str]:
raise mesonlib.EnvironmentException( raise mesonlib.EnvironmentException(
'Linker {} does not support link_whole'.format(self.id)) 'Linker {} does not support link_whole'.format(self.id))
def get_allow_undefined_link_args(self) -> typing.List[str]: def get_allow_undefined_link_args(self) -> T.List[str]:
raise mesonlib.EnvironmentException( raise mesonlib.EnvironmentException(
'Linker {} does not support allow undefined'.format(self.id)) 'Linker {} does not support allow undefined'.format(self.id))
def get_pie_link_args(self) -> typing.List[str]: def get_pie_link_args(self) -> T.List[str]:
m = 'Linker {} does not support position-independent executable' m = 'Linker {} does not support position-independent executable'
raise mesonlib.EnvironmentException(m.format(self.id)) raise mesonlib.EnvironmentException(m.format(self.id))
def get_undefined_link_args(self) -> typing.List[str]: def get_undefined_link_args(self) -> T.List[str]:
return [] return []
def get_coverage_link_args(self) -> typing.List[str]: def get_coverage_link_args(self) -> T.List[str]:
m = "Linker {} doesn't implement coverage data generation.".format(self.id) m = "Linker {} doesn't implement coverage data generation.".format(self.id)
raise mesonlib.EnvironmentException(m) raise mesonlib.EnvironmentException(m)
def no_undefined_link_args(self) -> typing.List[str]: def no_undefined_link_args(self) -> T.List[str]:
return [] return []
def bitcode_args(self) -> typing.List[str]: def bitcode_args(self) -> T.List[str]:
raise mesonlib.MesonException("This linker doesn't support bitcode bundles") raise mesonlib.MesonException("This linker doesn't support bitcode bundles")
def get_soname_args(self, for_machine: 'mesonlib.MachineChoice', def get_soname_args(self, for_machine: 'mesonlib.MachineChoice',
prefix: str, shlib_name: str, suffix: str, soversion: str, prefix: str, shlib_name: str, suffix: str, soversion: str,
darwin_versions: typing.Tuple[str, str], darwin_versions: T.Tuple[str, str],
is_shared_module: bool) -> typing.List[str]: is_shared_module: bool) -> T.List[str]:
raise mesonlib.MesonException("This linker doesn't support soname args") raise mesonlib.MesonException("This linker doesn't support soname args")
def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str, def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str,
rpath_paths: str, build_rpath: str, rpath_paths: str, build_rpath: str,
install_rpath: str) -> typing.List[str]: install_rpath: str) -> T.List[str]:
return [] return []
def get_linker_debug_crt_args(self) -> typing.List[str]: def get_linker_debug_crt_args(self) -> T.List[str]:
return [] return []
def get_asneeded_args(self) -> typing.List[str]: def get_asneeded_args(self) -> T.List[str]:
return [] return []
def get_buildtype_linker_args(self, buildtype: str) -> typing.List[str]: def get_buildtype_linker_args(self, buildtype: str) -> T.List[str]:
return [] return []

@ -14,7 +14,7 @@
"""Abstractions for the PGI family of compilers.""" """Abstractions for the PGI family of compilers."""
import typing import typing as T
import os import os
from pathlib import Path from pathlib import Path
@ -27,7 +27,7 @@ pgi_buildtype_args = {
'release': [], 'release': [],
'minsize': [], 'minsize': [],
'custom': [], 'custom': [],
} # type: typing.Dict[str, typing.List[str]] } # type: T.Dict[str, T.List[str]]
class PGICompiler: class PGICompiler:
@ -41,50 +41,50 @@ class PGICompiler:
'2': default_warn_args, '2': default_warn_args,
'3': default_warn_args} '3': default_warn_args}
def get_module_incdir_args(self) -> typing.Tuple[str]: def get_module_incdir_args(self) -> T.Tuple[str]:
return ('-module', ) return ('-module', )
def get_no_warn_args(self) -> typing.List[str]: def get_no_warn_args(self) -> T.List[str]:
return ['-silent'] return ['-silent']
def gen_import_library_args(self, implibname: str) -> typing.List[str]: def gen_import_library_args(self, implibname: str) -> T.List[str]:
return [] return []
def get_pic_args(self) -> typing.List[str]: def get_pic_args(self) -> T.List[str]:
# PGI -fPIC is Linux only. # PGI -fPIC is Linux only.
if self.info.is_linux(): if self.info.is_linux():
return ['-fPIC'] return ['-fPIC']
return [] return []
def openmp_flags(self) -> typing.List[str]: def openmp_flags(self) -> T.List[str]:
return ['-mp'] return ['-mp']
def get_buildtype_args(self, buildtype: str) -> typing.List[str]: def get_buildtype_args(self, buildtype: str) -> T.List[str]:
return pgi_buildtype_args[buildtype] return pgi_buildtype_args[buildtype]
def get_optimization_args(self, optimization_level: str) -> typing.List[str]: def get_optimization_args(self, optimization_level: str) -> T.List[str]:
return clike_optimization_args[optimization_level] return clike_optimization_args[optimization_level]
def get_debug_args(self, is_debug: bool) -> typing.List[str]: def get_debug_args(self, is_debug: bool) -> T.List[str]:
return clike_debug_args[is_debug] return clike_debug_args[is_debug]
def compute_parameters_with_absolute_paths(self, parameter_list: typing.List[str], build_dir: str) -> typing.List[str]: def compute_parameters_with_absolute_paths(self, parameter_list: T.List[str], build_dir: str) -> T.List[str]:
for idx, i in enumerate(parameter_list): for idx, i in enumerate(parameter_list):
if i[:2] == '-I' or i[:2] == '-L': if i[:2] == '-I' or i[:2] == '-L':
parameter_list[idx] = i[:2] + os.path.normpath(os.path.join(build_dir, i[2:])) parameter_list[idx] = i[:2] + os.path.normpath(os.path.join(build_dir, i[2:]))
return parameter_list return parameter_list
def get_dependency_gen_args(self, outtarget: str, outfile: str) -> typing.List[str]: def get_dependency_gen_args(self, outtarget: str, outfile: str) -> T.List[str]:
return [] return []
def get_always_args(self) -> typing.List[str]: def get_always_args(self) -> T.List[str]:
return [] return []
def get_pch_suffix(self) -> str: def get_pch_suffix(self) -> str:
# PGI defaults to .pch suffix for PCH on Linux and Windows with --pch option # PGI defaults to .pch suffix for PCH on Linux and Windows with --pch option
return 'pch' return 'pch'
def get_pch_use_args(self, pch_dir: str, header: str) -> typing.List[str]: def get_pch_use_args(self, pch_dir: str, header: str) -> T.List[str]:
# PGI supports PCH for C++ only. # PGI supports PCH for C++ only.
hdr = Path(pch_dir).resolve().parent / header hdr = Path(pch_dir).resolve().parent / header
if self.language == 'cpp': if self.language == 'cpp':

@ -18,12 +18,12 @@ interface.
import abc import abc
import os import os
import typing import typing as T
from ... import mesonlib from ... import mesonlib
from ... import mlog from ... import mlog
if typing.TYPE_CHECKING: if T.TYPE_CHECKING:
from ...environment import Environment from ...environment import Environment
vs32_instruction_set_args = { vs32_instruction_set_args = {
@ -36,7 +36,7 @@ vs32_instruction_set_args = {
'avx': ['/arch:AVX'], 'avx': ['/arch:AVX'],
'avx2': ['/arch:AVX2'], 'avx2': ['/arch:AVX2'],
'neon': None, 'neon': None,
} # typing.Dicst[str, typing.Optional[typing.List[str]]] } # T.Dicst[str, T.Optional[T.List[str]]]
# The 64 bit compiler defaults to /arch:avx. # The 64 bit compiler defaults to /arch:avx.
vs64_instruction_set_args = { vs64_instruction_set_args = {
@ -50,7 +50,7 @@ vs64_instruction_set_args = {
'avx': ['/arch:AVX'], 'avx': ['/arch:AVX'],
'avx2': ['/arch:AVX2'], 'avx2': ['/arch:AVX2'],
'neon': None, 'neon': None,
} # typing.Dicst[str, typing.Optional[typing.List[str]]] } # T.Dicst[str, T.Optional[T.List[str]]]
msvc_buildtype_args = { msvc_buildtype_args = {
'plain': [], 'plain': [],
@ -59,7 +59,7 @@ msvc_buildtype_args = {
'release': ["/Ob2", "/Gw"], 'release': ["/Ob2", "/Gw"],
'minsize': ["/Zi", "/Gw"], 'minsize': ["/Zi", "/Gw"],
'custom': [], 'custom': [],
} # type: typing.Dict[str, typing.List[str]] } # type: T.Dict[str, T.List[str]]
msvc_optimization_args = { msvc_optimization_args = {
'0': [], '0': [],
@ -68,12 +68,12 @@ msvc_optimization_args = {
'2': ['/O2'], '2': ['/O2'],
'3': ['/O2'], '3': ['/O2'],
's': ['/O1'], # Implies /Os. 's': ['/O1'], # Implies /Os.
} # type: typing.Dict[str, typing.List[str]] } # type: T.Dict[str, T.List[str]]
msvc_debug_args = { msvc_debug_args = {
False: [], False: [],
True: [] # Fixme! True: [] # Fixme!
} # type: typing.Dict[bool, typing.List[str]] } # type: T.Dict[bool, T.List[str]]
class VisualStudioLikeCompiler(metaclass=abc.ABCMeta): class VisualStudioLikeCompiler(metaclass=abc.ABCMeta):
@ -99,7 +99,7 @@ class VisualStudioLikeCompiler(metaclass=abc.ABCMeta):
'mdd': ['/MDd'], 'mdd': ['/MDd'],
'mt': ['/MT'], 'mt': ['/MT'],
'mtd': ['/MTd'], 'mtd': ['/MTd'],
} # type: typing.Dict[str, typing.List[str]] } # type: T.Dict[str, T.List[str]]
# /showIncludes is needed for build dependency tracking in Ninja # /showIncludes is needed for build dependency tracking in Ninja
# See: https://ninja-build.org/manual.html#_deps # See: https://ninja-build.org/manual.html#_deps
@ -109,7 +109,7 @@ class VisualStudioLikeCompiler(metaclass=abc.ABCMeta):
'1': ['/W2'], '1': ['/W2'],
'2': ['/W3'], '2': ['/W3'],
'3': ['/W4'], '3': ['/W4'],
} # type: typing.Dict[str, typing.List[str]] } # type: T.Dict[str, T.List[str]]
INVOKES_LINKER = False INVOKES_LINKER = False
@ -127,10 +127,10 @@ class VisualStudioLikeCompiler(metaclass=abc.ABCMeta):
self.linker.machine = self.machine self.linker.machine = self.machine
# Override CCompiler.get_always_args # Override CCompiler.get_always_args
def get_always_args(self) -> typing.List[str]: def get_always_args(self) -> T.List[str]:
return self.always_args return self.always_args
def get_buildtype_args(self, buildtype: str) -> typing.List[str]: def get_buildtype_args(self, buildtype: str) -> T.List[str]:
args = msvc_buildtype_args[buildtype] args = msvc_buildtype_args[buildtype]
if self.id == 'msvc' and mesonlib.version_compare(self.version, '<18.0'): if self.id == 'msvc' and mesonlib.version_compare(self.version, '<18.0'):
args = [arg for arg in args if arg != '/Gw'] args = [arg for arg in args if arg != '/Gw']
@ -145,40 +145,40 @@ class VisualStudioLikeCompiler(metaclass=abc.ABCMeta):
pchname = '.'.join(chopped) pchname = '.'.join(chopped)
return pchname return pchname
def get_pch_use_args(self, pch_dir: str, header: str) -> typing.List[str]: def get_pch_use_args(self, pch_dir: str, header: str) -> T.List[str]:
base = os.path.basename(header) base = os.path.basename(header)
if self.id == 'clang-cl': if self.id == 'clang-cl':
base = header base = header
pchname = self.get_pch_name(header) pchname = self.get_pch_name(header)
return ['/FI' + base, '/Yu' + base, '/Fp' + os.path.join(pch_dir, pchname)] return ['/FI' + base, '/Yu' + base, '/Fp' + os.path.join(pch_dir, pchname)]
def get_preprocess_only_args(self) -> typing.List[str]: def get_preprocess_only_args(self) -> T.List[str]:
return ['/EP'] return ['/EP']
def get_compile_only_args(self) -> typing.List[str]: def get_compile_only_args(self) -> T.List[str]:
return ['/c'] return ['/c']
def get_no_optimization_args(self) -> typing.List[str]: def get_no_optimization_args(self) -> T.List[str]:
return ['/Od'] return ['/Od']
def get_output_args(self, target: str) -> typing.List[str]: def get_output_args(self, target: str) -> T.List[str]:
if target.endswith('.exe'): if target.endswith('.exe'):
return ['/Fe' + target] return ['/Fe' + target]
return ['/Fo' + target] return ['/Fo' + target]
def get_optimization_args(self, optimization_level: str) -> typing.List[str]: def get_optimization_args(self, optimization_level: str) -> T.List[str]:
return msvc_optimization_args[optimization_level] return msvc_optimization_args[optimization_level]
def get_debug_args(self, is_debug: bool) -> typing.List[str]: def get_debug_args(self, is_debug: bool) -> T.List[str]:
return msvc_debug_args[is_debug] return msvc_debug_args[is_debug]
def get_dependency_gen_args(self, outtarget: str, outfile: str) -> typing.List[str]: def get_dependency_gen_args(self, outtarget: str, outfile: str) -> T.List[str]:
return [] return []
def linker_to_compiler_args(self, args: typing.List[str]) -> typing.List[str]: def linker_to_compiler_args(self, args: T.List[str]) -> T.List[str]:
return ['/link'] + args return ['/link'] + args
def get_gui_app_args(self, value: bool) -> typing.List[str]: def get_gui_app_args(self, value: bool) -> T.List[str]:
# the default is for the linker to guess the subsystem based on presence # the default is for the linker to guess the subsystem based on presence
# of main or WinMain symbols, so always be explicit # of main or WinMain symbols, so always be explicit
if value: if value:
@ -186,33 +186,33 @@ class VisualStudioLikeCompiler(metaclass=abc.ABCMeta):
else: else:
return ['/SUBSYSTEM:CONSOLE'] return ['/SUBSYSTEM:CONSOLE']
def get_pic_args(self) -> typing.List[str]: def get_pic_args(self) -> T.List[str]:
return [] # PIC is handled by the loader on Windows return [] # PIC is handled by the loader on Windows
def gen_vs_module_defs_args(self, defsfile: str) -> typing.List[str]: def gen_vs_module_defs_args(self, defsfile: str) -> T.List[str]:
if not isinstance(defsfile, str): if not isinstance(defsfile, str):
raise RuntimeError('Module definitions file should be str') raise RuntimeError('Module definitions file should be str')
# With MSVC, DLLs only export symbols that are explicitly exported, # With MSVC, DLLs only export symbols that are explicitly exported,
# so if a module defs file is specified, we use that to export symbols # so if a module defs file is specified, we use that to export symbols
return ['/DEF:' + defsfile] return ['/DEF:' + defsfile]
def gen_pch_args(self, header: str, source: str, pchname: str) -> typing.Tuple[str, typing.List[str]]: def gen_pch_args(self, header: str, source: str, pchname: str) -> T.Tuple[str, T.List[str]]:
objname = os.path.splitext(pchname)[0] + '.obj' objname = os.path.splitext(pchname)[0] + '.obj'
return objname, ['/Yc' + header, '/Fp' + pchname, '/Fo' + objname] return objname, ['/Yc' + header, '/Fp' + pchname, '/Fo' + objname]
def gen_import_library_args(self, implibname: str) -> typing.List[str]: def gen_import_library_args(self, implibname: str) -> T.List[str]:
"The name of the outputted import library" "The name of the outputted import library"
return ['/IMPLIB:' + implibname] return ['/IMPLIB:' + implibname]
def openmp_flags(self) -> typing.List[str]: def openmp_flags(self) -> T.List[str]:
return ['/openmp'] return ['/openmp']
# FIXME, no idea what these should be. # FIXME, no idea what these should be.
def thread_flags(self, env: 'Environment') -> typing.List[str]: def thread_flags(self, env: 'Environment') -> T.List[str]:
return [] return []
@classmethod @classmethod
def unix_args_to_native(cls, args: typing.List[str]) -> typing.List[str]: def unix_args_to_native(cls, args: T.List[str]) -> T.List[str]:
result = [] result = []
for i in args: for i in args:
# -mms-bitfields is specific to MinGW-GCC # -mms-bitfields is specific to MinGW-GCC
@ -251,7 +251,7 @@ class VisualStudioLikeCompiler(metaclass=abc.ABCMeta):
return result return result
@classmethod @classmethod
def native_args_to_unix(cls, args: typing.List[str]) -> typing.List[str]: def native_args_to_unix(cls, args: T.List[str]) -> T.List[str]:
result = [] result = []
for arg in args: for arg in args:
if arg.startswith(('/LIBPATH:', '-LIBPATH:')): if arg.startswith(('/LIBPATH:', '-LIBPATH:')):
@ -262,16 +262,16 @@ class VisualStudioLikeCompiler(metaclass=abc.ABCMeta):
result.append(arg) result.append(arg)
return result return result
def get_werror_args(self) -> typing.List[str]: def get_werror_args(self) -> T.List[str]:
return ['/WX'] return ['/WX']
def get_include_args(self, path: str, is_system: bool) -> typing.List[str]: def get_include_args(self, path: str, is_system: bool) -> T.List[str]:
if path == '': if path == '':
path = '.' path = '.'
# msvc does not have a concept of system header dirs. # msvc does not have a concept of system header dirs.
return ['-I' + path] return ['-I' + path]
def compute_parameters_with_absolute_paths(self, parameter_list: typing.List[str], build_dir: str) -> typing.List[str]: def compute_parameters_with_absolute_paths(self, parameter_list: T.List[str], build_dir: str) -> T.List[str]:
for idx, i in enumerate(parameter_list): for idx, i in enumerate(parameter_list):
if i[:2] == '-I' or i[:2] == '/I': if i[:2] == '-I' or i[:2] == '/I':
parameter_list[idx] = i[:2] + os.path.normpath(os.path.join(build_dir, i[2:])) parameter_list[idx] = i[:2] + os.path.normpath(os.path.join(build_dir, i[2:]))
@ -283,7 +283,7 @@ class VisualStudioLikeCompiler(metaclass=abc.ABCMeta):
# Visual Studio is special. It ignores some arguments it does not # Visual Studio is special. It ignores some arguments it does not
# understand and you can't tell it to error out on those. # 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 # 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: typing.List[str], env: 'Environment', code, mode: str) -> typing.Tuple[bool, bool]: def has_arguments(self, args: T.List[str], env: 'Environment', code, mode: str) -> T.Tuple[bool, bool]:
warning_text = '4044' if mode == 'link' else '9002' warning_text = '4044' if mode == 'link' else '9002'
if self.id == 'clang-cl' and mode != 'link': if self.id == 'clang-cl' and mode != 'link':
args = args + ['-Werror=unknown-argument'] args = args + ['-Werror=unknown-argument']
@ -292,7 +292,7 @@ class VisualStudioLikeCompiler(metaclass=abc.ABCMeta):
return False, p.cached 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.stde or warning_text in p.stdo), p.cached
def get_compile_debugfile_args(self, rel_obj: str, pch: bool = False) -> typing.List[str]: def get_compile_debugfile_args(self, rel_obj: str, pch: bool = False) -> T.List[str]:
pdbarr = rel_obj.split('.')[:-1] pdbarr = rel_obj.split('.')[:-1]
pdbarr += ['pdb'] pdbarr += ['pdb']
args = ['/Fd' + '.'.join(pdbarr)] args = ['/Fd' + '.'.join(pdbarr)]
@ -306,7 +306,7 @@ class VisualStudioLikeCompiler(metaclass=abc.ABCMeta):
args = ['/FS'] + args args = ['/FS'] + args
return args return args
def get_instruction_set_args(self, instruction_set: str) -> typing.Optional[typing.List[str]]: def get_instruction_set_args(self, instruction_set: str) -> T.Optional[T.List[str]]:
if self.is_64: if self.is_64:
return vs64_instruction_set_args.get(instruction_set, None) return vs64_instruction_set_args.get(instruction_set, None)
if self.id == 'msvc' and self.version.split('.')[0] == '16' and instruction_set == 'avx': if self.id == 'msvc' and self.version.split('.')[0] == '16' and instruction_set == 'avx':
@ -316,7 +316,7 @@ class VisualStudioLikeCompiler(metaclass=abc.ABCMeta):
return None return None
return vs32_instruction_set_args.get(instruction_set, None) return vs32_instruction_set_args.get(instruction_set, None)
def _calculate_toolset_version(self, version: int) -> typing.Optional[str]: def _calculate_toolset_version(self, version: int) -> T.Optional[str]:
if version < 1310: if version < 1310:
return '7.0' return '7.0'
elif version < 1400: elif version < 1400:
@ -340,7 +340,7 @@ class VisualStudioLikeCompiler(metaclass=abc.ABCMeta):
mlog.warning('Could not find toolset for version {!r}'.format(self.version)) mlog.warning('Could not find toolset for version {!r}'.format(self.version))
return None return None
def get_toolset_version(self) -> typing.Optional[str]: def get_toolset_version(self) -> T.Optional[str]:
if self.id == 'clang-cl': if self.id == 'clang-cl':
# I have no idea # I have no idea
return '14.1' return '14.1'
@ -352,12 +352,12 @@ class VisualStudioLikeCompiler(metaclass=abc.ABCMeta):
return None return None
return self._calculate_toolset_version(version) return self._calculate_toolset_version(version)
def get_default_include_dirs(self) -> typing.List[str]: def get_default_include_dirs(self) -> T.List[str]:
if 'INCLUDE' not in os.environ: if 'INCLUDE' not in os.environ:
return [] return []
return os.environ['INCLUDE'].split(os.pathsep) return os.environ['INCLUDE'].split(os.pathsep)
def get_crt_compile_args(self, crt_val: str, buildtype: str) -> typing.List[str]: def get_crt_compile_args(self, crt_val: str, buildtype: str) -> T.List[str]:
if crt_val in self.crt_args: if crt_val in self.crt_args:
return self.crt_args[crt_val] return self.crt_args[crt_val]
assert(crt_val == 'from_buildtype') assert(crt_val == 'from_buildtype')
@ -376,7 +376,7 @@ class VisualStudioLikeCompiler(metaclass=abc.ABCMeta):
assert(buildtype == 'custom') assert(buildtype == 'custom')
raise mesonlib.EnvironmentException('Requested C runtime based on buildtype, but buildtype is "custom".') raise mesonlib.EnvironmentException('Requested C runtime based on buildtype, but buildtype is "custom".')
def has_func_attribute(self, name: str, env: 'Environment') -> typing.Tuple[bool, bool]: def has_func_attribute(self, name: str, env: 'Environment') -> T.Tuple[bool, bool]:
# MSVC doesn't have __attribute__ like Clang and GCC do, so just return # MSVC doesn't have __attribute__ like Clang and GCC do, so just return
# false without compiling anything # false without compiling anything
return name in ['dllimport', 'dllexport'], False return name in ['dllimport', 'dllexport'], False
@ -385,5 +385,5 @@ class VisualStudioLikeCompiler(metaclass=abc.ABCMeta):
return 'msvc' return 'msvc'
@classmethod @classmethod
def use_linker_args(cls, linker: str) -> typing.List[str]: def use_linker_args(cls, linker: str) -> T.List[str]:
return [] return []

@ -13,7 +13,7 @@
# limitations under the License. # limitations under the License.
import os.path, subprocess import os.path, subprocess
import typing import typing as T
from ..mesonlib import EnvironmentException, MachineChoice from ..mesonlib import EnvironmentException, MachineChoice
@ -22,7 +22,7 @@ from .mixins.clike import CLikeCompiler
from .mixins.gnu import GnuCompiler from .mixins.gnu import GnuCompiler
from .mixins.clang import ClangCompiler from .mixins.clang import ClangCompiler
if typing.TYPE_CHECKING: if T.TYPE_CHECKING:
from ..envconfig import MachineInfo from ..envconfig import MachineInfo
@ -32,7 +32,7 @@ class ObjCCompiler(CLikeCompiler, Compiler):
def __init__(self, exelist, version, for_machine: MachineChoice, def __init__(self, exelist, version, for_machine: MachineChoice,
is_cross: bool, info: 'MachineInfo', is_cross: bool, info: 'MachineInfo',
exe_wrap: typing.Optional[str], **kwargs): exe_wrap: T.Optional[str], **kwargs):
Compiler.__init__(self, exelist, version, for_machine, info, **kwargs) Compiler.__init__(self, exelist, version, for_machine, info, **kwargs)
CLikeCompiler.__init__(self, is_cross, exe_wrap) CLikeCompiler.__init__(self, is_cross, exe_wrap)

@ -13,7 +13,7 @@
# limitations under the License. # limitations under the License.
import os.path, subprocess import os.path, subprocess
import typing import typing as T
from ..mesonlib import EnvironmentException, MachineChoice from ..mesonlib import EnvironmentException, MachineChoice
@ -22,7 +22,7 @@ from .compilers import Compiler
from .mixins.gnu import GnuCompiler from .mixins.gnu import GnuCompiler
from .mixins.clang import ClangCompiler from .mixins.clang import ClangCompiler
if typing.TYPE_CHECKING: if T.TYPE_CHECKING:
from ..envconfig import MachineInfo from ..envconfig import MachineInfo
class ObjCPPCompiler(CLikeCompiler, Compiler): class ObjCPPCompiler(CLikeCompiler, Compiler):
@ -31,7 +31,7 @@ class ObjCPPCompiler(CLikeCompiler, Compiler):
def __init__(self, exelist, version, for_machine: MachineChoice, def __init__(self, exelist, version, for_machine: MachineChoice,
is_cross: bool, info: 'MachineInfo', is_cross: bool, info: 'MachineInfo',
exe_wrap: typing.Optional[str], **kwargs): exe_wrap: T.Optional[str], **kwargs):
Compiler.__init__(self, exelist, version, for_machine, info, **kwargs) Compiler.__init__(self, exelist, version, for_machine, info, **kwargs)
CLikeCompiler.__init__(self, is_cross, exe_wrap) CLikeCompiler.__init__(self, is_cross, exe_wrap)

@ -13,12 +13,12 @@
# limitations under the License. # limitations under the License.
import subprocess, os.path import subprocess, os.path
import typing import typing as T
from ..mesonlib import EnvironmentException, MachineChoice, Popen_safe from ..mesonlib import EnvironmentException, MachineChoice, Popen_safe
from .compilers import Compiler, rust_buildtype_args, clike_debug_args from .compilers import Compiler, rust_buildtype_args, clike_debug_args
if typing.TYPE_CHECKING: if T.TYPE_CHECKING:
from ..envconfig import MachineInfo from ..envconfig import MachineInfo
from ..environment import Environment # noqa: F401 from ..environment import Environment # noqa: F401

@ -13,13 +13,13 @@
# limitations under the License. # limitations under the License.
import subprocess, os.path import subprocess, os.path
import typing import typing as T
from ..mesonlib import EnvironmentException, MachineChoice from ..mesonlib import EnvironmentException, MachineChoice
from .compilers import Compiler, swift_buildtype_args, clike_debug_args from .compilers import Compiler, swift_buildtype_args, clike_debug_args
if typing.TYPE_CHECKING: if T.TYPE_CHECKING:
from ..envconfig import MachineInfo from ..envconfig import MachineInfo
swift_optimization_args = {'0': [], swift_optimization_args = {'0': [],

@ -13,14 +13,14 @@
# limitations under the License. # limitations under the License.
import os.path import os.path
import typing import typing as T
from .. import mlog from .. import mlog
from ..mesonlib import EnvironmentException, MachineChoice, version_compare from ..mesonlib import EnvironmentException, MachineChoice, version_compare
from .compilers import Compiler from .compilers import Compiler
if typing.TYPE_CHECKING: if T.TYPE_CHECKING:
from ..envconfig import MachineInfo from ..envconfig import MachineInfo
class ValaCompiler(Compiler): class ValaCompiler(Compiler):

@ -26,19 +26,16 @@ from .wrap import WrapMode
import ast import ast
import argparse import argparse
import configparser import configparser
from typing import (
Any, Dict, Generic, Iterable, Iterator, List, MutableMapping, Optional, Tuple, Type, TypeVar, Union,
TYPE_CHECKING,
)
import enum import enum
import shlex import shlex
import typing as T
if TYPE_CHECKING: if T.TYPE_CHECKING:
from . import dependencies from . import dependencies
from .compilers import Compiler # noqa: F401 from .compilers import Compiler # noqa: F401
from .environment import Environment from .environment import Environment
OptionDictType = Dict[str, 'UserOption[Any]'] OptionDictType = T.Dict[str, 'UserOption[T.Any]']
version = '0.53.0' version = '0.53.0'
backendlist = ['ninja', 'vs', 'vs2010', 'vs2015', 'vs2017', 'vs2019', 'xcode'] backendlist = ['ninja', 'vs', 'vs2010', 'vs2015', 'vs2017', 'vs2019', 'xcode']
@ -46,9 +43,9 @@ backendlist = ['ninja', 'vs', 'vs2010', 'vs2015', 'vs2017', 'vs2019', 'xcode']
default_yielding = False default_yielding = False
# Can't bind this near the class method it seems, sadly. # Can't bind this near the class method it seems, sadly.
_T = TypeVar('_T') _T = T.TypeVar('_T')
class UserOption(Generic[_T]): class UserOption(T.Generic[_T]):
def __init__(self, description, choices, yielding): def __init__(self, description, choices, yielding):
super().__init__() super().__init__()
self.choices = choices self.choices = choices
@ -65,7 +62,7 @@ class UserOption(Generic[_T]):
# Check that the input is a valid value and return the # Check that the input is a valid value and return the
# "cleaned" or "native" version. For example the Boolean # "cleaned" or "native" version. For example the Boolean
# option could take the string "true" and return True. # option could take the string "true" and return True.
def validate_value(self, value: Any) -> _T: def validate_value(self, value: T.Any) -> _T:
raise RuntimeError('Derived option class did not override validate_value.') raise RuntimeError('Derived option class did not override validate_value.')
def set_value(self, newvalue): def set_value(self, newvalue):
@ -128,7 +125,7 @@ class UserIntegerOption(UserOption[int]):
except ValueError: except ValueError:
raise MesonException('Value string "%s" is not convertible to an integer.' % valuestring) raise MesonException('Value string "%s" is not convertible to an integer.' % valuestring)
class UserUmaskOption(UserIntegerOption, UserOption[Union[str, int]]): class UserUmaskOption(UserIntegerOption, UserOption[T.Union[str, int]]):
def __init__(self, description, value, yielding=None): def __init__(self, description, value, yielding=None):
super().__init__(description, 0, 0o777, value, yielding) super().__init__(description, 0, 0o777, value, yielding)
self.choices = ['preserve', '0000-0777'] self.choices = ['preserve', '0000-0777']
@ -150,7 +147,7 @@ class UserUmaskOption(UserIntegerOption, UserOption[Union[str, int]]):
raise MesonException('Invalid mode: {}'.format(e)) raise MesonException('Invalid mode: {}'.format(e))
class UserComboOption(UserOption[str]): class UserComboOption(UserOption[str]):
def __init__(self, description, choices: List[str], value, yielding=None): def __init__(self, description, choices: T.List[str], value, yielding=None):
super().__init__(description, choices, yielding) super().__init__(description, choices, yielding)
if not isinstance(self.choices, list): if not isinstance(self.choices, list):
raise MesonException('Combo choices must be an array.') raise MesonException('Combo choices must be an array.')
@ -165,14 +162,14 @@ class UserComboOption(UserOption[str]):
raise MesonException('Value "%s" for combo option is not one of the choices. Possible choices are: %s.' % (value, optionsstring)) raise MesonException('Value "%s" for combo option is not one of the choices. Possible choices are: %s.' % (value, optionsstring))
return value return value
class UserArrayOption(UserOption[List[str]]): class UserArrayOption(UserOption[T.List[str]]):
def __init__(self, description, value, split_args=False, user_input=False, allow_dups=False, **kwargs): def __init__(self, description, value, split_args=False, user_input=False, allow_dups=False, **kwargs):
super().__init__(description, kwargs.get('choices', []), yielding=kwargs.get('yielding', None)) super().__init__(description, kwargs.get('choices', []), yielding=kwargs.get('yielding', None))
self.split_args = split_args self.split_args = split_args
self.allow_dups = allow_dups self.allow_dups = allow_dups
self.value = self.validate_value(value, user_input=user_input) self.value = self.validate_value(value, user_input=user_input)
def validate_value(self, value, user_input: bool = True) -> List[str]: def validate_value(self, value, user_input: bool = True) -> T.List[str]:
# User input is for options defined on the command line (via -D # User input is for options defined on the command line (via -D
# options). Users can put their input in as a comma separated # options). Users can put their input in as a comma separated
# string, but for defining options in meson_options.txt the format # string, but for defining options in meson_options.txt the format
@ -229,16 +226,16 @@ class UserFeatureOption(UserComboOption):
return self.value == 'auto' return self.value == 'auto'
def load_configs(filenames: List[str]) -> configparser.ConfigParser: def load_configs(filenames: T.List[str]) -> configparser.ConfigParser:
"""Load configuration files from a named subdirectory.""" """Load configuration files from a named subdirectory."""
config = configparser.ConfigParser() config = configparser.ConfigParser()
config.read(filenames) config.read(filenames)
return config return config
if TYPE_CHECKING: if T.TYPE_CHECKING:
CacheKeyType = Tuple[Tuple[Any, ...], ...] CacheKeyType = T.Tuple[T.Tuple[T.Any, ...], ...]
SubCacheKeyType = Tuple[Any, ...] SubCacheKeyType = T.Tuple[T.Any, ...]
class DependencyCacheType(enum.Enum): class DependencyCacheType(enum.Enum):
@ -262,7 +259,7 @@ class DependencySubCache:
def __init__(self, type_: DependencyCacheType): def __init__(self, type_: DependencyCacheType):
self.types = [type_] self.types = [type_]
self.__cache = {} # type: Dict[SubCacheKeyType, dependencies.Dependency] self.__cache = {} # type: T.Dict[SubCacheKeyType, dependencies.Dependency]
def __getitem__(self, key: 'SubCacheKeyType') -> 'dependencies.Dependency': def __getitem__(self, key: 'SubCacheKeyType') -> 'dependencies.Dependency':
return self.__cache[key] return self.__cache[key]
@ -273,7 +270,7 @@ class DependencySubCache:
def __contains__(self, key: 'SubCacheKeyType') -> bool: def __contains__(self, key: 'SubCacheKeyType') -> bool:
return key in self.__cache return key in self.__cache
def values(self) -> Iterable['dependencies.Dependency']: def values(self) -> T.Iterable['dependencies.Dependency']:
return self.__cache.values() return self.__cache.values()
@ -285,12 +282,12 @@ class DependencyCache:
successfully lookup by providing a simple get/put interface. successfully lookup by providing a simple get/put interface.
""" """
def __init__(self, builtins_per_machine: PerMachine[Dict[str, UserOption[Any]]], for_machine: MachineChoice): def __init__(self, builtins_per_machine: PerMachine[T.Dict[str, UserOption[T.Any]]], for_machine: MachineChoice):
self.__cache = OrderedDict() # type: MutableMapping[CacheKeyType, DependencySubCache] self.__cache = OrderedDict() # type: T.MutableMapping[CacheKeyType, DependencySubCache]
self.__builtins_per_machine = builtins_per_machine self.__builtins_per_machine = builtins_per_machine
self.__for_machine = for_machine self.__for_machine = for_machine
def __calculate_subkey(self, type_: DependencyCacheType) -> Tuple[Any, ...]: def __calculate_subkey(self, type_: DependencyCacheType) -> T.Tuple[T.Any, ...]:
if type_ is DependencyCacheType.PKG_CONFIG: if type_ is DependencyCacheType.PKG_CONFIG:
return tuple(self.__builtins_per_machine[self.__for_machine]['pkg_config_path'].value) return tuple(self.__builtins_per_machine[self.__for_machine]['pkg_config_path'].value)
elif type_ is DependencyCacheType.CMAKE: elif type_ is DependencyCacheType.CMAKE:
@ -298,7 +295,7 @@ class DependencyCache:
assert type_ is DependencyCacheType.OTHER, 'Someone forgot to update subkey calculations for a new type' assert type_ is DependencyCacheType.OTHER, 'Someone forgot to update subkey calculations for a new type'
return tuple() return tuple()
def __iter__(self) -> Iterator['CacheKeyType']: def __iter__(self) -> T.Iterator['CacheKeyType']:
return self.keys() return self.keys()
def put(self, key: 'CacheKeyType', dep: 'dependencies.Dependency') -> None: def put(self, key: 'CacheKeyType', dep: 'dependencies.Dependency') -> None:
@ -308,7 +305,7 @@ class DependencyCache:
subkey = self.__calculate_subkey(t) subkey = self.__calculate_subkey(t)
self.__cache[key][subkey] = dep self.__cache[key][subkey] = dep
def get(self, key: 'CacheKeyType') -> Optional['dependencies.Dependency']: def get(self, key: 'CacheKeyType') -> T.Optional['dependencies.Dependency']:
"""Get a value from the cache. """Get a value from the cache.
If there is no cache entry then None will be returned. If there is no cache entry then None will be returned.
@ -326,14 +323,14 @@ class DependencyCache:
pass pass
return None return None
def values(self) -> Iterator['dependencies.Dependency']: def values(self) -> T.Iterator['dependencies.Dependency']:
for c in self.__cache.values(): for c in self.__cache.values():
yield from c.values() yield from c.values()
def keys(self) -> Iterator['CacheKeyType']: def keys(self) -> T.Iterator['CacheKeyType']:
return iter(self.__cache.keys()) return iter(self.__cache.keys())
def items(self) -> Iterator[Tuple['CacheKeyType', List['dependencies.Dependency']]]: def items(self) -> T.Iterator[T.Tuple['CacheKeyType', T.List['dependencies.Dependency']]]:
for k, v in self.__cache.items(): for k, v in self.__cache.items():
vs = [] vs = []
for t in v.types: for t in v.types:
@ -346,7 +343,7 @@ class DependencyCache:
self.__cache.clear() self.__cache.clear()
# Can't bind this near the class method it seems, sadly. # Can't bind this near the class method it seems, sadly.
_V = TypeVar('_V') _V = T.TypeVar('_V')
# This class contains all data that must persist over multiple # This class contains all data that must persist over multiple
# invocations of Meson. It is roughly the same thing as # invocations of Meson. It is roughly the same thing as
@ -368,10 +365,10 @@ class CoreData:
self.target_guids = {} self.target_guids = {}
self.version = version self.version = version
self.init_builtins() self.init_builtins()
self.backend_options = {} # : Dict[str, UserOption] self.backend_options = {} # : T.Dict[str, UserOption]
self.user_options = {} # : Dict[str, UserOption] self.user_options = {} # : T.Dict[str, UserOption]
self.compiler_options = PerMachine({}, {}) self.compiler_options = PerMachine({}, {})
self.base_options = {} # : Dict[str, UserOption] self.base_options = {} # : T.Dict[str, UserOption]
self.cross_files = self.__load_config_files(options, scratch_dir, 'cross') self.cross_files = self.__load_config_files(options, scratch_dir, 'cross')
self.compilers = PerMachine(OrderedDict(), OrderedDict()) self.compilers = PerMachine(OrderedDict(), OrderedDict())
@ -384,7 +381,7 @@ class CoreData:
self.libdir_cross_fixup() self.libdir_cross_fixup()
@staticmethod @staticmethod
def __load_config_files(options: argparse.Namespace, scratch_dir: str, ftype: str) -> List[str]: def __load_config_files(options: argparse.Namespace, scratch_dir: str, ftype: str) -> T.List[str]:
# Need to try and make the passed filenames absolute because when the # Need to try and make the passed filenames absolute because when the
# files are parsed later we'll have chdir()d. # files are parsed later we'll have chdir()d.
if ftype == 'cross': if ftype == 'cross':
@ -395,9 +392,9 @@ class CoreData:
if not filenames: if not filenames:
return [] return []
found_invalid = [] # type: List[str] found_invalid = [] # type: T.List[str]
missing = [] # type: List[str] missing = [] # type: T.List[str]
real = [] # type: List[str] real = [] # type: T.List[str]
for i, f in enumerate(filenames): for i, f in enumerate(filenames):
f = os.path.expanduser(os.path.expandvars(f)) f = os.path.expanduser(os.path.expandvars(f))
if os.path.exists(f): if os.path.exists(f):
@ -591,8 +588,8 @@ class CoreData:
@staticmethod @staticmethod
def get_prefixed_options_per_machine( def get_prefixed_options_per_machine(
options_per_machine # : PerMachine[Dict[str, _V]]] options_per_machine # : PerMachine[T.Dict[str, _V]]]
) -> Iterable[Dict[str, _V]]: ) -> T.Iterable[T.Dict[str, _V]]:
for for_machine in iter(MachineChoice): for for_machine in iter(MachineChoice):
prefix = for_machine.get_prefix() prefix = for_machine.get_prefix()
yield { yield {
@ -600,17 +597,17 @@ class CoreData:
for k, v in options_per_machine[for_machine].items() for k, v in options_per_machine[for_machine].items()
} }
def _get_all_nonbuiltin_options(self) -> Iterable[Dict[str, UserOption]]: def _get_all_nonbuiltin_options(self) -> T.Iterable[T.Dict[str, UserOption]]:
yield self.backend_options yield self.backend_options
yield self.user_options yield self.user_options
yield from self.get_prefixed_options_per_machine(self.compiler_options) yield from self.get_prefixed_options_per_machine(self.compiler_options)
yield self.base_options yield self.base_options
def _get_all_builtin_options(self) -> Dict[str, UserOption]: def _get_all_builtin_options(self) -> T.Dict[str, UserOption]:
yield from self.get_prefixed_options_per_machine(self.builtins_per_machine) yield from self.get_prefixed_options_per_machine(self.builtins_per_machine)
yield self.builtins yield self.builtins
def get_all_options(self) -> Dict[str, UserOption]: def get_all_options(self) -> T.Dict[str, UserOption]:
yield from self._get_all_nonbuiltin_options() yield from self._get_all_nonbuiltin_options()
yield from self._get_all_builtin_options() yield from self._get_all_builtin_options()
@ -744,7 +741,7 @@ class CoreData:
self.set_options(options, subproject=subproject) self.set_options(options, subproject=subproject)
def add_lang_args(self, lang: str, comp: Type['Compiler'], def add_lang_args(self, lang: str, comp: T.Type['Compiler'],
for_machine: MachineChoice, env: 'Environment') -> None: for_machine: MachineChoice, env: 'Environment') -> None:
"""Add global language arguments that are needed before compiler/linker detection.""" """Add global language arguments that are needed before compiler/linker detection."""
from .compilers import compilers from .compilers import compilers
@ -759,7 +756,7 @@ class CoreData:
o.set_value(env.cmd_line_options[opt_prefix + k]) o.set_value(env.cmd_line_options[opt_prefix + k])
self.compiler_options[for_machine].setdefault(k, o) self.compiler_options[for_machine].setdefault(k, o)
def process_new_compiler(self, lang: str, comp: Type['Compiler'], env: 'Environment') -> None: def process_new_compiler(self, lang: str, comp: T.Type['Compiler'], env: 'Environment') -> None:
from . import compilers from . import compilers
self.compilers[comp.for_machine][lang] = comp self.compilers[comp.for_machine][lang] = comp
@ -934,17 +931,17 @@ def parse_cmd_line_options(args):
delattr(args, name) delattr(args, name)
_U = TypeVar('_U', bound=UserOption[_T]) _U = T.TypeVar('_U', bound=UserOption[_T])
class BuiltinOption(Generic[_T, _U]): class BuiltinOption(T.Generic[_T, _U]):
"""Class for a builtin option type. """Class for a builtin option type.
Currently doesn't support UserIntegerOption, or a few other cases. Currently doesn't support UserIntegerOption, or a few other cases.
""" """
def __init__(self, opt_type: Type[_U], description: str, default: Any, yielding: Optional[bool] = None, *, def __init__(self, opt_type: T.Type[_U], description: str, default: T.Any, yielding: T.Optional[bool] = None, *,
choices: Any = None): choices: T.Any = None):
self.opt_type = opt_type self.opt_type = opt_type
self.description = description self.description = description
self.default = default self.default = default
@ -958,14 +955,14 @@ class BuiltinOption(Generic[_T, _U]):
keywords['choices'] = self.choices keywords['choices'] = self.choices
return self.opt_type(self.description, **keywords) return self.opt_type(self.description, **keywords)
def _argparse_action(self) -> Optional[str]: def _argparse_action(self) -> T.Optional[str]:
if self.default is True: if self.default is True:
return 'store_false' return 'store_false'
elif self.default is False: elif self.default is False:
return 'store_true' return 'store_true'
return None return None
def _argparse_choices(self) -> Any: def _argparse_choices(self) -> T.Any:
if self.opt_type is UserBooleanOption: if self.opt_type is UserBooleanOption:
return [True, False] return [True, False]
elif self.opt_type is UserFeatureOption: elif self.opt_type is UserFeatureOption:
@ -979,7 +976,7 @@ class BuiltinOption(Generic[_T, _U]):
else: else:
return '--' + name.replace('_', '-') return '--' + name.replace('_', '-')
def prefixed_default(self, name: str, prefix: str = '') -> Any: def prefixed_default(self, name: str, prefix: str = '') -> T.Any:
if self.opt_type in [UserComboOption, UserIntegerOption]: if self.opt_type in [UserComboOption, UserIntegerOption]:
return self.default return self.default
try: try:
@ -1042,8 +1039,8 @@ builtin_options = OrderedDict([
]) ])
builtin_options_per_machine = OrderedDict([ builtin_options_per_machine = OrderedDict([
('pkg_config_path', BuiltinOption(UserArrayOption, 'List of additional paths for pkg-config to search', [])), ('pkg_config_path', BuiltinOption(UserArrayOption, 'T.List of additional paths for pkg-config to search', [])),
('cmake_prefix_path', BuiltinOption(UserArrayOption, 'List of additional prefixes for cmake to search', [])), ('cmake_prefix_path', BuiltinOption(UserArrayOption, 'T.List of additional prefixes for cmake to search', [])),
]) ])
# Special prefix-dependent defaults for installation directories that reside in # Special prefix-dependent defaults for installation directories that reside in

@ -24,7 +24,7 @@ import shutil
import stat import stat
import textwrap import textwrap
import platform import platform
from typing import Any, Dict, List, Optional, Tuple, Type, Union import typing as T
from enum import Enum from enum import Enum
from pathlib import Path, PurePath from pathlib import Path, PurePath
@ -127,7 +127,7 @@ class Dependency:
self.sources = [] self.sources = []
self.methods = self._process_method_kw(kwargs) self.methods = self._process_method_kw(kwargs)
self.include_type = self._process_include_type_kw(kwargs) self.include_type = self._process_include_type_kw(kwargs)
self.ext_deps = [] # type: List[Dependency] self.ext_deps = [] # type: T.List[Dependency]
def __repr__(self): def __repr__(self):
s = '<{0} {1}: {2}>' s = '<{0} {1}: {2}>'
@ -152,7 +152,7 @@ class Dependency:
return converted return converted
return self.compile_args return self.compile_args
def get_link_args(self, raw: bool = False) -> List[str]: def get_link_args(self, raw: bool = False) -> T.List[str]:
if raw and self.raw_link_args is not None: if raw and self.raw_link_args is not None:
return self.raw_link_args return self.raw_link_args
return self.link_args return self.link_args
@ -208,8 +208,8 @@ class Dependency:
""" """
raise RuntimeError('Unreachable code in partial_dependency called') raise RuntimeError('Unreachable code in partial_dependency called')
def _add_sub_dependency(self, dep_type: Type['Dependency'], env: Environment, def _add_sub_dependency(self, dep_type: T.Type['Dependency'], env: Environment,
kwargs: Dict[str, Any], *, kwargs: T.Dict[str, T.Any], *,
method: DependencyMethods = DependencyMethods.AUTO) -> None: method: DependencyMethods = DependencyMethods.AUTO) -> None:
"""Add an internal dependency of of the given type. """Add an internal dependency of of the given type.
@ -222,14 +222,14 @@ class Dependency:
kwargs['method'] = method kwargs['method'] = method
self.ext_deps.append(dep_type(env, kwargs)) self.ext_deps.append(dep_type(env, kwargs))
def get_variable(self, *, cmake: Optional[str] = None, pkgconfig: Optional[str] = None, def get_variable(self, *, cmake: T.Optional[str] = None, pkgconfig: T.Optional[str] = None,
configtool: Optional[str] = None, default_value: Optional[str] = None, configtool: T.Optional[str] = None, default_value: T.Optional[str] = None,
pkgconfig_define: Optional[List[str]] = None) -> Union[str, List[str]]: pkgconfig_define: T.Optional[T.List[str]] = None) -> T.Union[str, T.List[str]]:
if default_value is not None: if default_value is not None:
return default_value return default_value
raise DependencyException('No default provided for dependency {!r}, which is not pkg-config, cmake, or config-tool based.'.format(self)) raise DependencyException('No default provided for dependency {!r}, which is not pkg-config, cmake, or config-tool based.'.format(self))
def generate_system_dependency(self, include_type: str) -> Type['Dependency']: def generate_system_dependency(self, include_type: str) -> T.Type['Dependency']:
new_dep = copy.deepcopy(self) new_dep = copy.deepcopy(self)
new_dep.include_type = self._process_include_type_kw({'include_type': include_type}) new_dep.include_type = self._process_include_type_kw({'include_type': include_type})
return new_dep return new_dep
@ -553,9 +553,9 @@ class ConfigToolDependency(ExternalDependency):
def log_tried(self): def log_tried(self):
return self.type_name return self.type_name
def get_variable(self, *, cmake: Optional[str] = None, pkgconfig: Optional[str] = None, def get_variable(self, *, cmake: T.Optional[str] = None, pkgconfig: T.Optional[str] = None,
configtool: Optional[str] = None, default_value: Optional[str] = None, configtool: T.Optional[str] = None, default_value: T.Optional[str] = None,
pkgconfig_define: Optional[List[str]] = None) -> Union[str, List[str]]: pkgconfig_define: T.Optional[T.List[str]] = None) -> T.Union[str, T.List[str]]:
if configtool: if configtool:
# In the not required case '' (empty string) will be returned if the # In the not required case '' (empty string) will be returned if the
# variable is not found. Since '' is a valid value to return we # variable is not found. Since '' is a valid value to return we
@ -704,7 +704,7 @@ class PkgConfigDependency(ExternalDependency):
cache[(self.pkgbin, targs, fenv)] = self._call_pkgbin_real(args, env) cache[(self.pkgbin, targs, fenv)] = self._call_pkgbin_real(args, env)
return cache[(self.pkgbin, targs, fenv)] return cache[(self.pkgbin, targs, fenv)]
def _convert_mingw_paths(self, args: List[str]) -> List[str]: def _convert_mingw_paths(self, args: T.List[str]) -> T.List[str]:
''' '''
Both MSVC and native Python on Windows cannot handle MinGW-esque /c/foo Both MSVC and native Python on Windows cannot handle MinGW-esque /c/foo
paths so convert them to C:/foo. We cannot resolve other paths starting paths so convert them to C:/foo. We cannot resolve other paths starting
@ -1006,9 +1006,9 @@ class PkgConfigDependency(ExternalDependency):
def log_tried(self): def log_tried(self):
return self.type_name return self.type_name
def get_variable(self, *, cmake: Optional[str] = None, pkgconfig: Optional[str] = None, def get_variable(self, *, cmake: T.Optional[str] = None, pkgconfig: T.Optional[str] = None,
configtool: Optional[str] = None, default_value: Optional[str] = None, configtool: T.Optional[str] = None, default_value: T.Optional[str] = None,
pkgconfig_define: Optional[List[str]] = None) -> Union[str, List[str]]: pkgconfig_define: T.Optional[T.List[str]] = None) -> T.Union[str, T.List[str]]:
if pkgconfig: if pkgconfig:
kwargs = {} kwargs = {}
if default_value is not None: if default_value is not None:
@ -1039,10 +1039,10 @@ class CMakeDependency(ExternalDependency):
def _main_cmake_file(self) -> str: def _main_cmake_file(self) -> str:
return 'CMakeLists.txt' return 'CMakeLists.txt'
def _extra_cmake_opts(self) -> List[str]: def _extra_cmake_opts(self) -> T.List[str]:
return [] return []
def _map_module_list(self, modules: List[Tuple[str, bool]]) -> List[Tuple[str, bool]]: def _map_module_list(self, modules: T.List[T.Tuple[str, bool]]) -> T.List[T.Tuple[str, bool]]:
# Map the input module list to something else # Map the input module list to something else
# This function will only be executed AFTER the initial CMake # This function will only be executed AFTER the initial CMake
# interpreter pass has completed. Thus variables defined in the # interpreter pass has completed. Thus variables defined in the
@ -1083,7 +1083,7 @@ class CMakeDependency(ExternalDependency):
# Where all CMake "build dirs" are located # Where all CMake "build dirs" are located
self.cmake_root_dir = environment.scratch_dir self.cmake_root_dir = environment.scratch_dir
# List of successfully found modules # T.List of successfully found modules
self.found_modules = [] self.found_modules = []
self.cmakebin = CMakeExecutor(environment, CMakeDependency.class_cmake_version, self.for_machine, silent=self.silent) self.cmakebin = CMakeExecutor(environment, CMakeDependency.class_cmake_version, self.for_machine, silent=self.silent)
@ -1203,7 +1203,7 @@ class CMakeDependency(ExternalDependency):
@staticmethod @staticmethod
@functools.lru_cache(maxsize=None) @functools.lru_cache(maxsize=None)
def _cached_listdir(path: str) -> Tuple[Tuple[str, str]]: def _cached_listdir(path: str) -> T.Tuple[T.Tuple[str, str]]:
try: try:
return tuple((x, str(x).lower()) for x in os.listdir(path)) return tuple((x, str(x).lower()) for x in os.listdir(path))
except OSError: except OSError:
@ -1217,7 +1217,7 @@ class CMakeDependency(ExternalDependency):
except OSError: except OSError:
return False return False
def _preliminary_find_check(self, name: str, module_path: List[str], prefix_path: List[str], machine: MachineInfo) -> bool: def _preliminary_find_check(self, name: str, module_path: T.List[str], prefix_path: T.List[str], machine: MachineInfo) -> bool:
lname = str(name).lower() lname = str(name).lower()
# Checks <path>, <path>/cmake, <path>/CMake # Checks <path>, <path>/cmake, <path>/CMake
@ -1295,7 +1295,7 @@ class CMakeDependency(ExternalDependency):
return False return False
def _detect_dep(self, name: str, modules: List[Tuple[str, bool]], args: List[str]): def _detect_dep(self, name: str, modules: T.List[T.Tuple[str, bool]], args: T.List[str]):
# Detect a dependency with CMake using the '--find-package' mode # Detect a dependency with CMake using the '--find-package' mode
# and the trace output (stderr) # and the trace output (stderr)
# #
@ -1410,7 +1410,7 @@ class CMakeDependency(ExternalDependency):
for i, required in modules: for i, required in modules:
if i not in self.traceparser.targets: if i not in self.traceparser.targets:
if not required: if not required:
mlog.warning('CMake: Optional module', mlog.bold(self._original_module_name(i)), 'for', mlog.bold(name), 'was not found') mlog.warning('CMake: T.Optional module', mlog.bold(self._original_module_name(i)), 'for', mlog.bold(name), 'was not found')
continue continue
raise self._gen_exception('CMake: invalid module {} for {}.\n' raise self._gen_exception('CMake: invalid module {} for {}.\n'
'Try to explicitly specify one or more targets with the "modules" property.\n' 'Try to explicitly specify one or more targets with the "modules" property.\n'
@ -1548,9 +1548,9 @@ project(MesonTemp LANGUAGES {})
return 'modules: ' + ', '.join(modules) return 'modules: ' + ', '.join(modules)
return '' return ''
def get_variable(self, *, cmake: Optional[str] = None, pkgconfig: Optional[str] = None, def get_variable(self, *, cmake: T.Optional[str] = None, pkgconfig: T.Optional[str] = None,
configtool: Optional[str] = None, default_value: Optional[str] = None, configtool: T.Optional[str] = None, default_value: T.Optional[str] = None,
pkgconfig_define: Optional[List[str]] = None) -> Union[str, List[str]]: pkgconfig_define: T.Optional[T.List[str]] = None) -> T.Union[str, T.List[str]]:
if cmake: if cmake:
try: try:
v = self.traceparser.vars[cmake] v = self.traceparser.vars[cmake]
@ -1765,9 +1765,9 @@ class ExternalProgram:
# An 'ExternalProgram' always runs on the build machine # An 'ExternalProgram' always runs on the build machine
for_machine = MachineChoice.BUILD for_machine = MachineChoice.BUILD
def __init__(self, name: str, command: Optional[List[str]] = None, def __init__(self, name: str, command: T.Optional[T.List[str]] = None,
silent: bool = False, search_dir: Optional[str] = None, silent: bool = False, search_dir: T.Optional[str] = None,
extra_search_dirs: Optional[List[str]] = None): extra_search_dirs: T.Optional[T.List[str]] = None):
self.name = name self.name = name
if command is not None: if command is not None:
self.command = listify(command) self.command = listify(command)
@ -2172,7 +2172,7 @@ class ExtraFrameworkDependency(ExternalDependency):
return 'framework' return 'framework'
def get_dep_identifier(name, kwargs) -> Tuple: def get_dep_identifier(name, kwargs) -> T.Tuple:
identifier = (name, ) identifier = (name, )
for key, value in kwargs.items(): for key, value in kwargs.items():
# 'version' is irrelevant for caching; the caller must check version matches # 'version' is irrelevant for caching; the caller must check version matches
@ -2286,7 +2286,7 @@ def find_external_dependency(name, env, kwargs):
return NotFoundDependency(env) return NotFoundDependency(env)
def _build_external_dependency_list(name, env: Environment, kwargs: Dict[str, Any]) -> list: def _build_external_dependency_list(name, env: Environment, kwargs: T.Dict[str, T.Any]) -> list:
# First check if the method is valid # First check if the method is valid
if 'method' in kwargs and kwargs['method'] not in [e.value for e in DependencyMethods]: if 'method' in kwargs and kwargs['method'] not in [e.value for e in DependencyMethods]:
raise DependencyException('method {!r} is invalid'.format(kwargs['method'])) raise DependencyException('method {!r} is invalid'.format(kwargs['method']))
@ -2343,7 +2343,7 @@ def _build_external_dependency_list(name, env: Environment, kwargs: Dict[str, An
return candidates return candidates
def sort_libpaths(libpaths: List[str], refpaths: List[str]) -> List[str]: def sort_libpaths(libpaths: T.List[str], refpaths: T.List[str]) -> T.List[str]:
"""Sort <libpaths> according to <refpaths> """Sort <libpaths> according to <refpaths>
It is intended to be used to sort -L flags returned by pkg-config. It is intended to be used to sort -L flags returned by pkg-config.

@ -29,7 +29,7 @@ from .base import (
) )
from .misc import ThreadDependency from .misc import ThreadDependency
from typing import List, Tuple import typing as T
def get_shared_library_suffix(environment, for_machine: MachineChoice): def get_shared_library_suffix(environment, for_machine: MachineChoice):
@ -407,10 +407,10 @@ class LLVMDependencyCMake(CMakeDependency):
# Use a custom CMakeLists.txt for LLVM # Use a custom CMakeLists.txt for LLVM
return 'CMakeListsLLVM.txt' return 'CMakeListsLLVM.txt'
def _extra_cmake_opts(self) -> List[str]: def _extra_cmake_opts(self) -> T.List[str]:
return ['-DLLVM_MESON_MODULES={}'.format(';'.join(self.llvm_modules + self.llvm_opt_modules))] return ['-DLLVM_MESON_MODULES={}'.format(';'.join(self.llvm_modules + self.llvm_opt_modules))]
def _map_module_list(self, modules: List[Tuple[str, bool]]) -> List[Tuple[str, bool]]: def _map_module_list(self, modules: T.List[T.Tuple[str, bool]]) -> T.List[T.Tuple[str, bool]]:
res = [] res = []
for mod, required in modules: for mod, required in modules:
cm_targets = self.traceparser.get_cmake_var('MESON_LLVM_TARGETS_{}'.format(mod)) cm_targets = self.traceparser.get_cmake_var('MESON_LLVM_TARGETS_{}'.format(mod))

@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
import typing import typing as T
import os import os
import re import re
import subprocess import subprocess
@ -118,7 +118,7 @@ class MPIDependency(ExternalDependency):
self.version, self.compile_args, self.link_args = result self.version, self.compile_args, self.link_args = result
return return
def _filter_compile_args(self, args: typing.Sequence[str]) -> typing.List[str]: def _filter_compile_args(self, args: T.Sequence[str]) -> T.List[str]:
""" """
MPI wrappers return a bunch of garbage args. MPI wrappers return a bunch of garbage args.
Drop -O2 and everything that is not needed. Drop -O2 and everything that is not needed.
@ -142,7 +142,7 @@ class MPIDependency(ExternalDependency):
result.append(f) result.append(f)
return result return result
def _filter_link_args(self, args: typing.Sequence[str], cid: str) -> typing.List[str]: def _filter_link_args(self, args: T.Sequence[str], cid: str) -> T.List[str]:
""" """
MPI wrappers return a bunch of garbage args. MPI wrappers return a bunch of garbage args.
Drop -O2 and everything that is not needed. Drop -O2 and everything that is not needed.
@ -210,7 +210,7 @@ class MPIDependency(ExternalDependency):
return version, cargs, libs return version, cargs, libs
def _try_other_wrapper(self, prog, cid: str) -> typing.Tuple[str, typing.List[str], typing.List[str]]: def _try_other_wrapper(self, prog, cid: str) -> T.Tuple[str, T.List[str], T.List[str]]:
prog = ExternalProgram(prog, silent=True) prog = ExternalProgram(prog, silent=True)
if not prog.found(): if not prog.found():
return None return None
@ -243,7 +243,7 @@ class MPIDependency(ExternalDependency):
return version, args, args return version, args, args
def _try_msmpi(self) -> typing.Tuple[str, typing.List[str], typing.List[str]]: def _try_msmpi(self) -> T.Tuple[str, T.List[str], T.List[str]]:
if self.language == 'cpp': if self.language == 'cpp':
# MS-MPI does not support the C++ version of MPI, only the standard C API. # MS-MPI does not support the C++ version of MPI, only the standard C API.
return None return None

@ -13,13 +13,13 @@
# limitations under the License. # limitations under the License.
import configparser, os, subprocess import configparser, os, subprocess
import typing import typing as T
from . import mesonlib from . import mesonlib
from .mesonlib import EnvironmentException, split_args from .mesonlib import EnvironmentException, split_args
from . import mlog from . import mlog
_T = typing.TypeVar('_T') _T = T.TypeVar('_T')
# These classes contains all the data pulled from configuration files (native # These classes contains all the data pulled from configuration files (native
@ -79,7 +79,7 @@ CPU_FAMILES_64_BIT = [
class MesonConfigFile: class MesonConfigFile:
@classmethod @classmethod
def from_config_parser(cls, parser: configparser.ConfigParser) -> typing.Dict[str, typing.Dict[str, typing.Dict[str, str]]]: def from_config_parser(cls, parser: configparser.ConfigParser) -> T.Dict[str, T.Dict[str, T.Dict[str, str]]]:
out = {} out = {}
# This is a bit hackish at the moment. # This is a bit hackish at the moment.
for s in parser.sections(): for s in parser.sections():
@ -122,10 +122,10 @@ class HasEnvVarFallback:
class Properties(HasEnvVarFallback): class Properties(HasEnvVarFallback):
def __init__( def __init__(
self, self,
properties: typing.Optional[typing.Dict[str, typing.Union[str, typing.List[str]]]] = None, properties: T.Optional[T.Dict[str, T.Union[str, T.List[str]]]] = None,
fallback: bool = True): fallback: bool = True):
super().__init__(fallback) super().__init__(fallback)
self.properties = properties or {} # type: typing.Dict[str, typing.Union[str, typing.List[str]]] self.properties = properties or {} # type: T.Dict[str, T.Union[str, T.List[str]]]
def has_stdlib(self, language: str) -> bool: def has_stdlib(self, language: str) -> bool:
return language + '_stdlib' in self.properties return language + '_stdlib' in self.properties
@ -133,30 +133,30 @@ class Properties(HasEnvVarFallback):
# Some of get_stdlib, get_root, get_sys_root are wider than is actually # Some of get_stdlib, get_root, get_sys_root are wider than is actually
# true, but without heterogenious dict annotations it's not practical to # true, but without heterogenious dict annotations it's not practical to
# narrow them # narrow them
def get_stdlib(self, language: str) -> typing.Union[str, typing.List[str]]: def get_stdlib(self, language: str) -> T.Union[str, T.List[str]]:
return self.properties[language + '_stdlib'] return self.properties[language + '_stdlib']
def get_root(self) -> typing.Optional[typing.Union[str, typing.List[str]]]: def get_root(self) -> T.Optional[T.Union[str, T.List[str]]]:
return self.properties.get('root', None) return self.properties.get('root', None)
def get_sys_root(self) -> typing.Optional[typing.Union[str, typing.List[str]]]: def get_sys_root(self) -> T.Optional[T.Union[str, T.List[str]]]:
return self.properties.get('sys_root', None) return self.properties.get('sys_root', None)
def __eq__(self, other: typing.Any) -> 'typing.Union[bool, NotImplemented]': def __eq__(self, other: T.Any) -> 'T.Union[bool, NotImplemented]':
if isinstance(other, type(self)): if isinstance(other, type(self)):
return self.properties == other.properties return self.properties == other.properties
return NotImplemented return NotImplemented
# TODO consider removing so Properties is less freeform # TODO consider removing so Properties is less freeform
def __getitem__(self, key: str) -> typing.Any: def __getitem__(self, key: str) -> T.Any:
return self.properties[key] return self.properties[key]
# TODO consider removing so Properties is less freeform # TODO consider removing so Properties is less freeform
def __contains__(self, item: typing.Any) -> bool: def __contains__(self, item: T.Any) -> bool:
return item in self.properties return item in self.properties
# TODO consider removing, for same reasons as above # TODO consider removing, for same reasons as above
def get(self, key: str, default: typing.Any = None) -> typing.Any: def get(self, key: str, default: T.Any = None) -> T.Any:
return self.properties.get(key, default) return self.properties.get(key, default)
class MachineInfo: class MachineInfo:
@ -167,7 +167,7 @@ class MachineInfo:
self.endian = endian self.endian = endian
self.is_64_bit = cpu_family in CPU_FAMILES_64_BIT # type: bool self.is_64_bit = cpu_family in CPU_FAMILES_64_BIT # type: bool
def __eq__(self, other: typing.Any) -> 'typing.Union[bool, NotImplemented]': def __eq__(self, other: T.Any) -> 'T.Union[bool, NotImplemented]':
if self.__class__ is not other.__class__: if self.__class__ is not other.__class__:
return NotImplemented return NotImplemented
return \ return \
@ -176,7 +176,7 @@ class MachineInfo:
self.cpu == other.cpu and \ self.cpu == other.cpu and \
self.endian == other.endian self.endian == other.endian
def __ne__(self, other: typing.Any) -> 'typing.Union[bool, NotImplemented]': def __ne__(self, other: T.Any) -> 'T.Union[bool, NotImplemented]':
if self.__class__ is not other.__class__: if self.__class__ is not other.__class__:
return NotImplemented return NotImplemented
return not self.__eq__(other) return not self.__eq__(other)
@ -185,7 +185,7 @@ class MachineInfo:
return '<MachineInfo: {} {} ({})>'.format(self.system, self.cpu_family, self.cpu) return '<MachineInfo: {} {} ({})>'.format(self.system, self.cpu_family, self.cpu)
@classmethod @classmethod
def from_literal(cls, literal: typing.Dict[str, str]) -> 'MachineInfo': def from_literal(cls, literal: T.Dict[str, str]) -> 'MachineInfo':
minimum_literal = {'cpu', 'cpu_family', 'endian', 'system'} minimum_literal = {'cpu', 'cpu_family', 'endian', 'system'}
if set(literal) < minimum_literal: if set(literal) < minimum_literal:
raise EnvironmentException( raise EnvironmentException(
@ -283,10 +283,10 @@ class MachineInfo:
class BinaryTable(HasEnvVarFallback): class BinaryTable(HasEnvVarFallback):
def __init__( def __init__(
self, self,
binaries: typing.Optional[typing.Dict[str, typing.Union[str, typing.List[str]]]] = None, binaries: T.Optional[T.Dict[str, T.Union[str, T.List[str]]]] = None,
fallback: bool = True): fallback: bool = True):
super().__init__(fallback) super().__init__(fallback)
self.binaries = binaries or {} # type: typing.Dict[str, typing.Union[str, typing.List[str]]] self.binaries = binaries or {} # type: T.Dict[str, T.Union[str, T.List[str]]]
for name, command in self.binaries.items(): for name, command in self.binaries.items():
if not isinstance(command, (list, str)): if not isinstance(command, (list, str)):
# TODO generalize message # TODO generalize message
@ -317,10 +317,10 @@ class BinaryTable(HasEnvVarFallback):
'cmake': 'CMAKE', 'cmake': 'CMAKE',
'qmake': 'QMAKE', 'qmake': 'QMAKE',
'pkgconfig': 'PKG_CONFIG', 'pkgconfig': 'PKG_CONFIG',
} # type: typing.Dict[str, str] } # type: T.Dict[str, str]
@staticmethod @staticmethod
def detect_ccache() -> typing.List[str]: def detect_ccache() -> T.List[str]:
try: try:
subprocess.check_call(['ccache', '--version'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) subprocess.check_call(['ccache', '--version'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
except (OSError, subprocess.CalledProcessError): except (OSError, subprocess.CalledProcessError):
@ -335,7 +335,7 @@ class BinaryTable(HasEnvVarFallback):
This is probably wrong, it should always point to the native compiler.''' % evar) This is probably wrong, it should always point to the native compiler.''' % evar)
@classmethod @classmethod
def parse_entry(cls, entry: typing.Union[str, typing.List[str]]) -> typing.Tuple[typing.List[str], typing.List[str]]: def parse_entry(cls, entry: T.Union[str, T.List[str]]) -> T.Tuple[T.List[str], T.List[str]]:
compiler = mesonlib.stringlistify(entry) compiler = mesonlib.stringlistify(entry)
# Ensure ccache exists and remove it if it doesn't # Ensure ccache exists and remove it if it doesn't
if compiler[0] == 'ccache': if compiler[0] == 'ccache':
@ -346,7 +346,7 @@ This is probably wrong, it should always point to the native compiler.''' % evar
# Return value has to be a list of compiler 'choices' # Return value has to be a list of compiler 'choices'
return compiler, ccache return compiler, ccache
def lookup_entry(self, name: str) -> typing.Optional[typing.List[str]]: def lookup_entry(self, name: str) -> T.Optional[T.List[str]]:
"""Lookup binaryk """Lookup binaryk
Returns command with args as list if found, Returns `None` if nothing is Returns command with args as list if found, Returns `None` if nothing is
@ -379,13 +379,13 @@ class Directories:
builds. builds.
""" """
def __init__(self, bindir: typing.Optional[str] = None, datadir: typing.Optional[str] = None, def __init__(self, bindir: T.Optional[str] = None, datadir: T.Optional[str] = None,
includedir: typing.Optional[str] = None, infodir: typing.Optional[str] = None, includedir: T.Optional[str] = None, infodir: T.Optional[str] = None,
libdir: typing.Optional[str] = None, libexecdir: typing.Optional[str] = None, libdir: T.Optional[str] = None, libexecdir: T.Optional[str] = None,
localedir: typing.Optional[str] = None, localstatedir: typing.Optional[str] = None, localedir: T.Optional[str] = None, localstatedir: T.Optional[str] = None,
mandir: typing.Optional[str] = None, prefix: typing.Optional[str] = None, mandir: T.Optional[str] = None, prefix: T.Optional[str] = None,
sbindir: typing.Optional[str] = None, sharedstatedir: typing.Optional[str] = None, sbindir: T.Optional[str] = None, sharedstatedir: T.Optional[str] = None,
sysconfdir: typing.Optional[str] = None): sysconfdir: T.Optional[str] = None):
self.bindir = bindir self.bindir = bindir
self.datadir = datadir self.datadir = datadir
self.includedir = includedir self.includedir = includedir
@ -403,12 +403,12 @@ class Directories:
def __contains__(self, key: str) -> bool: def __contains__(self, key: str) -> bool:
return hasattr(self, key) return hasattr(self, key)
def __getitem__(self, key: str) -> typing.Optional[str]: def __getitem__(self, key: str) -> T.Optional[str]:
# Mypy can't figure out what to do with getattr here, so we'll case for it # Mypy can't figure out what to do with getattr here, so we'll case for it
return typing.cast(typing.Optional[str], getattr(self, key)) return T.cast(T.Optional[str], getattr(self, key))
def __setitem__(self, key: str, value: typing.Optional[str]) -> None: def __setitem__(self, key: str, value: T.Optional[str]) -> None:
setattr(self, key, value) setattr(self, key, value)
def __iter__(self) -> typing.Iterator[typing.Tuple[str, str]]: def __iter__(self) -> T.Iterator[T.Tuple[str, str]]:
return iter(self.__dict__.items()) return iter(self.__dict__.items())

@ -12,9 +12,10 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
import os, platform, re, sys, shutil, subprocess, typing import os, platform, re, sys, shutil, subprocess
import tempfile import tempfile
import shlex import shlex
import typing as T
from . import coredata from . import coredata
from .linkers import ArLinker, ArmarLinker, VisualStudioLinker, DLinker, CcrxLinker, IntelVisualStudioLinker from .linkers import ArLinker, ArmarLinker, VisualStudioLinker, DLinker, CcrxLinker, IntelVisualStudioLinker
@ -110,7 +111,7 @@ from .compilers import (
build_filename = 'meson.build' build_filename = 'meson.build'
CompilersDict = typing.Dict[str, Compiler] CompilersDict = T.Dict[str, Compiler]
def detect_gcovr(min_version='3.3', new_rootdir_version='4.2', log=False): def detect_gcovr(min_version='3.3', new_rootdir_version='4.2', log=False):
gcovr_exe = 'gcovr' gcovr_exe = 'gcovr'
@ -167,7 +168,7 @@ def detect_ninja_command_and_version(version: str = '1.5', log: bool = False) ->
mlog.log('Found {}-{} at {}'.format(name, found, quote_arg(n))) mlog.log('Found {}-{} at {}'.format(name, found, quote_arg(n)))
return (n, found) return (n, found)
def get_llvm_tool_names(tool: str) -> typing.List[str]: def get_llvm_tool_names(tool: str) -> T.List[str]:
# Ordered list of possible suffixes of LLVM executables to try. Start with # Ordered list of possible suffixes of LLVM executables to try. Start with
# base, then try newest back to oldest (3.5 is arbitrary), and finally the # base, then try newest back to oldest (3.5 is arbitrary), and finally the
# devel version. Please note that the development snapshot in Debian does # devel version. Please note that the development snapshot in Debian does
@ -194,7 +195,7 @@ def get_llvm_tool_names(tool: str) -> typing.List[str]:
names.append(tool + suffix) names.append(tool + suffix)
return names return names
def detect_scanbuild() -> typing.List[str]: def detect_scanbuild() -> T.List[str]:
""" Look for scan-build binary on build platform """ Look for scan-build binary on build platform
First, if a SCANBUILD env variable has been provided, give it precedence First, if a SCANBUILD env variable has been provided, give it precedence
@ -225,7 +226,7 @@ def detect_scanbuild() -> typing.List[str]:
return [tool] return [tool]
return [] return []
def detect_clangformat() -> typing.List[str]: def detect_clangformat() -> T.List[str]:
""" Look for clang-format binary on build platform """ Look for clang-format binary on build platform
Do the same thing as detect_scanbuild to find clang-format except it Do the same thing as detect_scanbuild to find clang-format except it
@ -397,7 +398,7 @@ def detect_msys2_arch():
return os.environ['MSYSTEM_CARCH'] return os.environ['MSYSTEM_CARCH']
return None return None
def detect_machine_info(compilers: typing.Optional[CompilersDict] = None) -> MachineInfo: def detect_machine_info(compilers: T.Optional[CompilersDict] = None) -> MachineInfo:
"""Detect the machine we're running on """Detect the machine we're running on
If compilers are not provided, we cannot know as much. None out those If compilers are not provided, we cannot know as much. None out those
@ -732,7 +733,7 @@ class Environment:
errmsg += '\nRunning "{0}" gave "{1}"'.format(c, e) errmsg += '\nRunning "{0}" gave "{1}"'.format(c, e)
raise EnvironmentException(errmsg) raise EnvironmentException(errmsg)
def _guess_win_linker(self, compiler: typing.List[str], comp_class: Compiler, def _guess_win_linker(self, compiler: T.List[str], comp_class: Compiler,
for_machine: MachineChoice, *, for_machine: MachineChoice, *,
use_linker_prefix: bool = True) -> 'DynamicLinker': use_linker_prefix: bool = True) -> 'DynamicLinker':
self.coredata.add_lang_args(comp_class.language, comp_class, for_machine, self) self.coredata.add_lang_args(comp_class.language, comp_class, for_machine, self)
@ -747,7 +748,7 @@ class Environment:
check_args += self.coredata.compiler_options[for_machine][comp_class.language + '_args'].value check_args += self.coredata.compiler_options[for_machine][comp_class.language + '_args'].value
override = [] # type: typing.List[str] override = [] # type: T.List[str]
value = self.binaries[for_machine].lookup_entry('ld') value = self.binaries[for_machine].lookup_entry('ld')
if value is not None: if value is not None:
override = comp_class.use_linker_args(value[0]) override = comp_class.use_linker_args(value[0])
@ -791,9 +792,9 @@ class Environment:
"%PATH% variable to resolve this.") "%PATH% variable to resolve this.")
raise EnvironmentException('Unable to determine dynamic linker') raise EnvironmentException('Unable to determine dynamic linker')
def _guess_nix_linker(self, compiler: typing.List[str], comp_class: typing.Type[Compiler], def _guess_nix_linker(self, compiler: T.List[str], comp_class: T.Type[Compiler],
for_machine: MachineChoice, *, for_machine: MachineChoice, *,
extra_args: typing.Optional[typing.List[str]] = None) -> 'DynamicLinker': extra_args: T.Optional[T.List[str]] = None) -> 'DynamicLinker':
"""Helper for guessing what linker to use on Unix-Like OSes. """Helper for guessing what linker to use on Unix-Like OSes.
:compiler: Invocation to use to get linker :compiler: Invocation to use to get linker
@ -802,7 +803,7 @@ class Environment:
:extra_args: Any additional arguments required (such as a source file) :extra_args: Any additional arguments required (such as a source file)
""" """
self.coredata.add_lang_args(comp_class.language, comp_class, for_machine, self) self.coredata.add_lang_args(comp_class.language, comp_class, for_machine, self)
extra_args = typing.cast(typing.List[str], extra_args or []) extra_args = T.cast(T.List[str], extra_args or [])
extra_args += self.coredata.compiler_options[for_machine][comp_class.language + '_args'].value extra_args += self.coredata.compiler_options[for_machine][comp_class.language + '_args'].value
if isinstance(comp_class.LINKER_PREFIX, str): if isinstance(comp_class.LINKER_PREFIX, str):
@ -810,7 +811,7 @@ class Environment:
else: else:
check_args = comp_class.LINKER_PREFIX + ['--version'] + extra_args check_args = comp_class.LINKER_PREFIX + ['--version'] + extra_args
override = [] # type: typing.List[str] override = [] # type: T.List[str]
value = self.binaries[for_machine].lookup_entry('ld') value = self.binaries[for_machine].lookup_entry('ld')
if value is not None: if value is not None:
override = comp_class.use_linker_args(value[0]) override = comp_class.use_linker_args(value[0])

@ -41,7 +41,7 @@ import subprocess
import collections import collections
from itertools import chain from itertools import chain
import functools import functools
from typing import Sequence, List, Union, Optional, Dict, Any import typing as T
import importlib import importlib
@ -914,10 +914,10 @@ class RunTargetHolder(TargetHolder):
return r.format(self.__class__.__name__, h.get_id(), h.command) return r.format(self.__class__.__name__, h.get_id(), h.command)
class Test(InterpreterObject): class Test(InterpreterObject):
def __init__(self, name: str, project: str, suite: List[str], exe: build.Executable, def __init__(self, name: str, project: str, suite: T.List[str], exe: build.Executable,
depends: List[Union[build.CustomTarget, build.BuildTarget]], depends: T.List[T.Union[build.CustomTarget, build.BuildTarget]],
is_parallel: bool, cmd_args: List[str], env: build.EnvironmentVariables, is_parallel: bool, cmd_args: T.List[str], env: build.EnvironmentVariables,
should_fail: bool, timeout: int, workdir: Optional[str], protocol: str, should_fail: bool, timeout: int, workdir: T.Optional[str], protocol: str,
priority: int): priority: int):
InterpreterObject.__init__(self) InterpreterObject.__init__(self)
self.name = name self.name = name
@ -2944,7 +2944,7 @@ external dependencies (including libraries) must go to "dependencies".''')
self.validate_arguments(args, 0, []) self.validate_arguments(args, 0, [])
raise Exception() raise Exception()
def add_languages(self, args: Sequence[str], required: bool) -> bool: def add_languages(self, args: T.Sequence[str], required: bool) -> bool:
success = self.add_languages_for(args, required, MachineChoice.BUILD) success = self.add_languages_for(args, required, MachineChoice.BUILD)
success &= self.add_languages_for(args, required, MachineChoice.HOST) success &= self.add_languages_for(args, required, MachineChoice.HOST)
if not self.coredata.is_cross_build(): if not self.coredata.is_cross_build():
@ -3407,7 +3407,7 @@ external dependencies (including libraries) must go to "dependencies".''')
if 'input' not in kwargs or 'output' not in kwargs: if 'input' not in kwargs or 'output' not in kwargs:
raise InterpreterException('Keyword arguments input and output must exist') raise InterpreterException('Keyword arguments input and output must exist')
if 'fallback' not in kwargs: if 'fallback' not in kwargs:
FeatureNew('Optional fallback in vcs_tag', '0.41.0').use(self.subproject) FeatureNew('T.Optional fallback in vcs_tag', '0.41.0').use(self.subproject)
fallback = kwargs.pop('fallback', self.project_version) fallback = kwargs.pop('fallback', self.project_version)
if not isinstance(fallback, str): if not isinstance(fallback, str):
raise InterpreterException('Keyword argument fallback must be a string.') raise InterpreterException('Keyword argument fallback must be a string.')
@ -4469,7 +4469,7 @@ This will become a hard error in the future.''', location=self.current_node)
return varname in self.variables return varname in self.variables
@staticmethod @staticmethod
def machine_from_native_kwarg(kwargs: Dict[str, Any]) -> MachineChoice: def machine_from_native_kwarg(kwargs: T.Dict[str, T.Any]) -> MachineChoice:
native = kwargs.get('native', False) native = kwargs.get('native', False)
if not isinstance(native, bool): if not isinstance(native, bool):
raise InvalidArguments('Argument to "native" must be a boolean.') raise InvalidArguments('Argument to "native" must be a boolean.')

@ -14,18 +14,18 @@
import abc import abc
import os import os
import typing import typing as T
from . import mesonlib from . import mesonlib
if typing.TYPE_CHECKING: if T.TYPE_CHECKING:
from .coredata import OptionDictType from .coredata import OptionDictType
from .environment import Environment from .environment import Environment
class StaticLinker: class StaticLinker:
def __init__(self, exelist: typing.List[str]): def __init__(self, exelist: T.List[str]):
self.exelist = exelist self.exelist = exelist
def can_linker_accept_rsp(self) -> bool: def can_linker_accept_rsp(self) -> bool:
@ -34,55 +34,55 @@ class StaticLinker:
""" """
return mesonlib.is_windows() return mesonlib.is_windows()
def get_base_link_args(self, options: 'OptionDictType') -> typing.List[str]: def get_base_link_args(self, options: 'OptionDictType') -> T.List[str]:
"""Like compilers.get_base_link_args, but for the static linker.""" """Like compilers.get_base_link_args, but for the static linker."""
return [] return []
def get_exelist(self) -> typing.List[str]: def get_exelist(self) -> T.List[str]:
return self.exelist.copy() return self.exelist.copy()
def get_std_link_args(self) -> typing.List[str]: def get_std_link_args(self) -> T.List[str]:
return [] return []
def get_buildtype_linker_args(self, buildtype: str) -> typing.List[str]: def get_buildtype_linker_args(self, buildtype: str) -> T.List[str]:
return [] return []
def get_output_args(self, target: str) -> typing.List[str]: def get_output_args(self, target: str) -> T.List[str]:
return[] return[]
def get_coverage_link_args(self) -> typing.List[str]: def get_coverage_link_args(self) -> T.List[str]:
return [] return []
def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str, def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str,
rpath_paths: str, build_rpath: str, rpath_paths: str, build_rpath: str,
install_rpath: str) -> typing.List[str]: install_rpath: str) -> T.List[str]:
return [] return []
def thread_link_flags(self, env: 'Environment') -> typing.List[str]: def thread_link_flags(self, env: 'Environment') -> T.List[str]:
return [] return []
def openmp_flags(self) -> typing.List[str]: def openmp_flags(self) -> T.List[str]:
return [] return []
def get_option_link_args(self, options: 'OptionDictType') -> typing.List[str]: def get_option_link_args(self, options: 'OptionDictType') -> T.List[str]:
return [] return []
@classmethod @classmethod
def unix_args_to_native(cls, args: typing.List[str]) -> typing.List[str]: def unix_args_to_native(cls, args: T.List[str]) -> T.List[str]:
return args[:] return args[:]
@classmethod @classmethod
def native_args_to_unix(cls, args: typing.List[str]) -> typing.List[str]: def native_args_to_unix(cls, args: T.List[str]) -> T.List[str]:
return args[:] return args[:]
def get_link_debugfile_args(self, targetfile: str) -> typing.List[str]: def get_link_debugfile_args(self, targetfile: str) -> T.List[str]:
# Static libraries do not have PDB files # Static libraries do not have PDB files
return [] return []
def get_always_args(self) -> typing.List[str]: def get_always_args(self) -> T.List[str]:
return [] return []
def get_linker_always_args(self) -> typing.List[str]: def get_linker_always_args(self) -> T.List[str]:
return [] return []
@ -92,26 +92,26 @@ class VisualStudioLikeLinker:
def __init__(self, machine: str): def __init__(self, machine: str):
self.machine = machine self.machine = machine
def get_always_args(self) -> typing.List[str]: def get_always_args(self) -> T.List[str]:
return self.always_args.copy() return self.always_args.copy()
def get_linker_always_args(self) -> typing.List[str]: def get_linker_always_args(self) -> T.List[str]:
return self.always_args.copy() return self.always_args.copy()
def get_output_args(self, target: str) -> typing.List[str]: def get_output_args(self, target: str) -> T.List[str]:
args = [] # type: typing.List[str] args = [] # type: T.List[str]
if self.machine: if self.machine:
args += ['/MACHINE:' + self.machine] args += ['/MACHINE:' + self.machine]
args += ['/OUT:' + target] args += ['/OUT:' + target]
return args return args
@classmethod @classmethod
def unix_args_to_native(cls, args: typing.List[str]) -> typing.List[str]: def unix_args_to_native(cls, args: T.List[str]) -> T.List[str]:
from .compilers import VisualStudioCCompiler from .compilers import VisualStudioCCompiler
return VisualStudioCCompiler.unix_args_to_native(args) return VisualStudioCCompiler.unix_args_to_native(args)
@classmethod @classmethod
def native_args_to_unix(cls, args: typing.List[str]) -> typing.List[str]: def native_args_to_unix(cls, args: T.List[str]) -> T.List[str]:
from .compilers import VisualStudioCCompiler from .compilers import VisualStudioCCompiler
return VisualStudioCCompiler.native_args_to_unix(args) return VisualStudioCCompiler.native_args_to_unix(args)
@ -120,7 +120,7 @@ class VisualStudioLinker(VisualStudioLikeLinker, StaticLinker):
"""Microsoft's lib static linker.""" """Microsoft's lib static linker."""
def __init__(self, exelist: typing.List[str], machine: str): def __init__(self, exelist: T.List[str], machine: str):
StaticLinker.__init__(self, exelist) StaticLinker.__init__(self, exelist)
VisualStudioLikeLinker.__init__(self, machine) VisualStudioLikeLinker.__init__(self, machine)
@ -129,14 +129,14 @@ class IntelVisualStudioLinker(VisualStudioLikeLinker, StaticLinker):
"""Intel's xilib static linker.""" """Intel's xilib static linker."""
def __init__(self, exelist: typing.List[str], machine: str): def __init__(self, exelist: T.List[str], machine: str):
StaticLinker.__init__(self, exelist) StaticLinker.__init__(self, exelist)
VisualStudioLikeLinker.__init__(self, machine) VisualStudioLikeLinker.__init__(self, machine)
class ArLinker(StaticLinker): class ArLinker(StaticLinker):
def __init__(self, exelist: typing.List[str]): def __init__(self, exelist: T.List[str]):
super().__init__(exelist) super().__init__(exelist)
self.id = 'ar' self.id = 'ar'
pc, stdo = mesonlib.Popen_safe(self.exelist + ['-h'])[0:2] pc, stdo = mesonlib.Popen_safe(self.exelist + ['-h'])[0:2]
@ -146,16 +146,16 @@ class ArLinker(StaticLinker):
else: else:
self.std_args = ['csr'] self.std_args = ['csr']
def get_std_link_args(self) -> typing.List[str]: def get_std_link_args(self) -> T.List[str]:
return self.std_args return self.std_args
def get_output_args(self, target: str) -> typing.List[str]: def get_output_args(self, target: str) -> T.List[str]:
return [target] return [target]
class ArmarLinker(ArLinker): # lgtm [py/missing-call-to-init] class ArmarLinker(ArLinker): # lgtm [py/missing-call-to-init]
def __init__(self, exelist: typing.List[str]): def __init__(self, exelist: T.List[str]):
StaticLinker.__init__(self, exelist) StaticLinker.__init__(self, exelist)
self.id = 'armar' self.id = 'armar'
self.std_args = ['-csr'] self.std_args = ['-csr']
@ -166,18 +166,18 @@ class ArmarLinker(ArLinker): # lgtm [py/missing-call-to-init]
class DLinker(StaticLinker): class DLinker(StaticLinker):
def __init__(self, exelist: typing.List[str], arch: str): def __init__(self, exelist: T.List[str], arch: str):
super().__init__(exelist) super().__init__(exelist)
self.id = exelist[0] self.id = exelist[0]
self.arch = arch self.arch = arch
def get_std_link_args(self) -> typing.List[str]: def get_std_link_args(self) -> T.List[str]:
return ['-lib'] return ['-lib']
def get_output_args(self, target: str) -> typing.List[str]: def get_output_args(self, target: str) -> T.List[str]:
return ['-of=' + target] return ['-of=' + target]
def get_linker_always_args(self) -> typing.List[str]: def get_linker_always_args(self) -> T.List[str]:
if mesonlib.is_windows(): if mesonlib.is_windows():
if self.arch == 'x86_64': if self.arch == 'x86_64':
return ['-m64'] return ['-m64']
@ -189,21 +189,21 @@ class DLinker(StaticLinker):
class CcrxLinker(StaticLinker): class CcrxLinker(StaticLinker):
def __init__(self, exelist: typing.List[str]): def __init__(self, exelist: T.List[str]):
super().__init__(exelist) super().__init__(exelist)
self.id = 'rlink' self.id = 'rlink'
def can_linker_accept_rsp(self) -> bool: def can_linker_accept_rsp(self) -> bool:
return False return False
def get_output_args(self, target: str) -> typing.List[str]: def get_output_args(self, target: str) -> T.List[str]:
return ['-output=%s' % target] return ['-output=%s' % target]
def get_linker_always_args(self) -> typing.List[str]: def get_linker_always_args(self) -> T.List[str]:
return ['-nologo', '-form=library'] return ['-nologo', '-form=library']
def prepare_rpaths(raw_rpaths: str, build_dir: str, from_dir: str) -> typing.List[str]: def prepare_rpaths(raw_rpaths: str, build_dir: str, from_dir: str) -> T.List[str]:
# The rpaths we write must be relative if they point to the build dir, # The rpaths we write must be relative if they point to the build dir,
# because otherwise they have different length depending on the build # because otherwise they have different length depending on the build
# directory. This breaks reproducible builds. # directory. This breaks reproducible builds.
@ -212,7 +212,7 @@ def prepare_rpaths(raw_rpaths: str, build_dir: str, from_dir: str) -> typing.Lis
return ordered_rpaths return ordered_rpaths
def order_rpaths(rpath_list: typing.List[str]) -> typing.List[str]: def order_rpaths(rpath_list: T.List[str]) -> T.List[str]:
# We want rpaths that point inside our build dir to always override # We want rpaths that point inside our build dir to always override
# those pointing to other places in the file system. This is so built # those pointing to other places in the file system. This is so built
# binaries prefer our libraries to the ones that may lie somewhere # binaries prefer our libraries to the ones that may lie somewhere
@ -244,18 +244,18 @@ class DynamicLinker(metaclass=abc.ABCMeta):
'release': [], 'release': [],
'minsize': [], 'minsize': [],
'custom': [], 'custom': [],
} # type: typing.Dict[str, typing.List[str]] } # type: T.Dict[str, T.List[str]]
def _apply_prefix(self, arg: str) -> typing.List[str]: def _apply_prefix(self, arg: str) -> T.List[str]:
if self.prefix_arg is None: if self.prefix_arg is None:
return [arg] return [arg]
elif isinstance(self.prefix_arg, str): elif isinstance(self.prefix_arg, str):
return [self.prefix_arg + arg] return [self.prefix_arg + arg]
return self.prefix_arg + [arg] return self.prefix_arg + [arg]
def __init__(self, exelist: typing.List[str], for_machine: mesonlib.MachineChoice, def __init__(self, exelist: T.List[str], for_machine: mesonlib.MachineChoice,
id_: str, prefix_arg: typing.Union[str, typing.List[str]], id_: str, prefix_arg: T.Union[str, T.List[str]],
always_args: typing.List[str], *, version: str = 'unknown version'): always_args: T.List[str], *, version: str = 'unknown version'):
self.exelist = exelist self.exelist = exelist
self.for_machine = for_machine self.for_machine = for_machine
self.version = version self.version = version
@ -272,14 +272,14 @@ class DynamicLinker(metaclass=abc.ABCMeta):
def get_version_string(self) -> str: def get_version_string(self) -> str:
return '({} {})'.format(self.id, self.version) return '({} {})'.format(self.id, self.version)
def get_exelist(self) -> typing.List[str]: def get_exelist(self) -> T.List[str]:
return self.exelist.copy() return self.exelist.copy()
def get_accepts_rsp(self) -> bool: def get_accepts_rsp(self) -> bool:
# TODO: is it really a matter of is_windows or is it for_windows? # TODO: is it really a matter of is_windows or is it for_windows?
return mesonlib.is_windows() return mesonlib.is_windows()
def get_always_args(self) -> typing.List[str]: def get_always_args(self) -> T.List[str]:
return self.always_args.copy() return self.always_args.copy()
def get_lib_prefix(self) -> str: def get_lib_prefix(self) -> str:
@ -287,20 +287,20 @@ class DynamicLinker(metaclass=abc.ABCMeta):
# XXX: is use_ldflags a compiler or a linker attribute? # XXX: is use_ldflags a compiler or a linker attribute?
def get_args_from_envvars(self) -> typing.List[str]: def get_args_from_envvars(self) -> T.List[str]:
flags = os.environ.get('LDFLAGS') flags = os.environ.get('LDFLAGS')
if not flags: if not flags:
return [] return []
return mesonlib.split_args(flags) return mesonlib.split_args(flags)
def get_option_args(self, options: 'OptionDictType') -> typing.List[str]: def get_option_args(self, options: 'OptionDictType') -> T.List[str]:
return [] return []
def has_multi_arguments(self, args: typing.List[str], env: 'Environment') -> typing.Tuple[bool, bool]: def has_multi_arguments(self, args: T.List[str], env: 'Environment') -> T.Tuple[bool, bool]:
m = 'Language {} does not support has_multi_link_arguments.' m = 'Language {} does not support has_multi_link_arguments.'
raise mesonlib.EnvironmentException(m.format(self.id)) raise mesonlib.EnvironmentException(m.format(self.id))
def get_debugfile_args(self, targetfile: str) -> typing.List[str]: def get_debugfile_args(self, targetfile: str) -> T.List[str]:
"""Some compilers (MSVC) write debug into a separate file. """Some compilers (MSVC) write debug into a separate file.
This method takes the target object path and returns a list of This method takes the target object path and returns a list of
@ -309,67 +309,67 @@ class DynamicLinker(metaclass=abc.ABCMeta):
""" """
return [] return []
def get_std_shared_lib_args(self) -> typing.List[str]: def get_std_shared_lib_args(self) -> T.List[str]:
return [] return []
def get_std_shared_module_args(self, options: 'OptionDictType') -> typing.List[str]: def get_std_shared_module_args(self, options: 'OptionDictType') -> T.List[str]:
return self.get_std_shared_lib_args() return self.get_std_shared_lib_args()
def get_pie_args(self) -> typing.List[str]: def get_pie_args(self) -> T.List[str]:
# TODO: this really needs to take a boolean and return the args to # TODO: this really needs to take a boolean and return the args to
# disable pie, otherwise it only acts to enable pie if pie *isn't* the # disable pie, otherwise it only acts to enable pie if pie *isn't* the
# default. # default.
m = 'Linker {} does not support position-independent executable' m = 'Linker {} does not support position-independent executable'
raise mesonlib.EnvironmentException(m.format(self.id)) raise mesonlib.EnvironmentException(m.format(self.id))
def get_lto_args(self) -> typing.List[str]: def get_lto_args(self) -> T.List[str]:
return [] return []
def sanitizer_args(self, value: str) -> typing.List[str]: def sanitizer_args(self, value: str) -> T.List[str]:
return [] return []
def get_buildtype_args(self, buildtype: str) -> typing.List[str]: def get_buildtype_args(self, buildtype: str) -> T.List[str]:
# We can override these in children by just overriding the # We can override these in children by just overriding the
# _BUILDTYPE_ARGS value. # _BUILDTYPE_ARGS value.
return self._BUILDTYPE_ARGS[buildtype] return self._BUILDTYPE_ARGS[buildtype]
def get_asneeded_args(self) -> typing.List[str]: def get_asneeded_args(self) -> T.List[str]:
return [] return []
def get_link_whole_for(self, args: typing.List[str]) -> typing.List[str]: def get_link_whole_for(self, args: T.List[str]) -> T.List[str]:
raise mesonlib.EnvironmentException( raise mesonlib.EnvironmentException(
'Linker {} does not support link_whole'.format(self.id)) 'Linker {} does not support link_whole'.format(self.id))
def get_allow_undefined_args(self) -> typing.List[str]: def get_allow_undefined_args(self) -> T.List[str]:
raise mesonlib.EnvironmentException( raise mesonlib.EnvironmentException(
'Linker {} does not support allow undefined'.format(self.id)) 'Linker {} does not support allow undefined'.format(self.id))
@abc.abstractmethod @abc.abstractmethod
def get_output_args(self, outname: str) -> typing.List[str]: def get_output_args(self, outname: str) -> T.List[str]:
pass pass
def get_coverage_args(self) -> typing.List[str]: def get_coverage_args(self) -> T.List[str]:
m = "Linker {} doesn't implement coverage data generation.".format(self.id) m = "Linker {} doesn't implement coverage data generation.".format(self.id)
raise mesonlib.EnvironmentException(m) raise mesonlib.EnvironmentException(m)
@abc.abstractmethod @abc.abstractmethod
def get_search_args(self, dirname: str) -> typing.List[str]: def get_search_args(self, dirname: str) -> T.List[str]:
pass pass
def export_dynamic_args(self, env: 'Environment') -> typing.List[str]: def export_dynamic_args(self, env: 'Environment') -> T.List[str]:
return [] return []
def import_library_args(self, implibname: str) -> typing.List[str]: def import_library_args(self, implibname: str) -> T.List[str]:
"""The name of the outputted import library. """The name of the outputted import library.
This implementation is used only on Windows by compilers that use GNU ld This implementation is used only on Windows by compilers that use GNU ld
""" """
return [] return []
def thread_flags(self, env: 'Environment') -> typing.List[str]: def thread_flags(self, env: 'Environment') -> T.List[str]:
return [] return []
def no_undefined_args(self) -> typing.List[str]: def no_undefined_args(self) -> T.List[str]:
"""Arguments to error if there are any undefined symbols at link time. """Arguments to error if there are any undefined symbols at link time.
This is the inverse of get_allow_undefined_args(). This is the inverse of get_allow_undefined_args().
@ -380,24 +380,24 @@ class DynamicLinker(metaclass=abc.ABCMeta):
""" """
return [] return []
def fatal_warnings(self) -> typing.List[str]: def fatal_warnings(self) -> T.List[str]:
"""Arguments to make all warnings errors.""" """Arguments to make all warnings errors."""
return [] return []
def bitcode_args(self) -> typing.List[str]: def bitcode_args(self) -> T.List[str]:
raise mesonlib.MesonException('This linker does not support bitcode bundles') raise mesonlib.MesonException('This linker does not support bitcode bundles')
def get_debug_crt_args(self) -> typing.List[str]: def get_debug_crt_args(self) -> T.List[str]:
return [] return []
def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str, def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str,
rpath_paths: str, build_rpath: str, rpath_paths: str, build_rpath: str,
install_rpath: str) -> typing.List[str]: install_rpath: str) -> T.List[str]:
return [] return []
def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str, def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str,
suffix: str, soversion: str, darwin_versions: typing.Tuple[str, str], suffix: str, soversion: str, darwin_versions: T.Tuple[str, str],
is_shared_module: bool) -> typing.List[str]: is_shared_module: bool) -> T.List[str]:
return [] return []
@ -410,13 +410,13 @@ class PosixDynamicLinkerMixin:
GNU-like that it makes sense to split this out. GNU-like that it makes sense to split this out.
""" """
def get_output_args(self, outname: str) -> typing.List[str]: def get_output_args(self, outname: str) -> T.List[str]:
return ['-o', outname] return ['-o', outname]
def get_std_shared_lib_args(self) -> typing.List[str]: def get_std_shared_lib_args(self) -> T.List[str]:
return ['-shared'] return ['-shared']
def get_search_args(self, dirname: str) -> typing.List[str]: def get_search_args(self, dirname: str) -> T.List[str]:
return ['-L' + dirname] return ['-L' + dirname]
@ -435,61 +435,61 @@ class GnuLikeDynamicLinkerMixin:
'release': ['-O1'], 'release': ['-O1'],
'minsize': [], 'minsize': [],
'custom': [], 'custom': [],
} # type: typing.Dict[str, typing.List[str]] } # type: T.Dict[str, T.List[str]]
def get_buildtype_args(self, buildtype: str) -> typing.List[str]: def get_buildtype_args(self, buildtype: str) -> T.List[str]:
# We can override these in children by just overriding the # We can override these in children by just overriding the
# _BUILDTYPE_ARGS value. # _BUILDTYPE_ARGS value.
return mesonlib.listify([self._apply_prefix(a) for a in self._BUILDTYPE_ARGS[buildtype]]) return mesonlib.listify([self._apply_prefix(a) for a in self._BUILDTYPE_ARGS[buildtype]])
def get_pie_args(self) -> typing.List[str]: def get_pie_args(self) -> T.List[str]:
return ['-pie'] return ['-pie']
def get_asneeded_args(self) -> typing.List[str]: def get_asneeded_args(self) -> T.List[str]:
return self._apply_prefix('--as-needed') return self._apply_prefix('--as-needed')
def get_link_whole_for(self, args: typing.List[str]) -> typing.List[str]: def get_link_whole_for(self, args: T.List[str]) -> T.List[str]:
if not args: if not args:
return args return args
return self._apply_prefix('--whole-archive') + args + self._apply_prefix('--no-whole-archive') return self._apply_prefix('--whole-archive') + args + self._apply_prefix('--no-whole-archive')
def get_allow_undefined_args(self) -> typing.List[str]: def get_allow_undefined_args(self) -> T.List[str]:
return self._apply_prefix('--allow-shlib-undefined') return self._apply_prefix('--allow-shlib-undefined')
def get_lto_args(self) -> typing.List[str]: def get_lto_args(self) -> T.List[str]:
return ['-flto'] return ['-flto']
def sanitizer_args(self, value: str) -> typing.List[str]: def sanitizer_args(self, value: str) -> T.List[str]:
if value == 'none': if value == 'none':
return [] return []
return ['-fsanitize=' + value] return ['-fsanitize=' + value]
def get_coverage_args(self) -> typing.List[str]: def get_coverage_args(self) -> T.List[str]:
return ['--coverage'] return ['--coverage']
def export_dynamic_args(self, env: 'Environment') -> typing.List[str]: def export_dynamic_args(self, env: 'Environment') -> T.List[str]:
m = env.machines[self.for_machine] m = env.machines[self.for_machine]
if m.is_windows() or m.is_cygwin(): if m.is_windows() or m.is_cygwin():
return self._apply_prefix('--export-all-symbols') return self._apply_prefix('--export-all-symbols')
return self._apply_prefix('-export-dynamic') return self._apply_prefix('-export-dynamic')
def import_library_args(self, implibname: str) -> typing.List[str]: def import_library_args(self, implibname: str) -> T.List[str]:
return self._apply_prefix('--out-implib=' + implibname) return self._apply_prefix('--out-implib=' + implibname)
def thread_flags(self, env: 'Environment') -> typing.List[str]: def thread_flags(self, env: 'Environment') -> T.List[str]:
if env.machines[self.for_machine].is_haiku(): if env.machines[self.for_machine].is_haiku():
return [] return []
return ['-pthread'] return ['-pthread']
def no_undefined_args(self) -> typing.List[str]: def no_undefined_args(self) -> T.List[str]:
return self._apply_prefix('--no-undefined') return self._apply_prefix('--no-undefined')
def fatal_warnings(self) -> typing.List[str]: def fatal_warnings(self) -> T.List[str]:
return self._apply_prefix('--fatal-warnings') return self._apply_prefix('--fatal-warnings')
def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str, def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str,
suffix: str, soversion: str, darwin_versions: typing.Tuple[str, str], suffix: str, soversion: str, darwin_versions: T.Tuple[str, str],
is_shared_module: bool) -> typing.List[str]: is_shared_module: bool) -> T.List[str]:
m = env.machines[self.for_machine] m = env.machines[self.for_machine]
if m.is_windows() or m.is_cygwin(): if m.is_windows() or m.is_cygwin():
# For PE/COFF the soname argument has no effect # For PE/COFF the soname argument has no effect
@ -499,7 +499,7 @@ class GnuLikeDynamicLinkerMixin:
def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str, def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str,
rpath_paths: str, build_rpath: str, rpath_paths: str, build_rpath: str,
install_rpath: str) -> typing.List[str]: install_rpath: str) -> T.List[str]:
m = env.machines[self.for_machine] m = env.machines[self.for_machine]
if m.is_windows() or m.is_cygwin(): if m.is_windows() or m.is_cygwin():
return [] return []
@ -565,48 +565,48 @@ class AppleDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker):
"""Apple's ld implementation.""" """Apple's ld implementation."""
def get_asneeded_args(self) -> typing.List[str]: def get_asneeded_args(self) -> T.List[str]:
return self._apply_prefix('-dead_strip_dylibs') return self._apply_prefix('-dead_strip_dylibs')
def get_allow_undefined_args(self) -> typing.List[str]: def get_allow_undefined_args(self) -> T.List[str]:
return self._apply_prefix('-undefined,dynamic_lookup') return self._apply_prefix('-undefined,dynamic_lookup')
def get_std_shared_module_args(self, options: 'OptionDictType') -> typing.List[str]: def get_std_shared_module_args(self, options: 'OptionDictType') -> T.List[str]:
return ['-bundle'] + self._apply_prefix('-undefined,dynamic_lookup') return ['-bundle'] + self._apply_prefix('-undefined,dynamic_lookup')
def get_pie_args(self) -> typing.List[str]: def get_pie_args(self) -> T.List[str]:
return ['-pie'] return ['-pie']
def get_link_whole_for(self, args: typing.List[str]) -> typing.List[str]: def get_link_whole_for(self, args: T.List[str]) -> T.List[str]:
result = [] # type: typing.List[str] result = [] # type: T.List[str]
for a in args: for a in args:
result.extend(self._apply_prefix('-force_load')) result.extend(self._apply_prefix('-force_load'))
result.append(a) result.append(a)
return result return result
def get_coverage_args(self) -> typing.List[str]: def get_coverage_args(self) -> T.List[str]:
return ['--coverage'] return ['--coverage']
def sanitizer_args(self, value: str) -> typing.List[str]: def sanitizer_args(self, value: str) -> T.List[str]:
if value == 'none': if value == 'none':
return [] return []
return ['-fsanitize=' + value] return ['-fsanitize=' + value]
def no_undefined_args(self) -> typing.List[str]: def no_undefined_args(self) -> T.List[str]:
return self._apply_prefix('-undefined,error') return self._apply_prefix('-undefined,error')
def get_always_args(self) -> typing.List[str]: def get_always_args(self) -> T.List[str]:
return self._apply_prefix('-headerpad_max_install_names') + super().get_always_args() return self._apply_prefix('-headerpad_max_install_names') + super().get_always_args()
def bitcode_args(self) -> typing.List[str]: def bitcode_args(self) -> T.List[str]:
return self._apply_prefix('-bitcode_bundle') return self._apply_prefix('-bitcode_bundle')
def fatal_warnings(self) -> typing.List[str]: def fatal_warnings(self) -> T.List[str]:
return self._apply_prefix('-fatal_warnings') return self._apply_prefix('-fatal_warnings')
def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str, def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str,
suffix: str, soversion: str, darwin_versions: typing.Tuple[str, str], suffix: str, soversion: str, darwin_versions: T.Tuple[str, str],
is_shared_module: bool) -> typing.List[str]: is_shared_module: bool) -> T.List[str]:
if is_shared_module: if is_shared_module:
return [] return []
install_name = ['@rpath/', prefix, shlib_name] install_name = ['@rpath/', prefix, shlib_name]
@ -621,7 +621,7 @@ class AppleDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker):
def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str, def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str,
rpath_paths: str, build_rpath: str, rpath_paths: str, build_rpath: str,
install_rpath: str) -> typing.List[str]: install_rpath: str) -> T.List[str]:
if not rpath_paths and not install_rpath and not build_rpath: if not rpath_paths and not install_rpath and not build_rpath:
return [] return []
# Ensure that there is enough space for install_name_tool in-place # Ensure that there is enough space for install_name_tool in-place
@ -672,21 +672,21 @@ class CcrxDynamicLinker(DynamicLinker):
def get_lib_prefix(self) -> str: def get_lib_prefix(self) -> str:
return '-lib=' return '-lib='
def get_std_shared_lib_args(self) -> typing.List[str]: def get_std_shared_lib_args(self) -> T.List[str]:
return [] return []
def get_output_args(self, outputname: str) -> typing.List[str]: def get_output_args(self, outputname: str) -> T.List[str]:
return ['-output=%s' % outputname] return ['-output=%s' % outputname]
def get_search_args(self, dirname: str) -> 'typing.NoReturn': def get_search_args(self, dirname: str) -> 'T.NoReturn':
raise EnvironmentError('rlink.exe does not have a search dir argument') raise EnvironmentError('rlink.exe does not have a search dir argument')
def get_allow_undefined_args(self) -> typing.List[str]: def get_allow_undefined_args(self) -> T.List[str]:
return [] return []
def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str, def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str,
suffix: str, soversion: str, darwin_versions: typing.Tuple[str, str], suffix: str, soversion: str, darwin_versions: T.Tuple[str, str],
is_shared_module: bool) -> typing.List[str]: is_shared_module: bool) -> T.List[str]:
return [] return []
@ -702,10 +702,10 @@ class ArmDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker):
def get_accepts_rsp(self) -> bool: def get_accepts_rsp(self) -> bool:
return False return False
def get_std_shared_lib_args(self) -> 'typing.NoReturn': def get_std_shared_lib_args(self) -> 'T.NoReturn':
raise mesonlib.MesonException('The Arm Linkers do not support shared libraries') raise mesonlib.MesonException('The Arm Linkers do not support shared libraries')
def get_allow_undefined_args(self) -> typing.List[str]: def get_allow_undefined_args(self) -> T.List[str]:
return [] return []
@ -717,10 +717,10 @@ class ArmClangDynamicLinker(ArmDynamicLinker):
extends a few things as needed. extends a few things as needed.
""" """
def export_dynamic_args(self, env: 'Environment') -> typing.List[str]: def export_dynamic_args(self, env: 'Environment') -> T.List[str]:
return ['--export_dynamic'] return ['--export_dynamic']
def import_library_args(self, implibname: str) -> typing.List[str]: def import_library_args(self, implibname: str) -> T.List[str]:
return ['--symdefs=' + implibname] return ['--symdefs=' + implibname]
@ -728,15 +728,15 @@ class PGIDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker):
"""PGI linker.""" """PGI linker."""
def get_allow_undefined_args(self) -> typing.List[str]: def get_allow_undefined_args(self) -> T.List[str]:
return [] return []
def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str, def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str,
suffix: str, soversion: str, darwin_versions: typing.Tuple[str, str], suffix: str, soversion: str, darwin_versions: T.Tuple[str, str],
is_shared_module: bool) -> typing.List[str]: is_shared_module: bool) -> T.List[str]:
return [] return []
def get_std_shared_lib_args(self) -> typing.List[str]: def get_std_shared_lib_args(self) -> T.List[str]:
# PGI -shared is Linux only. # PGI -shared is Linux only.
if mesonlib.is_windows(): if mesonlib.is_windows():
return ['-Bdynamic', '-Mmakedll'] return ['-Bdynamic', '-Mmakedll']
@ -746,22 +746,22 @@ class PGIDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker):
def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str, def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str,
rpath_paths: str, build_rpath: str, rpath_paths: str, build_rpath: str,
install_rpath: str) -> typing.List[str]: install_rpath: str) -> T.List[str]:
if not env.machines[self.for_machine].is_windows(): if not env.machines[self.for_machine].is_windows():
return ['-R' + os.path.join(build_dir, p) for p in rpath_paths] return ['-R' + os.path.join(build_dir, p) for p in rpath_paths]
return [] return []
class PGIStaticLinker(StaticLinker): class PGIStaticLinker(StaticLinker):
def __init__(self, exelist: typing.List[str]): def __init__(self, exelist: T.List[str]):
super().__init__(exelist) super().__init__(exelist)
self.id = 'ar' self.id = 'ar'
self.std_args = ['-r'] self.std_args = ['-r']
def get_std_link_args(self) -> typing.List[str]: def get_std_link_args(self) -> T.List[str]:
return self.std_args return self.std_args
def get_output_args(self, target: str) -> typing.List[str]: def get_output_args(self, target: str) -> T.List[str]:
return [target] return [target]
class VisualStudioLikeLinkerMixin: class VisualStudioLikeLinkerMixin:
@ -775,7 +775,7 @@ class VisualStudioLikeLinkerMixin:
'release': ['/OPT:REF'], 'release': ['/OPT:REF'],
'minsize': ['/INCREMENTAL:NO', '/OPT:REF'], 'minsize': ['/INCREMENTAL:NO', '/OPT:REF'],
'custom': [], 'custom': [],
} # type: typing.Dict[str, typing.List[str]] } # type: T.Dict[str, T.List[str]]
def __init__(self, *args, direct: bool = True, machine: str = 'x86', **kwargs): def __init__(self, *args, direct: bool = True, machine: str = 'x86', **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
@ -784,7 +784,7 @@ class VisualStudioLikeLinkerMixin:
def invoked_by_compiler(self) -> bool: def invoked_by_compiler(self) -> bool:
return not self.direct return not self.direct
def get_debug_crt_args(self) -> typing.List[str]: def get_debug_crt_args(self) -> T.List[str]:
"""Arguments needed to select a debug crt for the linker. """Arguments needed to select a debug crt for the linker.
Sometimes we need to manually select the CRT (C runtime) to use with Sometimes we need to manually select the CRT (C runtime) to use with
@ -794,37 +794,37 @@ class VisualStudioLikeLinkerMixin:
""" """
return self._apply_prefix('/MDd') return self._apply_prefix('/MDd')
def get_output_args(self, outputname: str) -> typing.List[str]: def get_output_args(self, outputname: str) -> T.List[str]:
return self._apply_prefix('/MACHINE:' + self.machine) + self._apply_prefix('/OUT:' + outputname) return self._apply_prefix('/MACHINE:' + self.machine) + self._apply_prefix('/OUT:' + outputname)
def get_always_args(self) -> typing.List[str]: def get_always_args(self) -> T.List[str]:
return self._apply_prefix('/nologo') + super().get_always_args() return self._apply_prefix('/nologo') + super().get_always_args()
def get_search_args(self, dirname: str) -> typing.List[str]: def get_search_args(self, dirname: str) -> T.List[str]:
return self._apply_prefix('/LIBPATH:' + dirname) return self._apply_prefix('/LIBPATH:' + dirname)
def get_std_shared_lib_args(self) -> typing.List[str]: def get_std_shared_lib_args(self) -> T.List[str]:
return self._apply_prefix('/DLL') return self._apply_prefix('/DLL')
def get_debugfile_args(self, targetfile: str) -> typing.List[str]: def get_debugfile_args(self, targetfile: str) -> T.List[str]:
pdbarr = targetfile.split('.')[:-1] pdbarr = targetfile.split('.')[:-1]
pdbarr += ['pdb'] pdbarr += ['pdb']
return self._apply_prefix('/DEBUG') + self._apply_prefix('/PDB:' + '.'.join(pdbarr)) return self._apply_prefix('/DEBUG') + self._apply_prefix('/PDB:' + '.'.join(pdbarr))
def get_link_whole_for(self, args: typing.List[str]) -> typing.List[str]: def get_link_whole_for(self, args: T.List[str]) -> T.List[str]:
# Only since VS2015 # Only since VS2015
args = mesonlib.listify(args) args = mesonlib.listify(args)
l = [] # typing.List[str] l = [] # T.List[str]
for a in args: for a in args:
l.extend(self._apply_prefix('/WHOLEARCHIVE:' + a)) l.extend(self._apply_prefix('/WHOLEARCHIVE:' + a))
return l return l
def get_allow_undefined_args(self) -> typing.List[str]: def get_allow_undefined_args(self) -> T.List[str]:
return [] return []
def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str, def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str,
suffix: str, soversion: str, darwin_versions: typing.Tuple[str, str], suffix: str, soversion: str, darwin_versions: T.Tuple[str, str],
is_shared_module: bool) -> typing.List[str]: is_shared_module: bool) -> T.List[str]:
return [] return []
@ -832,9 +832,9 @@ class MSVCDynamicLinker(VisualStudioLikeLinkerMixin, DynamicLinker):
"""Microsoft's Link.exe.""" """Microsoft's Link.exe."""
def __init__(self, for_machine: mesonlib.MachineChoice, always_args: typing.List[str], *, def __init__(self, for_machine: mesonlib.MachineChoice, always_args: T.List[str], *,
exelist: typing.Optional[typing.List[str]] = None, exelist: T.Optional[T.List[str]] = None,
prefix: typing.Union[str, typing.List[str]] = '', prefix: T.Union[str, T.List[str]] = '',
machine: str = 'x86', version: str = 'unknown version', machine: str = 'x86', version: str = 'unknown version',
direct: bool = True): direct: bool = True):
super().__init__(exelist or ['link.exe'], for_machine, 'link', super().__init__(exelist or ['link.exe'], for_machine, 'link',
@ -845,9 +845,9 @@ class ClangClDynamicLinker(VisualStudioLikeLinkerMixin, DynamicLinker):
"""Clang's lld-link.exe.""" """Clang's lld-link.exe."""
def __init__(self, for_machine: mesonlib.MachineChoice, always_args: typing.List[str], *, def __init__(self, for_machine: mesonlib.MachineChoice, always_args: T.List[str], *,
exelist: typing.Optional[typing.List[str]] = None, exelist: T.Optional[T.List[str]] = None,
prefix: typing.Union[str, typing.List[str]] = '', prefix: T.Union[str, T.List[str]] = '',
machine: str = 'x86', version: str = 'unknown version', machine: str = 'x86', version: str = 'unknown version',
direct: bool = True): direct: bool = True):
super().__init__(exelist or ['lld-link.exe'], for_machine, 'lld-link', super().__init__(exelist or ['lld-link.exe'], for_machine, 'lld-link',
@ -858,7 +858,7 @@ class XilinkDynamicLinker(VisualStudioLikeLinkerMixin, DynamicLinker):
"""Intel's Xilink.exe.""" """Intel's Xilink.exe."""
def __init__(self, for_machine: mesonlib.MachineChoice, always_args: typing.List[str], def __init__(self, for_machine: mesonlib.MachineChoice, always_args: T.List[str],
*, version: str = 'unknown version'): *, version: str = 'unknown version'):
super().__init__(['xilink.exe'], for_machine, 'xilink', '', always_args, version=version) super().__init__(['xilink.exe'], for_machine, 'xilink', '', always_args, version=version)
@ -867,23 +867,23 @@ class SolarisDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker):
"""Sys-V derived linker used on Solaris and OpenSolaris.""" """Sys-V derived linker used on Solaris and OpenSolaris."""
def get_link_whole_for(self, args: typing.List[str]) -> typing.List[str]: def get_link_whole_for(self, args: T.List[str]) -> T.List[str]:
if not args: if not args:
return args return args
return self._apply_prefix('--whole-archive') + args + self._apply_prefix('--no-whole-archive') return self._apply_prefix('--whole-archive') + args + self._apply_prefix('--no-whole-archive')
def no_undefined_args(self) -> typing.List[str]: def no_undefined_args(self) -> T.List[str]:
return ['-z', 'defs'] return ['-z', 'defs']
def get_allow_undefined_args(self) -> typing.List[str]: def get_allow_undefined_args(self) -> T.List[str]:
return ['-z', 'nodefs'] return ['-z', 'nodefs']
def fatal_warnings(self) -> typing.List[str]: def fatal_warnings(self) -> T.List[str]:
return ['-z', 'fatal-warnings'] return ['-z', 'fatal-warnings']
def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str, def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str,
rpath_paths: str, build_rpath: str, rpath_paths: str, build_rpath: str,
install_rpath: str) -> typing.List[str]: install_rpath: str) -> T.List[str]:
if not rpath_paths and not install_rpath and not build_rpath: if not rpath_paths and not install_rpath and not build_rpath:
return [] return []
processed_rpaths = prepare_rpaths(rpath_paths, build_dir, from_dir) processed_rpaths = prepare_rpaths(rpath_paths, build_dir, from_dir)
@ -903,8 +903,8 @@ class SolarisDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker):
return self._apply_prefix('-rpath,{}'.format(paths)) return self._apply_prefix('-rpath,{}'.format(paths))
def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str, def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str,
suffix: str, soversion: str, darwin_versions: typing.Tuple[str, str], suffix: str, soversion: str, darwin_versions: T.Tuple[str, str],
is_shared_module: bool) -> typing.List[str]: is_shared_module: bool) -> T.List[str]:
sostr = '' if soversion is None else '.' + soversion sostr = '' if soversion is None else '.' + soversion
return self._apply_prefix('-soname,{}{}.{}{}'.format(prefix, shlib_name, suffix, sostr)) return self._apply_prefix('-soname,{}{}.{}{}'.format(prefix, shlib_name, suffix, sostr))
@ -919,7 +919,7 @@ class OptlinkDynamicLinker(VisualStudioLikeLinkerMixin, DynamicLinker):
# implementations. # implementations.
super().__init__(['optlink.exe'], for_machine, 'optlink', '', [], version=version) super().__init__(['optlink.exe'], for_machine, 'optlink', '', [], version=version)
def get_allow_undefined_args(self) -> typing.List[str]: def get_allow_undefined_args(self) -> T.List[str]:
return [] return []
class CudaLinker(PosixDynamicLinkerMixin, DynamicLinker): class CudaLinker(PosixDynamicLinkerMixin, DynamicLinker):
@ -956,13 +956,13 @@ class CudaLinker(PosixDynamicLinkerMixin, DynamicLinker):
from .compilers import CudaCompiler from .compilers import CudaCompiler
return CudaCompiler.LINKER_PREFIX return CudaCompiler.LINKER_PREFIX
def fatal_warnings(self) -> typing.List[str]: def fatal_warnings(self) -> T.List[str]:
return ['--warning-as-error'] return ['--warning-as-error']
def get_allow_undefined_args(self) -> typing.List[str]: def get_allow_undefined_args(self) -> T.List[str]:
return [] return []
def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str, def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str,
suffix: str, soversion: str, darwin_versions: typing.Tuple[str, str], suffix: str, soversion: str, darwin_versions: T.Tuple[str, str],
is_shared_module: bool) -> typing.List[str]: is_shared_module: bool) -> T.List[str]:
return [] return []

@ -22,13 +22,13 @@ import collections
from enum import Enum from enum import Enum
from functools import lru_cache, update_wrapper from functools import lru_cache, update_wrapper
from itertools import tee, filterfalse from itertools import tee, filterfalse
import typing import typing as T
import uuid import uuid
from mesonbuild import mlog from mesonbuild import mlog
_T = typing.TypeVar('_T') _T = T.TypeVar('_T')
_U = typing.TypeVar('_U') _U = T.TypeVar('_U')
have_fcntl = False have_fcntl = False
have_msvcrt = False have_msvcrt = False
@ -260,7 +260,7 @@ class File:
def endswith(self, ending: str) -> bool: def endswith(self, ending: str) -> bool:
return self.fname.endswith(ending) return self.fname.endswith(ending)
def split(self, s: str) -> typing.List[str]: def split(self, s: str) -> T.List[str]:
return self.fname.split(s) return self.fname.split(s)
def __eq__(self, other) -> bool: def __eq__(self, other) -> bool:
@ -331,7 +331,7 @@ class MachineChoice(OrderedEnum):
return PerMachine('build.', '')[self] return PerMachine('build.', '')[self]
class PerMachine(typing.Generic[_T]): class PerMachine(T.Generic[_T]):
def __init__(self, build: _T, host: _T): def __init__(self, build: _T, host: _T):
self.build = build self.build = build
self.host = host self.host = host
@ -345,14 +345,14 @@ class PerMachine(typing.Generic[_T]):
def __setitem__(self, machine: MachineChoice, val: _T) -> None: def __setitem__(self, machine: MachineChoice, val: _T) -> None:
setattr(self, machine.get_lower_case_name(), val) setattr(self, machine.get_lower_case_name(), val)
def miss_defaulting(self) -> "PerMachineDefaultable[typing.Optional[_T]]": def miss_defaulting(self) -> "PerMachineDefaultable[T.Optional[_T]]":
"""Unset definition duplicated from their previous to None """Unset definition duplicated from their previous to None
This is the inverse of ''default_missing''. By removing defaulted This is the inverse of ''default_missing''. By removing defaulted
machines, we can elaborate the original and then redefault them and thus machines, we can elaborate the original and then redefault them and thus
avoid repeating the elaboration explicitly. avoid repeating the elaboration explicitly.
""" """
unfreeze = PerMachineDefaultable() # type: PerMachineDefaultable[typing.Optional[_T]] unfreeze = PerMachineDefaultable() # type: PerMachineDefaultable[T.Optional[_T]]
unfreeze.build = self.build unfreeze.build = self.build
unfreeze.host = self.host unfreeze.host = self.host
if unfreeze.host == unfreeze.build: if unfreeze.host == unfreeze.build:
@ -371,14 +371,14 @@ class PerThreeMachine(PerMachine[_T]):
super().__init__(build, host) super().__init__(build, host)
self.target = target self.target = target
def miss_defaulting(self) -> "PerThreeMachineDefaultable[typing.Optional[_T]]": def miss_defaulting(self) -> "PerThreeMachineDefaultable[T.Optional[_T]]":
"""Unset definition duplicated from their previous to None """Unset definition duplicated from their previous to None
This is the inverse of ''default_missing''. By removing defaulted This is the inverse of ''default_missing''. By removing defaulted
machines, we can elaborate the original and then redefault them and thus machines, we can elaborate the original and then redefault them and thus
avoid repeating the elaboration explicitly. avoid repeating the elaboration explicitly.
""" """
unfreeze = PerThreeMachineDefaultable() # type: PerThreeMachineDefaultable[typing.Optional[_T]] unfreeze = PerThreeMachineDefaultable() # type: PerThreeMachineDefaultable[T.Optional[_T]]
unfreeze.build = self.build unfreeze.build = self.build
unfreeze.host = self.host unfreeze.host = self.host
unfreeze.target = self.target unfreeze.target = self.target
@ -391,13 +391,13 @@ class PerThreeMachine(PerMachine[_T]):
def matches_build_machine(self, machine: MachineChoice) -> bool: def matches_build_machine(self, machine: MachineChoice) -> bool:
return self.build == self[machine] return self.build == self[machine]
class PerMachineDefaultable(PerMachine[typing.Optional[_T]]): class PerMachineDefaultable(PerMachine[T.Optional[_T]]):
"""Extends `PerMachine` with the ability to default from `None`s. """Extends `PerMachine` with the ability to default from `None`s.
""" """
def __init__(self) -> None: def __init__(self) -> None:
super().__init__(None, None) super().__init__(None, None)
def default_missing(self) -> "PerMachine[typing.Optional[_T]]": def default_missing(self) -> "PerMachine[T.Optional[_T]]":
"""Default host to build """Default host to build
This allows just specifying nothing in the native case, and just host in the This allows just specifying nothing in the native case, and just host in the
@ -409,13 +409,13 @@ class PerMachineDefaultable(PerMachine[typing.Optional[_T]]):
return freeze return freeze
class PerThreeMachineDefaultable(PerMachineDefaultable, PerThreeMachine[typing.Optional[_T]]): class PerThreeMachineDefaultable(PerMachineDefaultable, PerThreeMachine[T.Optional[_T]]):
"""Extends `PerThreeMachine` with the ability to default from `None`s. """Extends `PerThreeMachine` with the ability to default from `None`s.
""" """
def __init__(self) -> None: def __init__(self) -> None:
PerThreeMachine.__init__(self, None, None, None) PerThreeMachine.__init__(self, None, None, None)
def default_missing(self) -> "PerThreeMachine[typing.Optional[_T]]": def default_missing(self) -> "PerThreeMachine[T.Optional[_T]]":
"""Default host to build and target to host. """Default host to build and target to host.
This allows just specifying nothing in the native case, just host in the This allows just specifying nothing in the native case, just host in the
@ -467,7 +467,7 @@ def is_netbsd() -> bool:
def is_freebsd() -> bool: def is_freebsd() -> bool:
return platform.system().lower() == 'freebsd' return platform.system().lower() == 'freebsd'
def exe_exists(arglist: typing.List[str]) -> bool: def exe_exists(arglist: T.List[str]) -> bool:
try: try:
if subprocess.run(arglist, timeout=10).returncode == 0: if subprocess.run(arglist, timeout=10).returncode == 0:
return True return True
@ -578,7 +578,7 @@ class Version:
# otherwise, the version with a suffix remaining is greater # otherwise, the version with a suffix remaining is greater
return comparator(len(self._v), len(other._v)) return comparator(len(self._v), len(other._v))
def _version_extract_cmpop(vstr2: str) -> typing.Tuple[typing.Callable[[typing.Any, typing.Any], bool], str]: def _version_extract_cmpop(vstr2: str) -> T.Tuple[T.Callable[[T.Any, T.Any], bool], str]:
if vstr2.startswith('>='): if vstr2.startswith('>='):
cmpop = operator.ge cmpop = operator.ge
vstr2 = vstr2[2:] vstr2 = vstr2[2:]
@ -686,7 +686,7 @@ def default_libexecdir():
def default_prefix(): def default_prefix():
return 'c:/' if is_windows() else '/usr/local' return 'c:/' if is_windows() else '/usr/local'
def get_library_dirs() -> typing.List[str]: def get_library_dirs() -> T.List[str]:
if is_windows(): if is_windows():
return ['C:/mingw/lib'] # TODO: get programmatically return ['C:/mingw/lib'] # TODO: get programmatically
if is_osx(): if is_osx():
@ -770,7 +770,7 @@ if is_windows():
result += (num_backslashes * 2) * '\\' + '"' result += (num_backslashes * 2) * '\\' + '"'
return result return result
def split_args(cmd: typing.Sequence[str]) -> typing.List[str]: def split_args(cmd: T.Sequence[str]) -> T.List[str]:
result = [] result = []
arg = '' arg = ''
num_backslashes = 0 num_backslashes = 0
@ -976,9 +976,9 @@ def replace_if_different(dst, dst_tmp):
else: else:
os.unlink(dst_tmp) os.unlink(dst_tmp)
def listify(item: typing.Any, def listify(item: T.Any,
flatten: bool = True, flatten: bool = True,
unholder: bool = False) -> typing.List[typing.Any]: unholder: bool = False) -> T.List[T.Any]:
''' '''
Returns a list with all args embedded in a list if they are not a list. Returns a list with all args embedded in a list if they are not a list.
This function preserves order. This function preserves order.
@ -1018,14 +1018,14 @@ def extract_as_list(dict_object, *keys, pop=False, **kwargs):
result.append(listify(fetch(key, []), **kwargs)) result.append(listify(fetch(key, []), **kwargs))
return result return result
def typeslistify(item: 'typing.Union[_T, typing.List[_T]]', def typeslistify(item: 'T.Union[_T, T.List[_T]]',
types: 'typing.Union[typing.Type[_T], typing.Tuple[typing.Type[_T]]]') -> typing.List[_T]: types: 'T.Union[T.Type[_T], T.Tuple[T.Type[_T]]]') -> T.List[_T]:
''' '''
Ensure that type(@item) is one of @types or a Ensure that type(@item) is one of @types or a
list of items all of which are of type @types list of items all of which are of type @types
''' '''
if isinstance(item, types): if isinstance(item, types):
item = typing.cast(typing.List[_T], [item]) item = T.cast(T.List[_T], [item])
if not isinstance(item, list): if not isinstance(item, list):
raise MesonException('Item must be a list or one of {!r}'.format(types)) raise MesonException('Item must be a list or one of {!r}'.format(types))
for i in item: for i in item:
@ -1033,7 +1033,7 @@ def typeslistify(item: 'typing.Union[_T, typing.List[_T]]',
raise MesonException('List item must be one of {!r}'.format(types)) raise MesonException('List item must be one of {!r}'.format(types))
return item return item
def stringlistify(item: typing.Union[str, typing.List[str]]) -> typing.List[str]: def stringlistify(item: T.Union[str, T.List[str]]) -> T.List[str]:
return typeslistify(item, str) return typeslistify(item, str)
def expand_arguments(args): def expand_arguments(args):
@ -1060,10 +1060,10 @@ def partition(pred, iterable):
t1, t2 = tee(iterable) t1, t2 = tee(iterable)
return filterfalse(pred, t1), filter(pred, t2) return filterfalse(pred, t1), filter(pred, t2)
def Popen_safe(args: typing.List[str], write: typing.Optional[str] = None, def Popen_safe(args: T.List[str], write: T.Optional[str] = None,
stdout: typing.Union[typing.BinaryIO, int] = subprocess.PIPE, stdout: T.Union[T.BinaryIO, int] = subprocess.PIPE,
stderr: typing.Union[typing.BinaryIO, int] = subprocess.PIPE, stderr: T.Union[T.BinaryIO, int] = subprocess.PIPE,
**kwargs: typing.Any) -> typing.Tuple[subprocess.Popen, str, str]: **kwargs: T.Any) -> T.Tuple[subprocess.Popen, str, str]:
import locale import locale
encoding = locale.getpreferredencoding() encoding = locale.getpreferredencoding()
if sys.version_info < (3, 6) or not sys.stdout.encoding or encoding.upper() != 'UTF-8': if sys.version_info < (3, 6) or not sys.stdout.encoding or encoding.upper() != 'UTF-8':
@ -1073,13 +1073,13 @@ def Popen_safe(args: typing.List[str], write: typing.Optional[str] = None,
o, e = p.communicate(write) o, e = p.communicate(write)
return p, o, e return p, o, e
def Popen_safe_legacy(args: typing.List[str], write: typing.Optional[str] = None, def Popen_safe_legacy(args: T.List[str], write: T.Optional[str] = None,
stdout: typing.Union[typing.BinaryIO, int] = subprocess.PIPE, stdout: T.Union[T.BinaryIO, int] = subprocess.PIPE,
stderr: typing.Union[typing.BinaryIO, int] = subprocess.PIPE, stderr: T.Union[T.BinaryIO, int] = subprocess.PIPE,
**kwargs: typing.Any) -> typing.Tuple[subprocess.Popen, str, str]: **kwargs: T.Any) -> T.Tuple[subprocess.Popen, str, str]:
p = subprocess.Popen(args, universal_newlines=False, close_fds=False, p = subprocess.Popen(args, universal_newlines=False, close_fds=False,
stdout=stdout, stderr=stderr, **kwargs) stdout=stdout, stderr=stderr, **kwargs)
input_ = None # type: typing.Optional[bytes] input_ = None # type: T.Optional[bytes]
if write is not None: if write is not None:
input_ = write.encode('utf-8') input_ = write.encode('utf-8')
o, e = p.communicate(input_) o, e = p.communicate(input_)
@ -1327,7 +1327,7 @@ def detect_subprojects(spdir_name, current_dir='', result=None):
def get_error_location_string(fname: str, lineno: str) -> str: def get_error_location_string(fname: str, lineno: str) -> str:
return '{}:{}:'.format(fname, lineno) return '{}:{}:'.format(fname, lineno)
def substring_is_in_list(substr: str, strlist: typing.List[str]) -> bool: def substring_is_in_list(substr: str, strlist: T.List[str]) -> bool:
for s in strlist: for s in strlist:
if substr in s: if substr in s:
return True return True

@ -26,7 +26,7 @@ from .ast import IntrospectionInterpreter, build_target_functions, AstConditionL
from . import mlog from . import mlog
from .backend import backends from .backend import backends
from .mparser import FunctionNode, ArrayNode, ArgumentNode, StringNode from .mparser import FunctionNode, ArrayNode, ArgumentNode, StringNode
from typing import Any, Callable, Dict, List, Optional, Sequence, Tuple, Union import typing as T
import os import os
import pathlib import pathlib
@ -36,22 +36,22 @@ def get_meson_info_file(info_dir: str) -> str:
def get_meson_introspection_version() -> str: def get_meson_introspection_version() -> str:
return '1.0.0' return '1.0.0'
def get_meson_introspection_required_version() -> List[str]: def get_meson_introspection_required_version() -> T.List[str]:
return ['>=1.0', '<2.0'] return ['>=1.0', '<2.0']
class IntroCommand: class IntroCommand:
def __init__(self, def __init__(self,
desc: str, desc: str,
func: Optional[Callable[[], Union[dict, list]]] = None, func: T.Optional[T.Callable[[], T.Union[dict, list]]] = None,
no_bd: Optional[Callable[[IntrospectionInterpreter], Union[dict, list]]] = None) -> None: no_bd: T.Optional[T.Callable[[IntrospectionInterpreter], T.Union[dict, list]]] = None) -> None:
self.desc = desc + '.' self.desc = desc + '.'
self.func = func self.func = func
self.no_bd = no_bd self.no_bd = no_bd
def get_meson_introspection_types(coredata: Optional[cdata.CoreData] = None, def get_meson_introspection_types(coredata: T.Optional[cdata.CoreData] = None,
builddata: Optional[build.Build] = None, builddata: T.Optional[build.Build] = None,
backend: Optional[backends.Backend] = None, backend: T.Optional[backends.Backend] = None,
sourcedir: Optional[str] = None) -> Dict[str, IntroCommand]: sourcedir: T.Optional[str] = None) -> T.Dict[str, IntroCommand]:
if backend and builddata: if backend and builddata:
benchmarkdata = backend.create_test_serialisation(builddata.get_benchmarks()) benchmarkdata = backend.create_test_serialisation(builddata.get_benchmarks())
testdata = backend.create_test_serialisation(builddata.get_tests()) testdata = backend.create_test_serialisation(builddata.get_tests())
@ -60,15 +60,15 @@ def get_meson_introspection_types(coredata: Optional[cdata.CoreData] = None,
benchmarkdata = testdata = installdata = None benchmarkdata = testdata = installdata = None
return { return {
'benchmarks': IntroCommand('List all benchmarks', func=lambda: list_benchmarks(benchmarkdata)), 'benchmarks': IntroCommand('T.List all benchmarks', func=lambda: list_benchmarks(benchmarkdata)),
'buildoptions': IntroCommand('List all build options', func=lambda: list_buildoptions(coredata), no_bd=list_buildoptions_from_source), 'buildoptions': IntroCommand('T.List all build options', func=lambda: list_buildoptions(coredata), no_bd=list_buildoptions_from_source),
'buildsystem_files': IntroCommand('List files that make up the build system', func=lambda: list_buildsystem_files(builddata)), 'buildsystem_files': IntroCommand('T.List files that make up the build system', func=lambda: list_buildsystem_files(builddata)),
'dependencies': IntroCommand('List external dependencies', func=lambda: list_deps(coredata), no_bd=list_deps_from_source), 'dependencies': IntroCommand('T.List external dependencies', func=lambda: list_deps(coredata), no_bd=list_deps_from_source),
'scan_dependencies': IntroCommand('Scan for dependencies used in the meson.build file', no_bd=list_deps_from_source), 'scan_dependencies': IntroCommand('Scan for dependencies used in the meson.build file', no_bd=list_deps_from_source),
'installed': IntroCommand('List all installed files and directories', func=lambda: list_installed(installdata)), 'installed': IntroCommand('T.List all installed files and directories', func=lambda: list_installed(installdata)),
'projectinfo': IntroCommand('Information about projects', func=lambda: list_projinfo(builddata), no_bd=list_projinfo_from_source), 'projectinfo': IntroCommand('Information about projects', func=lambda: list_projinfo(builddata), no_bd=list_projinfo_from_source),
'targets': IntroCommand('List top level targets', func=lambda: list_targets(builddata, installdata, backend), no_bd=list_targets_from_source), 'targets': IntroCommand('T.List top level targets', func=lambda: list_targets(builddata, installdata, backend), no_bd=list_targets_from_source),
'tests': IntroCommand('List all unit tests', func=lambda: list_tests(testdata)), 'tests': IntroCommand('T.List all unit tests', func=lambda: list_tests(testdata)),
} }
def add_arguments(parser): def add_arguments(parser):
@ -103,12 +103,12 @@ def list_installed(installdata):
res[path] = os.path.join(installdata.prefix, installpath) res[path] = os.path.join(installdata.prefix, installpath)
return res return res
def list_targets_from_source(intr: IntrospectionInterpreter) -> List[Dict[str, Union[bool, str, List[Union[str, Dict[str, Union[str, List[str], bool]]]]]]]: def list_targets_from_source(intr: IntrospectionInterpreter) -> T.List[T.Dict[str, T.Union[bool, str, T.List[T.Union[str, T.Dict[str, T.Union[str, T.List[str], bool]]]]]]]:
tlist = [] # type: List[Dict[str, Union[bool, str, List[Union[str, Dict[str, Union[str, List[str], bool]]]]]]] tlist = [] # type: T.List[T.Dict[str, T.Union[bool, str, T.List[T.Union[str, T.Dict[str, T.Union[str, T.List[str], bool]]]]]]]
for i in intr.targets: for i in intr.targets:
sources = [] # type: List[str] sources = [] # type: T.List[str]
for n in i['sources']: for n in i['sources']:
args = [] # type: List[Union[str, StringNode]] args = [] # type: T.List[T.Union[str, StringNode]]
if isinstance(n, FunctionNode): if isinstance(n, FunctionNode):
args = list(n.args.arguments) args = list(n.args.arguments)
if n.func_name in build_target_functions: if n.func_name in build_target_functions:
@ -143,8 +143,8 @@ def list_targets_from_source(intr: IntrospectionInterpreter) -> List[Dict[str, U
return tlist return tlist
def list_targets(builddata: build.Build, installdata, backend: backends.Backend) -> List[Dict[str, Union[bool, str, List[Union[str, Dict[str, Union[str, List[str], bool]]]]]]]: def list_targets(builddata: build.Build, installdata, backend: backends.Backend) -> T.List[T.Dict[str, T.Union[bool, str, T.List[T.Union[str, T.Dict[str, T.Union[str, T.List[str], bool]]]]]]]:
tlist = [] # type: List[Dict[str, Union[bool, str, List[Union[str, Dict[str, Union[str, List[str], bool]]]]]]] tlist = [] # type: T.List[T.Dict[str, T.Union[bool, str, T.List[T.Union[str, T.Dict[str, T.Union[str, T.List[str], bool]]]]]]]
build_dir = builddata.environment.get_build_dir() build_dir = builddata.environment.get_build_dir()
src_dir = builddata.environment.get_source_dir() src_dir = builddata.environment.get_source_dir()
@ -177,11 +177,11 @@ def list_targets(builddata: build.Build, installdata, backend: backends.Backend)
tlist.append(t) tlist.append(t)
return tlist return tlist
def list_buildoptions_from_source(intr: IntrospectionInterpreter) -> List[Dict[str, Union[str, bool, int, List[str]]]]: def list_buildoptions_from_source(intr: IntrospectionInterpreter) -> T.List[T.Dict[str, T.Union[str, bool, int, T.List[str]]]]:
return list_buildoptions(intr.coredata) return list_buildoptions(intr.coredata)
def list_buildoptions(coredata: cdata.CoreData) -> List[Dict[str, Union[str, bool, int, List[str]]]]: def list_buildoptions(coredata: cdata.CoreData) -> T.List[T.Dict[str, T.Union[str, bool, int, T.List[str]]]]:
optlist = [] # type: List[Dict[str, Union[str, bool, int, List[str]]]] optlist = [] # type: T.List[T.Dict[str, T.Union[str, bool, int, T.List[str]]]]
dir_option_names = ['bindir', dir_option_names = ['bindir',
'datadir', 'datadir',
@ -204,7 +204,7 @@ def list_buildoptions(coredata: cdata.CoreData) -> List[Dict[str, Union[str, boo
test_options = {k: o for k, o in coredata.builtins.items() if k in test_option_names} test_options = {k: o for k, o in coredata.builtins.items() if k in test_option_names}
core_options = {k: o for k, o in coredata.builtins.items() if k in core_option_names} core_options = {k: o for k, o in coredata.builtins.items() if k in core_option_names}
def add_keys(options: Dict[str, cdata.UserOption], section: str, machine: str = 'any') -> None: def add_keys(options: T.Dict[str, cdata.UserOption], section: str, machine: str = 'any') -> None:
for key in sorted(options.keys()): for key in sorted(options.keys()):
opt = options[key] opt = options[key]
optdict = {'name': key, 'value': opt.value, 'section': section, 'machine': machine} optdict = {'name': key, 'value': opt.value, 'section': section, 'machine': machine}
@ -245,23 +245,23 @@ def list_buildoptions(coredata: cdata.CoreData) -> List[Dict[str, Union[str, boo
add_keys(test_options, 'test') add_keys(test_options, 'test')
return optlist return optlist
def find_buildsystem_files_list(src_dir) -> List[str]: def find_buildsystem_files_list(src_dir) -> T.List[str]:
# I feel dirty about this. But only slightly. # I feel dirty about this. But only slightly.
filelist = [] # type: List[str] filelist = [] # type: T.List[str]
for root, _, files in os.walk(src_dir): for root, _, files in os.walk(src_dir):
for f in files: for f in files:
if f == 'meson.build' or f == 'meson_options.txt': if f == 'meson.build' or f == 'meson_options.txt':
filelist.append(os.path.relpath(os.path.join(root, f), src_dir)) filelist.append(os.path.relpath(os.path.join(root, f), src_dir))
return filelist return filelist
def list_buildsystem_files(builddata: build.Build) -> List[str]: def list_buildsystem_files(builddata: build.Build) -> T.List[str]:
src_dir = builddata.environment.get_source_dir() src_dir = builddata.environment.get_source_dir()
filelist = find_buildsystem_files_list(src_dir) filelist = find_buildsystem_files_list(src_dir)
filelist = [os.path.join(src_dir, x) for x in filelist] filelist = [os.path.join(src_dir, x) for x in filelist]
return filelist return filelist
def list_deps_from_source(intr: IntrospectionInterpreter) -> List[Dict[str, Union[str, bool]]]: def list_deps_from_source(intr: IntrospectionInterpreter) -> T.List[T.Dict[str, T.Union[str, bool]]]:
result = [] # type: List[Dict[str, Union[str, bool]]] result = [] # type: T.List[T.Dict[str, T.Union[str, bool]]]
for i in intr.dependencies: for i in intr.dependencies:
keys = [ keys = [
'name', 'name',
@ -273,8 +273,8 @@ def list_deps_from_source(intr: IntrospectionInterpreter) -> List[Dict[str, Unio
result += [{k: v for k, v in i.items() if k in keys}] result += [{k: v for k, v in i.items() if k in keys}]
return result return result
def list_deps(coredata: cdata.CoreData) -> List[Dict[str, Union[str, List[str]]]]: def list_deps(coredata: cdata.CoreData) -> T.List[T.Dict[str, T.Union[str, T.List[str]]]]:
result = [] # type: List[Dict[str, Union[str, List[str]]]] result = [] # type: T.List[T.Dict[str, T.Union[str, T.List[str]]]]
for d in coredata.deps.host.values(): for d in coredata.deps.host.values():
if d.found(): if d.found():
result += [{'name': d.name, result += [{'name': d.name,
@ -283,8 +283,8 @@ def list_deps(coredata: cdata.CoreData) -> List[Dict[str, Union[str, List[str]]]
'link_args': d.get_link_args()}] 'link_args': d.get_link_args()}]
return result return result
def get_test_list(testdata) -> List[Dict[str, Union[str, int, List[str], Dict[str, str]]]]: def get_test_list(testdata) -> T.List[T.Dict[str, T.Union[str, int, T.List[str], T.Dict[str, str]]]]:
result = [] # type: List[Dict[str, Union[str, int, List[str], Dict[str, str]]]] result = [] # type: T.List[T.Dict[str, T.Union[str, int, T.List[str], T.Dict[str, str]]]]
for t in testdata: for t in testdata:
to = {} to = {}
if isinstance(t.fname, str): if isinstance(t.fname, str):
@ -306,13 +306,13 @@ def get_test_list(testdata) -> List[Dict[str, Union[str, int, List[str], Dict[st
result.append(to) result.append(to)
return result return result
def list_tests(testdata) -> List[Dict[str, Union[str, int, List[str], Dict[str, str]]]]: def list_tests(testdata) -> T.List[T.Dict[str, T.Union[str, int, T.List[str], T.Dict[str, str]]]]:
return get_test_list(testdata) return get_test_list(testdata)
def list_benchmarks(benchdata) -> List[Dict[str, Union[str, int, List[str], Dict[str, str]]]]: def list_benchmarks(benchdata) -> T.List[T.Dict[str, T.Union[str, int, T.List[str], T.Dict[str, str]]]]:
return get_test_list(benchdata) return get_test_list(benchdata)
def list_projinfo(builddata: build.Build) -> Dict[str, Union[str, List[Dict[str, str]]]]: def list_projinfo(builddata: build.Build) -> T.Dict[str, T.Union[str, T.List[T.Dict[str, str]]]]:
result = {'version': builddata.project_version, result = {'version': builddata.project_version,
'descriptive_name': builddata.project_name, 'descriptive_name': builddata.project_name,
'subproject_dir': builddata.subproject_dir} 'subproject_dir': builddata.subproject_dir}
@ -325,7 +325,7 @@ def list_projinfo(builddata: build.Build) -> Dict[str, Union[str, List[Dict[str,
result['subprojects'] = subprojects result['subprojects'] = subprojects
return result return result
def list_projinfo_from_source(intr: IntrospectionInterpreter) -> Dict[str, Union[str, List[Dict[str, str]]]]: def list_projinfo_from_source(intr: IntrospectionInterpreter) -> T.Dict[str, T.Union[str, T.List[T.Dict[str, str]]]]:
sourcedir = intr.source_root sourcedir = intr.source_root
files = find_buildsystem_files_list(sourcedir) files = find_buildsystem_files_list(sourcedir)
files = [os.path.normpath(x) for x in files] files = [os.path.normpath(x) for x in files]
@ -339,7 +339,7 @@ def list_projinfo_from_source(intr: IntrospectionInterpreter) -> Dict[str, Union
intr.project_data['subproject_dir'] = intr.subproject_dir intr.project_data['subproject_dir'] = intr.subproject_dir
return intr.project_data return intr.project_data
def print_results(options, results: Sequence[Tuple[str, Union[dict, List[Any]]]], indent: int) -> int: def print_results(options, results: T.Sequence[T.Tuple[str, T.Union[dict, T.List[T.Any]]]], indent: int) -> int:
if not results and not options.force_dict: if not results and not options.force_dict:
print('No command specified') print('No command specified')
return 1 return 1
@ -360,7 +360,7 @@ def run(options) -> int:
datadir = os.path.join(options.builddir, datadir) datadir = os.path.join(options.builddir, datadir)
infodir = os.path.join(options.builddir, infodir) infodir = os.path.join(options.builddir, infodir)
indent = 4 if options.indent else None indent = 4 if options.indent else None
results = [] # type: List[Tuple[str, Union[dict, List[Any]]]] results = [] # type: T.List[T.Tuple[str, T.Union[dict, T.List[T.Any]]]]
sourcedir = '.' if options.builddir == 'meson.build' else options.builddir[:-11] sourcedir = '.' if options.builddir == 'meson.build' else options.builddir[:-11]
intro_types = get_meson_introspection_types(sourcedir=sourcedir) intro_types = get_meson_introspection_types(sourcedir=sourcedir)
@ -413,9 +413,9 @@ def run(options) -> int:
return print_results(options, results, indent) return print_results(options, results, indent)
updated_introspection_files = [] # type: List[str] updated_introspection_files = [] # type: T.List[str]
def write_intro_info(intro_info: Sequence[Tuple[str, Union[dict, List[Any]]]], info_dir: str) -> None: def write_intro_info(intro_info: T.Sequence[T.Tuple[str, T.Union[dict, T.List[T.Any]]]], info_dir: str) -> None:
global updated_introspection_files global updated_introspection_files
for i in intro_info: for i in intro_info:
out_file = os.path.join(info_dir, 'intro-{}.json'.format(i[0])) out_file = os.path.join(info_dir, 'intro-{}.json'.format(i[0]))
@ -429,7 +429,7 @@ def write_intro_info(intro_info: Sequence[Tuple[str, Union[dict, List[Any]]]], i
def generate_introspection_file(builddata: build.Build, backend: backends.Backend) -> None: def generate_introspection_file(builddata: build.Build, backend: backends.Backend) -> None:
coredata = builddata.environment.get_coredata() coredata = builddata.environment.get_coredata()
intro_types = get_meson_introspection_types(coredata=coredata, builddata=builddata, backend=backend) intro_types = get_meson_introspection_types(coredata=coredata, builddata=builddata, backend=backend)
intro_info = [] # type: List[Tuple[str, Union[dict, List[Any]]]] intro_info = [] # type: T.List[T.Tuple[str, T.Union[dict, T.List[T.Any]]]]
for key, val in intro_types.items(): for key, val in intro_types.items():
if not val.func: if not val.func:
@ -445,7 +445,7 @@ def update_build_options(coredata: cdata.CoreData, info_dir) -> None:
write_intro_info(intro_info, info_dir) write_intro_info(intro_info, info_dir)
def split_version_string(version: str) -> Dict[str, Union[str, int]]: def split_version_string(version: str) -> T.Dict[str, T.Union[str, int]]:
vers_list = version.split('.') vers_list = version.split('.')
return { return {
'full': version, 'full': version,

@ -17,19 +17,8 @@ import io
import sys import sys
import time import time
import platform import platform
import typing as T
from contextlib import contextmanager from contextlib import contextmanager
from typing import (
Any,
Generator,
List,
Optional,
Sequence,
Set,
TextIO,
Tuple,
Union,
cast,
)
from pathlib import Path from pathlib import Path
"""This is (mostly) a standalone module used to write logging """This is (mostly) a standalone module used to write logging
@ -58,16 +47,16 @@ try:
colorize_console = os.isatty(sys.stdout.fileno()) and os.environ.get('TERM') != 'dumb' colorize_console = os.isatty(sys.stdout.fileno()) and os.environ.get('TERM') != 'dumb'
except Exception: except Exception:
colorize_console = False colorize_console = False
log_dir = None # type: Optional[str] log_dir = None # type: T.Optional[str]
log_file = None # type: Optional[TextIO] log_file = None # type: T.Optional[T.TextIO]
log_fname = 'meson-log.txt' # type: str log_fname = 'meson-log.txt' # type: str
log_depth = 0 # type: int log_depth = 0 # type: int
log_timestamp_start = None # type: Optional[float] log_timestamp_start = None # type: T.Optional[float]
log_fatal_warnings = False # type: bool log_fatal_warnings = False # type: bool
log_disable_stdout = False # type: bool log_disable_stdout = False # type: bool
log_errors_only = False # type: bool log_errors_only = False # type: bool
_in_ci = 'CI' in os.environ # type: bool _in_ci = 'CI' in os.environ # type: bool
_logged_once = set() # type: Set[Tuple[str, ...]] _logged_once = set() # type: T.Set[T.Tuple[str, ...]]
def disable() -> None: def disable() -> None:
global log_disable_stdout global log_disable_stdout
@ -95,7 +84,7 @@ def set_timestamp_start(start: float) -> None:
global log_timestamp_start global log_timestamp_start
log_timestamp_start = start log_timestamp_start = start
def shutdown() -> Optional[str]: def shutdown() -> T.Optional[str]:
global log_file global log_file
if log_file is not None: if log_file is not None:
path = log_file.name path = log_file.name
@ -156,8 +145,8 @@ def normal_cyan(text: str) -> AnsiDecorator:
# This really should be AnsiDecorator or anything that implements # This really should be AnsiDecorator or anything that implements
# __str__(), but that requires protocols from typing_extensions # __str__(), but that requires protocols from typing_extensions
def process_markup(args: Sequence[Union[AnsiDecorator, str]], keep: bool) -> List[str]: def process_markup(args: T.Sequence[T.Union[AnsiDecorator, str]], keep: bool) -> T.List[str]:
arr = [] # type: List[str] arr = [] # type: T.List[str]
if log_timestamp_start is not None: if log_timestamp_start is not None:
arr = ['[{:.3f}]'.format(time.monotonic() - log_timestamp_start)] arr = ['[{:.3f}]'.format(time.monotonic() - log_timestamp_start)]
for arg in args: for arg in args:
@ -171,7 +160,7 @@ def process_markup(args: Sequence[Union[AnsiDecorator, str]], keep: bool) -> Lis
arr.append(str(arg)) arr.append(str(arg))
return arr return arr
def force_print(*args: str, **kwargs: Any) -> None: def force_print(*args: str, **kwargs: T.Any) -> None:
if log_disable_stdout: if log_disable_stdout:
return return
iostr = io.StringIO() iostr = io.StringIO()
@ -191,13 +180,13 @@ def force_print(*args: str, **kwargs: Any) -> None:
print(cleaned, end='') print(cleaned, end='')
# We really want a heterogeneous dict for this, but that's in typing_extensions # We really want a heterogeneous dict for this, but that's in typing_extensions
def debug(*args: Union[str, AnsiDecorator], **kwargs: Any) -> None: def debug(*args: T.Union[str, AnsiDecorator], **kwargs: T.Any) -> None:
arr = process_markup(args, False) arr = process_markup(args, False)
if log_file is not None: if log_file is not None:
print(*arr, file=log_file, **kwargs) print(*arr, file=log_file, **kwargs)
log_file.flush() log_file.flush()
def _debug_log_cmd(cmd: str, args: List[str]) -> None: def _debug_log_cmd(cmd: str, args: T.List[str]) -> None:
if not _in_ci: if not _in_ci:
return return
args = ['"{}"'.format(x) for x in args] # Quote all args, just in case args = ['"{}"'.format(x) for x in args] # Quote all args, just in case
@ -206,8 +195,8 @@ def _debug_log_cmd(cmd: str, args: List[str]) -> None:
def cmd_ci_include(file: str) -> None: def cmd_ci_include(file: str) -> None:
_debug_log_cmd('ci_include', [file]) _debug_log_cmd('ci_include', [file])
def log(*args: Union[str, AnsiDecorator], is_error: bool = False, def log(*args: T.Union[str, AnsiDecorator], is_error: bool = False,
**kwargs: Any) -> None: **kwargs: T.Any) -> None:
arr = process_markup(args, False) arr = process_markup(args, False)
if log_file is not None: if log_file is not None:
print(*arr, file=log_file, **kwargs) print(*arr, file=log_file, **kwargs)
@ -217,8 +206,8 @@ def log(*args: Union[str, AnsiDecorator], is_error: bool = False,
if not log_errors_only or is_error: if not log_errors_only or is_error:
force_print(*arr, **kwargs) force_print(*arr, **kwargs)
def log_once(*args: Union[str, AnsiDecorator], is_error: bool = False, def log_once(*args: T.Union[str, AnsiDecorator], is_error: bool = False,
**kwargs: Any) -> None: **kwargs: T.Any) -> None:
"""Log variant that only prints a given message one time per meson invocation. """Log variant that only prints a given message one time per meson invocation.
This considers nasi decorated values by the values they wrap without This considers nasi decorated values by the values they wrap without
@ -230,16 +219,16 @@ def log_once(*args: Union[str, AnsiDecorator], is_error: bool = False,
_logged_once.add(t) _logged_once.add(t)
log(*args, is_error=is_error, **kwargs) log(*args, is_error=is_error, **kwargs)
def _log_error(severity: str, *rargs: Union[str, AnsiDecorator], def _log_error(severity: str, *rargs: T.Union[str, AnsiDecorator],
once: bool = False, **kwargs: Any) -> None: once: bool = False, **kwargs: T.Any) -> None:
from .mesonlib import get_error_location_string from .mesonlib import get_error_location_string
from .environment import build_filename from .environment import build_filename
from .mesonlib import MesonException from .mesonlib import MesonException
# The tping requirements here are non-obvious. Lists are invariant, # The tping requirements here are non-obvious. Lists are invariant,
# therefore List[A] and List[Union[A, B]] are not able to be joined # therefore T.List[A] and T.List[T.Union[A, B]] are not able to be joined
if severity == 'warning': if severity == 'warning':
label = [yellow('WARNING:')] # type: List[Union[str, AnsiDecorator]] label = [yellow('WARNING:')] # type: T.List[T.Union[str, AnsiDecorator]]
elif severity == 'error': elif severity == 'error':
label = [red('ERROR:')] label = [red('ERROR:')]
elif severity == 'deprecation': elif severity == 'deprecation':
@ -253,9 +242,9 @@ def _log_error(severity: str, *rargs: Union[str, AnsiDecorator],
if location is not None: if location is not None:
location_file = os.path.join(location.subdir, build_filename) location_file = os.path.join(location.subdir, build_filename)
location_str = get_error_location_string(location_file, location.lineno) location_str = get_error_location_string(location_file, location.lineno)
# Unions are frankly awful, and we have to cast here to get mypy # Unions are frankly awful, and we have to T.cast here to get mypy
# to understand that the list concatenation is safe # to understand that the list concatenation is safe
location_list = cast(List[Union[str, AnsiDecorator]], [location_str]) location_list = T.cast(T.List[T.Union[str, AnsiDecorator]], [location_str])
args = location_list + args args = location_list + args
if once: if once:
@ -266,13 +255,13 @@ def _log_error(severity: str, *rargs: Union[str, AnsiDecorator],
if log_fatal_warnings: if log_fatal_warnings:
raise MesonException("Fatal warnings enabled, aborting") raise MesonException("Fatal warnings enabled, aborting")
def error(*args: Union[str, AnsiDecorator], once: bool = False, **kwargs: Any) -> None: def error(*args: T.Union[str, AnsiDecorator], once: bool = False, **kwargs: T.Any) -> None:
return _log_error('error', *args, **kwargs, is_error=True, once=once) return _log_error('error', *args, **kwargs, is_error=True, once=once)
def warning(*args: Union[str, AnsiDecorator], once: bool = False, **kwargs: Any) -> None: def warning(*args: T.Union[str, AnsiDecorator], once: bool = False, **kwargs: T.Any) -> None:
return _log_error('warning', *args, **kwargs, is_error=True, once=once) return _log_error('warning', *args, **kwargs, is_error=True, once=once)
def deprecation(*args: Union[str, AnsiDecorator], once: bool = False, **kwargs: Any) -> None: def deprecation(*args: T.Union[str, AnsiDecorator], once: bool = False, **kwargs: T.Any) -> None:
return _log_error('deprecation', *args, **kwargs, is_error=True, once=once) return _log_error('deprecation', *args, **kwargs, is_error=True, once=once)
def get_relative_path(target: Path, current: Path) -> Path: def get_relative_path(target: Path, current: Path) -> Path:
@ -290,11 +279,11 @@ def get_relative_path(target: Path, current: Path) -> Path:
# we failed, should not get here # we failed, should not get here
return target return target
def exception(e: Exception, prefix: Optional[AnsiDecorator] = None) -> None: def exception(e: Exception, prefix: T.Optional[AnsiDecorator] = None) -> None:
if prefix is None: if prefix is None:
prefix = red('ERROR:') prefix = red('ERROR:')
log() log()
args = [] # type: List[Union[AnsiDecorator, str]] args = [] # type: T.List[T.Union[AnsiDecorator, str]]
if hasattr(e, 'file') and hasattr(e, 'lineno') and hasattr(e, 'colno'): if hasattr(e, 'file') and hasattr(e, 'lineno') and hasattr(e, 'colno'):
# Mypy can't figure this out, and it's pretty easy to vidual inspect # Mypy can't figure this out, and it's pretty easy to vidual inspect
# that this is correct, so we'll just ignore it. # that this is correct, so we'll just ignore it.
@ -307,7 +296,7 @@ def exception(e: Exception, prefix: Optional[AnsiDecorator] = None) -> None:
# Format a list for logging purposes as a string. It separates # Format a list for logging purposes as a string. It separates
# all but the last item with commas, and the last with 'and'. # all but the last item with commas, and the last with 'and'.
def format_list(input_list: List[str]) -> str: def format_list(input_list: T.List[str]) -> str:
l = len(input_list) l = len(input_list)
if l > 2: if l > 2:
return ' and '.join([', '.join(input_list[:-1]), input_list[-1]]) return ' and '.join([', '.join(input_list[:-1]), input_list[-1]])
@ -319,7 +308,7 @@ def format_list(input_list: List[str]) -> str:
return '' return ''
@contextmanager @contextmanager
def nested() -> Generator[None, None, None]: def nested() -> T.Generator[None, None, None]:
global log_depth global log_depth
log_depth += 1 log_depth += 1
try: try:

@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
import typing import typing as T
import hashlib import hashlib
from pathlib import Path, PurePath from pathlib import Path, PurePath
@ -22,7 +22,7 @@ from . import ModuleReturnValue
from ..mesonlib import MesonException from ..mesonlib import MesonException
from ..interpreterbase import stringArgs, noKwargs from ..interpreterbase import stringArgs, noKwargs
if typing.TYPE_CHECKING: if T.TYPE_CHECKING:
from ..interpreter import ModuleState from ..interpreter import ModuleState
class FSModule(ExtensionModule): class FSModule(ExtensionModule):
@ -38,7 +38,7 @@ class FSModule(ExtensionModule):
""" """
return Path(state.source_root) / state.subdir / Path(arg).expanduser() return Path(state.source_root) / state.subdir / Path(arg).expanduser()
def _check(self, check: str, state: 'ModuleState', args: typing.Sequence[str]) -> ModuleReturnValue: def _check(self, check: str, state: 'ModuleState', args: T.Sequence[str]) -> ModuleReturnValue:
if len(args) != 1: if len(args) != 1:
raise MesonException('fs.{} takes exactly one argument.'.format(check)) raise MesonException('fs.{} takes exactly one argument.'.format(check))
test_file = self._resolve_dir(state, args[0]) test_file = self._resolve_dir(state, args[0])
@ -46,27 +46,27 @@ class FSModule(ExtensionModule):
@stringArgs @stringArgs
@noKwargs @noKwargs
def exists(self, state: 'ModuleState', args: typing.Sequence[str], kwargs: dict) -> ModuleReturnValue: def exists(self, state: 'ModuleState', args: T.Sequence[str], kwargs: dict) -> ModuleReturnValue:
return self._check('exists', state, args) return self._check('exists', state, args)
@stringArgs @stringArgs
@noKwargs @noKwargs
def is_symlink(self, state: 'ModuleState', args: typing.Sequence[str], kwargs: dict) -> ModuleReturnValue: def is_symlink(self, state: 'ModuleState', args: T.Sequence[str], kwargs: dict) -> ModuleReturnValue:
return self._check('is_symlink', state, args) return self._check('is_symlink', state, args)
@stringArgs @stringArgs
@noKwargs @noKwargs
def is_file(self, state: 'ModuleState', args: typing.Sequence[str], kwargs: dict) -> ModuleReturnValue: def is_file(self, state: 'ModuleState', args: T.Sequence[str], kwargs: dict) -> ModuleReturnValue:
return self._check('is_file', state, args) return self._check('is_file', state, args)
@stringArgs @stringArgs
@noKwargs @noKwargs
def is_dir(self, state: 'ModuleState', args: typing.Sequence[str], kwargs: dict) -> ModuleReturnValue: def is_dir(self, state: 'ModuleState', args: T.Sequence[str], kwargs: dict) -> ModuleReturnValue:
return self._check('is_dir', state, args) return self._check('is_dir', state, args)
@stringArgs @stringArgs
@noKwargs @noKwargs
def hash(self, state: 'ModuleState', args: typing.Sequence[str], kwargs: dict) -> ModuleReturnValue: def hash(self, state: 'ModuleState', args: T.Sequence[str], kwargs: dict) -> ModuleReturnValue:
if len(args) != 2: if len(args) != 2:
raise MesonException('method takes exactly two arguments.') raise MesonException('method takes exactly two arguments.')
file = self._resolve_dir(state, args[0]) file = self._resolve_dir(state, args[0])
@ -82,7 +82,7 @@ class FSModule(ExtensionModule):
@stringArgs @stringArgs
@noKwargs @noKwargs
def size(self, state: 'ModuleState', args: typing.Sequence[str], kwargs: dict) -> ModuleReturnValue: def size(self, state: 'ModuleState', args: T.Sequence[str], kwargs: dict) -> ModuleReturnValue:
if len(args) != 1: if len(args) != 1:
raise MesonException('method takes exactly one argument.') raise MesonException('method takes exactly one argument.')
file = self._resolve_dir(state, args[0]) file = self._resolve_dir(state, args[0])
@ -95,7 +95,7 @@ class FSModule(ExtensionModule):
@stringArgs @stringArgs
@noKwargs @noKwargs
def is_samepath(self, state: 'ModuleState', args: typing.Sequence[str], kwargs: dict) -> ModuleReturnValue: def is_samepath(self, state: 'ModuleState', args: T.Sequence[str], kwargs: dict) -> ModuleReturnValue:
if len(args) != 2: if len(args) != 2:
raise MesonException('fs.is_samepath takes exactly two arguments.') raise MesonException('fs.is_samepath takes exactly two arguments.')
file1 = self._resolve_dir(state, args[0]) file1 = self._resolve_dir(state, args[0])
@ -111,7 +111,7 @@ class FSModule(ExtensionModule):
@stringArgs @stringArgs
@noKwargs @noKwargs
def replace_suffix(self, state: 'ModuleState', args: typing.Sequence[str], kwargs: dict) -> ModuleReturnValue: def replace_suffix(self, state: 'ModuleState', args: T.Sequence[str], kwargs: dict) -> ModuleReturnValue:
if len(args) != 2: if len(args) != 2:
raise MesonException('method takes exactly two arguments.') raise MesonException('method takes exactly two arguments.')
original = PurePath(args[0]) original = PurePath(args[0])
@ -120,7 +120,7 @@ class FSModule(ExtensionModule):
@stringArgs @stringArgs
@noKwargs @noKwargs
def parent(self, state: 'ModuleState', args: typing.Sequence[str], kwargs: dict) -> ModuleReturnValue: def parent(self, state: 'ModuleState', args: T.Sequence[str], kwargs: dict) -> ModuleReturnValue:
if len(args) != 1: if len(args) != 1:
raise MesonException('method takes exactly one argument.') raise MesonException('method takes exactly one argument.')
original = PurePath(args[0]) original = PurePath(args[0])
@ -129,7 +129,7 @@ class FSModule(ExtensionModule):
@stringArgs @stringArgs
@noKwargs @noKwargs
def name(self, state: 'ModuleState', args: typing.Sequence[str], kwargs: dict) -> ModuleReturnValue: def name(self, state: 'ModuleState', args: T.Sequence[str], kwargs: dict) -> ModuleReturnValue:
if len(args) != 1: if len(args) != 1:
raise MesonException('method takes exactly one argument.') raise MesonException('method takes exactly one argument.')
original = PurePath(args[0]) original = PurePath(args[0])

@ -15,7 +15,7 @@
import os import os
import json import json
import shutil import shutil
import typing import typing as T
from pathlib import Path from pathlib import Path
from .. import mesonlib from .. import mesonlib
@ -495,9 +495,9 @@ class PythonModule(ExtensionModule):
def find_installation(self, interpreter, state, args, kwargs): def find_installation(self, interpreter, state, args, kwargs):
feature_check = FeatureNew('Passing "feature" option to find_installation', '0.48.0') feature_check = FeatureNew('Passing "feature" option to find_installation', '0.48.0')
disabled, required, feature = extract_required_kwarg(kwargs, state.subproject, feature_check) disabled, required, feature = extract_required_kwarg(kwargs, state.subproject, feature_check)
want_modules = mesonlib.extract_as_list(kwargs, 'modules') # type: typing.List[str] want_modules = mesonlib.extract_as_list(kwargs, 'modules') # type: T.List[str]
found_modules = [] # type: typing.List[str] found_modules = [] # type: T.List[str]
missing_modules = [] # type: typing.List[str] missing_modules = [] # type: T.List[str]
if len(args) > 1: if len(args) > 1:
raise InvalidArguments('find_installation takes zero or one positional argument.') raise InvalidArguments('find_installation takes zero or one positional argument.')

@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
import typing import typing as T
import time import time
import sys, stat import sys, stat
import datetime import datetime
@ -101,7 +101,7 @@ class MesonApp:
fname = os.path.join(dirname, environment.build_filename) fname = os.path.join(dirname, environment.build_filename)
return os.path.exists(fname) return os.path.exists(fname)
def validate_core_dirs(self, dir1: str, dir2: str) -> typing.Tuple[str, str]: def validate_core_dirs(self, dir1: str, dir2: str) -> T.Tuple[str, str]:
if dir1 is None: if dir1 is None:
if dir2 is None: if dir2 is None:
if not os.path.exists('meson.build') and os.path.exists('../meson.build'): if not os.path.exists('meson.build') and os.path.exists('../meson.build'):
@ -131,7 +131,7 @@ class MesonApp:
return ndir2, ndir1 return ndir2, ndir1
raise MesonException('Neither directory contains a build file %s.' % environment.build_filename) raise MesonException('Neither directory contains a build file %s.' % environment.build_filename)
def validate_dirs(self, dir1: str, dir2: str, reconfigure: bool, wipe: bool) -> typing.Tuple[str, str]: def validate_dirs(self, dir1: str, dir2: str, reconfigure: bool, wipe: bool) -> T.Tuple[str, str]:
(src_dir, build_dir) = self.validate_core_dirs(dir1, dir2) (src_dir, build_dir) = self.validate_core_dirs(dir1, dir2)
priv_dir = os.path.join(build_dir, 'meson-private/coredata.dat') priv_dir = os.path.join(build_dir, 'meson-private/coredata.dat')
if os.path.exists(priv_dir): if os.path.exists(priv_dir):

@ -34,7 +34,7 @@ import subprocess
import sys import sys
import tempfile import tempfile
import time import time
import typing import typing as T
from . import build from . import build
from . import environment from . import environment
@ -42,7 +42,7 @@ from . import mlog
from .dependencies import ExternalProgram from .dependencies import ExternalProgram
from .mesonlib import MesonException, get_wine_shortpath, split_args from .mesonlib import MesonException, get_wine_shortpath, split_args
if typing.TYPE_CHECKING: if T.TYPE_CHECKING:
from .backend.backends import TestSerialisation from .backend.backends import TestSerialisation
# GNU autotools interprets a return code of 77 from tests it executes to # GNU autotools interprets a return code of 77 from tests it executes to
@ -148,7 +148,7 @@ def returncode_to_status(retcode: int) -> str:
signame = 'SIGinvalid' signame = 'SIGinvalid'
return '(exit status %d or signal %d %s)' % (retcode, signum, signame) return '(exit status %d or signal %d %s)' % (retcode, signum, signame)
def env_tuple_to_str(env: typing.Iterable[typing.Tuple[str, str]]) -> str: def env_tuple_to_str(env: T.Iterable[T.Tuple[str, str]]) -> str:
return ''.join(["%s='%s' " % (k, v) for k, v in env]) return ''.join(["%s='%s' " % (k, v) for k, v in env])
@ -187,11 +187,11 @@ class TAPParser:
_RE_YAML_START = re.compile(r'(\s+)---.*') _RE_YAML_START = re.compile(r'(\s+)---.*')
_RE_YAML_END = re.compile(r'\s+\.\.\.\s*') _RE_YAML_END = re.compile(r'\s+\.\.\.\s*')
def __init__(self, io: typing.Iterator[str]): def __init__(self, io: T.Iterator[str]):
self.io = io self.io = io
def parse_test(self, ok: bool, num: int, name: str, directive: typing.Optional[str], explanation: typing.Optional[str]) -> \ def parse_test(self, ok: bool, num: int, name: str, directive: T.Optional[str], explanation: T.Optional[str]) -> \
typing.Generator[typing.Union['TAPParser.Test', 'TAPParser.Error'], None, None]: T.Generator[T.Union['TAPParser.Test', 'TAPParser.Error'], None, None]:
name = name.strip() name = name.strip()
explanation = explanation.strip() if explanation else None explanation = explanation.strip() if explanation else None
if directive is not None: if directive is not None:
@ -208,7 +208,7 @@ class TAPParser:
yield self.Test(num, name, TestResult.OK if ok else TestResult.FAIL, explanation) yield self.Test(num, name, TestResult.OK if ok else TestResult.FAIL, explanation)
def parse(self) -> typing.Generator[typing.Union['TAPParser.Test', 'TAPParser.Error', 'TAPParser.Version', 'TAPParser.Plan', 'TAPParser.Bailout'], None, None]: def parse(self) -> T.Generator[T.Union['TAPParser.Test', 'TAPParser.Error', 'TAPParser.Version', 'TAPParser.Plan', 'TAPParser.Bailout'], None, None]:
found_late_test = False found_late_test = False
bailed_out = False bailed_out = False
plan = None plan = None
@ -319,10 +319,10 @@ class TAPParser:
class TestRun: class TestRun:
@classmethod @classmethod
def make_exitcode(cls, test: 'TestSerialisation', test_env: typing.Dict[str, str], def make_exitcode(cls, test: 'TestSerialisation', test_env: T.Dict[str, str],
returncode: int, starttime: float, duration: float, returncode: int, starttime: float, duration: float,
stdo: typing.Optional[str], stde: typing.Optional[str], stdo: T.Optional[str], stde: T.Optional[str],
cmd: typing.Optional[typing.List[str]]) -> 'TestRun': cmd: T.Optional[T.List[str]]) -> 'TestRun':
if returncode == GNU_SKIP_RETURNCODE: if returncode == GNU_SKIP_RETURNCODE:
res = TestResult.SKIP res = TestResult.SKIP
elif returncode == GNU_ERROR_RETURNCODE: elif returncode == GNU_ERROR_RETURNCODE:
@ -334,10 +334,10 @@ class TestRun:
return cls(test, test_env, res, returncode, starttime, duration, stdo, stde, cmd) return cls(test, test_env, res, returncode, starttime, duration, stdo, stde, cmd)
@classmethod @classmethod
def make_tap(cls, test: 'TestSerialisation', test_env: typing.Dict[str, str], def make_tap(cls, test: 'TestSerialisation', test_env: T.Dict[str, str],
returncode: int, starttime: float, duration: float, returncode: int, starttime: float, duration: float,
stdo: str, stde: str, stdo: str, stde: str,
cmd: typing.Optional[typing.List[str]]) -> 'TestRun': cmd: T.Optional[T.List[str]]) -> 'TestRun':
res = None res = None
num_tests = 0 num_tests = 0
failed = False failed = False
@ -372,10 +372,10 @@ class TestRun:
return cls(test, test_env, res, returncode, starttime, duration, stdo, stde, cmd) return cls(test, test_env, res, returncode, starttime, duration, stdo, stde, cmd)
def __init__(self, test: 'TestSerialisation', test_env: typing.Dict[str, str], def __init__(self, test: 'TestSerialisation', test_env: T.Dict[str, str],
res: TestResult, returncode: int, starttime: float, duration: float, res: TestResult, returncode: int, starttime: float, duration: float,
stdo: typing.Optional[str], stde: typing.Optional[str], stdo: T.Optional[str], stde: T.Optional[str],
cmd: typing.Optional[typing.List[str]]): cmd: T.Optional[T.List[str]]):
assert isinstance(res, TestResult) assert isinstance(res, TestResult)
self.res = res self.res = res
self.returncode = returncode self.returncode = returncode
@ -410,7 +410,7 @@ class TestRun:
res += '-------\n\n' res += '-------\n\n'
return res return res
def decode(stream: typing.Union[None, bytes]) -> str: def decode(stream: T.Union[None, bytes]) -> str:
if stream is None: if stream is None:
return '' return ''
try: try:
@ -418,7 +418,7 @@ def decode(stream: typing.Union[None, bytes]) -> str:
except UnicodeDecodeError: except UnicodeDecodeError:
return stream.decode('iso-8859-1', errors='ignore') return stream.decode('iso-8859-1', errors='ignore')
def write_json_log(jsonlogfile: typing.TextIO, test_name: str, result: TestRun) -> None: def write_json_log(jsonlogfile: T.TextIO, test_name: str, result: TestRun) -> None:
jresult = {'name': test_name, jresult = {'name': test_name,
'stdout': result.stdo, 'stdout': result.stdo,
'result': result.res.value, 'result': result.res.value,
@ -426,7 +426,7 @@ def write_json_log(jsonlogfile: typing.TextIO, test_name: str, result: TestRun)
'duration': result.duration, 'duration': result.duration,
'returncode': result.returncode, 'returncode': result.returncode,
'env': result.env, 'env': result.env,
'command': result.cmd} # type: typing.Dict[str, typing.Any] 'command': result.cmd} # type: T.Dict[str, T.Any]
if result.stde: if result.stde:
jresult['stderr'] = result.stde jresult['stderr'] = result.stde
jsonlogfile.write(json.dumps(jresult) + '\n') jsonlogfile.write(json.dumps(jresult) + '\n')
@ -436,33 +436,33 @@ def run_with_mono(fname: str) -> bool:
return True return True
return False return False
def load_benchmarks(build_dir: str) -> typing.List['TestSerialisation']: def load_benchmarks(build_dir: str) -> T.List['TestSerialisation']:
datafile = Path(build_dir) / 'meson-private' / 'meson_benchmark_setup.dat' datafile = Path(build_dir) / 'meson-private' / 'meson_benchmark_setup.dat'
if not datafile.is_file(): if not datafile.is_file():
raise TestException('Directory {!r} does not seem to be a Meson build directory.'.format(build_dir)) raise TestException('Directory {!r} does not seem to be a Meson build directory.'.format(build_dir))
with datafile.open('rb') as f: with datafile.open('rb') as f:
obj = typing.cast(typing.List['TestSerialisation'], pickle.load(f)) obj = T.cast(T.List['TestSerialisation'], pickle.load(f))
return obj return obj
def load_tests(build_dir: str) -> typing.List['TestSerialisation']: def load_tests(build_dir: str) -> T.List['TestSerialisation']:
datafile = Path(build_dir) / 'meson-private' / 'meson_test_setup.dat' datafile = Path(build_dir) / 'meson-private' / 'meson_test_setup.dat'
if not datafile.is_file(): if not datafile.is_file():
raise TestException('Directory {!r} does not seem to be a Meson build directory.'.format(build_dir)) raise TestException('Directory {!r} does not seem to be a Meson build directory.'.format(build_dir))
with datafile.open('rb') as f: with datafile.open('rb') as f:
obj = typing.cast(typing.List['TestSerialisation'], pickle.load(f)) obj = T.cast(T.List['TestSerialisation'], pickle.load(f))
return obj return obj
class SingleTestRunner: class SingleTestRunner:
def __init__(self, test: 'TestSerialisation', test_env: typing.Dict[str, str], def __init__(self, test: 'TestSerialisation', test_env: T.Dict[str, str],
env: typing.Dict[str, str], options: argparse.Namespace): env: T.Dict[str, str], options: argparse.Namespace):
self.test = test self.test = test
self.test_env = test_env self.test_env = test_env
self.env = env self.env = env
self.options = options self.options = options
def _get_cmd(self) -> typing.Optional[typing.List[str]]: def _get_cmd(self) -> T.Optional[T.List[str]]:
if self.test.fname[0].endswith('.jar'): if self.test.fname[0].endswith('.jar'):
return ['java', '-jar'] + self.test.fname return ['java', '-jar'] + self.test.fname
elif not self.test.is_cross_built and run_with_mono(self.test.fname[0]): elif not self.test.is_cross_built and run_with_mono(self.test.fname[0]):
@ -493,7 +493,7 @@ class SingleTestRunner:
self.test.timeout = None self.test.timeout = None
return self._run_cmd(wrap + cmd + self.test.cmd_args + self.options.test_args) return self._run_cmd(wrap + cmd + self.test.cmd_args + self.options.test_args)
def _run_cmd(self, cmd: typing.List[str]) -> TestRun: def _run_cmd(self, cmd: T.List[str]) -> TestRun:
starttime = time.time() starttime = time.time()
if len(self.test.extra_paths) > 0: if len(self.test.extra_paths) > 0:
@ -629,7 +629,7 @@ class SingleTestRunner:
class TestHarness: class TestHarness:
def __init__(self, options: argparse.Namespace): def __init__(self, options: argparse.Namespace):
self.options = options self.options = options
self.collected_logs = [] # type: typing.List[str] self.collected_logs = [] # type: T.List[str]
self.fail_count = 0 self.fail_count = 0
self.expectedfail_count = 0 self.expectedfail_count = 0
self.unexpectedpass_count = 0 self.unexpectedpass_count = 0
@ -638,9 +638,9 @@ class TestHarness:
self.timeout_count = 0 self.timeout_count = 0
self.is_run = False self.is_run = False
self.tests = None self.tests = None
self.logfilename = None # type: typing.Optional[str] self.logfilename = None # type: T.Optional[str]
self.logfile = None # type: typing.Optional[typing.TextIO] self.logfile = None # type: T.Optional[T.TextIO]
self.jsonlogfile = None # type: typing.Optional[typing.TextIO] self.jsonlogfile = None # type: T.Optional[T.TextIO]
if self.options.benchmark: if self.options.benchmark:
self.tests = load_benchmarks(options.wd) self.tests = load_benchmarks(options.wd)
else: else:
@ -668,7 +668,7 @@ class TestHarness:
self.jsonlogfile.close() self.jsonlogfile.close()
self.jsonlogfile = None self.jsonlogfile = None
def merge_suite_options(self, options: argparse.Namespace, test: 'TestSerialisation') -> typing.Dict[str, str]: def merge_suite_options(self, options: argparse.Namespace, test: 'TestSerialisation') -> T.Dict[str, str]:
if ':' in options.setup: if ':' in options.setup:
if options.setup not in self.build_data.test_setups: if options.setup not in self.build_data.test_setups:
sys.exit("Unknown test setup '%s'." % options.setup) sys.exit("Unknown test setup '%s'." % options.setup)
@ -720,7 +720,7 @@ class TestHarness:
else: else:
sys.exit('Unknown test result encountered: {}'.format(result.res)) sys.exit('Unknown test result encountered: {}'.format(result.res))
def print_stats(self, numlen: int, tests: typing.List['TestSerialisation'], def print_stats(self, numlen: int, tests: T.List['TestSerialisation'],
name: str, result: TestRun, i: int) -> None: name: str, result: TestRun, i: int) -> None:
startpad = ' ' * (numlen - len('%d' % (i + 1))) startpad = ' ' * (numlen - len('%d' % (i + 1)))
num = '%s%d/%d' % (startpad, i + 1, len(tests)) num = '%s%d/%d' % (startpad, i + 1, len(tests))
@ -803,16 +803,16 @@ Timeout: %4d
return self.total_failure_count() return self.total_failure_count()
@staticmethod @staticmethod
def split_suite_string(suite: str) -> typing.Tuple[str, str]: def split_suite_string(suite: str) -> T.Tuple[str, str]:
if ':' in suite: if ':' in suite:
# mypy can't figure out that str.split(n, 1) will return a list of # mypy can't figure out that str.split(n, 1) will return a list of
# length 2, so we have to help it. # length 2, so we have to help it.
return typing.cast(typing.Tuple[str, str], tuple(suite.split(':', 1))) return T.cast(T.Tuple[str, str], tuple(suite.split(':', 1)))
else: else:
return suite, "" return suite, ""
@staticmethod @staticmethod
def test_in_suites(test: 'TestSerialisation', suites: typing.List[str]) -> bool: def test_in_suites(test: 'TestSerialisation', suites: T.List[str]) -> bool:
for suite in suites: for suite in suites:
(prj_match, st_match) = TestHarness.split_suite_string(suite) (prj_match, st_match) = TestHarness.split_suite_string(suite)
for prjst in test.suite: for prjst in test.suite:
@ -848,7 +848,7 @@ Timeout: %4d
TestHarness.test_in_suites(test, self.options.include_suites)) and not TestHarness.test_in_suites(test, self.options.include_suites)) and not
TestHarness.test_in_suites(test, self.options.exclude_suites)) TestHarness.test_in_suites(test, self.options.exclude_suites))
def get_tests(self) -> typing.List['TestSerialisation']: def get_tests(self) -> T.List['TestSerialisation']:
if not self.tests: if not self.tests:
print('No tests defined.') print('No tests defined.')
return [] return []
@ -897,8 +897,8 @@ Timeout: %4d
self.logfile.write('Inherited environment: {}\n\n'.format(inherit_env)) self.logfile.write('Inherited environment: {}\n\n'.format(inherit_env))
@staticmethod @staticmethod
def get_wrapper(options: argparse.Namespace) -> typing.List[str]: def get_wrapper(options: argparse.Namespace) -> T.List[str]:
wrap = [] # type: typing.List[str] wrap = [] # type: T.List[str]
if options.gdb: if options.gdb:
wrap = [options.gdb_path, '--quiet', '--nh'] wrap = [options.gdb_path, '--quiet', '--nh']
if options.repeat > 1: if options.repeat > 1:
@ -919,9 +919,9 @@ Timeout: %4d
else: else:
return test.name return test.name
def run_tests(self, tests: typing.List['TestSerialisation']) -> None: def run_tests(self, tests: T.List['TestSerialisation']) -> None:
executor = None executor = None
futures = [] # type: typing.List[typing.Tuple[conc.Future[TestRun], int, typing.List[TestSerialisation], str, int]] futures = [] # type: T.List[T.Tuple[conc.Future[TestRun], int, T.List[TestSerialisation], str, int]]
numlen = len('%d' % len(tests)) numlen = len('%d' % len(tests))
self.open_log_files() self.open_log_files()
startdir = os.getcwd() startdir = os.getcwd()
@ -960,7 +960,7 @@ Timeout: %4d
finally: finally:
os.chdir(startdir) os.chdir(startdir)
def drain_futures(self, futures: typing.List[typing.Tuple['conc.Future[TestRun]', int, typing.List['TestSerialisation'], str, int]]) -> None: def drain_futures(self, futures: T.List[T.Tuple['conc.Future[TestRun]', int, T.List['TestSerialisation'], str, int]]) -> None:
for x in futures: for x in futures:
(result, numlen, tests, name, i) = x (result, numlen, tests, name, i) = x
if self.options.repeat > 1 and self.fail_count: if self.options.repeat > 1 and self.fail_count:
@ -1052,7 +1052,7 @@ def run(options: argparse.Namespace) -> int:
print(e) print(e)
return 1 return 1
def run_with_args(args: typing.List[str]) -> int: def run_with_args(args: T.List[str]) -> int:
parser = argparse.ArgumentParser(prog='meson test') parser = argparse.ArgumentParser(prog='meson test')
add_arguments(parser) add_arguments(parser)
options = parser.parse_args(args) options = parser.parse_args(args)

@ -14,7 +14,7 @@
import os, re import os, re
import functools import functools
import typing import typing as T
from . import mparser from . import mparser
from . import coredata from . import coredata
@ -131,7 +131,7 @@ option_types = {'string': StringParser,
'integer': IntegerParser, 'integer': IntegerParser,
'array': string_array_parser, 'array': string_array_parser,
'feature': FeatureParser, 'feature': FeatureParser,
} # type: typing.Dict[str, typing.Callable[[str, typing.Dict], coredata.UserOption]] } # type: T.Dict[str, T.Callable[[str, T.Dict], coredata.UserOption]]
class OptionInterpreter: class OptionInterpreter:
def __init__(self, subproject): def __init__(self, subproject):

@ -27,9 +27,9 @@ from .ast import IntrospectionInterpreter, build_target_functions, AstConditionL
from mesonbuild.mesonlib import MesonException from mesonbuild.mesonlib import MesonException
from . import mlog, environment from . import mlog, environment
from functools import wraps from functools import wraps
from typing import List, Dict, Optional
from .mparser import Token, ArrayNode, ArgumentNode, AssignmentNode, BaseNode, BooleanNode, ElementaryNode, IdNode, FunctionNode, StringNode from .mparser import Token, ArrayNode, ArgumentNode, AssignmentNode, BaseNode, BooleanNode, ElementaryNode, IdNode, FunctionNode, StringNode
import json, os, re, sys import json, os, re, sys
import typing as T
class RewriterException(MesonException): class RewriterException(MesonException):
pass pass
@ -101,7 +101,7 @@ class RequiredKeys:
return wrapped return wrapped
class MTypeBase: class MTypeBase:
def __init__(self, node: Optional[BaseNode] = None): def __init__(self, node: T.Optional[BaseNode] = None):
if node is None: if node is None:
self.node = self._new_node() # lgtm [py/init-calls-subclass] (node creation does not depend on base class state) self.node = self._new_node() # lgtm [py/init-calls-subclass] (node creation does not depend on base class state)
else: else:
@ -142,7 +142,7 @@ class MTypeBase:
mlog.warning('Cannot remove a regex in type', mlog.bold(type(self).__name__), '--> skipping') mlog.warning('Cannot remove a regex in type', mlog.bold(type(self).__name__), '--> skipping')
class MTypeStr(MTypeBase): class MTypeStr(MTypeBase):
def __init__(self, node: Optional[BaseNode] = None): def __init__(self, node: T.Optional[BaseNode] = None):
super().__init__(node) super().__init__(node)
def _new_node(self): def _new_node(self):
@ -155,7 +155,7 @@ class MTypeStr(MTypeBase):
self.node.value = str(value) self.node.value = str(value)
class MTypeBool(MTypeBase): class MTypeBool(MTypeBase):
def __init__(self, node: Optional[BaseNode] = None): def __init__(self, node: T.Optional[BaseNode] = None):
super().__init__(node) super().__init__(node)
def _new_node(self): def _new_node(self):
@ -168,7 +168,7 @@ class MTypeBool(MTypeBase):
self.node.value = bool(value) self.node.value = bool(value)
class MTypeID(MTypeBase): class MTypeID(MTypeBase):
def __init__(self, node: Optional[BaseNode] = None): def __init__(self, node: T.Optional[BaseNode] = None):
super().__init__(node) super().__init__(node)
def _new_node(self): def _new_node(self):
@ -181,7 +181,7 @@ class MTypeID(MTypeBase):
self.node.value = str(value) self.node.value = str(value)
class MTypeList(MTypeBase): class MTypeList(MTypeBase):
def __init__(self, node: Optional[BaseNode] = None): def __init__(self, node: T.Optional[BaseNode] = None):
super().__init__(node) super().__init__(node)
def _new_node(self): def _new_node(self):
@ -256,7 +256,7 @@ class MTypeList(MTypeBase):
self._remove_helper(regex, self._check_regex_matches) self._remove_helper(regex, self._check_regex_matches)
class MTypeStrList(MTypeList): class MTypeStrList(MTypeList):
def __init__(self, node: Optional[BaseNode] = None): def __init__(self, node: T.Optional[BaseNode] = None):
super().__init__(node) super().__init__(node)
def _new_element_node(self, value): def _new_element_node(self, value):
@ -276,7 +276,7 @@ class MTypeStrList(MTypeList):
return [StringNode] return [StringNode]
class MTypeIDList(MTypeList): class MTypeIDList(MTypeList):
def __init__(self, node: Optional[BaseNode] = None): def __init__(self, node: T.Optional[BaseNode] = None):
super().__init__(node) super().__init__(node)
def _new_element_node(self, value): def _new_element_node(self, value):
@ -392,7 +392,7 @@ class Rewriter:
raise MesonException('Rewriting the meson.build failed') raise MesonException('Rewriting the meson.build failed')
def find_target(self, target: str): def find_target(self, target: str):
def check_list(name: str) -> List[BaseNode]: def check_list(name: str) -> T.List[BaseNode]:
result = [] result = []
for i in self.interpreter.targets: for i in self.interpreter.targets:
if name == i['name'] or name == i['id']: if name == i['name'] or name == i['id']:
@ -744,7 +744,7 @@ class Rewriter:
mlog.yellow('{}:{}'.format(os.path.join(to_remove.subdir, environment.build_filename), to_remove.lineno))) mlog.yellow('{}:{}'.format(os.path.join(to_remove.subdir, environment.build_filename), to_remove.lineno)))
elif cmd['operation'] == 'info': elif cmd['operation'] == 'info':
# List all sources in the target # T.List all sources in the target
src_list = [] src_list = []
for i in target['sources']: for i in target['sources']:
for j in arg_list_from_node(i): for j in arg_list_from_node(i):
@ -876,7 +876,7 @@ target_operation_map = {
'info': 'info', 'info': 'info',
} }
def list_to_dict(in_list: List[str]) -> Dict[str, str]: def list_to_dict(in_list: T.List[str]) -> T.Dict[str, str]:
result = {} result = {}
it = iter(in_list) it = iter(in_list)
try: try:
@ -889,7 +889,7 @@ def list_to_dict(in_list: List[str]) -> Dict[str, str]:
raise TypeError('in_list parameter of list_to_dict must have an even length.') raise TypeError('in_list parameter of list_to_dict must have an even length.')
return result return result
def generate_target(options) -> List[dict]: def generate_target(options) -> T.List[dict]:
return [{ return [{
'type': 'target', 'type': 'target',
'target': options.target, 'target': options.target,
@ -899,7 +899,7 @@ def generate_target(options) -> List[dict]:
'target_type': options.tgt_type, 'target_type': options.tgt_type,
}] }]
def generate_kwargs(options) -> List[dict]: def generate_kwargs(options) -> T.List[dict]:
return [{ return [{
'type': 'kwargs', 'type': 'kwargs',
'function': options.function, 'function': options.function,
@ -908,14 +908,14 @@ def generate_kwargs(options) -> List[dict]:
'kwargs': list_to_dict(options.kwargs), 'kwargs': list_to_dict(options.kwargs),
}] }]
def generate_def_opts(options) -> List[dict]: def generate_def_opts(options) -> T.List[dict]:
return [{ return [{
'type': 'default_options', 'type': 'default_options',
'operation': options.operation, 'operation': options.operation,
'options': list_to_dict(options.options), 'options': list_to_dict(options.options),
}] }]
def genreate_cmd(options) -> List[dict]: def genreate_cmd(options) -> T.List[dict]:
if os.path.exists(options.json): if os.path.exists(options.json):
with open(options.json, 'r') as fp: with open(options.json, 'r') as fp:
return json.load(fp) return json.load(fp)

@ -25,12 +25,12 @@ import stat
import subprocess import subprocess
import sys import sys
import configparser import configparser
import typing import typing as T
from . import WrapMode from . import WrapMode
from ..mesonlib import ProgressBar, MesonException from ..mesonlib import ProgressBar, MesonException
if typing.TYPE_CHECKING: if T.TYPE_CHECKING:
import http.client import http.client
try: try:
@ -48,7 +48,7 @@ ssl_warning_printed = False
whitelist_subdomain = 'wrapdb.mesonbuild.com' whitelist_subdomain = 'wrapdb.mesonbuild.com'
def quiet_git(cmd: typing.List[str], workingdir: str) -> typing.Tuple[bool, str]: def quiet_git(cmd: T.List[str], workingdir: str) -> T.Tuple[bool, str]:
git = shutil.which('git') git = shutil.which('git')
if not git: if not git:
return False, 'Git program not found.' return False, 'Git program not found.'
@ -258,7 +258,7 @@ class Resolver:
raise WrapException('Git program not found.') raise WrapException('Git program not found.')
revno = self.wrap.get('revision') revno = self.wrap.get('revision')
is_shallow = False is_shallow = False
depth_option = [] # type: typing.List[str] depth_option = [] # type: T.List[str]
if self.wrap.values.get('depth', '') != '': if self.wrap.values.get('depth', '') != '':
is_shallow = True is_shallow = True
depth_option = ['--depth', self.wrap.values.get('depth')] depth_option = ['--depth', self.wrap.values.get('depth')]
@ -330,7 +330,7 @@ class Resolver:
subprocess.check_call([svn, 'checkout', '-r', revno, self.wrap.get('url'), subprocess.check_call([svn, 'checkout', '-r', revno, self.wrap.get('url'),
self.directory], cwd=self.subdir_root) self.directory], cwd=self.subdir_root)
def get_data(self, urlstring: str) -> typing.Tuple[str, str]: def get_data(self, urlstring: str) -> T.Tuple[str, str]:
blocksize = 10 * 1024 blocksize = 10 * 1024
h = hashlib.sha256() h = hashlib.sha256()
tmpfile = tempfile.NamedTemporaryFile(mode='wb', dir=self.cachedir, delete=False) tmpfile = tempfile.NamedTemporaryFile(mode='wb', dir=self.cachedir, delete=False)

@ -14,7 +14,7 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
import typing import typing as T
import itertools import itertools
import os import os
import subprocess import subprocess
@ -117,7 +117,7 @@ def setup_commands(optbackend):
compile_commands, clean_commands, test_commands, install_commands, \ compile_commands, clean_commands, test_commands, install_commands, \
uninstall_commands = get_backend_commands(backend, do_debug) uninstall_commands = get_backend_commands(backend, do_debug)
def get_relative_files_list_from_dir(fromdir: Path) -> typing.List[Path]: def get_relative_files_list_from_dir(fromdir: Path) -> T.List[Path]:
return [file.relative_to(fromdir) for file in fromdir.rglob('*') if file.is_file()] return [file.relative_to(fromdir) for file in fromdir.rglob('*') if file.is_file()]
def platform_fix_name(fname: str, compiler, env) -> str: def platform_fix_name(fname: str, compiler, env) -> str:
@ -207,7 +207,7 @@ def validate_install(srcdir: str, installdir: Path, compiler, env) -> str:
installdir = Path(installdir) installdir = Path(installdir)
# If this exists, the test does not install any other files # If this exists, the test does not install any other files
noinst_file = Path('usr/no-installed-files') noinst_file = Path('usr/no-installed-files')
expected = {} # type: typing.Dict[Path, bool] expected = {} # type: T.Dict[Path, bool]
ret_msg = '' ret_msg = ''
# Generate list of expected files # Generate list of expected files
if (installdir / noinst_file).is_file(): if (installdir / noinst_file).is_file():
@ -279,7 +279,7 @@ def yellow(text):
return mlog.yellow(text).get_text(mlog.colorize_console) return mlog.yellow(text).get_text(mlog.colorize_console)
def _run_ci_include(args: typing.List[str]) -> str: def _run_ci_include(args: T.List[str]) -> str:
if not args: if not args:
return 'At least one parameter required' return 'At least one parameter required'
try: try:
@ -293,7 +293,7 @@ ci_commands = {
'ci_include': _run_ci_include 'ci_include': _run_ci_include
} }
def run_ci_commands(raw_log: str) -> typing.List[str]: def run_ci_commands(raw_log: str) -> T.List[str]:
res = [] res = []
for l in raw_log.splitlines(): for l in raw_log.splitlines():
if not l.startswith('!meson_ci!/'): if not l.startswith('!meson_ci!/'):
@ -474,7 +474,7 @@ def _run_test(testdir, test_build_dir, install_dir, extra_args, compiler, backen
return TestResult(validate_install(testdir, install_dir, compiler, builddata.environment), return TestResult(validate_install(testdir, install_dir, compiler, builddata.environment),
BuildStep.validate, stdo, stde, mesonlog, cicmds, gen_time, build_time, test_time) BuildStep.validate, stdo, stde, mesonlog, cicmds, gen_time, build_time, test_time)
def gather_tests(testdir: Path) -> typing.List[Path]: def gather_tests(testdir: Path) -> T.List[Path]:
test_names = [t.name for t in testdir.glob('*') if t.is_dir()] test_names = [t.name for t in testdir.glob('*') if t.is_dir()]
test_names = [t for t in test_names if not t.startswith('.')] # Filter non-tests files (dot files, etc) test_names = [t for t in test_names if not t.startswith('.')] # Filter non-tests files (dot files, etc)
test_nums = [(int(t.split()[0]), t) for t in test_names] test_nums = [(int(t.split()[0]), t) for t in test_names]
@ -630,7 +630,7 @@ def should_skip_rust(backend: Backend) -> bool:
return True return True
return False return False
def detect_tests_to_run(only: typing.List[str]) -> typing.List[typing.Tuple[str, typing.List[Path], bool]]: def detect_tests_to_run(only: T.List[str]) -> T.List[T.Tuple[str, T.List[Path], bool]]:
""" """
Parameters Parameters
---------- ----------
@ -689,18 +689,18 @@ def detect_tests_to_run(only: typing.List[str]) -> typing.List[typing.Tuple[str,
gathered_tests = [(name, gather_tests(Path('test cases', subdir)), skip) for name, subdir, skip in all_tests] gathered_tests = [(name, gather_tests(Path('test cases', subdir)), skip) for name, subdir, skip in all_tests]
return gathered_tests return gathered_tests
def run_tests(all_tests: typing.List[typing.Tuple[str, typing.List[Path], bool]], def run_tests(all_tests: T.List[T.Tuple[str, T.List[Path], bool]],
log_name_base: str, failfast: bool, log_name_base: str, failfast: bool,
extra_args: typing.List[str]) -> typing.Tuple[int, int, int]: extra_args: T.List[str]) -> T.Tuple[int, int, int]:
global logfile global logfile
txtname = log_name_base + '.txt' txtname = log_name_base + '.txt'
with open(txtname, 'w', encoding='utf-8', errors='ignore') as lf: with open(txtname, 'w', encoding='utf-8', errors='ignore') as lf:
logfile = lf logfile = lf
return _run_tests(all_tests, log_name_base, failfast, extra_args) return _run_tests(all_tests, log_name_base, failfast, extra_args)
def _run_tests(all_tests: typing.List[typing.Tuple[str, typing.List[Path], bool]], def _run_tests(all_tests: T.List[T.Tuple[str, T.List[Path], bool]],
log_name_base: str, failfast: bool, log_name_base: str, failfast: bool,
extra_args: typing.List[str]) -> typing.Tuple[int, int, int]: extra_args: T.List[str]) -> T.Tuple[int, int, int]:
global stop, executor, futures, system_compiler global stop, executor, futures, system_compiler
xmlname = log_name_base + '.xml' xmlname = log_name_base + '.xml'
junit_root = ET.Element('testsuites') junit_root = ET.Element('testsuites')

@ -14,7 +14,7 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
import typing import typing as T
from pathlib import Path from pathlib import Path
import sys import sys
import re import re
@ -47,7 +47,7 @@ class Lexer:
('rparen', re.compile(r'\)')), ('rparen', re.compile(r'\)')),
] ]
def lex(self, code: str) -> typing.Iterator[Token]: def lex(self, code: str) -> T.Iterator[Token]:
lineno = 1 lineno = 1
line_start = 0 line_start = 0
loc = 0 loc = 0
@ -135,7 +135,7 @@ class Parser:
args += rest args += rest
return args return args
def parse(self) -> typing.Iterator[Statement]: def parse(self) -> T.Iterator[Statement]:
while not self.accept('eof'): while not self.accept('eof'):
yield(self.statement()) yield(self.statement())
@ -148,9 +148,9 @@ class Converter:
self.cmake_root = Path(cmake_root).expanduser() self.cmake_root = Path(cmake_root).expanduser()
self.indent_unit = ' ' self.indent_unit = ' '
self.indent_level = 0 self.indent_level = 0
self.options = [] # type: typing.List[tuple] self.options = [] # type: T.List[tuple]
def convert_args(self, args: typing.List[Token], as_array: bool = True) -> str: def convert_args(self, args: T.List[Token], as_array: bool = True) -> str:
res = [] res = []
if as_array: if as_array:
start = '[' start = '['
@ -173,7 +173,7 @@ class Converter:
return res[0] return res[0]
return '' return ''
def write_entry(self, outfile: typing.TextIO, t: Statement): def write_entry(self, outfile: T.TextIO, t: Statement):
if t.name in Converter.ignored_funcs: if t.name in Converter.ignored_funcs:
return return
preincrement = 0 preincrement = 0

@ -32,14 +32,14 @@ to this:
This directory must be run from source root as it touches run_unittests.py. This directory must be run from source root as it touches run_unittests.py.
''' '''
import typing import typing as T
import os import os
import sys import sys
import subprocess import subprocess
from glob import glob from glob import glob
def get_entries() -> typing.List[typing.Tuple[int, str]]: def get_entries() -> T.List[T.Tuple[int, str]]:
entries = [] entries = []
for e in glob('*'): for e in glob('*'):
if not os.path.isdir(e): if not os.path.isdir(e):
@ -53,7 +53,7 @@ def get_entries() -> typing.List[typing.Tuple[int, str]]:
entries.sort() entries.sort()
return entries return entries
def replace_source(sourcefile: str, replacements: typing.List[typing.Tuple[str, str]]): def replace_source(sourcefile: str, replacements: T.List[T.Tuple[str, str]]):
with open(sourcefile, 'r') as f: with open(sourcefile, 'r') as f:
contents = f.read() contents = f.read()
for old_name, new_name in replacements: for old_name, new_name in replacements:

Loading…
Cancel
Save