Skip to content

Commit

Permalink
subproject: Fix inheritance of language options
Browse files Browse the repository at this point in the history
Add handling of language args for subprojects, which was
previously only done for the main project as part of the detection
of the language compiler.

Language options were deferred for later handling during
language load. This caused default language options to break for
subprojects which were missing this loading step.

Resolves #13260.

Signed-off-by: Eyal Itkin <eyal.itkin@gmail.com>
  • Loading branch information
Eyal Itkin committed Nov 23, 2024
1 parent 9f3f88f commit 4c77093
Show file tree
Hide file tree
Showing 8 changed files with 32 additions and 17 deletions.
7 changes: 6 additions & 1 deletion mesonbuild/ast/introspection.py
Original file line number Diff line number Diff line change
Expand Up @@ -197,11 +197,16 @@ def _add_languages(self, raw_langs: T.List[TYPE_var], required: bool, for_machin
continue
if self.subproject:
options = {}
lang_options = compilers.compilers.get_global_options(lang, type(comp), for_machine, self.environment)
for k in lang_options:
v = copy.copy(self.coredata.optstore.get_value_object(k))
k = k.evolve(subproject=self.subproject)
options[k] = v
for k in comp.get_options():
v = copy.copy(self.coredata.optstore.get_value_object(k))
k = k.evolve(subproject=self.subproject)
options[k] = v
self.coredata.add_compiler_options(options, lang, for_machine, self.environment, self.subproject)
self.coredata.add_compiler_options(options, 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)
Expand Down
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_compiler_options(lang, comp, env, subproject)
env.coredata.process_compiler_options(comp, env, subproject)
if not skip_sanity_check:
comp.sanity_check(env.get_scratch_dir(), env)
env.coredata.compilers[comp.for_machine][lang] = comp
Expand Down
6 changes: 3 additions & 3 deletions mesonbuild/coredata.py
Original file line number Diff line number Diff line change
Expand Up @@ -710,7 +710,7 @@ def set_default_options(self, default_options: T.MutableMapping[OptionKey, str],

self.set_options(options, subproject=subproject, first_invocation=env.first_invocation)

def add_compiler_options(self, c_options: MutableKeyedOptionDictType, lang: str, for_machine: MachineChoice,
def add_compiler_options(self, c_options: MutableKeyedOptionDictType, for_machine: MachineChoice,
env: Environment, subproject: str) -> None:
for k, o in c_options.items():
value = env.options.get(k)
Expand Down Expand Up @@ -738,10 +738,10 @@ def add_lang_args(self, lang: str, comp: T.Type['Compiler'],
for gopt_key, gopt_valobj in compilers.get_global_options(lang, comp, for_machine, env).items():
self.optstore.add_compiler_option(lang, gopt_key, gopt_valobj)

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

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

enabled_opts: T.List[OptionKey] = []
for key in comp.base_options:
Expand Down
12 changes: 9 additions & 3 deletions mesonbuild/interpreter/interpreter.py
Original file line number Diff line number Diff line change
Expand Up @@ -1538,16 +1538,22 @@ def add_languages_for(self, args: T.List[str], required: bool, for_machine: Mach
self.backend.allow_thin_archives[for_machine] = False
else:
# update new values from commandline, if it applies
self.coredata.process_compiler_options(lang, comp, self.environment, self.subproject)
self.coredata.process_compiler_options(comp, self.environment, self.subproject)

# Add per-subproject compiler options. They inherit value from main project.
# Add per-subproject language and compiler options. They inherit value from main project.
if self.subproject:
options = {}
lang_options = compilers.compilers.get_global_options(lang, type(comp), for_machine, self.environment)
for k in lang_options:
v = copy.copy(self.coredata.optstore.get_value_object(k))
k = k.evolve(subproject=self.subproject)
options[k] = v

for k in comp.get_options():
v = copy.copy(self.coredata.optstore.get_value_object(k))
k = k.evolve(subproject=self.subproject)
options[k] = v
self.coredata.add_compiler_options(options, lang, for_machine, self.environment, self.subproject)
self.coredata.add_compiler_options(options, for_machine, self.environment, self.subproject)

if for_machine == MachineChoice.HOST or self.environment.is_cross_build():
logger_fun = mlog.log
Expand Down
2 changes: 1 addition & 1 deletion run_project_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -990,7 +990,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(compiler, env, '')
try:
compiler.sanity_check(env.get_scratch_dir(), env)
except mesonlib.MesonException:
Expand Down
4 changes: 3 additions & 1 deletion test cases/common/87 default options/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,6 @@ assert(w_level == '3', 'warning level "' + w_level + '" instead of "3"')
# assert(cc.compiles('int foobar;', no_builtin_args : true), 'No_builtin did not disable builtins.')
# endif

subproject('sub1')
subproject('sub1', default_options : [
'c_args=-Dtest',
])
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
project('sub1')
project('sub1', 'c')

assert(get_option('test_option') == false)
assert(get_option('c_args') == ['-Dtest'])
13 changes: 7 additions & 6 deletions unittests/machinefiletests.py
Original file line number Diff line number Diff line change
Expand Up @@ -523,20 +523,21 @@ def test_builtin_options_subprojects(self):

self.init(testcase, extra_args=['--native-file', config])
configuration = self.introspect('--buildoptions')
found = 0
score = 0
for each in configuration:
# Test that no-per subproject options are inherited from the parent
# while the rest of the options are inherited as-is
if 'c_args' in each['name']:
# This path will be hit twice, once for build and once for host,
# This path will be hit twice per project: for build and for host
self.assertEqual(each['value'], ['-Dfoo'])
found += 1
score += 1
elif each['name'] == 'default_library':
self.assertEqual(each['value'], 'both')
found += 1
score += 10
elif each['name'] == 'sub:default_library':
self.assertEqual(each['value'], 'static')
found += 1
self.assertEqual(found, 4, 'Did not find all three sections')
score += 100
self.assertEqual(score, 118, 'Did not find all three sections')

def test_builtin_options_subprojects_overrides_buildfiles(self):
# If the buildfile says subproject(... default_library: shared), ensure that's overwritten
Expand Down

0 comments on commit 4c77093

Please sign in to comment.