Skip to content

Type safe option value getter #14561

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

Draft
wants to merge 9 commits into
base: master
Choose a base branch
from
2 changes: 1 addition & 1 deletion mesonbuild/ast/introspection.py
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ def traverse_nodes(inqueue: T.List[BaseNode]) -> T.List[BaseNode]:
return new_target

def build_library(self, node: BaseNode, args: T.List[TYPE_var], kwargs: T.Dict[str, TYPE_var]) -> T.Optional[T.Dict[str, T.Any]]:
default_library = self.coredata.optstore.get_value_for(OptionKey('default_library'))
default_library = self.coredata.optstore.get_value_for(OptionKey('default_library'), str)
if default_library == 'shared':
return self.build_target(node, args, kwargs, SharedLibrary)
elif default_library == 'static':
Expand Down
55 changes: 19 additions & 36 deletions mesonbuild/backend/backends.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
from .. import mlog
from ..compilers import LANGUAGES_USING_LDFLAGS, detect, lang_suffixes
from ..mesonlib import (
File, MachineChoice, MesonException, MesonBugException, OrderedSet,
File, MachineChoice, MesonException, OrderedSet,
ExecutableSerialisation, EnvironmentException,
classify_unity_sources, get_compiler_for_source,
is_parent_path,
Expand All @@ -42,7 +42,6 @@
from ..interpreter import Interpreter, Test
from ..linkers.linkers import StaticLinker
from ..mesonlib import FileMode, FileOrString
from ..options import ElementaryOptionValues

from typing_extensions import TypedDict, NotRequired

Expand Down Expand Up @@ -373,7 +372,7 @@ def get_target_dir(self, target: T.Union[build.Target, build.CustomTargetIndex])
if isinstance(target, build.RunTarget):
# this produces no output, only a dummy top-level name
dirname = ''
elif self.environment.coredata.optstore.get_value_for(OptionKey('layout')) == 'mirror':
elif self.environment.coredata.optstore.get_value_for(OptionKey('layout'), str) == 'mirror':
dirname = target.get_subdir()
else:
dirname = 'meson-out'
Expand Down Expand Up @@ -426,8 +425,7 @@ def generate_unity_files(self, target: build.BuildTarget, unity_src: str) -> T.L
abs_files: T.List[str] = []
result: T.List[mesonlib.File] = []
compsrcs = classify_unity_sources(target.compilers.values(), unity_src)
unity_size = self.get_target_option(target, 'unity_size')
assert isinstance(unity_size, int), 'for mypy'
unity_size = self.environment.coredata.optstore.get_option_for_target(target, OptionKey('unity_size'), int)

def init_language_file(suffix: str, unity_file_number: int) -> T.TextIO:
unity_src = self.get_unity_source_file(target, suffix, unity_file_number)
Expand Down Expand Up @@ -815,7 +813,7 @@ def rpaths_for_non_system_absolute_shared_libraries(self, target: build.BuildTar
def determine_rpath_dirs(self, target: T.Union[build.BuildTarget, build.CustomTarget, build.CustomTargetIndex]
) -> T.Tuple[str, ...]:
result: OrderedSet[str]
if self.environment.coredata.optstore.get_value_for(OptionKey('layout')) == 'mirror':
if self.environment.coredata.optstore.get_value_for(OptionKey('layout'), str) == 'mirror':
# Need a copy here
result = OrderedSet(target.get_link_dep_subdirs())
else:
Expand Down Expand Up @@ -877,7 +875,7 @@ def object_filename_from_source(self, target: build.BuildTarget, compiler: Compi
object_suffix = machine.get_object_suffix()
# For the TASKING compiler, in case of LTO or prelinking the object suffix has to be .mil
if compiler.get_id() == 'tasking':
use_lto = self.get_target_option(target, 'b_lto')
use_lto = self.environment.coredata.optstore.get_option_for_target(target, OptionKey('b_lto'), bool)
if use_lto or (isinstance(target, build.StaticLibrary) and target.prelink):
if not source.rsplit('.', 1)[1] in lang_suffixes['c']:
if isinstance(target, build.StaticLibrary) and not target.prelink:
Expand Down Expand Up @@ -928,8 +926,8 @@ def _determine_ext_objs(self, extobj: 'build.ExtractedObjects') -> T.List[str]:
if self.is_unity(extobj.target):
compsrcs = classify_unity_sources(extobj.target.compilers.values(), sources)
sources = []
unity_size = self.get_target_option(extobj.target, 'unity_size')
assert isinstance(unity_size, int), 'for mypy'
unity_size = self.environment.coredata.optstore.get_option_for_target(
extobj.target, OptionKey('unity_size'), int)

for comp, srcs in compsrcs.items():
if comp.language in LANGS_CANT_UNITY:
Expand Down Expand Up @@ -980,10 +978,8 @@ def create_msvc_pch_implementation(self, target: build.BuildTarget, lang: str, p
return pch_rel_to_build

def target_uses_pch(self, target: build.BuildTarget) -> bool:
try:
return T.cast('bool', self.get_target_option(target, 'b_pch'))
except (KeyError, AttributeError):
return False
return self.environment.coredata.optstore.get_option_for_target(
target, OptionKey('b_pch'), bool, fallback=False)

@staticmethod
def escape_extra_args(args: T.List[str]) -> T.List[str]:
Expand Down Expand Up @@ -1014,24 +1010,23 @@ def generate_basic_compiler_args(self, target: build.BuildTarget, compiler: 'Com
# Add things like /NOLOGO or -pipe; usually can't be overridden
commands += compiler.get_always_args()
# warning_level is a string, but mypy can't determine that
commands += compiler.get_warn_args(T.cast('str', self.get_target_option(target, 'warning_level')))
commands += compiler.get_warn_args(self.environment.coredata.optstore.get_option_for_target(
target, OptionKey('warning_level'), str))
# Add -Werror if werror=true is set in the build options set on the
# command-line or default_options inside project(). This only sets the
# action to be done for warnings if/when they are emitted, so it's ok
# to set it after or get_warn_args().
if self.get_target_option(target, 'werror'):
if self.environment.coredata.optstore.get_option_for_target(target, OptionKey('werror'), bool):
commands += compiler.get_werror_args()
# Add compile args for c_* or cpp_* build options set on the
# command-line or default_options inside project().
commands += compiler.get_option_compile_args(target, self.environment, target.subproject)
commands += compiler.get_option_std_args(target, self.environment, target.subproject)

optimization = self.get_target_option(target, 'optimization')
assert isinstance(optimization, str), 'for mypy'
optimization = self.environment.coredata.optstore.get_option_for_target(target, OptionKey('optimization'), str)
commands += compiler.get_optimization_args(optimization)

debug = self.get_target_option(target, 'debug')
assert isinstance(debug, bool), 'for mypy'
debug = self.environment.coredata.optstore.get_option_for_target(target, OptionKey('debug'), bool)
commands += compiler.get_debug_args(debug)

# Add compile args added using add_project_arguments()
Expand Down Expand Up @@ -1342,8 +1337,7 @@ def construct_target_rel_paths(self, t: T.Union[build.Target, build.CustomTarget
def generate_depmf_install(self, d: InstallData) -> None:
depmf_path = self.build.dep_manifest_name
if depmf_path is None:
option_dir = self.environment.coredata.optstore.get_value_for(OptionKey('licensedir'))
assert isinstance(option_dir, str), 'for mypy'
option_dir = self.environment.coredata.optstore.get_value_for(OptionKey('licensedir'), str)
if option_dir:
depmf_path = os.path.join(option_dir, 'depmf.json')
else:
Expand Down Expand Up @@ -1673,7 +1667,7 @@ def create_install_data(self) -> InstallData:
# TODO go through all candidates, like others
strip_bin = [detect.defaults['strip'][0]]

umask = self.environment.coredata.optstore.get_value_for(OptionKey('install_umask'))
umask = self.environment.coredata.optstore.get_value_for_unsafe(OptionKey('install_umask'))
assert isinstance(umask, (str, int)), 'for mypy'

d = InstallData(self.environment.get_source_dir(),
Expand Down Expand Up @@ -1705,8 +1699,7 @@ def guess_install_tag(self, fname: str, outdir: T.Optional[str] = None) -> T.Opt
bindir = Path(prefix, self.environment.get_bindir())
libdir = Path(prefix, self.environment.get_libdir())
incdir = Path(prefix, self.environment.get_includedir())
_ldir = self.environment.coredata.optstore.get_value_for(OptionKey('localedir'))
assert isinstance(_ldir, str), 'for mypy'
_ldir = self.environment.coredata.optstore.get_value_for(OptionKey('localedir'), str)
localedir = Path(prefix, _ldir)
dest_path = Path(prefix, outdir, Path(fname).name) if outdir else Path(prefix, fname)
if bindir in dest_path.parents:
Expand Down Expand Up @@ -1761,8 +1754,7 @@ def generate_target_install(self, d: InstallData) -> None:
# TODO: Create GNUStrip/AppleStrip/etc. hierarchy for more
# fine-grained stripping of static archives.
can_strip = not isinstance(t, build.StaticLibrary)
should_strip = can_strip and self.get_target_option(t, 'strip')
assert isinstance(should_strip, bool), 'for mypy'
should_strip = can_strip and self.environment.coredata.optstore.get_option_for_target(t, OptionKey('strip'), bool)
# Install primary build output (library/executable/jar, etc)
# Done separately because of strip/aliases/rpath
if first_outdir is not False:
Expand Down Expand Up @@ -2101,20 +2093,11 @@ def compile_target_to_generator(self, target: build.CompileTarget) -> build.Gene
def is_unity(self, target: build.BuildTarget) -> bool:
if isinstance(target, build.CompileTarget):
return False
val = self.get_target_option(target, 'unity')
val = self.environment.coredata.optstore.get_option_for_target(target, OptionKey('unity'), str)
if val == 'on':
return True
if val == 'off':
return False
if val == 'subprojects':
return target.subproject != ''
raise MesonException(f'Internal error: invalid option type for "unity": {val}')

def get_target_option(self, target: build.BuildTarget, name: T.Union[str, OptionKey]) -> ElementaryOptionValues:
if isinstance(name, str):
key = OptionKey(name, subproject=target.subproject)
elif isinstance(name, OptionKey):
key = name
else:
raise MesonBugException('Internal error: invalid option type.')
return self.environment.coredata.get_option_for_target(target, key)
Loading
Loading