|
|
|
@ -33,7 +33,7 @@ from ..interpreterbase import InterpreterException, InvalidArguments, InvalidCod |
|
|
|
|
from ..interpreterbase import Disabler, disablerIfNotFound |
|
|
|
|
from ..interpreterbase import FeatureNew, FeatureDeprecated, FeatureNewKwargs, FeatureDeprecatedKwargs |
|
|
|
|
from ..interpreterbase import ObjectHolder |
|
|
|
|
from ..interpreterbase.baseobjects import TYPE_var, TYPE_kwargs |
|
|
|
|
from ..interpreterbase.baseobjects import InterpreterObject, TYPE_var, TYPE_kwargs |
|
|
|
|
from ..modules import ExtensionModule, ModuleObject, MutableModuleObject, NewExtensionModule, NotFoundExtensionModule |
|
|
|
|
from ..cmake import CMakeInterpreter |
|
|
|
|
from ..backend.backends import Backend, ExecutableSerialisation |
|
|
|
@ -93,6 +93,8 @@ import importlib |
|
|
|
|
if T.TYPE_CHECKING: |
|
|
|
|
import argparse |
|
|
|
|
|
|
|
|
|
from typing_extensions import Literal |
|
|
|
|
|
|
|
|
|
from . import kwargs |
|
|
|
|
from ..programs import OverrideProgram |
|
|
|
|
|
|
|
|
@ -115,7 +117,7 @@ def _project_version_validator(value: T.Union[T.List, str, mesonlib.File, None]) |
|
|
|
|
return None |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def stringifyUserArguments(args, quote=False): |
|
|
|
|
def stringifyUserArguments(args: T.List[T.Any], quote: bool = False) -> str: |
|
|
|
|
if isinstance(args, list): |
|
|
|
|
return '[%s]' % ', '.join([stringifyUserArguments(x, True) for x in args]) |
|
|
|
|
elif isinstance(args, dict): |
|
|
|
@ -258,7 +260,7 @@ class Interpreter(InterpreterBase, HoldableObject): |
|
|
|
|
subproject: str = '', |
|
|
|
|
subdir: str = '', |
|
|
|
|
subproject_dir: str = 'subprojects', |
|
|
|
|
default_project_options: T.Optional[T.Dict[str, str]] = None, |
|
|
|
|
default_project_options: T.Optional[T.Dict[OptionKey, str]] = None, |
|
|
|
|
mock: bool = False, |
|
|
|
|
ast: T.Optional[mparser.CodeBlockNode] = None, |
|
|
|
|
is_translated: bool = False, |
|
|
|
@ -271,7 +273,7 @@ class Interpreter(InterpreterBase, HoldableObject): |
|
|
|
|
self.coredata = self.environment.get_coredata() |
|
|
|
|
self.backend = backend |
|
|
|
|
self.summary: T.Dict[str, 'Summary'] = {} |
|
|
|
|
self.modules = {} |
|
|
|
|
self.modules: T.Dict[str, NewExtensionModule] = {} |
|
|
|
|
# Subproject directory is usually the name of the subproject, but can |
|
|
|
|
# be different for dependencies provided by wrap files. |
|
|
|
|
self.subproject_directory_name = subdir.split(os.path.sep)[-1] |
|
|
|
@ -289,14 +291,14 @@ class Interpreter(InterpreterBase, HoldableObject): |
|
|
|
|
self.project_args_frozen = False |
|
|
|
|
self.global_args_frozen = False # implies self.project_args_frozen |
|
|
|
|
self.subprojects: T.Dict[str, SubprojectHolder] = {} |
|
|
|
|
self.subproject_stack = [] |
|
|
|
|
self.configure_file_outputs = {} |
|
|
|
|
self.subproject_stack: T.List[str] = [] |
|
|
|
|
self.configure_file_outputs: T.Dict[str, int] = {} |
|
|
|
|
# Passed from the outside, only used in subprojects. |
|
|
|
|
if default_project_options: |
|
|
|
|
self.default_project_options = default_project_options.copy() |
|
|
|
|
else: |
|
|
|
|
self.default_project_options = {} |
|
|
|
|
self.project_default_options = {} |
|
|
|
|
self.project_default_options: T.Dict[OptionKey, str] = {} |
|
|
|
|
self.build_func_dict() |
|
|
|
|
self.build_holder_map() |
|
|
|
|
self.user_defined_options = user_defined_options |
|
|
|
@ -306,10 +308,10 @@ class Interpreter(InterpreterBase, HoldableObject): |
|
|
|
|
# For non-meson subprojects, we'll be using the ast. Even if it does |
|
|
|
|
# exist we don't want to add a dependency on it, it's autogenerated |
|
|
|
|
# from the actual build files, and is just for reference. |
|
|
|
|
self.build_def_files = [] |
|
|
|
|
self.build_def_files: mesonlib.OrderedSet[str] = mesonlib.OrderedSet() |
|
|
|
|
build_filename = os.path.join(self.subdir, environment.build_filename) |
|
|
|
|
if not is_translated: |
|
|
|
|
self.build_def_files.append(build_filename) |
|
|
|
|
self.build_def_files.add(build_filename) |
|
|
|
|
if not mock: |
|
|
|
|
self.parse_project() |
|
|
|
|
self._redetect_machines() |
|
|
|
@ -317,7 +319,7 @@ class Interpreter(InterpreterBase, HoldableObject): |
|
|
|
|
def __getnewargs_ex__(self) -> T.Tuple[T.Tuple[object], T.Dict[str, object]]: |
|
|
|
|
raise MesonBugException('This class is unpicklable') |
|
|
|
|
|
|
|
|
|
def _redetect_machines(self): |
|
|
|
|
def _redetect_machines(self) -> None: |
|
|
|
|
# Re-initialize machine descriptions. We can do a better job now because we |
|
|
|
|
# have the compilers needed to gain more knowledge, so wipe out old |
|
|
|
|
# inference and start over. |
|
|
|
@ -335,7 +337,7 @@ class Interpreter(InterpreterBase, HoldableObject): |
|
|
|
|
self.builtin['target_machine'] = \ |
|
|
|
|
OBJ.MachineHolder(self.build.environment.machines.target, self) |
|
|
|
|
|
|
|
|
|
def build_func_dict(self): |
|
|
|
|
def build_func_dict(self) -> None: |
|
|
|
|
self.funcs.update({'add_global_arguments': self.func_add_global_arguments, |
|
|
|
|
'add_global_link_arguments': self.func_add_global_link_arguments, |
|
|
|
|
'add_languages': self.func_add_languages, |
|
|
|
@ -501,7 +503,7 @@ class Interpreter(InterpreterBase, HoldableObject): |
|
|
|
|
else: |
|
|
|
|
raise InterpreterException(f'Module returned a value of unknown type {v!r}.') |
|
|
|
|
|
|
|
|
|
def get_build_def_files(self) -> T.List[str]: |
|
|
|
|
def get_build_def_files(self) -> mesonlib.OrderedSet[str]: |
|
|
|
|
return self.build_def_files |
|
|
|
|
|
|
|
|
|
def add_build_def_file(self, f: mesonlib.FileOrString) -> None: |
|
|
|
@ -517,32 +519,32 @@ class Interpreter(InterpreterBase, HoldableObject): |
|
|
|
|
srcdir = Path(self.environment.get_source_dir()) |
|
|
|
|
builddir = Path(self.environment.get_build_dir()) |
|
|
|
|
try: |
|
|
|
|
f = Path(f).resolve() |
|
|
|
|
f_ = Path(f).resolve() |
|
|
|
|
except OSError: |
|
|
|
|
f = Path(f) |
|
|
|
|
s = f.stat() |
|
|
|
|
f_ = Path(f) |
|
|
|
|
s = f_.stat() |
|
|
|
|
if (hasattr(s, 'st_file_attributes') and |
|
|
|
|
s.st_file_attributes & stat.FILE_ATTRIBUTE_REPARSE_POINT != 0 and |
|
|
|
|
s.st_reparse_tag == stat.IO_REPARSE_TAG_APPEXECLINK): |
|
|
|
|
# This is a Windows Store link which we can't |
|
|
|
|
# resolve, so just do our best otherwise. |
|
|
|
|
f = f.parent.resolve() / f.name |
|
|
|
|
f_ = f_.parent.resolve() / f_.name |
|
|
|
|
else: |
|
|
|
|
raise |
|
|
|
|
if builddir in f.parents: |
|
|
|
|
if builddir in f_.parents: |
|
|
|
|
return |
|
|
|
|
if srcdir in f.parents: |
|
|
|
|
f = f.relative_to(srcdir) |
|
|
|
|
f = str(f) |
|
|
|
|
if srcdir in f_.parents: |
|
|
|
|
f_ = f_.relative_to(srcdir) |
|
|
|
|
f = str(f_) |
|
|
|
|
else: |
|
|
|
|
return |
|
|
|
|
if f not in self.build_def_files: |
|
|
|
|
self.build_def_files.append(f) |
|
|
|
|
self.build_def_files.add(f) |
|
|
|
|
|
|
|
|
|
def get_variables(self): |
|
|
|
|
def get_variables(self) -> T.Dict[str, InterpreterObject]: |
|
|
|
|
return self.variables |
|
|
|
|
|
|
|
|
|
def check_stdlibs(self): |
|
|
|
|
def check_stdlibs(self) -> None: |
|
|
|
|
machine_choices = [MachineChoice.HOST] |
|
|
|
|
if self.coredata.is_cross_build(): |
|
|
|
|
machine_choices.append(MachineChoice.BUILD) |
|
|
|
@ -563,7 +565,7 @@ class Interpreter(InterpreterBase, HoldableObject): |
|
|
|
|
dep = df.lookup(kwargs, force_fallback=True) |
|
|
|
|
self.build.stdlibs[for_machine][l] = dep |
|
|
|
|
|
|
|
|
|
def _import_module(self, modname: str, required: bool) -> T.Union[ExtensionModule, NewExtensionModule, NotFoundExtensionModule]: |
|
|
|
|
def _import_module(self, modname: str, required: bool) -> NewExtensionModule: |
|
|
|
|
if modname in self.modules: |
|
|
|
|
return self.modules[modname] |
|
|
|
|
try: |
|
|
|
@ -797,24 +799,37 @@ external dependencies (including libraries) must go to "dependencies".''') |
|
|
|
|
@FeatureNewKwargs('subproject', '0.38.0', ['default_options']) |
|
|
|
|
@permittedKwargs({'version', 'default_options', 'required'}) |
|
|
|
|
@typed_pos_args('subproject', str) |
|
|
|
|
def func_subproject(self, nodes: mparser.BaseNode, args: T.Tuple[str], kwargs: 'TYPE_kwargs') -> SubprojectHolder: |
|
|
|
|
return self.do_subproject(args[0], 'meson', kwargs) |
|
|
|
|
@typed_kwargs( |
|
|
|
|
'subproject', |
|
|
|
|
REQUIRED_KW, |
|
|
|
|
DEFAULT_OPTIONS.evolve(since='0.38.0'), |
|
|
|
|
KwargInfo('version', ContainerTypeInfo(list, str), default=[], listify=True), |
|
|
|
|
) |
|
|
|
|
def func_subproject(self, nodes: mparser.BaseNode, args: T.Tuple[str], kwargs_: kwargs.Subproject) -> SubprojectHolder: |
|
|
|
|
kw: kwargs.DoSubproject = { |
|
|
|
|
'required': kwargs_['required'], |
|
|
|
|
'default_options': kwargs_['default_options'], |
|
|
|
|
'version': kwargs_['version'], |
|
|
|
|
'options': None, |
|
|
|
|
'cmake_options': [], |
|
|
|
|
} |
|
|
|
|
return self.do_subproject(args[0], 'meson', kw) |
|
|
|
|
|
|
|
|
|
def disabled_subproject(self, subp_name, disabled_feature=None, exception=None): |
|
|
|
|
def disabled_subproject(self, subp_name: str, disabled_feature: T.Optional[str] = None, |
|
|
|
|
exception: T.Optional[Exception] = None) -> SubprojectHolder: |
|
|
|
|
sub = SubprojectHolder(NullSubprojectInterpreter(), os.path.join(self.subproject_dir, subp_name), |
|
|
|
|
disabled_feature=disabled_feature, exception=exception) |
|
|
|
|
self.subprojects[subp_name] = sub |
|
|
|
|
self.coredata.initialized_subprojects.add(subp_name) |
|
|
|
|
return sub |
|
|
|
|
|
|
|
|
|
def do_subproject(self, subp_name: str, method: str, kwargs): |
|
|
|
|
def do_subproject(self, subp_name: str, method: Literal['meson', 'cmake'], kwargs: kwargs.DoSubproject) -> SubprojectHolder: |
|
|
|
|
disabled, required, feature = extract_required_kwarg(kwargs, self.subproject) |
|
|
|
|
if disabled: |
|
|
|
|
mlog.log('Subproject', mlog.bold(subp_name), ':', 'skipped: feature', mlog.bold(feature), 'disabled') |
|
|
|
|
return self.disabled_subproject(subp_name, disabled_feature=feature) |
|
|
|
|
|
|
|
|
|
default_options = mesonlib.stringlistify(kwargs.get('default_options', [])) |
|
|
|
|
default_options = coredata.create_options_dict(default_options, subp_name) |
|
|
|
|
default_options = coredata.create_options_dict(kwargs['default_options'], subp_name) |
|
|
|
|
|
|
|
|
|
if subp_name == '': |
|
|
|
|
raise InterpreterException('Subproject name must not be empty.') |
|
|
|
@ -835,7 +850,7 @@ external dependencies (including libraries) must go to "dependencies".''') |
|
|
|
|
subproject = self.subprojects[subp_name] |
|
|
|
|
if required and not subproject.found(): |
|
|
|
|
raise InterpreterException(f'Subproject "{subproject.subdir}" required but not found.') |
|
|
|
|
if 'version' in kwargs: |
|
|
|
|
if kwargs['version']: |
|
|
|
|
pv = self.build.subprojects[subp_name] |
|
|
|
|
wanted = kwargs['version'] |
|
|
|
|
if pv == 'undefined' or not mesonlib.version_compare_many(pv, wanted)[0]: |
|
|
|
@ -882,7 +897,9 @@ external dependencies (including libraries) must go to "dependencies".''') |
|
|
|
|
return self.disabled_subproject(subp_name, exception=e) |
|
|
|
|
raise e |
|
|
|
|
|
|
|
|
|
def _do_subproject_meson(self, subp_name: str, subdir: str, default_options, kwargs, |
|
|
|
|
def _do_subproject_meson(self, subp_name: str, subdir: str, |
|
|
|
|
default_options: T.Dict[OptionKey, str], |
|
|
|
|
kwargs: kwargs.DoSubproject, |
|
|
|
|
ast: T.Optional[mparser.CodeBlockNode] = None, |
|
|
|
|
build_def_files: T.Optional[T.List[str]] = None, |
|
|
|
|
is_translated: bool = False) -> SubprojectHolder: |
|
|
|
@ -911,7 +928,7 @@ external dependencies (including libraries) must go to "dependencies".''') |
|
|
|
|
|
|
|
|
|
mlog.log() |
|
|
|
|
|
|
|
|
|
if 'version' in kwargs: |
|
|
|
|
if kwargs['version']: |
|
|
|
|
pv = subi.project_version |
|
|
|
|
wanted = kwargs['version'] |
|
|
|
|
if pv == 'undefined' or not mesonlib.version_compare_many(pv, wanted)[0]: |
|
|
|
@ -921,27 +938,24 @@ external dependencies (including libraries) must go to "dependencies".''') |
|
|
|
|
self.subprojects[subp_name] = SubprojectHolder(subi, subdir, warnings=subi_warnings) |
|
|
|
|
# Duplicates are possible when subproject uses files from project root |
|
|
|
|
if build_def_files: |
|
|
|
|
self.build_def_files = list(set(self.build_def_files + build_def_files)) |
|
|
|
|
self.build_def_files.update(build_def_files) |
|
|
|
|
# We always need the subi.build_def_files, to propgate sub-sub-projects |
|
|
|
|
self.build_def_files = list(set(self.build_def_files + subi.build_def_files)) |
|
|
|
|
self.build_def_files.update(subi.build_def_files) |
|
|
|
|
self.build.merge(subi.build) |
|
|
|
|
self.build.subprojects[subp_name] = subi.project_version |
|
|
|
|
self.coredata.initialized_subprojects.add(subp_name) |
|
|
|
|
return self.subprojects[subp_name] |
|
|
|
|
|
|
|
|
|
def _do_subproject_cmake(self, subp_name, subdir, subdir_abs, default_options, kwargs): |
|
|
|
|
def _do_subproject_cmake(self, subp_name: str, subdir: str, subdir_abs: str, |
|
|
|
|
default_options: T.Dict[OptionKey, str], |
|
|
|
|
kwargs: kwargs.DoSubproject) -> SubprojectHolder: |
|
|
|
|
with mlog.nested(subp_name): |
|
|
|
|
new_build = self.build.copy() |
|
|
|
|
prefix = self.coredata.options[OptionKey('prefix')].value |
|
|
|
|
|
|
|
|
|
from ..modules.cmake import CMakeSubprojectOptions |
|
|
|
|
options = kwargs.get('options', CMakeSubprojectOptions()) |
|
|
|
|
if not isinstance(options, CMakeSubprojectOptions): |
|
|
|
|
raise InterpreterException('"options" kwarg must be CMakeSubprojectOptions' |
|
|
|
|
' object (created by cmake.subproject_options())') |
|
|
|
|
|
|
|
|
|
cmake_options = mesonlib.stringlistify(kwargs.get('cmake_options', [])) |
|
|
|
|
cmake_options += options.cmake_options |
|
|
|
|
options = kwargs['options'] or CMakeSubprojectOptions() |
|
|
|
|
cmake_options = kwargs['cmake_options'] + options.cmake_options |
|
|
|
|
cm_int = CMakeInterpreter(new_build, Path(subdir), Path(subdir_abs), Path(prefix), new_build.environment, self.backend) |
|
|
|
|
cm_int.initialise(cmake_options) |
|
|
|
|
cm_int.analyse() |
|
|
|
@ -967,13 +981,13 @@ external dependencies (including libraries) must go to "dependencies".''') |
|
|
|
|
mlog.cmd_ci_include(meson_filename) |
|
|
|
|
mlog.log() |
|
|
|
|
|
|
|
|
|
result = self._do_subproject_meson(subp_name, subdir, default_options, kwargs, ast, cm_int.bs_files, is_translated=True) |
|
|
|
|
result = self._do_subproject_meson(subp_name, subdir, default_options, kwargs, ast, [str(f) for f in cm_int.bs_files], is_translated=True) |
|
|
|
|
result.cm_interpreter = cm_int |
|
|
|
|
|
|
|
|
|
mlog.log() |
|
|
|
|
return result |
|
|
|
|
|
|
|
|
|
def get_option_internal(self, optname: str): |
|
|
|
|
def get_option_internal(self, optname: str) -> coredata.UserOption: |
|
|
|
|
key = OptionKey.from_string(optname).evolve(subproject=self.subproject) |
|
|
|
|
|
|
|
|
|
if not key.is_project(): |
|
|
|
@ -982,6 +996,7 @@ external dependencies (including libraries) must go to "dependencies".''') |
|
|
|
|
if v is None or v.yielding: |
|
|
|
|
v = opts.get(key.as_root()) |
|
|
|
|
if v is not None: |
|
|
|
|
assert isinstance(v, coredata.UserOption), 'for mypy' |
|
|
|
|
return v |
|
|
|
|
|
|
|
|
|
try: |
|
|
|
@ -1037,7 +1052,7 @@ external dependencies (including libraries) must go to "dependencies".''') |
|
|
|
|
f'"configuration_data": initial value dictionary key "{k!r}"" must be "str | int | bool", not "{v!r}"') |
|
|
|
|
return build.ConfigurationData(initial_values) |
|
|
|
|
|
|
|
|
|
def set_backend(self): |
|
|
|
|
def set_backend(self) -> None: |
|
|
|
|
# The backend is already set when parsing subprojects |
|
|
|
|
if self.backend is not None: |
|
|
|
|
return |
|
|
|
@ -1326,7 +1341,7 @@ external dependencies (including libraries) must go to "dependencies".''') |
|
|
|
|
return False |
|
|
|
|
return should |
|
|
|
|
|
|
|
|
|
def add_languages_for(self, args: T.List[str], required: bool, for_machine: MachineChoice) -> None: |
|
|
|
|
def add_languages_for(self, args: T.List[str], required: bool, for_machine: MachineChoice) -> bool: |
|
|
|
|
args = [a.lower() for a in args] |
|
|
|
|
langs = set(self.coredata.compilers[for_machine].keys()) |
|
|
|
|
langs.update(args) |
|
|
|
@ -1378,7 +1393,8 @@ external dependencies (including libraries) must go to "dependencies".''') |
|
|
|
|
|
|
|
|
|
return success |
|
|
|
|
|
|
|
|
|
def program_from_file_for(self, for_machine, prognames): |
|
|
|
|
def program_from_file_for(self, for_machine: MachineChoice, prognames: T.List[mesonlib.FileOrString] |
|
|
|
|
) -> T.Optional[ExternalProgram]: |
|
|
|
|
for p in prognames: |
|
|
|
|
if isinstance(p, mesonlib.File): |
|
|
|
|
continue # Always points to a local (i.e. self generated) file. |
|
|
|
@ -1389,7 +1405,8 @@ external dependencies (including libraries) must go to "dependencies".''') |
|
|
|
|
return prog |
|
|
|
|
return None |
|
|
|
|
|
|
|
|
|
def program_from_system(self, args, search_dirs, extra_info): |
|
|
|
|
def program_from_system(self, args: T.List[mesonlib.FileOrString], search_dirs: T.List[str], |
|
|
|
|
extra_info: T.List[mlog.TV_Loggable]) -> T.Optional[ExternalProgram]: |
|
|
|
|
# Search for scripts relative to current subdir. |
|
|
|
|
# Do not cache found programs because find_program('foobar') |
|
|
|
|
# might give different results when run from different source dirs. |
|
|
|
@ -1415,9 +1432,11 @@ external dependencies (including libraries) must go to "dependencies".''') |
|
|
|
|
if extprog.found(): |
|
|
|
|
extra_info.append(f"({' '.join(extprog.get_command())})") |
|
|
|
|
return extprog |
|
|
|
|
return None |
|
|
|
|
|
|
|
|
|
def program_from_overrides(self, command_names: T.List[str], extra_info: T.List['mlog.TV_Loggable']) -> \ |
|
|
|
|
T.Optional[T.Union[ExternalProgram, 'OverrideProgram', 'build.Executable']]: |
|
|
|
|
def program_from_overrides(self, command_names: T.List[mesonlib.FileOrString], |
|
|
|
|
extra_info: T.List['mlog.TV_Loggable'] |
|
|
|
|
) -> T.Optional[T.Union[ExternalProgram, OverrideProgram, build.Executable]]: |
|
|
|
|
for name in command_names: |
|
|
|
|
if not isinstance(name, str): |
|
|
|
|
continue |
|
|
|
@ -1427,7 +1446,7 @@ external dependencies (including libraries) must go to "dependencies".''') |
|
|
|
|
return exe |
|
|
|
|
return None |
|
|
|
|
|
|
|
|
|
def store_name_lookups(self, command_names): |
|
|
|
|
def store_name_lookups(self, command_names: T.List[mesonlib.FileOrString]) -> None: |
|
|
|
|
for name in command_names: |
|
|
|
|
if isinstance(name, str): |
|
|
|
|
self.build.searched_programs.add(name) |
|
|
|
@ -1455,7 +1474,7 @@ external dependencies (including libraries) must go to "dependencies".''') |
|
|
|
|
) -> T.Union['ExternalProgram', 'build.Executable', 'OverrideProgram']: |
|
|
|
|
args = mesonlib.listify(args) |
|
|
|
|
|
|
|
|
|
extra_info = [] |
|
|
|
|
extra_info: T.List[mlog.TV_Loggable] = [] |
|
|
|
|
progobj = self.program_lookup(args, for_machine, required, search_dirs, extra_info) |
|
|
|
|
if progobj is None: |
|
|
|
|
progobj = self.notfound_program(args) |
|
|
|
@ -1472,14 +1491,15 @@ external dependencies (including libraries) must go to "dependencies".''') |
|
|
|
|
if version_func: |
|
|
|
|
version = version_func(progobj) |
|
|
|
|
elif isinstance(progobj, build.Executable): |
|
|
|
|
interp = self |
|
|
|
|
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, found = mesonlib.version_compare_many(version, wanted) |
|
|
|
|
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:', |
|
|
|
@ -1498,7 +1518,9 @@ external dependencies (including libraries) must go to "dependencies".''') |
|
|
|
|
progobj.was_returned_by_find_program = True |
|
|
|
|
return progobj |
|
|
|
|
|
|
|
|
|
def program_lookup(self, args, for_machine, required, search_dirs, extra_info): |
|
|
|
|
def program_lookup(self, args: T.List[mesonlib.FileOrString], for_machine: MachineChoice, |
|
|
|
|
required: bool, search_dirs: T.List[str], 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: |
|
|
|
|
return progobj |
|
|
|
@ -1521,10 +1543,18 @@ external dependencies (including libraries) must go to "dependencies".''') |
|
|
|
|
|
|
|
|
|
return progobj |
|
|
|
|
|
|
|
|
|
def find_program_fallback(self, fallback, args, required, extra_info): |
|
|
|
|
def find_program_fallback(self, fallback: str, args: T.List[mesonlib.FileOrString], |
|
|
|
|
required: bool, extra_info: T.List[mlog.TV_Loggable] |
|
|
|
|
) -> T.Optional[T.Union[ExternalProgram, build.Executable, OverrideProgram]]: |
|
|
|
|
mlog.log('Fallback to subproject', mlog.bold(fallback), 'which provides program', |
|
|
|
|
mlog.bold(' '.join(args))) |
|
|
|
|
sp_kwargs = {'required': required} |
|
|
|
|
sp_kwargs: kwargs.DoSubproject = { |
|
|
|
|
'required': required, |
|
|
|
|
'default_options': [], |
|
|
|
|
'version': [], |
|
|
|
|
'cmake_options': [], |
|
|
|
|
'options': None, |
|
|
|
|
} |
|
|
|
|
self.do_subproject(fallback, 'meson', sp_kwargs) |
|
|
|
|
return self.program_from_overrides(args, extra_info) |
|
|
|
|
|
|
|
|
@ -2115,7 +2145,7 @@ external dependencies (including libraries) must go to "dependencies".''') |
|
|
|
|
self.subdir = subdir |
|
|
|
|
os.makedirs(os.path.join(self.environment.build_dir, subdir), exist_ok=True) |
|
|
|
|
buildfilename = os.path.join(self.subdir, environment.build_filename) |
|
|
|
|
self.build_def_files.append(buildfilename) |
|
|
|
|
self.build_def_files.add(buildfilename) |
|
|
|
|
absname = os.path.join(self.environment.get_source_dir(), buildfilename) |
|
|
|
|
if not os.path.isfile(absname): |
|
|
|
|
self.subdir = prev_subdir |
|
|
|
|