aboutsummaryrefslogtreecommitdiff
path: root/mesonbuild
diff options
context:
space:
mode:
Diffstat (limited to 'mesonbuild')
-rw-r--r--mesonbuild/dependencies/pkgconfig.py73
-rw-r--r--mesonbuild/utils/universal.py4
2 files changed, 35 insertions, 42 deletions
diff --git a/mesonbuild/dependencies/pkgconfig.py b/mesonbuild/dependencies/pkgconfig.py
index 1d9863a..9729baa 100644
--- a/mesonbuild/dependencies/pkgconfig.py
+++ b/mesonbuild/dependencies/pkgconfig.py
@@ -16,7 +16,7 @@ from __future__ import annotations
from pathlib import Path
from .base import ExternalDependency, DependencyException, sort_libpaths, DependencyTypeName
-from ..mesonlib import EnvironmentVariables, OptionKey, OrderedSet, PerMachine, Popen_safe, Popen_safe_logged
+from ..mesonlib import EnvironmentVariables, OptionKey, OrderedSet, PerMachine, Popen_safe, Popen_safe_logged, MachineChoice
from ..programs import find_external_program, ExternalProgram
from .. import mlog
from pathlib import PurePath
@@ -29,20 +29,31 @@ if T.TYPE_CHECKING:
from typing_extensions import Literal
from ..environment import Environment
- from ..mesonlib import MachineChoice
from ..utils.core import EnvironOrDict
from ..interpreter.type_checking import PkgConfigDefineType
class PkgConfigInterface:
'''Base class wrapping a pkg-config implementation'''
+ class_impl: PerMachine[T.Union[Literal[False], T.Optional[PkgConfigInterface]]] = PerMachine(False, False)
+
@staticmethod
def instance(env: Environment, for_machine: MachineChoice, silent: bool) -> T.Optional[PkgConfigInterface]:
- impl = PkgConfigCLI(env, for_machine, silent)
- if not impl.found():
- return None
+ for_machine = for_machine if env.is_cross_build() else MachineChoice.HOST
+ impl = PkgConfigInterface.class_impl[for_machine]
+ if impl is False:
+ impl = PkgConfigCLI(env, for_machine, silent)
+ if not impl.found():
+ impl = None
+ if not impl and not silent:
+ mlog.log('Found pkg-config:', mlog.red('NO'))
+ PkgConfigInterface.class_impl[for_machine] = impl
return impl
+ def __init__(self, env: Environment, for_machine: MachineChoice) -> None:
+ self.env = env
+ self.for_machine = for_machine
+
def found(self) -> bool:
'''Return whether pkg-config is supported'''
raise NotImplementedError
@@ -78,9 +89,6 @@ class PkgConfigInterface:
class PkgConfigCLI(PkgConfigInterface):
'''pkg-config CLI implementation'''
- # The class's copy of the pkg-config path. Avoids having to search for it
- # multiple times in the same Meson invocation.
- class_pkgbin: PerMachine[T.Union[None, Literal[False], ExternalProgram]] = PerMachine(None, None)
# We cache all pkg-config subprocess invocations to avoid redundant calls
pkgbin_cache: T.Dict[
T.Tuple[ExternalProgram, T.Tuple[str, ...], T.FrozenSet[T.Tuple[str, str]]],
@@ -88,11 +96,12 @@ class PkgConfigCLI(PkgConfigInterface):
] = {}
def __init__(self, env: Environment, for_machine: MachineChoice, silent: bool) -> None:
- self.env = env
- self.for_machine = for_machine
+ super().__init__(env, for_machine)
# Store a copy of the pkg-config path on the object itself so it is
# stored in the pickled coredata and recovered.
- self.pkgbin = self._detect_pkgbin(env, for_machine, silent)
+ self.pkgbin = self._detect_pkgbin(env, for_machine)
+ if self.pkgbin and not silent:
+ mlog.log('Found pkg-config:', mlog.green('YES'), mlog.blue(self.pkgbin.get_path()))
def found(self) -> bool:
return bool(self.pkgbin)
@@ -162,41 +171,21 @@ class PkgConfigCLI(PkgConfigInterface):
raise DependencyException(f'could not list modules:\n{err}\n')
return [i.split(' ', 1)[0] for i in out.splitlines()]
- def _split_args(self, cmd: str) -> T.List[str]:
+ @staticmethod
+ def _split_args(cmd: str) -> T.List[str]:
# pkg-config paths follow Unix conventions, even on Windows; split the
# output using shlex.split rather than mesonlib.split_args
return shlex.split(cmd)
- @classmethod
- def _detect_pkgbin(cls, env: Environment, for_machine: MachineChoice, silent: bool) -> T.Optional[ExternalProgram]:
- # Only search for pkg-config for each machine the first time and store
- # the result in the class definition
- if cls.class_pkgbin[for_machine] is False:
- mlog.debug(f'Pkg-config binary for {for_machine} is cached as not found.')
- elif cls.class_pkgbin[for_machine] is not None:
- mlog.debug(f'Pkg-config binary for {for_machine} is cached.')
- else:
- assert cls.class_pkgbin[for_machine] is None, 'for mypy'
- mlog.debug(f'Pkg-config binary for {for_machine} is not cached.')
- for potential_pkgbin in find_external_program(
- env, for_machine, 'pkgconfig', 'Pkg-config',
- env.default_pkgconfig, allow_default_for_cross=False):
- version_if_ok = cls.check_pkgconfig(env, potential_pkgbin)
- if not version_if_ok:
- continue
- if not silent:
- mlog.log('Found pkg-config:', mlog.bold(potential_pkgbin.get_path()),
- f'({version_if_ok})')
- cls.class_pkgbin[for_machine] = potential_pkgbin
- break
- else:
- if not silent:
- mlog.log('Found pkg-config:', mlog.red('NO'))
- # Set to False instead of None to signify that we've already
- # searched for it and not found it
- cls.class_pkgbin[for_machine] = False
-
- return cls.class_pkgbin[for_machine] or None
+ @staticmethod
+ def _detect_pkgbin(env: Environment, for_machine: MachineChoice) -> T.Optional[ExternalProgram]:
+ for potential_pkgbin in find_external_program(
+ env, for_machine, 'pkgconfig', 'Pkg-config',
+ env.default_pkgconfig, allow_default_for_cross=False):
+ version_if_ok = PkgConfigCLI.check_pkgconfig(env, potential_pkgbin)
+ if version_if_ok:
+ return potential_pkgbin
+ return None
def _call_pkgbin_real(self, args: T.List[str], env: T.Dict[str, str]) -> T.Tuple[int, str, str]:
assert isinstance(self.pkgbin, ExternalProgram)
diff --git a/mesonbuild/utils/universal.py b/mesonbuild/utils/universal.py
index 1d0e382..8216e78 100644
--- a/mesonbuild/utils/universal.py
+++ b/mesonbuild/utils/universal.py
@@ -524,6 +524,10 @@ class PerMachine(T.Generic[_T]):
unfreeze.host = None
return unfreeze
+ def assign(self, build: _T, host: _T) -> None:
+ self.build = build
+ self.host = host
+
def __repr__(self) -> str:
return f'PerMachine({self.build!r}, {self.host!r})'