diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 092d1d1e5db5..96a2210c4170 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -1907,7 +1907,7 @@ def __init__( compilers: T.Dict[str, 'Compiler'], kwargs): key = OptionKey('b_pie') - if 'pie' not in kwargs and environment.coredata.optstore.has_option(key): + if 'pie' not in kwargs and key in environment.coredata.optstore: kwargs['pie'] = environment.coredata.optstore.get_value_for(key) super().__init__(name, subdir, subproject, for_machine, sources, structured_sources, objects, environment, compilers, kwargs) diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index ed7ade0ecdba..5ea02817380e 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -259,10 +259,10 @@ def __init__(self, cmd_options: SharedCMDOptions, scratch_dir: str, meson_comman self.meson_command = meson_command self.target_guids = {} self.version = version - self.optstore = options.OptionStore() self.sp_option_overrides: T.Dict[str, str] = {} self.cross_files = self.__load_config_files(cmd_options, scratch_dir, 'cross') self.compilers: PerMachine[T.Dict[str, Compiler]] = PerMachine(OrderedDict(), OrderedDict()) + self.optstore = options.OptionStore(self.is_cross_build()) # Stores the (name, hash) of the options file, The name will be either # "meson_options.txt" or "meson.options". diff --git a/mesonbuild/options.py b/mesonbuild/options.py index 6406dd84234a..f62782c1a9b3 100644 --- a/mesonbuild/options.py +++ b/mesonbuild/options.py @@ -687,7 +687,7 @@ def add_to_argparse(self, name: str, parser: argparse.ArgumentParser, help_suffi class OptionStore: - def __init__(self): + def __init__(self, is_cross: bool): self.options: T.Dict['OptionKey', 'UserOption[T.Any]'] = {} self.project_options = set() self.all_languages = set() @@ -699,10 +699,23 @@ def __init__(self): self.project_options = set() self.augments = {} self.pending_project_options = {} + self.is_cross = is_cross - def ensure_key(self, key: T.Union[OptionKey, str]) -> OptionKey: + def ensure_and_validate_key(self, key: T.Union[OptionKey, str]) -> OptionKey: if isinstance(key, str): return OptionKey(key) + # FIXME. When not cross building all "build" options need to fall back + # to "host" options due to how the old code worked. + # + # This is NOT how it should be. + # + # This needs to be changed to that trying to add or access "build" keys + # is a hard error and fix issues that arise. + # + # I did not do this yet, because it would make this MR even + # more massive than it already is. Later then. + if not self.is_cross and key.machine == MachineChoice.BUILD: + key = key.evolve(machine=MachineChoice.HOST) return key def get_value(self, key: T.Union[OptionKey, str]) -> 'T.Any': @@ -714,7 +727,7 @@ def num_options(self): return basic + build def get_value_object_for(self, key): - key = self.ensure_key(key) + key = self.ensure_and_validate_key(key) potential = self.options.get(key, None) if self.is_project_option(key): assert key.subproject is not None @@ -738,13 +751,13 @@ def get_value_object_for(self, key): return potential def add_system_option(self, key: T.Union[OptionKey, str], valobj: 'UserOption[T.Any]'): - key = self.ensure_key(key) + key = self.ensure_and_validate_key(key) if '.' in key.name: raise MesonException(f'Internal error: non-module option has a period in its name {key.name}.') self.add_system_option_internal(key, valobj) def add_system_option_internal(self, key: T.Union[OptionKey, str], valobj: 'UserOption[T.Any]'): - key = self.ensure_key(key) + key = self.ensure_and_validate_key(key) assert isinstance(valobj, UserOption) if not isinstance(valobj.name, str): assert isinstance(valobj.name, str) @@ -756,7 +769,7 @@ def add_system_option_internal(self, key: T.Union[OptionKey, str], valobj: 'User def add_compiler_option(self, language: str, key: T.Union[OptionKey, str], valobj: 'UserOption[T.Any]'): - key = self.ensure_key(key) + key = self.ensure_and_validate_key(key) if not key.name.startswith(language + '_'): raise MesonException(f'Internal error: all compiler option names must start with language prefix. ({key.name} vs {language}_)') self.add_system_option(key, valobj) @@ -772,7 +785,7 @@ def add_project_option(self, key: OptionKey, valobj: 'UserOption[T.Any]'): self.set_option(key.name, key.subproject, pval) def add_module_option(self, modulename: str, key: T.Union[OptionKey, str], valobj: 'UserOption[T.Any]'): - key = self.ensure_key(key) + key = self.ensure_and_validate_key(key) if key.name.startswith('build.'): raise MesonException('FATAL internal error: somebody goofed option handling.') if not key.name.startswith(modulename + '.'): @@ -781,7 +794,7 @@ def add_module_option(self, modulename: str, key: T.Union[OptionKey, str], valob self.module_options.add(key) def set_value(self, key: T.Union[OptionKey, str], new_value: 'T.Any') -> bool: - key = self.ensure_key(key) + key = self.ensure_and_validate_key(key) if key not in self.options: raise MesonException(f'Internal error, tried to access non-existing option {key.name}.') return self.options[key].set_value(new_value) @@ -815,11 +828,11 @@ def replace(v): # FIXME, this should be removed.or renamed to "change_type_of_existing_object" or something like that def set_value_object(self, key: T.Union[OptionKey, str], new_object: 'UserOption[T.Any]') -> bool: - key = self.ensure_key(key) + key = self.ensure_and_validate_key(key) self.options[key] = new_object def get_value_object(self, key: T.Union[OptionKey, str]) -> 'UserOption[T.Any]': - key = self.ensure_key(key) + key = self.ensure_and_validate_key(key) return self.options[key] def get_value_object_and_value_for(self, key: OptionKey): @@ -841,7 +854,7 @@ def remove(self, key): del self.options[key] def __contains__(self, key): - key = self.ensure_key(key) + key = self.ensure_and_validate_key(key) return key in self.options def __repr__(self):