Files
meson/mesonbuild/dependencies/factory.py
T
Dylan Baker e991c4d454 Use SPDX-License-Identifier consistently
This replaces all of the Apache blurbs at the start of each file with an
`# SPDX-License-Identifier: Apache-2.0` string. It also fixes existing
uses to be consistent in capitalization, and to be placed above any
copyright notices.

This removes nearly 3000 lines of boilerplate from the project (only
python files), which no developer cares to look at.

SPDX is in common use, particularly in the Linux kernel, and is the
recommended format for Meson's own `project(license: )` field
2023-12-13 15:19:21 -05:00

147 lines
6.4 KiB
Python

# SPDX-License-Identifier: Apache-2.0
# Copyright 2013-2021 The Meson development team
# Copyright © 2021-2023 Intel Corporation
from __future__ import annotations
import functools
import typing as T
from .base import DependencyException, DependencyMethods
from .base import process_method_kw
from .base import BuiltinDependency, SystemDependency
from .cmake import CMakeDependency
from .framework import ExtraFrameworkDependency
from .pkgconfig import PkgConfigDependency
if T.TYPE_CHECKING:
from .base import ExternalDependency
from .configtool import ConfigToolDependency
from ..environment import Environment
from ..mesonlib import MachineChoice
DependencyGenerator = T.Callable[[], ExternalDependency]
FactoryFunc = T.Callable[
[
'Environment',
MachineChoice,
T.Dict[str, T.Any],
T.List[DependencyMethods]
],
T.List[DependencyGenerator]
]
WrappedFactoryFunc = T.Callable[
[
'Environment',
MachineChoice,
T.Dict[str, T.Any]
],
T.List[DependencyGenerator]
]
# This should be str, Environment, T.Dict[str, T.Any], T.Optional[str]
# But if you try that, you get error: Cannot infer type of lambda
CmakeDependencyFunc = T.Callable[..., CMakeDependency]
class DependencyFactory:
"""Factory to get dependencies from multiple sources.
This class provides an initializer that takes a set of names and classes
for various kinds of dependencies. When the initialized object is called
it returns a list of callables return Dependency objects to try in order.
:name: The name of the dependency. This will be passed as the name
parameter of the each dependency unless it is overridden on a per
type basis.
:methods: An ordered list of DependencyMethods. This is the order
dependencies will be returned in unless they are removed by the
_process_method function
:*_name: This will overwrite the name passed to the corresponding class.
For example, if the name is 'zlib', but cmake calls the dependency
'Z', then using `cmake_name='Z'` will pass the name as 'Z' to cmake.
:*_class: A *type* or callable that creates a class, and has the
signature of an ExternalDependency
:system_class: If you pass DependencyMethods.SYSTEM in methods, you must
set this argument.
"""
def __init__(self, name: str, methods: T.List[DependencyMethods], *,
extra_kwargs: T.Optional[T.Dict[str, T.Any]] = None,
pkgconfig_name: T.Optional[str] = None,
pkgconfig_class: 'T.Type[PkgConfigDependency]' = PkgConfigDependency,
cmake_name: T.Optional[str] = None,
cmake_class: 'T.Union[T.Type[CMakeDependency], CmakeDependencyFunc]' = CMakeDependency,
configtool_class: 'T.Optional[T.Type[ConfigToolDependency]]' = None,
framework_name: T.Optional[str] = None,
framework_class: 'T.Type[ExtraFrameworkDependency]' = ExtraFrameworkDependency,
builtin_class: 'T.Type[BuiltinDependency]' = BuiltinDependency,
system_class: 'T.Type[SystemDependency]' = SystemDependency):
if DependencyMethods.CONFIG_TOOL in methods and not configtool_class:
raise DependencyException('A configtool must have a custom class')
self.extra_kwargs = extra_kwargs or {}
self.methods = methods
self.classes: T.Dict[
DependencyMethods,
T.Callable[['Environment', T.Dict[str, T.Any]], ExternalDependency]
] = {
# Just attach the correct name right now, either the generic name
# or the method specific name.
DependencyMethods.EXTRAFRAMEWORK: functools.partial(framework_class, framework_name or name),
DependencyMethods.PKGCONFIG: functools.partial(pkgconfig_class, pkgconfig_name or name),
DependencyMethods.CMAKE: functools.partial(cmake_class, cmake_name or name),
DependencyMethods.SYSTEM: functools.partial(system_class, name),
DependencyMethods.BUILTIN: functools.partial(builtin_class, name),
DependencyMethods.CONFIG_TOOL: None,
}
if configtool_class is not None:
self.classes[DependencyMethods.CONFIG_TOOL] = functools.partial(configtool_class, name)
@staticmethod
def _process_method(method: DependencyMethods, env: 'Environment', for_machine: MachineChoice) -> bool:
"""Report whether a method is valid or not.
If the method is valid, return true, otherwise return false. This is
used in a list comprehension to filter methods that are not possible.
By default this only remove EXTRAFRAMEWORK dependencies for non-mac platforms.
"""
# Extra frameworks are only valid for macOS and other apple products
if (method is DependencyMethods.EXTRAFRAMEWORK and
not env.machines[for_machine].is_darwin()):
return False
return True
def __call__(self, env: 'Environment', for_machine: MachineChoice,
kwargs: T.Dict[str, T.Any]) -> 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()
nwargs.update(kwargs)
return [functools.partial(self.classes[m], env, nwargs) for m in methods
if self._process_method(m, env, for_machine)]
def factory_methods(methods: T.Set[DependencyMethods]) -> T.Callable[['FactoryFunc'], 'WrappedFactoryFunc']:
"""Decorator for handling methods for dependency factory functions.
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']:
>>> 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']:
return func(env, for_machine, kwargs, process_method_kw(methods, kwargs))
return wrapped
return inner