Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix base and compiler options not reconfigurable. #12922

Merged
merged 4 commits into from
Mar 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion mesonbuild/compilers/detect.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ def detect_compiler_for(env: 'Environment', lang: str, for_machine: MachineChoic
if comp is None:
return comp
assert comp.for_machine == for_machine
env.coredata.process_new_compiler(lang, comp, env)
env.coredata.process_compiler_options(lang, comp, env)
if not skip_sanity_check:
comp.sanity_check(env.get_scratch_dir(), env)
env.coredata.compilers[comp.for_machine][lang] = comp
Expand Down
24 changes: 14 additions & 10 deletions mesonbuild/coredata.py
Original file line number Diff line number Diff line change
Expand Up @@ -974,6 +974,8 @@ def set_options(self, options: T.Dict[OptionKey, T.Any], subproject: str = '', f
return dirty

def set_default_options(self, default_options: T.MutableMapping[OptionKey, str], subproject: str, env: 'Environment') -> None:
from .compilers import base_options
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bruchar1 this commit broke subprojects for me:

subprojects/mysubproj/meson.build:1:0: ERROR: In subproject mysubproj: Unknown options: "mysubproj:b_ndebug"


# Main project can set default options on subprojects, but subprojects
# can only set default options on themselves.
# Preserve order: if env.options has 'buildtype' it must come after
Expand Down Expand Up @@ -1003,11 +1005,12 @@ def set_default_options(self, default_options: T.MutableMapping[OptionKey, str],
# not differ between them even when they are valid for both.
if subproject and k.is_builtin() and self.options[k.evolve(subproject='', machine=MachineChoice.HOST)].yielding:
continue
# Skip compiler and backend options, they are handled when
# Skip base, compiler, and backend options, they are handled when
# adding languages and setting backend.
if k.type in {OptionType.COMPILER, OptionType.BACKEND}:
continue
if k.type == OptionType.BASE and env.first_invocation:
if k.type == OptionType.BASE and k in base_options:
# set_options will report unknown base options
continue
options[k] = v

Expand All @@ -1019,6 +1022,7 @@ def add_compiler_options(self, options: 'MutableKeyedOptionDictType', lang: str,
value = env.options.get(k)
if value is not None:
o.set_value(value)
self.options[k] = o # override compiler option on reconfigure
self.options.setdefault(k, o)

def add_lang_args(self, lang: str, comp: T.Type['Compiler'],
Expand All @@ -1030,20 +1034,20 @@ def add_lang_args(self, lang: str, comp: T.Type['Compiler'],
# `self.options.update()`` is perfectly safe.
self.options.update(compilers.get_global_options(lang, comp, for_machine, env))

def process_new_compiler(self, lang: str, comp: 'Compiler', env: 'Environment') -> None:
def process_compiler_options(self, lang: str, comp: 'Compiler', env: 'Environment') -> None:
from . import compilers

self.add_compiler_options(comp.get_options(), lang, comp.for_machine, env)

enabled_opts: T.List[OptionKey] = []
for key in comp.base_options:
if key in self.options:
continue
oobj = copy.deepcopy(compilers.base_options[key])
if key in env.options:
oobj.set_value(env.options[key])
enabled_opts.append(key)
self.options[key] = oobj
if key not in self.options:
self.options[key] = copy.deepcopy(compilers.base_options[key])
if key in env.options:
self.options[key].set_value(env.options[key])
enabled_opts.append(key)
elif key in env.options:
self.options[key].set_value(env.options[key])
self.emit_base_options_warnings(enabled_opts)

def emit_base_options_warnings(self, enabled_opts: T.List[OptionKey]) -> None:
Expand Down
3 changes: 3 additions & 0 deletions mesonbuild/interpreter/interpreter.py
Original file line number Diff line number Diff line change
Expand Up @@ -1518,6 +1518,9 @@ def add_languages_for(self, args: T.List[str], required: bool, for_machine: Mach
continue
else:
raise
else:
# update new values from commandline, if it applies
self.coredata.process_compiler_options(lang, comp, self.environment)

# Add per-subproject compiler options. They inherit value from main project.
if self.subproject:
Expand Down
2 changes: 1 addition & 1 deletion run_project_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -981,7 +981,7 @@ def have_working_compiler(lang: str, use_tmp: bool) -> bool:
return False
if not compiler:
return False
env.coredata.process_new_compiler(lang, compiler, env)
env.coredata.process_compiler_options(lang, compiler, env)
try:
compiler.sanity_check(env.get_scratch_dir(), env)
except mesonlib.MesonException:
Expand Down
5 changes: 5 additions & 0 deletions test cases/unit/122 reconfigure base options/meson.build
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
project('reconfigure', 'c',
default_options: ['c_std=c89'])

message('b_ndebug: ' + get_option('b_ndebug'))
message('c_std: ' + get_option('c_std'))
4 changes: 2 additions & 2 deletions unittests/allplatformstests.py
Original file line number Diff line number Diff line change
Expand Up @@ -471,7 +471,7 @@ def test_replace_unencodable_xml_chars_unit(self):
# Ensure command output and JSON / text logs are not mangled.
raw_output_sample = '\x00\x01\x02\x03\x04\x05\x06\x07\x08\x0b'
assert raw_output_sample in tests_command_output
text_log = Path(self.logdir, 'testlog.txt').read_text()
text_log = Path(self.logdir, 'testlog.txt').read_text(encoding='utf-8')
assert raw_output_sample in text_log
json_log = json.loads(Path(self.logdir, 'testlog.json').read_bytes())
assert raw_output_sample in json_log['stdout']
Expand Down Expand Up @@ -2694,7 +2694,7 @@ def test_command_line(self):

# It is not an error to set wrong option for unknown subprojects or
# language because we don't have control on which one will be selected.
self.init(testdir, extra_args=['-Dc_wrong=1', '-Dwrong:bad=1', '-Db_wrong=1'])
self.init(testdir, extra_args=['-Dc_wrong=1', '-Dwrong:bad=1'])
self.wipe()

# Test we can set subproject option
Expand Down
1 change: 1 addition & 0 deletions unittests/baseplatformtests.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ def setUp(self):
# XCode backend is untested with unit tests, help welcome!
self.no_rebuild_stdout = [f'UNKNOWN BACKEND {self.backend.name!r}']
os.environ['COLUMNS'] = '80'
os.environ['PYTHONIOENCODING'] = 'utf8'

self.builddirs = []
self.new_builddir()
Expand Down
17 changes: 17 additions & 0 deletions unittests/platformagnostictests.py
Original file line number Diff line number Diff line change
Expand Up @@ -275,3 +275,20 @@ def test_error_configuring_subdir(self):
self.assertIn('first statement must be a call to project()', out)
# provide guidance diagnostics by finding a file whose first AST statement is project()
self.assertIn(f'Did you mean to run meson from the directory: "{testdir}"?', out)

def test_reconfigure_base_options(self):
testdir = os.path.join(self.unit_test_dir, '122 reconfigure base options')
out = self.init(testdir, extra_args=['-Db_ndebug=true'])
self.assertIn('\nMessage: b_ndebug: true\n', out)
self.assertIn('\nMessage: c_std: c89\n', out)

out = self.init(testdir, extra_args=['--reconfigure', '-Db_ndebug=if-release', '-Dc_std=c99'])
self.assertIn('\nMessage: b_ndebug: if-release\n', out)
self.assertIn('\nMessage: c_std: c99\n', out)

def test_setup_with_unknown_option(self):
testdir = os.path.join(self.common_test_dir, '1 trivial')

for option in ('not_an_option', 'b_not_an_option'):
out = self.init(testdir, extra_args=['--wipe', f'-D{option}=1'], allow_fail=True)
self.assertIn(f'ERROR: Unknown options: "{option}"', out)
Loading