options: merge set_value and set_option

Which are basically the same, except for handling of deprecated options,
and various bugs that only existed in one implementation or the other.
master
Dylan Baker 3 weeks ago committed by Eli Schwartz
parent 251f74dcf3
commit c56e42c119
  1. 18
      mesonbuild/coredata.py
  2. 68
      mesonbuild/options.py
  3. 4
      unittests/platformagnostictests.py

@ -417,7 +417,7 @@ class CoreData:
def set_option(self, key: OptionKey, value, first_invocation: bool = False) -> bool:
dirty = False
try:
changed = self.optstore.set_value(key, value, first_invocation)
changed = self.optstore.set_option(key, value, first_invocation)
except KeyError:
raise MesonException(f'Tried to set unknown builtin option {str(key)}')
dirty |= changed
@ -484,8 +484,8 @@ class CoreData:
assert value == 'custom'
return False
dirty |= self.optstore.set_value('optimization', opt)
dirty |= self.optstore.set_value('debug', debug)
dirty |= self.optstore.set_option(OptionKey('optimization'), opt)
dirty |= self.optstore.set_option(OptionKey('debug'), debug)
return dirty
@ -517,7 +517,7 @@ class CoreData:
oldval = self.optstore.get_value_object(key)
if type(oldval) is not type(value):
self.optstore.set_value(key, value.value)
self.optstore.set_option(key, value.value)
elif options.choices_are_different(oldval, value):
# If the choices have changed, use the new value, but attempt
# to keep the old options. If they are not valid keep the new
@ -548,7 +548,7 @@ class CoreData:
assert not self.is_cross_build()
for k in options.BUILTIN_OPTIONS_PER_MACHINE:
o = self.optstore.get_value_object_for(k.name)
dirty |= self.optstore.set_value(k, o.value, True)
dirty |= self.optstore.set_option(k, o.value, True)
for bk, bv in self.optstore.items():
if bk.machine is MachineChoice.BUILD:
hk = bk.as_host()
@ -692,16 +692,16 @@ class CoreData:
if skey not in self.optstore:
self.optstore.add_system_option(skey, copy.deepcopy(compilers.BASE_OPTIONS[key]))
if skey in env.options:
self.optstore.set_value(skey, env.options[skey])
self.optstore.set_option(skey, env.options[skey])
elif subproject and key in env.options:
self.optstore.set_value(skey, env.options[key])
self.optstore.set_option(skey, env.options[key])
# FIXME
#if subproject and not self.optstore.has_option(key):
# self.optstore[key] = copy.deepcopy(self.optstore[skey])
elif skey in env.options:
self.optstore.set_value(skey, env.options[skey])
self.optstore.set_option(skey, env.options[skey])
elif subproject and key in env.options:
self.optstore.set_value(skey, env.options[key])
self.optstore.set_option(skey, env.options[key])
self.emit_base_options_warnings()
def emit_base_options_warnings(self) -> None:

