Skip to content

Commit 50c617b

Browse files
bonzinijpakkane
authored andcommitted
options: ensure all build keys are changed to host
OptionStore.get_value did not change build keys to host when not cross-compiling. get_value_object_and_value_for also didn't when accessing self.augments. Make all accessors go through ensure_and_validate_key so that the conversion is done early. Otherwise, when "native: true" targets look up compiler options they do so with the "build.*" name, which does not exist when not cross compiling. This removes the distinction between get_value(), meant to be for global options, and get_value_for() which would be for project-specific options. While the distinction was added in commit d37d649 ("Make all Meson level options overridable per subproject.", 2025-02-13), it is not particularly useful and can be a source of bugs like the one in test_build_to_host_subproject testcase (corresponding to issue #14869). Fixes: #14869 Signed-off-by: Paolo Bonzini <[email protected]>
1 parent 7082dfe commit 50c617b

File tree

2 files changed

+67
-1
lines changed

2 files changed

+67
-1
lines changed

mesonbuild/options.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -844,7 +844,7 @@ def get_pending_value(self, key: T.Union[OptionKey, str], default: T.Optional[El
844844
return self.pending_options.get(key, default)
845845

846846
def get_value(self, key: T.Union[OptionKey, str]) -> ElementaryOptionValues:
847-
return self.get_value_object(key).value
847+
return self.get_value_for(key)
848848

849849
def __len__(self) -> int:
850850
return len(self.options)
@@ -868,6 +868,7 @@ def get_value_object_for(self, key: 'T.Union[OptionKey, str]') -> AnyOptionType:
868868

869869
def get_value_object_and_value_for(self, key: OptionKey) -> T.Tuple[AnyOptionType, ElementaryOptionValues]:
870870
assert isinstance(key, OptionKey)
871+
key = self.ensure_and_validate_key(key)
871872
vobject = self.get_value_object_for(key)
872873
computed_value = vobject.value
873874
if key in self.augments:

unittests/optiontests.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,71 @@ def test_augment_set_sub(self):
246246
self.assertEqual(optstore.get_value_for(name), top_value)
247247
self.assertEqual(optstore.get_value_for(name, sub_name), set_value)
248248

249+
def test_build_to_host(self):
250+
key = OptionKey('cpp_std')
251+
def_value = 'c++98'
252+
opt_value = 'c++17'
253+
optstore = OptionStore(False)
254+
co = UserComboOption(key.name,
255+
'C++ language standard to use',
256+
def_value,
257+
choices=['c++98', 'c++11', 'c++14', 'c++17', 'c++20', 'c++23'],
258+
)
259+
optstore.add_compiler_option('cpp', key, co)
260+
261+
cmd_line = {key: opt_value}
262+
optstore.initialize_from_top_level_project_call({}, cmd_line, {})
263+
self.assertEqual(optstore.get_value_object_and_value_for(key.as_build())[1], opt_value)
264+
self.assertEqual(optstore.get_value(key.as_build()), opt_value)
265+
self.assertEqual(optstore.get_value_for(key.as_build()), opt_value)
266+
267+
def test_build_to_host_subproject(self):
268+
key = OptionKey('cpp_std')
269+
def_value = 'c++98'
270+
opt_value = 'c++17'
271+
subp = 'subp'
272+
optstore = OptionStore(False)
273+
co = UserComboOption(key.name,
274+
'C++ language standard to use',
275+
def_value,
276+
choices=['c++98', 'c++11', 'c++14', 'c++17', 'c++20', 'c++23'],
277+
)
278+
optstore.add_compiler_option('cpp', key, co)
279+
280+
spcall = {key: opt_value}
281+
optstore.initialize_from_top_level_project_call({}, {}, {})
282+
optstore.initialize_from_subproject_call(subp, spcall, {}, {}, {})
283+
self.assertEqual(optstore.get_value_object_and_value_for(key.evolve(subproject=subp,
284+
machine=MachineChoice.BUILD))[1], opt_value)
285+
self.assertEqual(optstore.get_value(key.evolve(subproject=subp,
286+
machine=MachineChoice.BUILD)), opt_value)
287+
self.assertEqual(optstore.get_value_for(key.evolve(subproject=subp,
288+
machine=MachineChoice.BUILD)), opt_value)
289+
290+
def test_build_to_host_cross(self):
291+
key = OptionKey('cpp_std')
292+
def_value = 'c++98'
293+
opt_value = 'c++17'
294+
optstore = OptionStore(True)
295+
for k in [key, key.as_build()]:
296+
co = UserComboOption(key.name,
297+
'C++ language standard to use',
298+
def_value,
299+
choices=['c++98', 'c++11', 'c++14', 'c++17', 'c++20', 'c++23'],
300+
)
301+
optstore.add_compiler_option('cpp', k, co)
302+
303+
cmd_line = {key: opt_value}
304+
optstore.initialize_from_top_level_project_call({}, cmd_line, {})
305+
print(optstore.options)
306+
307+
self.assertEqual(optstore.get_value_object_and_value_for(key)[1], opt_value)
308+
self.assertEqual(optstore.get_value_object_and_value_for(key.as_build())[1], def_value)
309+
self.assertEqual(optstore.get_value(key), opt_value)
310+
self.assertEqual(optstore.get_value(key.as_build()), def_value)
311+
self.assertEqual(optstore.get_value_for(key), opt_value)
312+
self.assertEqual(optstore.get_value_for(key.as_build()), def_value)
313+
249314
def test_b_default(self):
250315
optstore = OptionStore(False)
251316
value = optstore.get_default_for_b_option(OptionKey('b_vscrt'))

0 commit comments

Comments
 (0)