diff options
author | Dylan Baker <dylan@pnwbakers.com> | 2020-09-14 11:36:38 -0700 |
---|---|---|
committer | Jussi Pakkanen <jpakkane@gmail.com> | 2020-10-05 23:10:35 +0300 |
commit | 94ac51fdda0408c6d1f61e7e5e89cebaa9182842 (patch) | |
tree | 58fd6d3b44c2cb2b57fb9c8f6dbfb17fe4c36cae | |
parent | c4fa87692547a25f772b3da336147b4eb9114f64 (diff) | |
download | meson-94ac51fdda0408c6d1f61e7e5e89cebaa9182842.zip meson-94ac51fdda0408c6d1f61e7e5e89cebaa9182842.tar.gz meson-94ac51fdda0408c6d1f61e7e5e89cebaa9182842.tar.bz2 |
options: Handle updates to choices in options
Currently if you change the `choices` field in the meson_options.txt
file, no update will be done until `meson setup --wipe` is called. Now
if the choices change then the options will be properly merged.
If the currently select value is still valid it is guaranteed to be
kept, if it is now invalid the new default value will be used and a
warning will be printed.
Fixes #7386
-rw-r--r-- | mesonbuild/coredata.py | 20 | ||||
-rwxr-xr-x | run_unittests.py | 40 | ||||
-rw-r--r-- | test cases/unit/84 change option choices/meson.build | 1 | ||||
-rw-r--r-- | test cases/unit/84 change option choices/meson_options.1.txt | 13 | ||||
-rw-r--r-- | test cases/unit/84 change option choices/meson_options.2.txt | 13 |
5 files changed, 82 insertions, 5 deletions
diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index 4be828b..e3b3b01 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 0385404..881b781 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 0000000..d056d65 --- /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 0000000..d0326a5 --- /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 0000000..4684673 --- /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'], +) |