diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index 4be828b9d..e3b3b01ec 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -689,14 +689,24 @@ class CoreData: def get_external_link_args(self, for_machine: MachineChoice, lang): return self.compiler_options[for_machine][lang]['link_args'].value - def merge_user_options(self, options: T.Dict[str, T.Union[str, bool, int]]) -> None: + def merge_user_options(self, options: T.Dict[str, UserOption[T.Any]]) -> None: for (name, value) in options.items(): if name not in self.user_options: self.user_options[name] = value - else: - oldval = self.user_options[name] - if type(oldval) != type(value): - self.user_options[name] = value + continue + + oldval = self.user_options[name] + if type(oldval) != type(value): + self.user_options[name] = value + elif oldval.choices != value.choices: + # If the choices have changed, use the new value, but attempt + # to keep the old options. If they are not valid keep the new + # defaults but warn. + self.user_options[name] = value + try: + value.set_value(oldval.value) + except MesonException as e: + mlog.warning('Old value(s) of {} are no longer valid, resetting to default ({}).'.format(name, value.value)) def is_cross_build(self, when_building_for: MachineChoice = MachineChoice.HOST) -> bool: if when_building_for == MachineChoice.BUILD: diff --git a/run_unittests.py b/run_unittests.py index 038540404..881b7811b 100755 --- a/run_unittests.py +++ b/run_unittests.py @@ -3325,6 +3325,46 @@ int main(int argc, char **argv) { self.setconf("-Dfree_array_opt=['a,b', 'c,d']", will_build=False) self.opt_has('free_array_opt', ['a,b', 'c,d']) + def test_options_with_choices_changing(self) -> None: + """Detect when options like arrays or combos have their choices change.""" + testdir = Path(os.path.join(self.unit_test_dir, '84 change option choices')) + options1 = str(testdir / 'meson_options.1.txt') + options2 = str(testdir / 'meson_options.2.txt') + + # Test that old options are changed to the new defaults if they are not valid + real_options = str(testdir / 'meson_options.txt') + self.addCleanup(os.unlink, real_options) + + shutil.copy(options1, real_options) + self.init(str(testdir)) + shutil.copy(options2, real_options) + + self.build() + opts = self.introspect('--buildoptions') + for item in opts: + if item['name'] == 'combo': + self.assertEqual(item['value'], 'b') + self.assertEqual(item['choices'], ['b', 'c', 'd']) + elif item['name'] == 'arr': + self.assertEqual(item['value'], ['b']) + self.assertEqual(item['choices'], ['b', 'c', 'd']) + + self.wipe() + + # When the old options are valid they should remain + shutil.copy(options1, real_options) + self.init(str(testdir), extra_args=['-Dcombo=c', '-Darray=b,c']) + shutil.copy(options2, real_options) + self.build() + opts = self.introspect('--buildoptions') + for item in opts: + if item['name'] == 'combo': + self.assertEqual(item['value'], 'c') + self.assertEqual(item['choices'], ['b', 'c', 'd']) + elif item['name'] == 'arr': + self.assertEqual(item['value'], ['b', 'c']) + self.assertEqual(item['choices'], ['b', 'c', 'd']) + def test_subproject_promotion(self): testdir = os.path.join(self.unit_test_dir, '12 promote') workdir = os.path.join(self.builddir, 'work') diff --git a/test cases/unit/84 change option choices/meson.build b/test cases/unit/84 change option choices/meson.build new file mode 100644 index 000000000..d056d6594 --- /dev/null +++ b/test cases/unit/84 change option choices/meson.build @@ -0,0 +1 @@ +project('change option choices') diff --git a/test cases/unit/84 change option choices/meson_options.1.txt b/test cases/unit/84 change option choices/meson_options.1.txt new file mode 100644 index 000000000..d0326a55b --- /dev/null +++ b/test cases/unit/84 change option choices/meson_options.1.txt @@ -0,0 +1,13 @@ +option( + 'combo', + type : 'combo', + choices : ['a', 'b', 'c'], + value : 'a', +) + +option( + 'array', + type : 'array', + choices : ['a', 'b', 'c'], + value : ['a'], +) diff --git a/test cases/unit/84 change option choices/meson_options.2.txt b/test cases/unit/84 change option choices/meson_options.2.txt new file mode 100644 index 000000000..4684673e1 --- /dev/null +++ b/test cases/unit/84 change option choices/meson_options.2.txt @@ -0,0 +1,13 @@ +option( + 'combo', + type : 'combo', + choices : ['b', 'c', 'd'], + value : 'b', +) + +option( + 'array', + type : 'array', + choices : ['b', 'c', 'd'], + value : ['b'], +)