@ -941,53 +941,27 @@ class OptionStore:
# .as_posix() keeps the posix-like file separators Meson uses.
return value.as_posix()
def set_value(self, key: T.Union[OptionKey, str], new_value: 'T.Any', first_invocation: bool = False) -> bool:
key = self.ensure_and_validate_key(key)
if key.name == 'prefix':
new_value = self.sanitize_prefix(new_value)
elif self.is_builtin_option(key):
prefix = self.get_value_for('prefix')
assert isinstance(prefix, str)
new_value = self.sanitize_dir_option_value(prefix, key, new_value)
if key not in self.options:
raise MesonException(f'Unknown options: "{key.name}" not found.')
valobj = self.options[key]
old_value = valobj.value
changed = valobj.set_value(new_value)
if valobj.readonly and changed and not first_invocation:
raise MesonException(f'Tried to modify read only option {str(key)!r}')
if key.name == 'prefix' and first_invocation and changed:
assert isinstance(old_value, str)
self.reset_prefixed_options(old_value, new_value)
if changed:
self.set_dependents(key, new_value)
return changed
def set_dependents(self, key: OptionKey, value: str) -> None:
if key.name != 'buildtype':
return
def _set_dependents(self, key: OptionKey, value: str) -> None:
opt, debug = self.DEFAULT_DEPENDENTS[value]
dkey = key.evolve(name='debug')
optkey = key.evolve(name='optimization')
self.options[dkey].set_value(debug)
self.options[optkey].set_value(opt)
def set_option(self, key: OptionKey, new_value: str, first_invocation: bool = False) -> bool:
assert isinstance(key, OptionKey)
# FIXME, dupe of set_value
# Remove one of the two before merging to master.
def set_option(self, key: OptionKey, new_value: ElementaryOptionValues, first_invocation: bool = False) -> bool:
if key.name == 'prefix':
assert isinstance(new_value, str), 'for mypy'
new_value = self.sanitize_prefix(new_value)
elif self.is_builtin_option(key):
prefix = self.get_value_for('prefix')
assert isinstance(prefix, str)
assert isinstance(prefix, str), 'for mypy'
new_value = self.sanitize_dir_option_value(prefix, key, new_value)
opt = self.get_value_object_for(key)
try:
opt = self.get_value_object_for(key)
except KeyError:
raise MesonException(f'Unknown options: "{key!s}" not found.')
if opt.deprecated is True:
mlog.deprecation(f'Option {key.name!r} is deprecated')
elif isinstance(opt.deprecated, list):
@ -1014,15 +988,17 @@ class OptionStore:
old_value = opt.value
changed = opt.set_value(new_value)
if opt.readonly and changed:
raise MesonException(f'Tried modify read only option {str(key)!r}')
if opt.readonly and changed and not first_invocation:
raise MesonException(f'Tried to modify read only option {str(key)!r}')
if key.name == 'prefix' and first_invocation and changed:
assert isinstance(old_value, str), 'for mypy'
assert isinstance(new_value, str), 'for mypy'
self.reset_prefixed_options(old_value, new_value)
if changed:
self.set_dependents(key, new_value)
if changed and key.name == 'buildtype':
assert isinstance(new_value, str), 'for mypy'
self._set_dependents(key, new_value)
return changed
@ -1032,9 +1008,9 @@ class OptionStore:
else:
o = OptionKey.from_string(keystr)
if o in self.options:
return self.set_value(o, new_value)
return self.set_option(o, new_value)
o = o.as_root()
return self.set_value(o, new_value)
return self.set_option(o, new_value)
def set_from_configure_command(self, D_args: T.List[str], U_args: T.List[str]) -> bool:
dirty = False
@ -1279,7 +1255,7 @@ class OptionStore:
augstr = str(key)
self.augments[augstr] = valstr
elif key in self.options:
self.set_value(key, valstr, first_invocation)
self.set_option(key, valstr, first_invocation)
else:
proj_key = key.as_root()
if proj_key in self.options:
@ -1330,7 +1306,7 @@ class OptionStore:
if not self.is_cross and key.is_for_build():
continue
if key in self.options:
self.set_value(key, valstr, True)
self.set_option(key, valstr, True)
elif key.subproject is None:
projectkey = key.as_root()
if projectkey in self.options:
@ -1371,7 +1347,7 @@ class OptionStore:
# If the key points to a project option, set the value from that.
# Otherwise set an augment.
if key in self.project_options:
self.set_value(key, valstr, is_first_invocation)
self.set_option(key, valstr, is_first_invocation)
else:
self.pending_project_options.pop(key, None)
aug_str = f'{subproject}:{keystr}'
@ -1385,6 +1361,6 @@ class OptionStore:
continue
self.pending_project_options.pop(key, None)
if key in self.options:
self.set_value(key, valstr, is_first_invocation)
self.set_option(key, valstr, is_first_invocation)
else:
self.augments[str(key)] = valstr

@ -451,7 +451,7 @@ class PlatformAgnosticTests(BasePlatformTests):
f.write(line)
with self.assertRaises(subprocess.CalledProcessError) as e:
self.setconf('-Dneg_int_opt=0')
self.assertIn('Unknown options: "neg_int_opt"', e.exception.stdout)
self.assertIn('Unknown options: ":neg_int_opt"', e.exception.stdout)
def test_configure_option_changed_constraints(self) -> None:
"""Changing the constraints of an option without reconfiguring should work."""
@ -491,7 +491,7 @@ class PlatformAgnosticTests(BasePlatformTests):
os.unlink(os.path.join(testdir, 'meson_options.txt'))
with self.assertRaises(subprocess.CalledProcessError) as e:
self.setconf('-Dneg_int_opt=0')
self.assertIn('Unknown options: "neg_int_opt"', e.exception.stdout)
self.assertIn('Unknown options: ":neg_int_opt"', e.exception.stdout)
def test_configure_options_file_added(self) -> None:
"""A new project option file should be detected."""

Loading…
Cancel
Save