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.py61
1 files changed, 36 insertions, 25 deletions
diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py
index abdc889..29bb705 100644
--- a/mesonbuild/interpreter/interpreter.py
+++ b/mesonbuild/interpreter/interpreter.py
@@ -115,6 +115,7 @@ if T.TYPE_CHECKING:
from . import kwargs as kwtypes
from ..backend.backends import Backend
from ..interpreterbase.baseobjects import InterpreterObject, TYPE_var, TYPE_kwargs
+ from ..options import OptionDict
from ..programs import OverrideProgram
from .type_checking import SourcesVarargsType
@@ -270,7 +271,7 @@ class Interpreter(InterpreterBase, HoldableObject):
subproject: str = '',
subdir: str = '',
subproject_dir: str = 'subprojects',
- default_project_options: T.Optional[T.Dict[OptionKey, str]] = None,
+ invoker_method_default_options: T.Optional[OptionDict] = None,
ast: T.Optional[mparser.CodeBlockNode] = None,
relaxations: T.Optional[T.Set[InterpreterRuleRelaxation]] = None,
user_defined_options: T.Optional[coredata.SharedCMDOptions] = None,
@@ -295,13 +296,12 @@ class Interpreter(InterpreterBase, HoldableObject):
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 if isinstance(default_project_options, str) else default_project_options.copy()
- if isinstance(default_project_options, dict):
- pass
+ if invoker_method_default_options:
+ assert isinstance(invoker_method_default_options, dict)
+ self.invoker_method_default_options = invoker_method_default_options
else:
- self.default_project_options = {}
- self.project_default_options: T.List[str] = []
+ self.invoker_method_default_options = {}
+ self.project_default_options: OptionDict = {}
self.build_func_dict()
self.build_holder_map()
self.user_defined_options = user_defined_options
@@ -426,6 +426,7 @@ class Interpreter(InterpreterBase, HoldableObject):
build.Generator: OBJ.GeneratorHolder,
build.GeneratedList: OBJ.GeneratedListHolder,
build.ExtractedObjects: OBJ.GeneratedObjectsHolder,
+ build.OverrideExecutable: OBJ.OverrideExecutableHolder,
build.RunTarget: OBJ.RunTargetHolder,
build.AliasTarget: OBJ.AliasTargetHolder,
build.Headers: OBJ.HeadersHolder,
@@ -868,7 +869,8 @@ class Interpreter(InterpreterBase, HoldableObject):
self.subprojects[subp_name] = sub
return sub
- def do_subproject(self, subp_name: str, kwargs: kwtypes.DoSubproject, force_method: T.Optional[wrap.Method] = None) -> SubprojectHolder:
+ def do_subproject(self, subp_name: str, kwargs: kwtypes.DoSubproject, force_method: T.Optional[wrap.Method] = None,
+ forced_options: T.Optional[OptionDict] = None) -> SubprojectHolder:
if subp_name == 'sub_static':
pass
disabled, required, feature = extract_required_kwarg(kwargs, self.subproject)
@@ -879,6 +881,16 @@ class Interpreter(InterpreterBase, HoldableObject):
default_options = kwargs['default_options']
+ # This in practice is only used for default_library. forced_options is the
+ # only case in which a meson.build file overrides the machine file or the
+ # command line.
+ if forced_options:
+ for k, v in forced_options.items():
+ # FIXME: this should have no business poking at augments[],
+ # but set_option() does not do what we want
+ self.coredata.optstore.augments[k.evolve(subproject=subp_name)] = v
+ default_options = {**forced_options, **default_options}
+
if subp_name == '':
raise InterpreterException('Subproject name must not be empty.')
if subp_name[0] == '.':
@@ -930,7 +942,8 @@ class Interpreter(InterpreterBase, HoldableObject):
m += ['method', mlog.bold(method)]
mlog.log(*m, '\n', nested=False)
- methods_map: T.Dict[wrap.Method, T.Callable[[str, str, T.Dict[OptionKey, str, kwtypes.DoSubproject]], SubprojectHolder]] = {
+ methods_map: T.Dict[wrap.Method, T.Callable[[str, str, OptionDict, kwtypes.DoSubproject],
+ SubprojectHolder]] = {
'meson': self._do_subproject_meson,
'cmake': self._do_subproject_cmake,
'cargo': self._do_subproject_cargo,
@@ -952,7 +965,7 @@ class Interpreter(InterpreterBase, HoldableObject):
raise e
def _do_subproject_meson(self, subp_name: str, subdir: str,
- default_options: T.List[str],
+ default_options: OptionDict,
kwargs: kwtypes.DoSubproject,
ast: T.Optional[mparser.CodeBlockNode] = None,
build_def_files: T.Optional[T.List[str]] = None,
@@ -1012,7 +1025,7 @@ class Interpreter(InterpreterBase, HoldableObject):
return self.subprojects[subp_name]
def _do_subproject_cmake(self, subp_name: str, subdir: str,
- default_options: T.List[str],
+ default_options: OptionDict,
kwargs: kwtypes.DoSubproject) -> SubprojectHolder:
from ..cmake import CMakeInterpreter
with mlog.nested(subp_name):
@@ -1039,13 +1052,14 @@ class Interpreter(InterpreterBase, HoldableObject):
return result
def _do_subproject_cargo(self, subp_name: str, subdir: str,
- default_options: T.List[str],
+ default_options: OptionDict,
kwargs: kwtypes.DoSubproject) -> SubprojectHolder:
from .. import cargo
FeatureNew.single_use('Cargo subproject', '1.3.0', self.subproject, location=self.current_node)
mlog.warning('Cargo subproject is an experimental feature and has no backwards compatibility guarantees.',
once=True, location=self.current_node)
if self.environment.cargo is None:
+ self.add_languages(['rust'], True, MachineChoice.HOST)
self.environment.cargo = cargo.Interpreter(self.environment)
with mlog.nested(subp_name):
ast = self.environment.cargo.interpret(subdir)
@@ -1184,20 +1198,17 @@ class Interpreter(InterpreterBase, HoldableObject):
self._load_option_file()
self.project_default_options = kwargs['default_options']
- if isinstance(self.project_default_options, str):
- self.project_default_options = [self.project_default_options]
- assert isinstance(self.project_default_options, (list, dict))
if self.environment.first_invocation or (self.subproject != '' and self.subproject not in self.coredata.initialized_subprojects):
if self.subproject == '':
self.coredata.optstore.initialize_from_top_level_project_call(self.project_default_options,
self.user_defined_options.cmd_line_options,
self.environment.options)
else:
- invoker_method_default_options = self.default_project_options
self.coredata.optstore.initialize_from_subproject_call(self.subproject,
- invoker_method_default_options,
+ self.invoker_method_default_options,
self.project_default_options,
- self.user_defined_options.cmd_line_options)
+ self.user_defined_options.cmd_line_options,
+ self.environment.options)
self.coredata.initialized_subprojects.add(self.subproject)
if not self.is_subproject():
@@ -1529,7 +1540,7 @@ class Interpreter(InterpreterBase, HoldableObject):
self.backend.allow_thin_archives[for_machine] = False
else:
# update new values from commandline, if it applies
- self.coredata.process_compiler_options(lang, comp, self.environment, self.subproject)
+ self.coredata.process_compiler_options(lang, comp, self.subproject)
if for_machine == MachineChoice.HOST or self.environment.is_cross_build():
logger_fun = mlog.log
@@ -1590,7 +1601,7 @@ class Interpreter(InterpreterBase, HoldableObject):
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]]:
+ ) -> T.Optional[T.Union[ExternalProgram, OverrideProgram, build.OverrideExecutable]]:
for name in command_names:
if not isinstance(name, str):
continue
@@ -1605,7 +1616,7 @@ class Interpreter(InterpreterBase, HoldableObject):
if isinstance(name, str):
self.build.searched_programs.add(name)
- def add_find_program_override(self, name: str, exe: T.Union[build.Executable, ExternalProgram, 'OverrideProgram']) -> None:
+ def add_find_program_override(self, name: str, exe: T.Union[build.OverrideExecutable, ExternalProgram, 'OverrideProgram']) -> None:
if name in self.build.searched_programs:
raise InterpreterException(f'Tried to override finding of executable "{name}" which has already been found.')
if name in self.build.find_overrides:
@@ -1624,13 +1635,13 @@ class Interpreter(InterpreterBase, HoldableObject):
# the host machine.
def find_program_impl(self, args: T.List[mesonlib.FileOrString],
for_machine: MachineChoice = MachineChoice.HOST,
- default_options: T.Optional[T.Dict[OptionKey, options.ElementaryOptionValues]] = None,
+ default_options: T.Optional[OptionDict] = None,
required: bool = True, silent: bool = True,
wanted: T.Union[str, T.List[str]] = '',
search_dirs: T.Optional[T.List[str]] = None,
version_arg: T.Optional[str] = '',
version_func: T.Optional[ProgramVersionFunc] = None
- ) -> T.Union['ExternalProgram', 'build.Executable', 'OverrideProgram']:
+ ) -> T.Union['ExternalProgram', 'build.OverrideExecutable', 'OverrideProgram']:
args = mesonlib.listify(args)
extra_info: T.List[mlog.TV_Loggable] = []
@@ -1655,7 +1666,7 @@ class Interpreter(InterpreterBase, HoldableObject):
return progobj
def program_lookup(self, args: T.List[mesonlib.FileOrString], for_machine: MachineChoice,
- default_options: T.Optional[T.Dict[OptionKey, options.ElementaryOptionValues]],
+ default_options: T.Optional[OptionDict],
required: bool,
search_dirs: T.Optional[T.List[str]],
wanted: T.Union[str, T.List[str]],
@@ -1723,7 +1734,7 @@ class Interpreter(InterpreterBase, HoldableObject):
return True
def find_program_fallback(self, fallback: str, args: T.List[mesonlib.FileOrString],
- default_options: T.Dict[OptionKey, options.ElementaryOptionValues],
+ default_options: OptionDict,
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',