fix reconfigure subproject base options

pull/12957/head
Charles Brunet 9 months ago committed by Dylan Baker
parent 9e270f030f
commit f9479787a0
  1. 4
      mesonbuild/ast/introspection.py
  2. 4
      mesonbuild/compilers/detect.py
  3. 42
      mesonbuild/coredata.py
  4. 6
      mesonbuild/interpreter/interpreter.py
  5. 2
      mesonbuild/modules/java.py
  6. 2
      run_project_tests.py
  7. 14
      unittests/allplatformstests.py
  8. 4
      unittests/platformagnostictests.py

@ -170,7 +170,7 @@ class IntrospectionInterpreter(AstInterpreter):
lang = lang.lower()
if lang not in self.coredata.compilers[for_machine]:
try:
comp = detect_compiler_for(self.environment, lang, for_machine, True)
comp = detect_compiler_for(self.environment, lang, for_machine, True, self.subproject)
except mesonlib.MesonException:
# do we even care about introspecting this language?
if required:
@ -183,7 +183,7 @@ class IntrospectionInterpreter(AstInterpreter):
v = copy.copy(self.coredata.options[k])
k = k.evolve(subproject=self.subproject)
options[k] = v
self.coredata.add_compiler_options(options, lang, for_machine, self.environment)
self.coredata.add_compiler_options(options, lang, for_machine, self.environment, self.subproject)
def func_dependency(self, node: BaseNode, args: T.List[TYPE_var], kwargs: T.Dict[str, TYPE_var]) -> None:
args = self.flatten_args(args)

@ -101,12 +101,12 @@ def compiler_from_language(env: 'Environment', lang: str, for_machine: MachineCh
}
return lang_map[lang](env, for_machine) if lang in lang_map else None
def detect_compiler_for(env: 'Environment', lang: str, for_machine: MachineChoice, skip_sanity_check: bool) -> T.Optional[Compiler]:
def detect_compiler_for(env: 'Environment', lang: str, for_machine: MachineChoice, skip_sanity_check: bool, subproject: str) -> T.Optional[Compiler]:
comp = compiler_from_language(env, lang, for_machine)
if comp is None:
return comp
assert comp.for_machine == for_machine
env.coredata.process_compiler_options(lang, comp, env)
env.coredata.process_compiler_options(lang, comp, env, subproject)
if not skip_sanity_check:
comp.sanity_check(env.get_scratch_dir(), env)
env.coredata.compilers[comp.for_machine][lang] = comp

@ -1016,15 +1016,24 @@ class CoreData:
self.set_options(options, subproject=subproject, first_invocation=env.first_invocation)
def add_compiler_options(self, options: 'MutableKeyedOptionDictType', lang: str, for_machine: MachineChoice,
env: 'Environment') -> None:
def add_compiler_options(self, options: MutableKeyedOptionDictType, lang: str, for_machine: MachineChoice,
env: Environment, subproject: str) -> None:
for k, o in options.items():
value = env.options.get(k)
if value is not None:
o.set_value(value)
if not subproject:
self.options[k] = o # override compiler option on reconfigure
self.options.setdefault(k, o)
if subproject:
sk = k.evolve(subproject=subproject)
value = env.options.get(sk) or value
if value is not None:
o.set_value(value)
self.options[sk] = o # override compiler option on reconfigure
self.options.setdefault(sk, o)
def add_lang_args(self, lang: str, comp: T.Type['Compiler'],
for_machine: MachineChoice, env: 'Environment') -> None:
"""Add global language arguments that are needed before compiler/linker detection."""
@ -1034,20 +1043,31 @@ class CoreData:
# `self.options.update()`` is perfectly safe.
self.options.update(compilers.get_global_options(lang, comp, for_machine, env))
def process_compiler_options(self, lang: str, comp: 'Compiler', env: 'Environment') -> None:
def process_compiler_options(self, lang: str, comp: Compiler, env: Environment, subproject: str) -> None:
from . import compilers
self.add_compiler_options(comp.get_options(), lang, comp.for_machine, env)
self.add_compiler_options(comp.get_options(), lang, comp.for_machine, env, subproject)
enabled_opts: T.List[OptionKey] = []
for key in comp.base_options:
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])
if subproject:
skey = key.evolve(subproject=subproject)
else:
skey = key
if skey not in self.options:
self.options[skey] = copy.deepcopy(compilers.base_options[key])
if skey in env.options:
self.options[skey].set_value(env.options[skey])
enabled_opts.append(skey)
elif subproject and key in env.options:
self.options[skey].set_value(env.options[key])
enabled_opts.append(skey)
if subproject and key not in self.options:
self.options[key] = copy.deepcopy(self.options[skey])
elif skey in env.options:
self.options[skey].set_value(env.options[skey])
elif subproject and key in env.options:
self.options[skey].set_value(env.options[key])
self.emit_base_options_warnings(enabled_opts)
def emit_base_options_warnings(self, enabled_opts: T.List[OptionKey]) -> None:

@ -1506,7 +1506,7 @@ class Interpreter(InterpreterBase, HoldableObject):
skip_sanity_check = self.should_skip_sanity_check(for_machine)
if skip_sanity_check:
mlog.log('Cross compiler sanity tests disabled via the cross file.', once=True)
comp = compilers.detect_compiler_for(self.environment, lang, for_machine, skip_sanity_check)
comp = compilers.detect_compiler_for(self.environment, lang, for_machine, skip_sanity_check, self.subproject)
if comp is None:
raise InvalidArguments(f'Tried to use unknown language "{lang}".')
except mesonlib.MesonException:
@ -1520,7 +1520,7 @@ class Interpreter(InterpreterBase, HoldableObject):
raise
else:
# update new values from commandline, if it applies
self.coredata.process_compiler_options(lang, comp, self.environment)
self.coredata.process_compiler_options(lang, comp, self.environment, self.subproject)
# Add per-subproject compiler options. They inherit value from main project.
if self.subproject:
@ -1529,7 +1529,7 @@ class Interpreter(InterpreterBase, HoldableObject):
v = copy.copy(self.coredata.options[k])
k = k.evolve(subproject=self.subproject)
options[k] = v
self.coredata.add_compiler_options(options, lang, for_machine, self.environment)
self.coredata.add_compiler_options(options, lang, for_machine, self.environment, self.subproject)
if for_machine == MachineChoice.HOST or self.environment.is_cross_build():
logger_fun = mlog.log

