File ensure-pending-subproject-options-are-validated.patch of Package meson
From c0a5e9293209f465ab114ae0fcd92de640ef48a6 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Tue, 30 Sep 2025 17:33:02 +0200
Subject: [PATCH] options: ensure pending subproject options are validated
Boolean options need to be translated from string "true" to True and
so on, otherwise we will get an assertion later when trying to set the
value:
```
Traceback (most recent call last):
File "meson.git/mesonbuild/mesonmain.py", line 193, in run
return options.run_func(options)
~~~~~~~~~~~~~~~~^^^^^^^^^
File "meson.git/mesonbuild/msetup.py", line 395, in run
app.generate()
~~~~~~~~~~~~^^
File "meson.git/mesonbuild/msetup.py", line 194, in generate
return self._generate(env, capture, vslite_ctx)
~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^
File "meson.git/mesonbuild/msetup.py", line 282, in _generate
captured_compile_args = intr.backend.generate(capture, vslite_ctx)
File "meson.git/mesonbuild/backend/ninjabackend.py", line 647, in generate
self.generate_target(t)
~~~~~~~~~~~~~~~~~~~~^^^
File "meson.git/mesonbuild/backend/ninjabackend.py", line 1099, in generate_target
elem = self.generate_link(target, outname, final_obj_list, linker, pch_objects, stdlib_args=stdlib_args)
File "meson.git/mesonbuild/backend/ninjabackend.py", line 3632, in generate_link
base_link_args = compilers.get_base_link_args(target,
linker,
self.environment)
File "meson.git/mesonbuild/compilers/compilers.py", line 405, in get_base_link_args
option_enabled(linker.base_options, target, env, 'b_lundef')):
~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "meson.git/mesonbuild/compilers/compilers.py", line 234, in option_enabled
assert isinstance(ret, bool), 'must return bool' # could also be str
~~~~~~~~~~^^^^^^^^^^^
AssertionError: must return bool
```
This assertion is being hit because the vo-aacenc wrap sets
`b_lundef=true` in `default_options:` in `project()`, which ends up in
`self.augments` when the project is being invoked as a subproject.
The fix is to use set_option even for pending subproject options. This
will follow this path:
new_value = opt.validate_value(new_value)
old_value = self.augments.get(key, opt.value)
self.augments[key] = new_value
This regressed in 2bafe7dc403b92c7b1f7bbad62dd8533e90f8523.
First noticed at: https://github.com/mesonbuild/wrapdb/actions/runs/18123699172/job/51573947286?pr=2425
[Commit message by Nirbheek Chauhan <nirbheek@centricular.com>]
---
mesonbuild/options.py | 6 ++----
unittests/optiontests.py | 18 ++++++++++++++++++
2 files changed, 20 insertions(+), 4 deletions(-)
diff --git a/mesonbuild/options.py b/mesonbuild/options.py
index 57b765bef446..35ed43e62618 100644
--- a/mesonbuild/options.py
+++ b/mesonbuild/options.py
@@ -909,12 +909,10 @@ def add_system_option_internal(self, key: OptionKey, valobj: AnyOptionType) -> N
if key.subproject:
proj_key = key.evolve(subproject=None)
self.add_system_option_internal(proj_key, valobj)
- if pval is not None:
- self.augments[key] = pval
else:
self.options[key] = valobj
- if pval is not None:
- self.set_option(key, pval)
+ if pval is not None:
+ self.set_option(key, pval)
def add_compiler_option(self, language: str, key: T.Union[OptionKey, str], valobj: AnyOptionType) -> None:
key = self.ensure_and_validate_key(key)
diff --git a/unittests/optiontests.py b/unittests/optiontests.py
index 8f49a804e59d..7273ecf47f04 100644
--- a/unittests/optiontests.py
+++ b/unittests/optiontests.py
@@ -474,3 +474,21 @@ def test_deprecated_nonstring_value(self):
optstore.set_option(OptionKey(name), True)
value = optstore.get_value(name)
self.assertEqual(value, '1')
+
+ def test_pending_augment_validation(self):
+ name = 'b_lto'
+ subproject = 'mysubproject'
+
+ optstore = OptionStore(False)
+ prefix = UserStringOption('prefix', 'This is needed by OptionStore', '/usr')
+ optstore.add_system_option('prefix', prefix)
+
+ optstore.initialize_from_top_level_project_call({}, {}, {})
+ optstore.initialize_from_subproject_call(subproject, {}, {OptionKey(name): 'true'}, {}, {})
+
+ bo = UserBooleanOption(name, 'LTO', False)
+ key = OptionKey(name, subproject=subproject)
+ optstore.add_system_option(key, bo)
+ stored_value = optstore.get_value_for(key)
+ self.assertIsInstance(stored_value, bool)
+ self.assertTrue(stored_value)