aboutsummaryrefslogtreecommitdiff
path: root/mesonbuild/compilers/compilers.py
diff options
context:
space:
mode:
Diffstat (limited to 'mesonbuild/compilers/compilers.py')
-rw-r--r--mesonbuild/compilers/compilers.py179
1 files changed, 124 insertions, 55 deletions
diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py
index 0f7ef17..e4c7f77 100644
--- a/mesonbuild/compilers/compilers.py
+++ b/mesonbuild/compilers/compilers.py
@@ -256,12 +256,16 @@ BASE_OPTIONS: T.Mapping[OptionKey, BaseOption] = {
base_options = {key: base_opt.init_option(key) for key, base_opt in BASE_OPTIONS.items()}
-def option_enabled(boptions: T.Set[OptionKey], options: 'KeyedOptionDictType',
- option: OptionKey) -> bool:
+def option_enabled(boptions: T.Set[OptionKey],
+ target: 'BuildTarget',
+ env: 'Environment',
+ option: T.Union[str, OptionKey]) -> bool:
+ if isinstance(option, str):
+ option = OptionKey(option)
try:
if option not in boptions:
return False
- ret = options.get_value(option)
+ ret = env.coredata.get_option_for_target(target, option)
assert isinstance(ret, bool), 'must return bool' # could also be str
return ret
except KeyError:
@@ -271,7 +275,7 @@ def option_enabled(boptions: T.Set[OptionKey], options: 'KeyedOptionDictType',
def get_option_value(options: 'KeyedOptionDictType', opt: OptionKey, fallback: '_T') -> '_T':
"""Get the value of an option, or the fallback value."""
try:
- v: '_T' = options.get_value(opt)
+ v: '_T' = options.get_value(opt) # type: ignore [assignment]
except (KeyError, AttributeError):
return fallback
@@ -279,37 +283,75 @@ def get_option_value(options: 'KeyedOptionDictType', opt: OptionKey, fallback: '
# Mypy doesn't understand that the above assert ensures that v is type _T
return v
+def get_option_value_for_target(env: 'Environment', target: 'BuildTarget', opt: OptionKey, fallback: '_T') -> '_T':
+ """Get the value of an option, or the fallback value."""
+ try:
+ v = env.coredata.get_option_for_target(target, opt)
+ except (KeyError, AttributeError):
+ return fallback
+
+ assert isinstance(v, type(fallback)), f'Should have {type(fallback)!r} but was {type(v)!r}'
+ # Mypy doesn't understand that the above assert ensures that v is type _T
+ return v
+
+
+def get_target_option_value(target: 'BuildTarget',
+ env: 'Environment',
+ opt: T.Union[OptionKey, str],
+ fallback: '_T') -> '_T':
+ """Get the value of an option, or the fallback value."""
+ try:
+ v = env.coredata.get_option_for_target(target, opt)
+ except KeyError:
+ return fallback
+
+ assert isinstance(v, type(fallback)), f'Should have {type(fallback)!r} but was {type(v)!r}'
+ # Mypy doesn't understand that the above assert ensures that v is type _T
+ return v
+
-def are_asserts_disabled(options: KeyedOptionDictType) -> bool:
+def are_asserts_disabled(target: 'BuildTarget', env: 'Environment') -> bool:
"""Should debug assertions be disabled
- :param options: OptionDictionary
+ :param target: a target to check for
+ :param env: the environment
:return: whether to disable assertions or not
"""
- return (options.get_value('b_ndebug') == 'true' or
- (options.get_value('b_ndebug') == 'if-release' and
- options.get_value('buildtype') in {'release', 'plain'}))
+ return (env.coredata.get_option_for_target(target, 'b_ndebug') == 'true' or
+ (env.coredata.get_option_for_target(target, 'b_ndebug') == 'if-release' and
+ env.coredata.get_option_for_target(target, 'buildtype') in {'release', 'plain'}))
+def are_asserts_disabled_for_subproject(subproject: str, env: 'Environment') -> bool:
+ return (env.coredata.get_option_for_subproject('b_ndebug', subproject) == 'true' or
+ (env.coredata.get_option_for_subproject('b_ndebug', subproject) == 'if-release' and
+ env.coredata.get_option_for_subproject('buildtype', subproject) in {'release', 'plain'}))
-def get_base_compile_args(options: 'KeyedOptionDictType', compiler: 'Compiler', env: 'Environment') -> T.List[str]:
+
+def get_base_compile_args(target: 'BuildTarget', compiler: 'Compiler', env: 'Environment') -> T.List[str]:
args: T.List[str] = []
try:
- if options.get_value(OptionKey('b_lto')):
+ if env.coredata.get_option_for_target(target, 'b_lto'):
+ num_threads = get_option_value_for_target(env, target, OptionKey('b_lto_threads'), 0)
+ ltomode = get_option_value_for_target(env, target, OptionKey('b_lto_mode'), 'default')
args.extend(compiler.get_lto_compile_args(
- threads=get_option_value(options, OptionKey('b_lto_threads'), 0),
- mode=get_option_value(options, OptionKey('b_lto_mode'), 'default')))
+ threads=num_threads,
+ mode=ltomode))
except (KeyError, AttributeError):
pass
try:
- args += compiler.get_colorout_args(options.get_value(OptionKey('b_colorout')))
- except (KeyError, AttributeError):
+ clrout = env.coredata.get_option_for_target(target, 'b_colorout')
+ assert isinstance(clrout, str)
+ args += compiler.get_colorout_args(clrout)
+ except KeyError:
pass
try:
- args += compiler.sanitizer_compile_args(options.get_value(OptionKey('b_sanitize')))
- except (KeyError, AttributeError):
+ sanitize = env.coredata.get_option_for_target(target, 'b_sanitize')
+ assert isinstance(sanitize, str)
+ args += compiler.sanitizer_compile_args(sanitize)
+ except KeyError:
pass
try:
- pgo_val = options.get_value(OptionKey('b_pgo'))
+ pgo_val = env.coredata.get_option_for_target(target, 'b_pgo')
if pgo_val == 'generate':
args.extend(compiler.get_profile_generate_args())
elif pgo_val == 'use':
@@ -317,21 +359,23 @@ def get_base_compile_args(options: 'KeyedOptionDictType', compiler: 'Compiler',
except (KeyError, AttributeError):
pass
try:
- if options.get_value(OptionKey('b_coverage')):
+ if env.coredata.get_option_for_target(target, 'b_coverage'):
args += compiler.get_coverage_args()
except (KeyError, AttributeError):
pass
try:
- args += compiler.get_assert_args(are_asserts_disabled(options), env)
- except (KeyError, AttributeError):
+ args += compiler.get_assert_args(are_asserts_disabled(target, env), env)
+ except KeyError:
pass
# This does not need a try...except
- if option_enabled(compiler.base_options, options, OptionKey('b_bitcode')):
+ if option_enabled(compiler.base_options, target, env, 'b_bitcode'):
args.append('-fembed-bitcode')
try:
+ crt_val = env.coredata.get_option_for_target(target, 'b_vscrt')
+ assert isinstance(crt_val, str)
+ buildtype = env.coredata.get_option_for_target(target, 'buildtype')
+ assert isinstance(buildtype, str)
try:
- crt_val = options.get_value(OptionKey('b_vscrt'))
- buildtype = options.get_value(OptionKey('buildtype'))
args += compiler.get_crt_compile_args(crt_val, buildtype)
except AttributeError:
pass
@@ -339,31 +383,38 @@ def get_base_compile_args(options: 'KeyedOptionDictType', compiler: 'Compiler',
pass
return args
-def get_base_link_args(options: 'KeyedOptionDictType', linker: 'Compiler',
- is_shared_module: bool, build_dir: str) -> T.List[str]:
+def get_base_link_args(target: 'BuildTarget',
+ linker: 'Compiler',
+ env: 'Environment') -> T.List[str]:
args: T.List[str] = []
+ build_dir = env.get_build_dir()
try:
- if options.get_value('b_lto'):
- if options.get_value('werror'):
+ if env.coredata.get_option_for_target(target, 'b_lto'):
+ if env.coredata.get_option_for_target(target, 'werror'):
args.extend(linker.get_werror_args())
thinlto_cache_dir = None
- if get_option_value(options, OptionKey('b_thinlto_cache'), False):
- thinlto_cache_dir = get_option_value(options, OptionKey('b_thinlto_cache_dir'), '')
+ cachedir_key = OptionKey('b_thinlto_cache')
+ if get_option_value_for_target(env, target, cachedir_key, False):
+ thinlto_cache_dir = get_option_value_for_target(env, target, OptionKey('b_thinlto_cache_dir'), '')
if thinlto_cache_dir == '':
thinlto_cache_dir = os.path.join(build_dir, 'meson-private', 'thinlto-cache')
+ num_threads = get_option_value_for_target(env, target, OptionKey('b_lto_threads'), 0)
+ lto_mode = get_option_value_for_target(env, target, OptionKey('b_lto_mode'), 'default')
args.extend(linker.get_lto_link_args(
- threads=get_option_value(options, OptionKey('b_lto_threads'), 0),
- mode=get_option_value(options, OptionKey('b_lto_mode'), 'default'),
+ threads=num_threads,
+ mode=lto_mode,
thinlto_cache_dir=thinlto_cache_dir))
except (KeyError, AttributeError):
pass
try:
- args += linker.sanitizer_link_args(options.get_value('b_sanitize'))
- except (KeyError, AttributeError):
+ sanitizer = env.coredata.get_option_for_target(target, 'b_sanitize')
+ assert isinstance(sanitizer, str)
+ args += linker.sanitizer_link_args(sanitizer)
+ except KeyError:
pass
try:
- pgo_val = options.get_value('b_pgo')
+ pgo_val = env.coredata.get_option_for_target(target, 'b_pgo')
if pgo_val == 'generate':
args.extend(linker.get_profile_generate_args())
elif pgo_val == 'use':
@@ -371,16 +422,16 @@ def get_base_link_args(options: 'KeyedOptionDictType', linker: 'Compiler',
except (KeyError, AttributeError):
pass
try:
- if options.get_value('b_coverage'):
+ if env.coredata.get_option_for_target(target, 'b_coverage'):
args += linker.get_coverage_link_args()
except (KeyError, AttributeError):
pass
- as_needed = option_enabled(linker.base_options, options, OptionKey('b_asneeded'))
- bitcode = option_enabled(linker.base_options, options, OptionKey('b_bitcode'))
+ as_needed = option_enabled(linker.base_options, target, env, 'b_asneeded')
+ bitcode = option_enabled(linker.base_options, target, env, 'b_bitcode')
# Shared modules cannot be built with bitcode_bundle because
# -bitcode_bundle is incompatible with -undefined and -bundle
- if bitcode and not is_shared_module:
+ if bitcode and not target.typename == 'shared module':
args.extend(linker.bitcode_args())
elif as_needed:
# -Wl,-dead_strip_dylibs is incompatible with bitcode
@@ -389,18 +440,23 @@ def get_base_link_args(options: 'KeyedOptionDictType', linker: 'Compiler',
# Apple's ld (the only one that supports bitcode) does not like -undefined
# arguments or -headerpad_max_install_names when bitcode is enabled
if not bitcode:
+ from ..build import SharedModule
args.extend(linker.headerpad_args())
- if (not is_shared_module and
- option_enabled(linker.base_options, options, OptionKey('b_lundef'))):
+ if (not isinstance(target, SharedModule) and
+ option_enabled(linker.base_options, target, env, 'b_lundef')):
args.extend(linker.no_undefined_link_args())
else:
args.extend(linker.get_allow_undefined_link_args())
try:
+ crt_val = env.coredata.get_option_for_target(target, 'b_vscrt')
+ assert isinstance(crt_val, str)
+ buildtype = env.coredata.get_option_for_target(target, 'buildtype')
+ assert isinstance(buildtype, str)
try:
- crt_val = options.get_value(OptionKey('b_vscrt'))
- buildtype = options.get_value(OptionKey('buildtype'))
- args += linker.get_crt_link_args(crt_val, buildtype)
+ crtargs = linker.get_crt_link_args(crt_val, buildtype)
+ assert isinstance(crtargs, list)
+ args += crtargs
except AttributeError:
pass
except KeyError:
@@ -598,11 +654,11 @@ class Compiler(HoldableObject, metaclass=abc.ABCMeta):
def get_options(self) -> 'MutableKeyedOptionDictType':
return {}
- def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
+ def get_option_compile_args(self, target: 'BuildTarget', env: 'Environment', subproject: T.Optional[str] = None) -> T.List[str]:
return []
- def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
- return self.linker.get_option_args(options)
+ def get_option_link_args(self, target: 'BuildTarget', env: 'Environment', subproject: T.Optional[str] = None) -> T.List[str]:
+ return self.linker.get_option_link_args(target, env, subproject)
def check_header(self, hname: str, prefix: str, env: 'Environment', *,
extra_args: T.Union[None, T.List[str], T.Callable[[CompileCheckMode], T.List[str]]] = None,
@@ -894,8 +950,8 @@ class Compiler(HoldableObject, metaclass=abc.ABCMeta):
def get_std_shared_lib_link_args(self) -> T.List[str]:
return self.linker.get_std_shared_lib_args()
- def get_std_shared_module_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
- return self.linker.get_std_shared_module_args(options)
+ def get_std_shared_module_link_args(self, target: 'BuildTarget') -> T.List[str]:
+ return self.linker.get_std_shared_module_args(target)
def get_link_whole_for(self, args: T.List[str]) -> T.List[str]:
return self.linker.get_link_whole_for(args)
@@ -1358,6 +1414,19 @@ class Compiler(HoldableObject, metaclass=abc.ABCMeta):
def form_compileropt_key(self, basename: str) -> OptionKey:
return OptionKey(f'{self.language}_{basename}', machine=self.for_machine)
+ def get_compileropt_value(self,
+ key: T.Union[str, OptionKey],
+ env: Environment,
+ target: T.Optional[BuildTarget],
+ subproject: T.Optional[str] = None
+ ) -> T.Union[str, int, bool, T.List[str]]:
+ if isinstance(key, str):
+ key = self.form_compileropt_key(key)
+ if target:
+ return env.coredata.get_option_for_target(target, key)
+ else:
+ return env.coredata.get_option_for_subproject(key, subproject)
+
def _update_language_stds(self, opts: MutableKeyedOptionDictType, value: T.List[str]) -> None:
key = self.form_compileropt_key('std')
std = opts[key]
@@ -1370,12 +1439,12 @@ class Compiler(HoldableObject, metaclass=abc.ABCMeta):
def get_global_options(lang: str,
comp: T.Type[Compiler],
for_machine: MachineChoice,
- env: 'Environment') -> dict[OptionKey, options.UserOption[T.Any]]:
+ env: 'Environment') -> dict[OptionKey, options.AnyOptionType]:
"""Retrieve options that apply to all compilers for a given language."""
description = f'Extra arguments passed to the {lang}'
argkey = OptionKey(f'{lang}_args', machine=for_machine)
- largkey = argkey.evolve(f'{lang}_link_args')
- envkey = argkey.evolve(f'{lang}_env_args')
+ largkey = OptionKey(f'{lang}_link_args', machine=for_machine)
+ envkey = OptionKey(f'{lang}_env_args', machine=for_machine)
comp_key = argkey if argkey in env.options else envkey
@@ -1383,12 +1452,12 @@ def get_global_options(lang: str,
link_options = env.options.get(largkey, [])
cargs = options.UserStringArrayOption(
- f'{lang}_{argkey.name}',
+ argkey.name,
description + ' compiler',
comp_options, split_args=True, allow_dups=True)
largs = options.UserStringArrayOption(
- f'{lang}_{largkey.name}',
+ largkey.name,
description + ' linker',
link_options, split_args=True, allow_dups=True)
@@ -1400,6 +1469,6 @@ def get_global_options(lang: str,
# autotools compatibility.
largs.extend_value(comp_options)
- opts: dict[OptionKey, options.UserOption[T.Any]] = {argkey: cargs, largkey: largs}
+ opts: dict[OptionKey, options.AnyOptionType] = {argkey: cargs, largkey: largs}
return opts