@ -32,7 +32,7 @@ class JavaModule(NewExtensionModule):
def __get_java_compiler(self, state: ModuleState) -> Compiler:
if 'java' not in state.environment.coredata.compilers[MachineChoice.BUILD]:
detect_compiler_for(state.environment, 'java', MachineChoice.BUILD, False)
detect_compiler_for(state.environment, 'java', MachineChoice.BUILD, False, state.subproject)
return state.environment.coredata.compilers[MachineChoice.BUILD]['java']
@FeatureNew('java.generate_native_headers', '0.62.0')

@ -981,7 +981,7 @@ def have_working_compiler(lang: str, use_tmp: bool) -> bool:
return False
if not compiler:
return False
env.coredata.process_compiler_options(lang, compiler, env)
env.coredata.process_compiler_options(lang, compiler, env, '')
try:
compiler.sanity_check(env.get_scratch_dir(), env)
except mesonlib.MesonException:

@ -944,7 +944,7 @@ class AllPlatformTests(BasePlatformTests):
testdir = os.path.join("test cases/cython", '2 generated sources')
env = get_fake_env(testdir, self.builddir, self.prefix)
try:
detect_compiler_for(env, "cython", MachineChoice.HOST, True)
detect_compiler_for(env, "cython", MachineChoice.HOST, True, '')
except EnvironmentException:
raise SkipTest("Cython is not installed")
self.init(testdir)
@ -969,7 +969,7 @@ class AllPlatformTests(BasePlatformTests):
testdir = os.path.join("test cases/cython", '2 generated sources')
env = get_fake_env(testdir, self.builddir, self.prefix)
try:
cython = detect_compiler_for(env, "cython", MachineChoice.HOST, True)
cython = detect_compiler_for(env, "cython", MachineChoice.HOST, True, '')
if not version_compare(cython.version, '>=0.29.33'):
raise SkipTest('Cython is too old')
except EnvironmentException:
@ -2355,7 +2355,7 @@ class AllPlatformTests(BasePlatformTests):
env = get_fake_env()
for l in ['cpp', 'cs', 'd', 'java', 'cuda', 'fortran', 'objc', 'objcpp', 'rust', 'vala']:
try:
comp = detect_compiler_for(env, l, MachineChoice.HOST, True)
comp = detect_compiler_for(env, l, MachineChoice.HOST, True, '')
with tempfile.TemporaryDirectory() as d:
comp.sanity_check(d, env)
langs.append(l)
@ -2373,7 +2373,7 @@ class AllPlatformTests(BasePlatformTests):
if is_windows() and lang == 'fortran' and target_type == 'library':
# non-Gfortran Windows Fortran compilers do not do shared libraries in a Fortran standard way
# see "test cases/fortran/6 dynamic"
fc = detect_compiler_for(env, 'fortran', MachineChoice.HOST, True)
fc = detect_compiler_for(env, 'fortran', MachineChoice.HOST, True, '')
if fc.get_id() in {'intel-cl', 'pgi'}:
continue
# test empty directory
@ -4433,18 +4433,18 @@ class AllPlatformTests(BasePlatformTests):
env = get_fake_env()
# Get the compiler so we know which compiler class to mock.
cc = detect_compiler_for(env, 'c', MachineChoice.HOST, True)
cc = detect_compiler_for(env, 'c', MachineChoice.HOST, True, '')
cc_type = type(cc)
# Test a compiler that acts as a linker
with mock.patch.object(cc_type, 'INVOKES_LINKER', True):
cc = detect_compiler_for(env, 'c', MachineChoice.HOST, True)
cc = detect_compiler_for(env, 'c', MachineChoice.HOST, True, '')
link_args = env.coredata.get_external_link_args(cc.for_machine, cc.language)
self.assertEqual(sorted(link_args), sorted(['-DCFLAG', '-flto']))
# And one that doesn't
with mock.patch.object(cc_type, 'INVOKES_LINKER', False):
cc = detect_compiler_for(env, 'c', MachineChoice.HOST, True)
cc = detect_compiler_for(env, 'c', MachineChoice.HOST, True, '')
link_args = env.coredata.get_external_link_args(cc.for_machine, cc.language)
self.assertEqual(sorted(link_args), sorted(['-flto']))

@ -282,9 +282,11 @@ class PlatformAgnosticTests(BasePlatformTests):
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', '-Dsub:b_ndebug=false', '-Dc_std=c99'])
out = self.init(testdir, extra_args=['--reconfigure', '-Db_ndebug=if-release', '-Dsub:b_ndebug=false', '-Dc_std=c99', '-Dsub:c_std=c11'])
self.assertIn('\nMessage: b_ndebug: if-release\n', out)
self.assertIn('\nMessage: c_std: c99\n', out)
self.assertIn('\nsub| Message: b_ndebug: false\n', out)
self.assertIn('\nsub| Message: c_std: c11\n', out)
def test_setup_with_unknown_option(self):
testdir = os.path.join(self.common_test_dir, '1 trivial')

Loading…
Cancel
Save