aboutsummaryrefslogtreecommitdiff
path: root/mesonbuild/interpreter/interpreter.py
diff options
context:
space:
mode:
Diffstat (limited to 'mesonbuild/interpreter/interpreter.py')
-rw-r--r--mesonbuild/interpreter/interpreter.py70
1 files changed, 42 insertions, 28 deletions
diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py
index 7bba4fa..4751af9 100644
--- a/mesonbuild/interpreter/interpreter.py
+++ b/mesonbuild/interpreter/interpreter.py
@@ -131,6 +131,8 @@ if T.TYPE_CHECKING:
BuildTargetSource = T.Union[mesonlib.FileOrString, build.GeneratedTypes, build.StructuredSources]
+ ProgramVersionFunc = T.Callable[[T.Union[ExternalProgram, build.Executable, OverrideProgram]], str]
+
def _project_version_validator(value: T.Union[T.List, str, mesonlib.File, None]) -> T.Optional[str]:
if isinstance(value, list):
@@ -1621,46 +1623,23 @@ class Interpreter(InterpreterBase, HoldableObject):
required: bool = True, silent: bool = True,
wanted: T.Union[str, T.List[str]] = '',
search_dirs: T.Optional[T.List[str]] = None,
- version_func: T.Optional[T.Callable[[T.Union['ExternalProgram', 'build.Executable', 'OverrideProgram']], str]] = None
+ version_func: T.Optional[ProgramVersionFunc] = None
) -> T.Union['ExternalProgram', 'build.Executable', 'OverrideProgram']:
args = mesonlib.listify(args)
extra_info: T.List[mlog.TV_Loggable] = []
- progobj = self.program_lookup(args, for_machine, default_options, required, search_dirs, extra_info)
- if progobj is None:
+ progobj = self.program_lookup(args, for_machine, default_options, required, search_dirs, wanted, version_func, extra_info)
+ if progobj is None or not self.check_program_version(progobj, wanted, version_func, extra_info):
progobj = self.notfound_program(args)
if isinstance(progobj, ExternalProgram) and not progobj.found():
if not silent:
- mlog.log('Program', mlog.bold(progobj.get_name()), 'found:', mlog.red('NO'))
+ mlog.log('Program', mlog.bold(progobj.get_name()), 'found:', mlog.red('NO'), *extra_info)
if required:
m = 'Program {!r} not found or not executable'
raise InterpreterException(m.format(progobj.get_name()))
return progobj
- if wanted:
- if version_func:
- version = version_func(progobj)
- elif isinstance(progobj, build.Executable):
- if progobj.subproject:
- interp = self.subprojects[progobj.subproject].held_object
- else:
- interp = self
- assert isinstance(interp, Interpreter)
- version = interp.project_version
- else:
- version = progobj.get_version(self)
- is_found, not_found, _ = mesonlib.version_compare_many(version, wanted)
- if not is_found:
- mlog.log('Program', mlog.bold(progobj.name), 'found:', mlog.red('NO'),
- 'found', mlog.normal_cyan(version), 'but need:',
- mlog.bold(', '.join([f"'{e}'" for e in not_found])), *extra_info)
- if required:
- m = 'Invalid version of program, need {!r} {!r} found {!r}.'
- raise InterpreterException(m.format(progobj.name, not_found, version))
- return self.notfound_program(args)
- extra_info.insert(0, mlog.normal_cyan(version))
-
# Only store successful lookups
self.store_name_lookups(args)
if not silent:
@@ -1671,7 +1650,11 @@ class Interpreter(InterpreterBase, HoldableObject):
def program_lookup(self, args: T.List[mesonlib.FileOrString], for_machine: MachineChoice,
default_options: T.Optional[T.Dict[OptionKey, T.Union[str, int, bool, T.List[str]]]],
- required: bool, search_dirs: T.List[str], extra_info: T.List[mlog.TV_Loggable]
+ required: bool,
+ search_dirs: T.List[str],
+ wanted: T.Union[str, T.List[str]],
+ version_func: T.Optional[ProgramVersionFunc],
+ extra_info: T.List[mlog.TV_Loggable]
) -> T.Optional[T.Union[ExternalProgram, build.Executable, OverrideProgram]]:
progobj = self.program_from_overrides(args, extra_info)
if progobj:
@@ -1694,11 +1677,42 @@ class Interpreter(InterpreterBase, HoldableObject):
if progobj is None and args[0].endswith('python3'):
prog = ExternalProgram('python3', mesonlib.python_command, silent=True)
progobj = prog if prog.found() else None
+
+ if progobj and not self.check_program_version(progobj, wanted, version_func, extra_info):
+ progobj = None
+
if progobj is None and fallback and required:
+ progobj = self.notfound_program(args)
+ mlog.log('Program', mlog.bold(progobj.get_name()), 'found:', mlog.red('NO'), *extra_info)
+ extra_info.clear()
progobj = self.find_program_fallback(fallback, args, default_options, required, extra_info)
return progobj
+ def check_program_version(self, progobj: T.Union[ExternalProgram, build.Executable, OverrideProgram],
+ wanted: T.Union[str, T.List[str]],
+ version_func: T.Optional[ProgramVersionFunc],
+ extra_info: T.List[mlog.TV_Loggable]) -> bool:
+ if wanted:
+ if version_func:
+ version = version_func(progobj)
+ elif isinstance(progobj, build.Executable):
+ if progobj.subproject:
+ interp = self.subprojects[progobj.subproject].held_object
+ else:
+ interp = self
+ assert isinstance(interp, Interpreter)
+ version = interp.project_version
+ else:
+ version = progobj.get_version(self)
+ is_found, not_found, _ = mesonlib.version_compare_many(version, wanted)
+ if not is_found:
+ extra_info[:0] = ['found', mlog.normal_cyan(version), 'but need:',
+ mlog.bold(', '.join([f"'{e}'" for e in not_found]))]
+ return False
+ extra_info.insert(0, mlog.normal_cyan(version))
+ return True
+
def find_program_fallback(self, fallback: str, args: T.List[mesonlib.FileOrString],
default_options: T.Dict[OptionKey, T.Union[str, int, bool, T.List[str]]],
required: bool, extra_info: T.List[mlog.TV_Loggable]