diff --git a/mesonbuild/dependencies/__init__.py b/mesonbuild/dependencies/__init__.py index 7f03eec79d99..56f1229b9c72 100644 --- a/mesonbuild/dependencies/__init__.py +++ b/mesonbuild/dependencies/__init__.py @@ -105,7 +105,7 @@ def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T. ```python class FooSystemDependency(ExternalDependency): - def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any]): + def __init__(self, name: str, environment: Environment, kwargs: DependencyKWs): super().__init__(name, environment, kwargs) root = environment.properties[self.for_machine].foo_root if root is None: diff --git a/mesonbuild/dependencies/base.py b/mesonbuild/dependencies/base.py index d3c18cec22d2..e3e7942a6f90 100644 --- a/mesonbuild/dependencies/base.py +++ b/mesonbuild/dependencies/base.py @@ -21,7 +21,7 @@ #from ..interpreterbase import FeatureDeprecated, FeatureNew if T.TYPE_CHECKING: - from typing_extensions import Literal + from typing_extensions import Literal, TypedDict from ..compilers.compilers import Compiler from ..environment import Environment @@ -32,6 +32,44 @@ ) from ..interpreter.type_checking import PkgConfigDefineType + # This must be kept in sync with the FuncDependency class in + # interpreter.type_checking + # They cannot share in anyway due to the way total works + class DependencyKWs(TypedDict, total=False): + + # The following arguments to `dependency()` are used in the interpreter, + # and are not needed here: + # - allow_fallback + # - default_options + # - fallback + # - not_found_message + + cmake_args: T.List[str] + cmake_module_path: T.List[str] + cmake_package_version: str + components: T.List[str] + embed: bool + include_type: Literal['system', 'non-system', 'preserve'] + language: T.Optional[str] # TODO: use a shared literal? + main: bool + method: str + modules: T.List[str] + native: MachineChoice + optional_modules: T.List[str] + private_headers: bool + required: bool + static: T.Optional[bool] + version: T.List[str] + + # These options only exist as implementation details to Dependency + # classes, and are not available to the DSL + silent: bool + tools: T.List[str] + returncode_value: int + paths: T.List[str] + version_arg: str + skip_version: str + _MissingCompilerBase = Compiler else: _MissingCompilerBase = object @@ -99,7 +137,7 @@ class DependencyMethods(Enum): class Dependency(HoldableObject): - def __init__(self, type_name: DependencyTypeName, kwargs: T.Dict[str, T.Any]) -> None: + def __init__(self, type_name: DependencyTypeName, kwargs: DependencyKWs) -> None: # This allows two Dependencies to be compared even after being copied. # The purpose is to allow the name to be changed, but still have a proper comparison self._id = uuid.uuid4().int @@ -373,25 +411,23 @@ def get_as_shared(self, recursive: bool) -> InternalDependency: return new_dep class ExternalDependency(Dependency): - def __init__(self, type_name: DependencyTypeName, environment: 'Environment', kwargs: T.Dict[str, T.Any], language: T.Optional[str] = None): + def __init__(self, type_name: DependencyTypeName, environment: 'Environment', kwargs: DependencyKWs, language: T.Optional[str] = None): Dependency.__init__(self, type_name, kwargs) self.env = environment self.name = type_name # default self.is_found = False self.language = language version_reqs = kwargs.get('version', None) - if isinstance(version_reqs, str): - version_reqs = [version_reqs] - self.version_reqs: T.Optional[T.List[str]] = version_reqs + self.version_reqs = version_reqs self.required = kwargs.get('required', True) self.silent = kwargs.get('silent', False) static = kwargs.get('static') if static is None: - static = self.env.coredata.get_option(OptionKey('prefer_static')) - self.static = T.cast('bool', static) + static = T.cast('bool', self.env.coredata.get_option(OptionKey('prefer_static'))) + self.static = static self.libtype = LibType.STATIC if self.static else LibType.PREFER_SHARED # Is this dependency to be run on the build platform? - self.for_machine = T.cast('MachineChoice', kwargs.get('native', MachineChoice.HOST)) + self.for_machine = kwargs.get('native', MachineChoice.HOST) self.clib_compiler = detect_compiler(self.name, environment, self.for_machine, self.language) def get_compiler(self) -> T.Union['MissingCompiler', 'Compiler']: @@ -580,7 +616,7 @@ def strip_system_includedirs(environment: 'Environment', for_machine: MachineCho exclude = {f'-I{p}' for p in environment.get_compiler_system_include_dirs(for_machine)} return [i for i in include_args if i not in exclude] -def process_method_kw(possible: T.Iterable[DependencyMethods], kwargs: T.Dict[str, T.Any]) -> T.List[DependencyMethods]: +def process_method_kw(possible: T.Iterable[DependencyMethods], kwargs: DependencyKWs) -> T.List[DependencyMethods]: method: T.Union[DependencyMethods, str] = kwargs.get('method', 'auto') if isinstance(method, DependencyMethods): return [method] @@ -646,7 +682,7 @@ class SystemDependency(ExternalDependency): """Dependency base for System type dependencies.""" - def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any], + def __init__(self, name: str, env: 'Environment', kwargs: DependencyKWs, language: T.Optional[str] = None) -> None: super().__init__(DependencyTypeName('system'), env, kwargs, language=language) self.name = name @@ -660,7 +696,7 @@ class BuiltinDependency(ExternalDependency): """Dependency base for Builtin type dependencies.""" - def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any], + def __init__(self, name: str, env: 'Environment', kwargs: DependencyKWs, language: T.Optional[str] = None) -> None: super().__init__(DependencyTypeName('builtin'), env, kwargs, language=language) self.name = name diff --git a/mesonbuild/dependencies/boost.py b/mesonbuild/dependencies/boost.py index 1aac2ce24313..53c82f6615fe 100644 --- a/mesonbuild/dependencies/boost.py +++ b/mesonbuild/dependencies/boost.py @@ -19,6 +19,7 @@ from .misc import threads_factory if T.TYPE_CHECKING: + from .base import DependencyKWs from ..envconfig import Properties from ..environment import Environment @@ -339,7 +340,7 @@ def get_link_args(self) -> T.List[str]: return [self.path.as_posix()] class BoostDependency(SystemDependency): - def __init__(self, environment: Environment, kwargs: T.Dict[str, T.Any]) -> None: + def __init__(self, environment: Environment, kwargs: DependencyKWs) -> None: super().__init__('boost', environment, kwargs, language='cpp') buildtype = environment.coredata.get_option(OptionKey('buildtype')) assert isinstance(buildtype, str) diff --git a/mesonbuild/dependencies/cmake.py b/mesonbuild/dependencies/cmake.py index 96f723e26331..6c5cb2c42d86 100644 --- a/mesonbuild/dependencies/cmake.py +++ b/mesonbuild/dependencies/cmake.py @@ -17,6 +17,7 @@ import typing as T if T.TYPE_CHECKING: + from .base import DependencyKWs from ..cmake import CMakeTarget from ..environment import Environment from ..envconfig import MachineInfo @@ -69,11 +70,11 @@ def _original_module_name(self, module: str) -> str: # one module return module - def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any], language: T.Optional[str] = None, force_use_global_compilers: bool = False) -> None: + def __init__(self, name: str, environment: 'Environment', kwargs: DependencyKWs, language: T.Optional[str] = None, force_use_global_compilers: bool = False) -> None: # Gather a list of all languages to support self.language_list: T.List[str] = [] if language is None or force_use_global_compilers: - for_machine = T.cast('MachineChoice', kwargs.get('native', MachineChoice.HOST)) + for_machine = kwargs.get('native', MachineChoice.HOST) compilers = environment.coredata.compilers[for_machine] candidates = ['c', 'cpp', 'fortran', 'objc', 'objcxx'] self.language_list += [x for x in candidates if x in compilers] @@ -112,7 +113,7 @@ def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T. # Setup the trace parser self.traceparser = CMakeTraceParser(self.cmakebin.version(), self._get_build_dir(), self.env) - cm_args = T.cast('T.List[str]', kwargs.get('cmake_args', [])) + cm_args = kwargs.get('cmake_args', []) cm_args = check_cmake_args(cm_args) if CMakeDependency.class_cmakeinfo[self.for_machine] is None: CMakeDependency.class_cmakeinfo[self.for_machine] = self._get_cmake_info(cm_args) @@ -121,11 +122,11 @@ def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T. raise self._gen_exception('Unable to obtain CMake system information') self.cmakeinfo = cmakeinfo - package_version = T.cast('str', kwargs.get('cmake_package_version', '')) - components = [(x, True) for x in T.cast('T.List[str]', kwargs.get('components', []))] - modules = [(x, True) for x in T.cast('T.List[str]', kwargs.get('modules', []))] - modules += [(x, False) for x in T.cast('T.List[str]', kwargs.get('optional_modules', []))] - cm_path = T.cast('T.List[str]', kwargs.get('cmake_module_path', [])) + package_version = kwargs.get('cmake_package_version', '') + components = [(x, True) for x in kwargs.get('components', [])] + modules = [(x, True) for x in kwargs.get('modules', [])] + modules += [(x, False) for x in kwargs.get('optional_modules', [])] + cm_path = kwargs.get('cmake_module_path', []) cm_path = [x if os.path.isabs(x) else os.path.join(environment.get_source_dir(), x) for x in cm_path] if cm_path: cm_args.append('-DCMAKE_MODULE_PATH=' + ';'.join(cm_path)) @@ -640,7 +641,7 @@ def __init__(self, name: T.Optional[str] = None, modules: T.Optional[T.List[str] self.name = name self.modules = modules - def __call__(self, name: str, env: Environment, kwargs: T.Dict[str, T.Any], language: T.Optional[str] = None, force_use_global_compilers: bool = False) -> CMakeDependency: + def __call__(self, name: str, env: Environment, kwargs: DependencyKWs, language: T.Optional[str] = None, force_use_global_compilers: bool = False) -> CMakeDependency: if self.modules: kwargs['modules'] = self.modules return CMakeDependency(self.name or name, env, kwargs, language, force_use_global_compilers) diff --git a/mesonbuild/dependencies/coarrays.py b/mesonbuild/dependencies/coarrays.py index 01213d1fb0f0..be8c2e3d2afb 100644 --- a/mesonbuild/dependencies/coarrays.py +++ b/mesonbuild/dependencies/coarrays.py @@ -13,6 +13,7 @@ from .factory import factory_methods if T.TYPE_CHECKING: + from .base import DependencyKWs from . factory import DependencyGenerator from ..environment import Environment from ..mesonlib import MachineChoice @@ -21,7 +22,7 @@ @factory_methods({DependencyMethods.PKGCONFIG, DependencyMethods.CMAKE, DependencyMethods.SYSTEM}) def coarray_factory(env: 'Environment', for_machine: 'MachineChoice', - kwargs: T.Dict[str, T.Any], + kwargs: DependencyKWs, methods: T.List[DependencyMethods]) -> T.List['DependencyGenerator']: fcid = detect_compiler('coarray', env, for_machine, 'fortran').get_id() candidates: T.List['DependencyGenerator'] = [] @@ -55,7 +56,7 @@ class CoarrayDependency(SystemDependency): Coarrays may be thought of as a high-level language abstraction of low-level MPI calls. """ - def __init__(self, environment: 'Environment', kwargs: T.Dict[str, T.Any]) -> None: + def __init__(self, environment: 'Environment', kwargs: DependencyKWs) -> None: super().__init__('coarray', environment, kwargs, language='fortran') kwargs['required'] = False kwargs['silent'] = True diff --git a/mesonbuild/dependencies/configtool.py b/mesonbuild/dependencies/configtool.py index 7d632a00cd59..4caa4e366c55 100644 --- a/mesonbuild/dependencies/configtool.py +++ b/mesonbuild/dependencies/configtool.py @@ -11,6 +11,7 @@ import typing as T if T.TYPE_CHECKING: + from .base import DependencyKWs from ..environment import Environment from ..interpreter.type_checking import PkgConfigDefineType @@ -35,7 +36,7 @@ class ConfigToolDependency(ExternalDependency): allow_default_for_cross = False __strip_version = re.compile(r'^[0-9][0-9.]+') - def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any], language: T.Optional[str] = None, exclude_paths: T.Optional[T.List[str]] = None): + def __init__(self, name: str, environment: 'Environment', kwargs: DependencyKWs, language: T.Optional[str] = None, exclude_paths: T.Optional[T.List[str]] = None): super().__init__(DependencyTypeName('config-tool'), environment, kwargs, language=language) self.name = name # You may want to overwrite the class version in some cases diff --git a/mesonbuild/dependencies/cuda.py b/mesonbuild/dependencies/cuda.py index 096a4d834bf9..fa3535d54c61 100644 --- a/mesonbuild/dependencies/cuda.py +++ b/mesonbuild/dependencies/cuda.py @@ -17,6 +17,7 @@ if T.TYPE_CHECKING: + from .base import DependencyKWs from ..environment import Environment from ..compilers import Compiler @@ -26,7 +27,7 @@ class CudaDependency(SystemDependency): supported_languages = ['cpp', 'c', 'cuda'] # see also _default_language - def __init__(self, environment: 'Environment', kwargs: T.Dict[str, T.Any]) -> None: + def __init__(self, environment: 'Environment', kwargs: DependencyKWs) -> None: compilers = environment.coredata.compilers[kwargs.get('native', mesonlib.MachineChoice.HOST)] language = self._detect_language(compilers) if language not in self.supported_languages: @@ -276,8 +277,8 @@ def log_details(self) -> str: def log_info(self) -> str: return self.cuda_path if self.cuda_path else '' - def get_requested(self, kwargs: T.Dict[str, T.Any]) -> T.List[str]: - candidates = T.cast('T.List[str]', kwargs.get('modules', [])) + def get_requested(self, kwargs: DependencyKWs) -> T.List[str]: + candidates = kwargs.get('modules', []) for c in candidates: if not isinstance(c, str): raise DependencyException('CUDA module argument is not a string.') diff --git a/mesonbuild/dependencies/detect.py b/mesonbuild/dependencies/detect.py index 1886ba1e9441..99e993d86b40 100644 --- a/mesonbuild/dependencies/detect.py +++ b/mesonbuild/dependencies/detect.py @@ -12,6 +12,7 @@ from .. import mlog if T.TYPE_CHECKING: + from .base import DependencyKWs from ..environment import Environment from .factory import DependencyFactory, WrappedFactoryFunc, DependencyGenerator @@ -38,7 +39,7 @@ def __contains__(self, key: object) -> bool: packages = DependencyPackages() _packages_accept_language: T.Set[str] = set() -def get_dep_identifier(name: str, kwargs: T.Dict[str, T.Any]) -> 'TV_DepID': +def get_dep_identifier(name: str, kwargs: DependencyKWs) -> 'TV_DepID': identifier: 'TV_DepID' = (('name', name), ) from ..interpreter.type_checking import DEPENDENCY_KWS @@ -85,7 +86,7 @@ def get_dep_identifier(name: str, kwargs: T.Dict[str, T.Any]) -> 'TV_DepID': 'wxwidgets': 'WxWidgets', } -def find_external_dependency(name: str, env: 'Environment', kwargs: T.Dict[str, object], candidates: T.Optional[T.List['DependencyGenerator']] = None) -> T.Union['ExternalDependency', NotFoundDependency]: +def find_external_dependency(name: str, env: 'Environment', kwargs: DependencyKWs, candidates: T.Optional[T.List['DependencyGenerator']] = None) -> T.Union['ExternalDependency', NotFoundDependency]: assert name required = kwargs.get('required', True) lname = name.lower() @@ -95,7 +96,7 @@ def find_external_dependency(name: str, env: 'Environment', kwargs: T.Dict[str, # display the dependency name with correct casing display_name = display_name_map.get(lname, lname) - for_machine = T.cast('MachineChoice', kwargs.get('native', MachineChoice.HOST)) + for_machine = kwargs.get('native', MachineChoice.HOST) type_text = PerMachine('Build-time', 'Run-time')[for_machine] + ' dependency' # build a list of dependency methods to try @@ -167,7 +168,7 @@ def find_external_dependency(name: str, env: 'Environment', kwargs: T.Dict[str, def _build_external_dependency_list(name: str, env: 'Environment', for_machine: MachineChoice, - kwargs: T.Dict[str, T.Any]) -> T.List['DependencyGenerator']: + kwargs: DependencyKWs) -> T.List['DependencyGenerator']: # Is there a specific dependency detector for this dependency? lname = name.lower() if lname in packages: diff --git a/mesonbuild/dependencies/dev.py b/mesonbuild/dependencies/dev.py index 269de3454544..9744c6912260 100644 --- a/mesonbuild/dependencies/dev.py +++ b/mesonbuild/dependencies/dev.py @@ -26,19 +26,13 @@ from .pkgconfig import PkgConfigDependency if T.TYPE_CHECKING: + from .base import DependencyKWs from ..envconfig import MachineInfo from ..environment import Environment from ..compilers import Compiler from ..mesonlib import MachineChoice - from typing_extensions import TypedDict from ..interpreter.type_checking import PkgConfigDefineType - class JNISystemDependencyKW(TypedDict): - modules: T.List[str] - # FIXME: When dependency() moves to typed Kwargs, this should inherit - # from its TypedDict type. - version: T.Optional[str] - def get_shared_library_suffix(environment: 'Environment', for_machine: MachineChoice) -> str: """This is only guaranteed to work for languages that compile to machine @@ -53,7 +47,7 @@ def get_shared_library_suffix(environment: 'Environment', for_machine: MachineCh class GTestDependencySystem(SystemDependency): - def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any]) -> None: + def __init__(self, name: str, environment: 'Environment', kwargs: DependencyKWs) -> None: super().__init__(name, environment, kwargs, language='cpp') self.main = kwargs.get('main', False) self.src_dirs = ['/usr/src/gtest/src', '/usr/src/googletest/googletest/src'] @@ -108,7 +102,7 @@ def log_info(self) -> str: class GTestDependencyPC(PkgConfigDependency): - def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any]): + def __init__(self, name: str, environment: 'Environment', kwargs: DependencyKWs): assert name == 'gtest' if kwargs.get('main'): name = 'gtest_main' @@ -116,7 +110,7 @@ def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T. class GMockDependencySystem(SystemDependency): - def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any]) -> None: + def __init__(self, name: str, environment: 'Environment', kwargs: DependencyKWs) -> None: super().__init__(name, environment, kwargs, language='cpp') self.main = kwargs.get('main', False) if not self._add_sub_dependency(threads_factory(environment, self.for_machine, {})): @@ -176,7 +170,7 @@ def log_info(self) -> str: class GMockDependencyPC(PkgConfigDependency): - def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any]): + def __init__(self, name: str, environment: 'Environment', kwargs: DependencyKWs): assert name == 'gmock' if kwargs.get('main'): name = 'gmock_main' @@ -191,7 +185,7 @@ class LLVMDependencyConfigTool(ConfigToolDependency): tool_name = 'llvm-config' __cpp_blacklist = {'-DNDEBUG'} - def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any]): + def __init__(self, name: str, environment: 'Environment', kwargs: DependencyKWs): self.tools = get_llvm_tool_names('llvm-config') # Fedora starting with Fedora 30 adds a suffix of the number @@ -213,9 +207,9 @@ def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T. return self.provided_modules = self.get_config_value(['--components'], 'modules') - modules = T.cast('T.List[str]', kwargs.get('modules', [])) + modules = kwargs.get('modules', []) self.check_components(modules) - opt_modules = T.cast('T.List[str]', kwargs.get('optional_modules', [])) + opt_modules = kwargs.get('optional_modules', []) self.check_components(opt_modules, required=False) cargs = mesonlib.OrderedSet(self.get_config_value(['--cppflags'], 'compile_args')) @@ -386,11 +380,11 @@ def log_details(self) -> str: return '' class LLVMDependencyCMake(CMakeDependency): - def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]) -> None: - self.llvm_modules = T.cast('T.List[str]', kwargs.get('modules', [])) - self.llvm_opt_modules = T.cast('T.List[str]', kwargs.get('optional_modules', [])) + def __init__(self, name: str, env: 'Environment', kwargs: DependencyKWs) -> None: + self.llvm_modules = kwargs.get('modules', []) + self.llvm_opt_modules = kwargs.get('optional_modules', []) - for_machine = T.cast('MachineChoice', kwargs.get('native', mesonlib.MachineChoice.HOST)) + for_machine = kwargs.get('native', mesonlib.MachineChoice.HOST) compilers = env.coredata.compilers[for_machine] if not compilers or not {'c', 'cpp'}.issubset(compilers): # Initialize basic variables @@ -510,7 +504,7 @@ class ValgrindDependency(PkgConfigDependency): Consumers of Valgrind usually only need the compile args and do not want to link to its (static) libraries. ''' - def __init__(self, env: 'Environment', kwargs: T.Dict[str, T.Any]): + def __init__(self, env: 'Environment', kwargs: DependencyKWs): super().__init__('valgrind', env, kwargs) def get_link_args(self, language: T.Optional[str] = None, raw: bool = False) -> T.List[str]: @@ -521,7 +515,7 @@ def get_link_args(self, language: T.Optional[str] = None, raw: bool = False) -> class ZlibSystemDependency(SystemDependency): - def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any]): + def __init__(self, name: str, environment: 'Environment', kwargs: DependencyKWs): super().__init__(name, environment, kwargs) from ..compilers.c import AppleClangCCompiler from ..compilers.cpp import AppleClangCPPCompiler @@ -558,8 +552,8 @@ def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T. class JNISystemDependency(SystemDependency): - def __init__(self, environment: 'Environment', kwargs: JNISystemDependencyKW): - super().__init__('jni', environment, T.cast('T.Dict[str, T.Any]', kwargs)) + def __init__(self, environment: 'Environment', kwargs: DependencyKWs): + super().__init__('jni', environment, kwargs) self.feature_since = ('0.62.0', '') @@ -570,7 +564,7 @@ def __init__(self, environment: 'Environment', kwargs: JNISystemDependencyKW): self.javac = environment.coredata.compilers[self.for_machine]['java'] self.version = self.javac.version - modules = T.cast('T.List[str]', kwargs.get('modules', [])) + modules = kwargs.get('modules', []) for module in modules: if module not in {'jvm', 'awt'}: msg = f'Unknown JNI module ({module})' @@ -686,7 +680,7 @@ def __machine_info_to_platform_include_dir(m: 'MachineInfo') -> T.Optional[str]: class JDKSystemDependency(JNISystemDependency): - def __init__(self, environment: 'Environment', kwargs: JNISystemDependencyKW): + def __init__(self, environment: 'Environment', kwargs: DependencyKWs): super().__init__(environment, kwargs) self.feature_since = ('0.59.0', '') @@ -752,7 +746,7 @@ def _has_define(compiler: 'Compiler', dname: str, env: 'Environment') -> bool: defval, _ = compiler.get_define(dname, '', env, [], []) return defval is not None - def __init__(self, environment: 'Environment', kwargs: T.Dict[str, T.Any]) -> None: + def __init__(self, environment: 'Environment', kwargs: DependencyKWs) -> None: super().__init__('diasdk', environment, kwargs) self.is_found = False diff --git a/mesonbuild/dependencies/dub.py b/mesonbuild/dependencies/dub.py index cf59d78abe7a..42d9bb769b7d 100644 --- a/mesonbuild/dependencies/dub.py +++ b/mesonbuild/dependencies/dub.py @@ -17,6 +17,7 @@ if T.TYPE_CHECKING: from typing_extensions import TypedDict + from .base import DependencyKWs from ..environment import Environment # Definition of what `dub describe` returns (only the fields used by Meson) @@ -69,7 +70,7 @@ class DubDependency(ExternalDependency): 'llvm': 'ldc', } - def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any]): + def __init__(self, name: str, environment: 'Environment', kwargs: DependencyKWs): super().__init__(DependencyTypeName('dub'), environment, kwargs, language='d') self.name = name from ..compilers.d import DCompiler, d_feature_args @@ -79,7 +80,7 @@ def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T. self.compiler = _temp_comp if kwargs.get('required') is not None: - self.required = T.cast('bool', kwargs['required']) + self.required = kwargs['required'] if DubDependency.class_dubbin is None and not DubDependency.class_dubbin_searched: DubDependency.class_dubbin = self._check_dub() @@ -117,9 +118,7 @@ def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T. # if an explicit version spec was stated, use this when querying Dub main_pack_spec = name if kwargs.get('version'): - version_spec = kwargs['version'] - if isinstance(version_spec, list): - version_spec = " ".join(version_spec) + version_spec = ' '.join(kwargs['version']) main_pack_spec = f'{name}@{version_spec}' # we need to know the target architecture @@ -328,7 +327,7 @@ def find_package_target(pkg: DubPackDesc) -> bool: for lib in bs['libs']: if os.name != 'nt': # trying to add system libraries by pkg-config - pkgdep = PkgConfigDependency(lib, environment, {'required': 'true', 'silent': True}) + pkgdep = PkgConfigDependency(lib, environment, {'required': True, 'silent': True}) if pkgdep.is_found: for arg in pkgdep.get_compile_args(): self.compile_args.append(arg) diff --git a/mesonbuild/dependencies/factory.py b/mesonbuild/dependencies/factory.py index aac09cafa616..729d71dc5bd7 100644 --- a/mesonbuild/dependencies/factory.py +++ b/mesonbuild/dependencies/factory.py @@ -1,6 +1,6 @@ # SPDX-License-Identifier: Apache-2.0 # Copyright 2013-2021 The Meson development team -# Copyright © 2021-2023 Intel Corporation +# Copyright © 2021-2024 Intel Corporation from __future__ import annotations @@ -15,7 +15,7 @@ from .pkgconfig import PkgConfigDependency if T.TYPE_CHECKING: - from .base import ExternalDependency + from .base import DependencyKWs, ExternalDependency from .configtool import ConfigToolDependency from ..environment import Environment from ..mesonlib import MachineChoice @@ -25,7 +25,7 @@ [ 'Environment', MachineChoice, - T.Dict[str, T.Any], + DependencyKWs, T.List[DependencyMethods] ], T.List[DependencyGenerator] @@ -35,12 +35,12 @@ [ 'Environment', MachineChoice, - T.Dict[str, T.Any] + DependencyKWs ], T.List[DependencyGenerator] ] - # This should be str, Environment, T.Dict[str, T.Any], T.Optional[str] + # This should be str, Environment, DependencyKWs, T.Optional[str] # But if you try that, you get error: Cannot infer type of lambda CmakeDependencyFunc = T.Callable[..., CMakeDependency] @@ -68,7 +68,7 @@ class DependencyFactory: """ def __init__(self, name: str, methods: T.List[DependencyMethods], *, - extra_kwargs: T.Optional[T.Dict[str, T.Any]] = None, + extra_kwargs: T.Optional[DependencyKWs] = None, pkgconfig_name: T.Optional[str] = None, pkgconfig_class: 'T.Type[PkgConfigDependency]' = PkgConfigDependency, cmake_name: T.Optional[str] = None, @@ -86,7 +86,7 @@ def __init__(self, name: str, methods: T.List[DependencyMethods], *, self.methods = methods self.classes: T.Dict[ DependencyMethods, - T.Callable[['Environment', T.Dict[str, T.Any]], ExternalDependency] + T.Callable[['Environment', DependencyKWs], ExternalDependency] ] = { # Just attach the correct name right now, either the generic name # or the method specific name. @@ -116,7 +116,7 @@ def _process_method(method: DependencyMethods, env: 'Environment', for_machine: return True def __call__(self, env: 'Environment', for_machine: MachineChoice, - kwargs: T.Dict[str, T.Any]) -> T.List['DependencyGenerator']: + kwargs: DependencyKWs) -> T.List['DependencyGenerator']: """Return a list of Dependencies with the arguments already attached.""" methods = process_method_kw(self.methods, kwargs) nwargs = self.extra_kwargs.copy() @@ -131,14 +131,14 @@ def factory_methods(methods: T.Set[DependencyMethods]) -> T.Callable[['FactoryFu This helps to make factory functions self documenting >>> @factory_methods([DependencyMethods.PKGCONFIG, DependencyMethods.CMAKE]) - >>> def factory(env: Environment, for_machine: MachineChoice, kwargs: T.Dict[str, T.Any], methods: T.List[DependencyMethods]) -> T.List['DependencyGenerator']: + >>> def factory(env: Environment, for_machine: MachineChoice, kwargs: DependencyKWs, methods: T.List[DependencyMethods]) -> T.List['DependencyGenerator']: >>> pass """ def inner(func: 'FactoryFunc') -> 'WrappedFactoryFunc': @functools.wraps(func) - def wrapped(env: 'Environment', for_machine: MachineChoice, kwargs: T.Dict[str, T.Any]) -> T.List['DependencyGenerator']: + def wrapped(env: 'Environment', for_machine: MachineChoice, kwargs: DependencyKWs) -> T.List['DependencyGenerator']: return func(env, for_machine, kwargs, process_method_kw(methods, kwargs)) return wrapped diff --git a/mesonbuild/dependencies/framework.py b/mesonbuild/dependencies/framework.py index 1fbd628235ba..56fdec24f6b4 100644 --- a/mesonbuild/dependencies/framework.py +++ b/mesonbuild/dependencies/framework.py @@ -10,12 +10,13 @@ import typing as T if T.TYPE_CHECKING: + from .base import DependencyKWs from ..environment import Environment class ExtraFrameworkDependency(ExternalDependency): system_framework_paths: T.Optional[T.List[str]] = None - def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any], language: T.Optional[str] = None) -> None: + def __init__(self, name: str, env: 'Environment', kwargs: DependencyKWs, language: T.Optional[str] = None) -> None: paths = stringlistify(kwargs.get('paths', [])) super().__init__(DependencyTypeName('extraframeworks'), env, kwargs, language=language) self.name = name diff --git a/mesonbuild/dependencies/hdf5.py b/mesonbuild/dependencies/hdf5.py index 743f98ac5754..a1a2bdde4e2f 100644 --- a/mesonbuild/dependencies/hdf5.py +++ b/mesonbuild/dependencies/hdf5.py @@ -18,6 +18,7 @@ import typing as T if T.TYPE_CHECKING: + from .base import DependencyKWs from .factory import DependencyGenerator from ..environment import Environment from ..mesonlib import MachineChoice @@ -27,7 +28,7 @@ class HDF5PkgConfigDependency(PkgConfigDependency): """Handle brokenness in the HDF5 pkg-config files.""" - def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any], language: T.Optional[str] = None) -> None: + def __init__(self, name: str, environment: 'Environment', kwargs: DependencyKWs, language: T.Optional[str] = None) -> None: language = language or 'c' if language not in {'c', 'cpp', 'fortran'}: raise DependencyException(f'Language {language} is not supported with HDF5.') @@ -78,7 +79,7 @@ class HDF5ConfigToolDependency(ConfigToolDependency): version_arg = '-showconfig' - def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any], language: T.Optional[str] = None) -> None: + def __init__(self, name: str, environment: 'Environment', kwargs: DependencyKWs, language: T.Optional[str] = None) -> None: language = language or 'c' if language not in {'c', 'cpp', 'fortran'}: raise DependencyException(f'Language {language} is not supported with HDF5.') @@ -144,7 +145,7 @@ def _sanitize_version(self, ver: str) -> str: @factory_methods({DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL}) def hdf5_factory(env: 'Environment', for_machine: 'MachineChoice', - kwargs: T.Dict[str, T.Any], methods: T.List[DependencyMethods]) -> T.List['DependencyGenerator']: + kwargs: DependencyKWs, methods: T.List[DependencyMethods]) -> T.List['DependencyGenerator']: language = kwargs.get('language') candidates: T.List['DependencyGenerator'] = [] diff --git a/mesonbuild/dependencies/misc.py b/mesonbuild/dependencies/misc.py index 46c70a9c7c76..75653c4420e0 100644 --- a/mesonbuild/dependencies/misc.py +++ b/mesonbuild/dependencies/misc.py @@ -20,6 +20,7 @@ from ..options import OptionKey if T.TYPE_CHECKING: + from .base import DependencyKWs from ..environment import Environment from .factory import DependencyGenerator @@ -27,7 +28,7 @@ @factory_methods({DependencyMethods.PKGCONFIG, DependencyMethods.CMAKE}) def netcdf_factory(env: 'Environment', for_machine: 'mesonlib.MachineChoice', - kwargs: T.Dict[str, T.Any], + kwargs: DependencyKWs, methods: T.List[DependencyMethods]) -> T.List['DependencyGenerator']: language = kwargs.get('language') if language not in (None, 'c', 'cpp', 'fortran'): @@ -52,7 +53,7 @@ def netcdf_factory(env: 'Environment', class DlBuiltinDependency(BuiltinDependency): - def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]): + def __init__(self, name: str, env: 'Environment', kwargs: DependencyKWs): super().__init__(name, env, kwargs) self.feature_since = ('0.62.0', "consider checking for `dlopen` with and without `find_library('dl')`") @@ -61,7 +62,7 @@ def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]): class DlSystemDependency(SystemDependency): - def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]): + def __init__(self, name: str, env: 'Environment', kwargs: DependencyKWs): super().__init__(name, env, kwargs) self.feature_since = ('0.62.0', "consider checking for `dlopen` with and without `find_library('dl')`") @@ -88,7 +89,7 @@ class OpenMPDependency(SystemDependency): '199810': '1.0', } - def __init__(self, environment: 'Environment', kwargs: T.Dict[str, T.Any]) -> None: + def __init__(self, environment: 'Environment', kwargs: DependencyKWs) -> None: language = kwargs.get('language') super().__init__('openmp', environment, kwargs, language=language) self.is_found = False @@ -142,7 +143,7 @@ def __init__(self, environment: 'Environment', kwargs: T.Dict[str, T.Any]) -> No class ThreadDependency(SystemDependency): - def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any]) -> None: + def __init__(self, name: str, environment: 'Environment', kwargs: DependencyKWs) -> None: super().__init__(name, environment, kwargs) self.is_found = True # Happens if you are using a language with threads @@ -156,7 +157,7 @@ def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T. class BlocksDependency(SystemDependency): - def __init__(self, environment: 'Environment', kwargs: T.Dict[str, T.Any]) -> None: + def __init__(self, environment: 'Environment', kwargs: DependencyKWs) -> None: super().__init__('blocks', environment, kwargs) self.name = 'blocks' self.is_found = False @@ -199,7 +200,7 @@ class PcapDependencyConfigTool(ConfigToolDependency): # version 1.10.3 will hopefully add actual support for --version skip_version = '--help' - def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any]): + def __init__(self, name: str, environment: 'Environment', kwargs: DependencyKWs): super().__init__(name, environment, kwargs) if not self.is_found: return @@ -228,7 +229,7 @@ class CupsDependencyConfigTool(ConfigToolDependency): tools = ['cups-config'] tool_name = 'cups-config' - def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any]): + def __init__(self, name: str, environment: 'Environment', kwargs: DependencyKWs): super().__init__(name, environment, kwargs) if not self.is_found: return @@ -241,7 +242,7 @@ class LibWmfDependencyConfigTool(ConfigToolDependency): tools = ['libwmf-config'] tool_name = 'libwmf-config' - def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any]): + def __init__(self, name: str, environment: 'Environment', kwargs: DependencyKWs): super().__init__(name, environment, kwargs) if not self.is_found: return @@ -254,7 +255,7 @@ class LibGCryptDependencyConfigTool(ConfigToolDependency): tools = ['libgcrypt-config'] tool_name = 'libgcrypt-config' - def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any]): + def __init__(self, name: str, environment: 'Environment', kwargs: DependencyKWs): super().__init__(name, environment, kwargs) if not self.is_found: return @@ -268,7 +269,7 @@ class GpgmeDependencyConfigTool(ConfigToolDependency): tools = ['gpgme-config'] tool_name = 'gpg-config' - def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any]): + def __init__(self, name: str, environment: 'Environment', kwargs: DependencyKWs): super().__init__(name, environment, kwargs) if not self.is_found: return @@ -279,7 +280,7 @@ def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T. class ShadercDependency(SystemDependency): - def __init__(self, environment: 'Environment', kwargs: T.Dict[str, T.Any]): + def __init__(self, environment: 'Environment', kwargs: DependencyKWs): super().__init__('shaderc', environment, kwargs) static_lib = 'shaderc_combined' @@ -311,7 +312,7 @@ class CursesConfigToolDependency(ConfigToolDependency): # ncurses5.4-config is for macOS Catalina tools = ['ncursesw6-config', 'ncursesw5-config', 'ncurses6-config', 'ncurses5-config', 'ncurses5.4-config'] - def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any], language: T.Optional[str] = None): + def __init__(self, name: str, env: 'Environment', kwargs: DependencyKWs, language: T.Optional[str] = None): exclude_paths = None # macOS mistakenly ships /usr/bin/ncurses5.4-config and a man page for # it, but none of the headers or libraries. Ignore /usr/bin because it @@ -335,7 +336,7 @@ class CursesSystemDependency(SystemDependency): implementations, and the differences between them can be very annoying. """ - def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]): + def __init__(self, name: str, env: 'Environment', kwargs: DependencyKWs): super().__init__(name, env, kwargs) candidates = [ @@ -382,7 +383,7 @@ def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]): class IconvBuiltinDependency(BuiltinDependency): - def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]): + def __init__(self, name: str, env: 'Environment', kwargs: DependencyKWs): super().__init__(name, env, kwargs) self.feature_since = ('0.60.0', "consider checking for `iconv_open` with and without `find_library('iconv')`") code = '''#include \n\nint main() {\n iconv_open("","");\n}''' # [ignore encoding] this is C, not python, Mr. Lint @@ -392,7 +393,7 @@ def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]): class IconvSystemDependency(SystemDependency): - def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]): + def __init__(self, name: str, env: 'Environment', kwargs: DependencyKWs): super().__init__(name, env, kwargs) self.feature_since = ('0.60.0', "consider checking for `iconv_open` with and without find_library('iconv')") @@ -404,7 +405,7 @@ def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]): class IntlBuiltinDependency(BuiltinDependency): - def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]): + def __init__(self, name: str, env: 'Environment', kwargs: DependencyKWs): super().__init__(name, env, kwargs) self.feature_since = ('0.59.0', "consider checking for `ngettext` with and without `find_library('intl')`") code = '''#include \n\nint main() {\n gettext("Hello world");\n}''' @@ -414,7 +415,7 @@ def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]): class IntlSystemDependency(SystemDependency): - def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]): + def __init__(self, name: str, env: 'Environment', kwargs: DependencyKWs): super().__init__(name, env, kwargs) self.feature_since = ('0.59.0', "consider checking for `ngettext` with and without `find_library('intl')`") @@ -430,10 +431,10 @@ def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]): class OpensslSystemDependency(SystemDependency): - def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]): + def __init__(self, name: str, env: 'Environment', kwargs: DependencyKWs): super().__init__(name, env, kwargs) - dependency_kwargs = { + dependency_kwargs: DependencyKWs = { 'method': 'system', 'static': self.static, } @@ -483,7 +484,7 @@ class ObjFWDependency(ConfigToolDependency): tools = ['objfw-config'] tool_name = 'objfw-config' - def __init__(self, environment: 'Environment', kwargs: T.Dict[str, T.Any]): + def __init__(self, environment: 'Environment', kwargs: DependencyKWs): super().__init__('objfw', environment, kwargs) self.feature_since = ('1.5.0', '') if not self.is_found: @@ -493,7 +494,7 @@ def __init__(self, environment: 'Environment', kwargs: T.Dict[str, T.Any]): # TODO: Expose --framework-libs extra_flags = [] - for module in T.cast('T.List[str]', kwargs.get('modules', [])): + for module in kwargs.get('modules', []): extra_flags.append('--package') extra_flags.append(module) @@ -505,7 +506,7 @@ def __init__(self, environment: 'Environment', kwargs: T.Dict[str, T.Any]): @factory_methods({DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL, DependencyMethods.SYSTEM}) def curses_factory(env: 'Environment', for_machine: 'mesonlib.MachineChoice', - kwargs: T.Dict[str, T.Any], + kwargs: DependencyKWs, methods: T.List[DependencyMethods]) -> T.List['DependencyGenerator']: candidates: T.List['DependencyGenerator'] = [] @@ -531,7 +532,7 @@ def curses_factory(env: 'Environment', @factory_methods({DependencyMethods.PKGCONFIG, DependencyMethods.SYSTEM}) def shaderc_factory(env: 'Environment', for_machine: 'mesonlib.MachineChoice', - kwargs: T.Dict[str, T.Any], + kwargs: DependencyKWs, methods: T.List[DependencyMethods]) -> T.List['DependencyGenerator']: """Custom DependencyFactory for ShaderC. diff --git a/mesonbuild/dependencies/mpi.py b/mesonbuild/dependencies/mpi.py index a259972b0586..ef36a5f6ad44 100644 --- a/mesonbuild/dependencies/mpi.py +++ b/mesonbuild/dependencies/mpi.py @@ -17,6 +17,7 @@ from .pkgconfig import PkgConfigDependency if T.TYPE_CHECKING: + from .base import DependencyKWs from .factory import DependencyGenerator from ..environment import Environment from ..mesonlib import MachineChoice @@ -25,7 +26,7 @@ @factory_methods({DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL, DependencyMethods.SYSTEM}) def mpi_factory(env: 'Environment', for_machine: 'MachineChoice', - kwargs: T.Dict[str, T.Any], + kwargs: DependencyKWs, methods: T.List[DependencyMethods]) -> T.List['DependencyGenerator']: language = kwargs.get('language') if language is None: @@ -104,7 +105,7 @@ def mpi_factory(env: 'Environment', class MPIConfigToolDependency(ConfigToolDependency): """Wrapper around mpicc, Intel's mpiicc and friends.""" - def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any], + def __init__(self, name: str, env: 'Environment', kwargs: DependencyKWs, language: T.Optional[str] = None): super().__init__(name, env, kwargs, language=language) if not self.is_found: @@ -214,7 +215,7 @@ class MSMPIDependency(SystemDependency): """The Microsoft MPI.""" - def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any], + def __init__(self, name: str, env: 'Environment', kwargs: DependencyKWs, language: T.Optional[str] = None): super().__init__(name, env, kwargs, language=language) # MSMPI only supports the C API diff --git a/mesonbuild/dependencies/pkgconfig.py b/mesonbuild/dependencies/pkgconfig.py index c6e6a5e4f2ca..44f355dfc813 100644 --- a/mesonbuild/dependencies/pkgconfig.py +++ b/mesonbuild/dependencies/pkgconfig.py @@ -19,6 +19,7 @@ import typing as T if T.TYPE_CHECKING: + from .base import DependencyKWs from typing_extensions import Literal from .._typing import ImmutableListProtocol @@ -291,7 +292,7 @@ def _call_pkgbin(self, args: T.List[str], env: T.Optional[EnvironOrDict] = None) class PkgConfigDependency(ExternalDependency): - def __init__(self, name: str, environment: Environment, kwargs: T.Dict[str, T.Any], + def __init__(self, name: str, environment: Environment, kwargs: DependencyKWs, language: T.Optional[str] = None) -> None: super().__init__(DependencyTypeName('pkgconfig'), environment, kwargs, language=language) self.name = name diff --git a/mesonbuild/dependencies/platform.py b/mesonbuild/dependencies/platform.py index 335faed2cdbb..9efafa8544ad 100644 --- a/mesonbuild/dependencies/platform.py +++ b/mesonbuild/dependencies/platform.py @@ -11,10 +11,11 @@ import typing as T if T.TYPE_CHECKING: + from .base import DependencyKWs from ..environment import Environment class AppleFrameworks(ExternalDependency): - def __init__(self, env: 'Environment', kwargs: T.Dict[str, T.Any]) -> None: + def __init__(self, env: 'Environment', kwargs: DependencyKWs) -> None: super().__init__(DependencyTypeName('appleframeworks'), env, kwargs) modules = kwargs.get('modules', []) if isinstance(modules, str): diff --git a/mesonbuild/dependencies/python.py b/mesonbuild/dependencies/python.py index c978ad62e82e..465bcbd5fd4d 100644 --- a/mesonbuild/dependencies/python.py +++ b/mesonbuild/dependencies/python.py @@ -21,6 +21,7 @@ if T.TYPE_CHECKING: from typing_extensions import TypedDict + from .base import DependencyKWs from .factory import DependencyGenerator from ..environment import Environment from ..mesonlib import MachineChoice @@ -56,7 +57,7 @@ class Pybind11ConfigToolDependency(ConfigToolDependency): # in the meantime skip_version = '--pkgconfigdir' - def __init__(self, name: str, environment: Environment, kwargs: T.Dict[str, T.Any]): + def __init__(self, name: str, environment: Environment, kwargs: DependencyKWs): super().__init__(name, environment, kwargs) if not self.is_found: return @@ -67,7 +68,7 @@ class NumPyConfigToolDependency(ConfigToolDependency): tools = ['numpy-config'] - def __init__(self, name: str, environment: Environment, kwargs: T.Dict[str, T.Any]): + def __init__(self, name: str, environment: Environment, kwargs: DependencyKWs): super().__init__(name, environment, kwargs) if not self.is_found: return @@ -310,7 +311,7 @@ def find_libpy_windows(self, env: 'Environment', limited_api: bool = False) -> N class PythonPkgConfigDependency(PkgConfigDependency, _PythonDependencyBase): def __init__(self, name: str, environment: 'Environment', - kwargs: T.Dict[str, T.Any], installation: 'BasicPythonExternalProgram', + kwargs: DependencyKWs, installation: 'BasicPythonExternalProgram', libpc: bool = False): if libpc: mlog.debug(f'Searching for {name!r} via pkgconfig lookup in LIBPC') @@ -331,7 +332,7 @@ def __init__(self, name: str, environment: 'Environment', class PythonFrameworkDependency(ExtraFrameworkDependency, _PythonDependencyBase): def __init__(self, name: str, environment: 'Environment', - kwargs: T.Dict[str, T.Any], installation: 'BasicPythonExternalProgram'): + kwargs: DependencyKWs, installation: 'BasicPythonExternalProgram'): ExtraFrameworkDependency.__init__(self, name, environment, kwargs) _PythonDependencyBase.__init__(self, installation, kwargs.get('embed', False)) @@ -339,7 +340,7 @@ def __init__(self, name: str, environment: 'Environment', class PythonSystemDependency(SystemDependency, _PythonDependencyBase): def __init__(self, name: str, environment: 'Environment', - kwargs: T.Dict[str, T.Any], installation: 'BasicPythonExternalProgram'): + kwargs: DependencyKWs, installation: 'BasicPythonExternalProgram'): SystemDependency.__init__(self, name, environment, kwargs) _PythonDependencyBase.__init__(self, installation, kwargs.get('embed', False)) @@ -374,7 +375,7 @@ def log_tried() -> str: return 'sysconfig' def python_factory(env: 'Environment', for_machine: 'MachineChoice', - kwargs: T.Dict[str, T.Any], + kwargs: DependencyKWs, installation: T.Optional['BasicPythonExternalProgram'] = None) -> T.List['DependencyGenerator']: # We can't use the factory_methods decorator here, as we need to pass the # extra installation argument @@ -395,7 +396,7 @@ def python_factory(env: 'Environment', for_machine: 'MachineChoice', pkg_name = f'python-{pkg_version}{pkg_embed}' # If python-X.Y.pc exists in LIBPC, we will try to use it - def wrap_in_pythons_pc_dir(name: str, env: 'Environment', kwargs: T.Dict[str, T.Any], + def wrap_in_pythons_pc_dir(name: str, env: 'Environment', kwargs: DependencyKWs, installation: 'BasicPythonExternalProgram') -> 'ExternalDependency': if not pkg_libdir: # there is no LIBPC, so we can't search in it diff --git a/mesonbuild/dependencies/qt.py b/mesonbuild/dependencies/qt.py index 3fe9b15fbd6a..e8e248022259 100644 --- a/mesonbuild/dependencies/qt.py +++ b/mesonbuild/dependencies/qt.py @@ -22,6 +22,7 @@ from ..options import OptionKey if T.TYPE_CHECKING: + from .base import DependencyKWs from ..compilers import Compiler from ..envconfig import MachineInfo from ..environment import Environment @@ -96,7 +97,7 @@ def _get_modules_lib_suffix(version: str, info: 'MachineInfo', is_debug: bool) - class QtExtraFrameworkDependency(ExtraFrameworkDependency): - def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any], qvars: T.Dict[str, str], language: T.Optional[str] = None): + def __init__(self, name: str, env: 'Environment', kwargs: DependencyKWs, qvars: T.Dict[str, str], language: T.Optional[str] = None): super().__init__(name, env, kwargs, language=language) self.mod_name = name[2:] self.qt_extra_include_directory = qvars['QT_INSTALL_HEADERS'] @@ -123,7 +124,7 @@ class _QtBase: libexecdir: T.Optional[str] = None version: str - def __init__(self, name: str, kwargs: T.Dict[str, T.Any]): + def __init__(self, name: str, kwargs: DependencyKWs): self.name = name self.qtname = name.capitalize() self.qtver = name[-1] @@ -132,13 +133,13 @@ def __init__(self, name: str, kwargs: T.Dict[str, T.Any]): else: self.qtpkgname = self.qtname - self.private_headers = T.cast('bool', kwargs.get('private_headers', False)) + self.private_headers = kwargs.get('private_headers', False) - self.requested_modules = T.cast('T.List[str]', kwargs.get('modules', [])) + self.requested_modules = kwargs.get('modules', []) if not self.requested_modules: raise DependencyException('No ' + self.qtname + ' modules specified.') - self.qtmain = T.cast('bool', kwargs.get('main', False)) + self.qtmain = kwargs.get('main', False) if not isinstance(self.qtmain, bool): raise DependencyException('"main" argument must be a boolean') @@ -171,7 +172,7 @@ class QtPkgConfigDependency(_QtBase, PkgConfigDependency, metaclass=abc.ABCMeta) """Specialization of the PkgConfigDependency for Qt.""" - def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]): + def __init__(self, name: str, env: 'Environment', kwargs: DependencyKWs): _QtBase.__init__(self, name, kwargs) # Always use QtCore as the "main" dependency, since it has the extra @@ -250,7 +251,7 @@ class QmakeQtDependency(_QtBase, ConfigToolDependency, metaclass=abc.ABCMeta): version: str version_arg = '-v' - def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]): + def __init__(self, name: str, env: 'Environment', kwargs: DependencyKWs): _QtBase.__init__(self, name, kwargs) self.tool_name = f'qmake{self.qtver}' self.tools = [f'qmake{self.qtver}', f'qmake-{self.name}', 'qmake'] @@ -349,7 +350,7 @@ def get_variable_args(self, variable_name: str) -> T.List[str]: def get_private_includes(self, mod_inc_dir: str, module: str) -> T.List[str]: pass - def _framework_detect(self, qvars: T.Dict[str, str], modules: T.List[str], kwargs: T.Dict[str, T.Any]) -> None: + def _framework_detect(self, qvars: T.Dict[str, str], modules: T.List[str], kwargs: DependencyKWs) -> None: libdir = qvars['QT_INSTALL_LIBS'] # ExtraFrameworkDependency doesn't support any methods @@ -443,7 +444,7 @@ def get_private_includes(self, mod_inc_dir: str, module: str) -> T.List[str]: class Qt6PkgConfigDependency(Qt6WinMainMixin, QtPkgConfigDependency): - def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]): + def __init__(self, name: str, env: 'Environment', kwargs: DependencyKWs): super().__init__(name, env, kwargs) if not self.libexecdir: mlog.debug(f'detected Qt6 {self.version} pkg-config dependency does not ' diff --git a/mesonbuild/dependencies/scalapack.py b/mesonbuild/dependencies/scalapack.py index b3fae60aeab9..3982e426dc54 100644 --- a/mesonbuild/dependencies/scalapack.py +++ b/mesonbuild/dependencies/scalapack.py @@ -16,6 +16,7 @@ from .factory import factory_methods if T.TYPE_CHECKING: + from .base import DependencyKWs from ..environment import Environment from ..mesonlib import MachineChoice from .factory import DependencyGenerator @@ -23,7 +24,7 @@ @factory_methods({DependencyMethods.PKGCONFIG, DependencyMethods.CMAKE}) def scalapack_factory(env: 'Environment', for_machine: 'MachineChoice', - kwargs: T.Dict[str, T.Any], + kwargs: DependencyKWs, methods: T.List[DependencyMethods]) -> T.List['DependencyGenerator']: candidates: T.List['DependencyGenerator'] = [] @@ -54,7 +55,7 @@ class MKLPkgConfigDependency(PkgConfigDependency): bunch of fixups to make it work correctly. """ - def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any], + def __init__(self, name: str, env: 'Environment', kwargs: DependencyKWs, language: T.Optional[str] = None): _m = os.environ.get('MKLROOT') self.__mklroot = Path(_m).resolve() if _m else None diff --git a/mesonbuild/dependencies/ui.py b/mesonbuild/dependencies/ui.py index f3263645a4e3..559f605db17b 100644 --- a/mesonbuild/dependencies/ui.py +++ b/mesonbuild/dependencies/ui.py @@ -24,11 +24,12 @@ from .factory import DependencyFactory if T.TYPE_CHECKING: + from .base import DependencyKWs from ..environment import Environment class GLDependencySystem(SystemDependency): - def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any]) -> None: + def __init__(self, name: str, environment: 'Environment', kwargs: DependencyKWs) -> None: super().__init__(name, environment, kwargs) if self.env.machines[self.for_machine].is_darwin(): @@ -57,7 +58,7 @@ class GnuStepDependency(ConfigToolDependency): tools = ['gnustep-config'] tool_name = 'gnustep-config' - def __init__(self, environment: 'Environment', kwargs: T.Dict[str, T.Any]) -> None: + def __init__(self, environment: 'Environment', kwargs: DependencyKWs) -> None: super().__init__('gnustep', environment, kwargs, language='objc') if not self.is_found: return @@ -136,7 +137,7 @@ class SDL2DependencyConfigTool(ConfigToolDependency): tools = ['sdl2-config'] tool_name = 'sdl2-config' - def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any]): + def __init__(self, name: str, environment: 'Environment', kwargs: DependencyKWs): super().__init__(name, environment, kwargs) if not self.is_found: return @@ -149,7 +150,7 @@ class WxDependency(ConfigToolDependency): tools = ['wx-config-3.0', 'wx-config-3.1', 'wx-config', 'wx-config-gtk3'] tool_name = 'wx-config' - def __init__(self, environment: 'Environment', kwargs: T.Dict[str, T.Any]): + def __init__(self, environment: 'Environment', kwargs: DependencyKWs): super().__init__('WxWidgets', environment, kwargs, language='cpp') if not self.is_found: return @@ -172,14 +173,14 @@ def __init__(self, environment: 'Environment', kwargs: T.Dict[str, T.Any]): self.link_args = self.get_config_value(['--libs'] + extra_args + self.requested_modules, 'link_args') @staticmethod - def get_requested(kwargs: T.Dict[str, T.Any]) -> T.List[str]: - return T.cast('T.List[str]', kwargs.get('modules', [])) + def get_requested(kwargs: DependencyKWs) -> T.List[str]: + return kwargs.get('modules', []) packages['wxwidgets'] = WxDependency class VulkanDependencySystem(SystemDependency): - def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any], language: T.Optional[str] = None) -> None: + def __init__(self, name: str, environment: 'Environment', kwargs: DependencyKWs, language: T.Optional[str] = None) -> None: super().__init__(name, environment, kwargs, language=language) try: diff --git a/mesonbuild/interpreter/kwargs.py b/mesonbuild/interpreter/kwargs.py index 45ba798f79fa..8edf713fa947 100644 --- a/mesonbuild/interpreter/kwargs.py +++ b/mesonbuild/interpreter/kwargs.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 -# Copyright © 2021 The Meson Developers +# Copyright © 2021-2024 Intel Corporation # Copyright © 2021-2024 Intel Corporation from __future__ import annotations @@ -484,6 +484,9 @@ class FuncDeclareDependency(TypedDict): version: T.Optional[str] +# This must be kept in sync with the DependencyKws class in +# dependencies.base +# They cannot share in anyway due to the way total works class FuncDependency(ExtractRequired): allow_fallback: T.Optional[bool] diff --git a/mesonbuild/interpreter/mesonmain.py b/mesonbuild/interpreter/mesonmain.py index 289c8913e74c..272a69180365 100644 --- a/mesonbuild/interpreter/mesonmain.py +++ b/mesonbuild/interpreter/mesonmain.py @@ -25,6 +25,7 @@ if T.TYPE_CHECKING: from typing_extensions import Literal, TypedDict + from ..dependencies.base import DependencyKWs from ..compilers import Compiler from ..interpreterbase import TYPE_kwargs, TYPE_var from ..mesonlib import ExecutableSerialisation @@ -388,10 +389,10 @@ def override_dependency_method(self, args: T.Tuple[str, dependencies.Dependency] def _override_dependency_impl(self, name: str, dep: dependencies.Dependency, kwargs: 'FuncOverrideDependency', static: T.Optional[bool], permissive: bool = False) -> None: - # We need the cast here as get_dep_identifier works on such a dict, - # which FuncOverrideDependency is, but mypy can't figure that out - nkwargs = T.cast('T.Dict[str, T.Any]', kwargs.copy()) - nkwargs['static'] = T.cast('T.Optional[bool]', static) + # Neither mypy nor pyright can figure out that FuncOverrideDependency is + # a subset of DependencyKWs, so we have to cast to help it out. + nkwargs = T.cast('DependencyKWs', kwargs.copy()) + nkwargs['static'] = static identifier = dependencies.get_dep_identifier(name, nkwargs) for_machine = kwargs['native'] override = self.build.dependency_overrides[for_machine].get(identifier) diff --git a/mesonbuild/modules/_qt.py b/mesonbuild/modules/_qt.py index 1f17a004b36f..1b75ec5c0c26 100644 --- a/mesonbuild/modules/_qt.py +++ b/mesonbuild/modules/_qt.py @@ -22,6 +22,7 @@ if T.TYPE_CHECKING: from . import ModuleState + from ..dependencies.base import DependencyKWs from ..dependencies.qt import QtPkgConfigDependency, QmakeQtDependency from ..interpreter import Interpreter from ..interpreter import kwargs @@ -174,7 +175,7 @@ def _detect_tools(self, state: 'ModuleState', method: str, required: bool = True return self._tools_detected = True mlog.log(f'Detecting Qt{self.qt_version} tools') - kwargs = {'required': required, 'modules': ['Core'], 'method': method} + kwargs: DependencyKWs = {'required': required, 'modules': ['Core'], 'method': method} # Just pick one to make mypy happy qt = T.cast('QtPkgConfigDependency', find_external_dependency(f'qt{self.qt_version}', state.environment, kwargs)) if qt.found():