diff --git a/mesonbuild/ast/introspection.py b/mesonbuild/ast/introspection.py index 6bc6286f24f3..ca477f67bfb8 100644 --- a/mesonbuild/ast/introspection.py +++ b/mesonbuild/ast/introspection.py @@ -1,6 +1,6 @@ # SPDX-License-Identifier: Apache-2.0 # Copyright 2018 The Meson development team -# Copyright © 2024 Intel Corporation +# Copyright © 2024-2025 Intel Corporation # This class contains the basic functionality needed to run any interpreter # or an interpreter-based tool @@ -66,7 +66,7 @@ def __init__(self, self.subproject_dir = subproject_dir self.coredata = self.environment.get_coredata() self.backend = backend - self.default_options = {OptionKey('backend'): self.backend} + self.default_options = {OptionKey.factory('backend'): self.backend} self.project_data: T.Dict[str, T.Any] = {} self.targets: T.List[T.Dict[str, T.Any]] = [] self.dependencies: T.List[T.Dict[str, T.Any]] = [] @@ -312,7 +312,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.get_option(OptionKey('default_library')) + default_library = self.coredata.get_option(OptionKey.factory('default_library')) if default_library == 'shared': return self.build_target(node, args, kwargs, SharedLibrary) elif default_library == 'static': diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index 8d9796db95c6..46043cf8c439 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -371,7 +371,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.get_option(OptionKey('layout')) == 'mirror': + elif self.environment.coredata.get_option(OptionKey.factory('layout')) == 'mirror': dirname = target.get_subdir() else: dirname = 'meson-out' @@ -424,7 +424,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 = target.get_option(OptionKey('unity_size')) + unity_size = target.get_option(OptionKey.factory('unity_size')) assert isinstance(unity_size, int), 'for mypy' def init_language_file(suffix: str, unity_file_number: int) -> T.TextIO: @@ -818,7 +818,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.get_option(OptionKey('layout')) == 'mirror': + if self.environment.coredata.get_option(OptionKey.factory('layout')) == 'mirror': # Need a copy here result = OrderedSet(target.get_link_dep_subdirs()) else: @@ -878,7 +878,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': - if target.get_option(OptionKey('b_lto')) or (isinstance(target, build.StaticLibrary) and target.prelink): + if target.get_option(OptionKey.factory('b_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: raise EnvironmentException('Tried using MIL linking for a static library with a assembly file. This can only be done if the static library is prelinked or disable \'b_lto\'.') @@ -928,7 +928,7 @@ def _determine_ext_objs(self, extobj: 'build.ExtractedObjects') -> T.List[str]: if extobj.target.is_unity: compsrcs = classify_unity_sources(extobj.target.compilers.values(), sources) sources = [] - unity_size = extobj.target.get_option(OptionKey('unity_size')) + unity_size = extobj.target.get_option(OptionKey.factory('unity_size')) assert isinstance(unity_size, int), 'for mypy' for comp, srcs in compsrcs.items(): @@ -981,7 +981,7 @@ def create_msvc_pch_implementation(self, target: build.BuildTarget, lang: str, p def target_uses_pch(self, target: build.BuildTarget) -> bool: try: - return T.cast('bool', target.get_option(OptionKey('b_pch'))) + return T.cast('bool', target.get_option(OptionKey.factory('b_pch'))) except (KeyError, AttributeError): return False @@ -1015,22 +1015,22 @@ 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', target.get_option(OptionKey('warning_level')))) + commands += compiler.get_warn_args(T.cast('str', target.get_option(OptionKey.factory('warning_level')))) # 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 target.get_option(OptionKey('werror')): + if target.get_option(OptionKey.factory('werror')): 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(copt_proxy) - optimization = target.get_option(OptionKey('optimization')) + optimization = target.get_option(OptionKey.factory('optimization')) assert isinstance(optimization, str), 'for mypy' commands += compiler.get_optimization_args(optimization) - debug = target.get_option(OptionKey('debug')) + debug = target.get_option(OptionKey.factory('debug')) assert isinstance(debug, bool), 'for mypy' commands += compiler.get_debug_args(debug) @@ -1336,7 +1336,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.get_option(OptionKey('licensedir')) + option_dir = self.environment.coredata.get_option(OptionKey.factory('licensedir')) assert isinstance(option_dir, str), 'for mypy' if option_dir: depmf_path = os.path.join(option_dir, 'depmf.json') @@ -1667,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.get_option(OptionKey('install_umask')) + umask = self.environment.coredata.get_option(OptionKey.factory('install_umask')) assert isinstance(umask, (str, int)), 'for mypy' d = InstallData(self.environment.get_source_dir(), @@ -1699,7 +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.get_option(OptionKey('localedir')) + _ldir = self.environment.coredata.get_option(OptionKey.factory('localedir')) assert isinstance(_ldir, str), 'for mypy' localedir = Path(prefix, _ldir) dest_path = Path(prefix, outdir, Path(fname).name) if outdir else Path(prefix, fname) @@ -1755,7 +1755,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 t.get_option(OptionKey('strip')) + should_strip = can_strip and t.get_option(OptionKey.factory('strip')) assert isinstance(should_strip, bool), 'for mypy' # Install primary build output (library/executable/jar, etc) # Done separately because of strip/aliases/rpath diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index cabb7be04445..cbf989a2d4f3 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -613,7 +613,7 @@ def generate(self, capture: bool = False, vslite_ctx: T.Optional[T.Dict] = None) # so no harm in catching and reporting something unexpected. raise MesonBugException('We do not expect the ninja backend to be given a valid \'vslite_ctx\'') ninja = environment.detect_ninja_command_and_version(log=True) - if self.environment.coredata.get_option(OptionKey('vsenv')): + if self.environment.coredata.get_option(OptionKey.factory('vsenv')): builddir = Path(self.environment.get_build_dir()) try: # For prettier printing, reduce to a relative path. If @@ -670,7 +670,7 @@ def generate(self, capture: bool = False, vslite_ctx: T.Optional[T.Dict] = None) mlog.log_timestamp("Install generated") self.generate_dist() mlog.log_timestamp("Dist generated") - key = OptionKey('b_coverage') + key = OptionKey.factory('b_coverage') if (key in self.environment.coredata.optstore and self.environment.coredata.optstore.get_value(key)): gcovr_exe, gcovr_version, lcov_exe, lcov_version, genhtml_exe, llvm_cov_exe = environment.find_coverage_tools(self.environment.coredata) @@ -1117,7 +1117,7 @@ def should_use_dyndeps_for_target(self, target: 'build.BuildTarget') -> bool: cpp = target.compilers['cpp'] if cpp.get_id() != 'msvc': return False - cppversion = target.get_option(OptionKey('cpp_std', machine=target.for_machine)) + cppversion = target.get_option(OptionKey.factory('cpp_std', machine=target.for_machine)) if cppversion not in ('latest', 'c++latest', 'vc++latest'): return False if not mesonlib.current_vs_supports_modules(): @@ -1337,9 +1337,9 @@ def generate_install(self) -> None: def generate_tests(self) -> None: self.serialize_tests() cmd = self.environment.get_build_command(True) + ['test', '--no-rebuild'] - if not self.environment.coredata.get_option(OptionKey('stdsplit')): + if not self.environment.coredata.get_option(OptionKey.factory('stdsplit')): cmd += ['--no-stdsplit'] - if self.environment.coredata.get_option(OptionKey('errorlogs')): + if self.environment.coredata.get_option(OptionKey.factory('errorlogs')): cmd += ['--print-errorlogs'] elem = self.create_phony_target('test', 'CUSTOM_COMMAND', ['all', 'meson-test-prereq', 'PHONY']) elem.add_item('COMMAND', cmd) @@ -1725,7 +1725,7 @@ def generate_vala_compile(self, target: build.BuildTarget) -> \ valac_outputs.append(vala_c_file) args = self.generate_basic_compiler_args(target, valac) - args += valac.get_colorout_args(target.get_option(OptionKey('b_colorout'))) + args += valac.get_colorout_args(target.get_option(OptionKey.factory('b_colorout'))) # Tell Valac to output everything in our private directory. Sadly this # means it will also preserve the directory components of Vala sources # found inside the build tree (generated sources). @@ -1803,14 +1803,14 @@ def generate_cython_transpile(self, target: build.BuildTarget) -> \ args: T.List[str] = [] args += cython.get_always_args() - args += cython.get_debug_args(target.get_option(OptionKey('debug'))) - args += cython.get_optimization_args(target.get_option(OptionKey('optimization'))) + args += cython.get_debug_args(target.get_option(OptionKey.factory('debug'))) + args += cython.get_optimization_args(target.get_option(OptionKey.factory('optimization'))) args += cython.get_option_compile_args(target.get_options()) args += self.build.get_global_args(cython, target.for_machine) args += self.build.get_project_args(cython, target.subproject, target.for_machine) args += target.get_extra_args('cython') - ext = target.get_option(OptionKey('cython_language', machine=target.for_machine)) + ext = target.get_option(OptionKey.factory('cython_language', machine=target.for_machine)) pyx_sources = [] # Keep track of sources we're adding to build @@ -2017,8 +2017,8 @@ def generate_rust_target(self, target: build.BuildTarget) -> None: # https://github.com/rust-lang/rust/issues/39016 if not isinstance(target, build.StaticLibrary): try: - buildtype = target.get_option(OptionKey('buildtype')) - crt = target.get_option(OptionKey('b_vscrt')) + buildtype = target.get_option(OptionKey.factory('buildtype')) + crt = target.get_option(OptionKey.factory('b_vscrt')) args += rustc.get_crt_link_args(crt, buildtype) except (KeyError, AttributeError): pass @@ -3064,7 +3064,7 @@ def generate_single_compile(self, target: build.BuildTarget, src, # If TASKING compiler family is used and MIL linking is enabled for the target, # then compilation rule name is a special one to output MIL files # instead of object files for .c files - key = OptionKey('b_lto') + key = OptionKey.factory('b_lto') if compiler.get_id() == 'tasking': if ((isinstance(target, build.StaticLibrary) and target.prelink) or target.get_option(key)) and src.rsplit('.', 1)[1] in compilers.lang_suffixes['c']: compiler_name = self.get_compiler_rule_name('tasking_mil_compile', compiler.for_machine) @@ -3522,9 +3522,9 @@ def generate_link(self, target: build.BuildTarget, outname, obj_list, linker: T. # Add things like /NOLOGO; usually can't be overridden commands += linker.get_linker_always_args() # Add buildtype linker args: optimization level, etc. - commands += linker.get_optimization_link_args(target.get_option(OptionKey('optimization'))) + commands += linker.get_optimization_link_args(target.get_option(OptionKey.factory('optimization'))) # Add /DEBUG and the pdb filename when using MSVC - if target.get_option(OptionKey('debug')): + if target.get_option(OptionKey.factory('debug')): commands += self.get_link_debugfile_args(linker, target) debugfile = self.get_link_debugfile_name(linker, target) if debugfile is not None: @@ -3611,7 +3611,7 @@ def generate_link(self, target: build.BuildTarget, outname, obj_list, linker: T. elem = NinjaBuildElement(self.all_outputs, outname, linker_rule, obj_list, implicit_outs=implicit_outs) elem.add_dep(dep_targets + custom_target_libraries) if linker.get_id() == 'tasking': - if len([x for x in dep_targets + custom_target_libraries if x.endswith('.ma')]) > 0 and not target.get_option(OptionKey('b_lto')): + if len([x for x in dep_targets + custom_target_libraries if x.endswith('.ma')]) > 0 and not target.get_option(OptionKey.factory('b_lto')): raise MesonException(f'Tried to link the target named \'{target.name}\' with a MIL archive without LTO enabled! This causes the compiler to ignore the archive.') # Compiler args must be included in TI C28x linker commands. @@ -3731,7 +3731,7 @@ def generate_clangtool(self, name: str, extra_arg: T.Optional[str] = None) -> No target_name += f'-{extra_arg}' extra_args.append(f'--{extra_arg}') colorout = self.environment.coredata.optstore.get_value('b_colorout') \ - if OptionKey('b_colorout') in self.environment.coredata.optstore else 'always' + if OptionKey.factory('b_colorout') in self.environment.coredata.optstore else 'always' extra_args.extend(['--color', colorout]) if not os.path.exists(os.path.join(self.environment.source_dir, '.clang-' + name)) and \ not os.path.exists(os.path.join(self.environment.source_dir, '_clang-' + name)): @@ -3826,7 +3826,7 @@ def generate_ending(self) -> None: if ctlist: elem.add_dep(self.generate_custom_target_clean(ctlist)) - if OptionKey('b_coverage') in self.environment.coredata.optstore and \ + if OptionKey.factory('b_coverage') in self.environment.coredata.optstore and \ self.environment.coredata.optstore.get_value('b_coverage'): self.generate_gcov_clean() elem.add_dep('clean-gcda') diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py index e837c89ced0e..28d127ba487e 100644 --- a/mesonbuild/backend/vs2010backend.py +++ b/mesonbuild/backend/vs2010backend.py @@ -266,11 +266,11 @@ def generate(self, else: raise MesonException('Unsupported Visual Studio platform: ' + build_machine) - self.buildtype = self.environment.coredata.get_option(OptionKey('buildtype')) - self.optimization = self.environment.coredata.get_option(OptionKey('optimization')) - self.debug = self.environment.coredata.get_option(OptionKey('debug')) + self.buildtype = self.environment.coredata.get_option(OptionKey.factory('buildtype')) + self.optimization = self.environment.coredata.get_option(OptionKey.factory('optimization')) + self.debug = self.environment.coredata.get_option(OptionKey.factory('debug')) try: - self.sanitize = self.environment.coredata.get_option(OptionKey('b_sanitize')) + self.sanitize = self.environment.coredata.get_option(OptionKey.factory('b_sanitize')) except MesonException: self.sanitize = 'none' sln_filename = os.path.join(self.environment.get_build_dir(), self.build.project_name + '.sln') @@ -421,7 +421,7 @@ def generate_solution(self, sln_filename: str, projlist: T.List[Project]) -> Non ofile.write('# Visual Studio %s\n' % self.sln_version_comment) prj_templ = 'Project("{%s}") = "%s", "%s", "{%s}"\n' for prj in projlist: - if self.environment.coredata.get_option(OptionKey('layout')) == 'mirror': + if self.environment.coredata.get_option(OptionKey.factory('layout')) == 'mirror': self.generate_solution_dirs(ofile, prj[1].parents) target = self.build.targets[prj[0]] lang = 'default' @@ -1012,7 +1012,7 @@ def get_args_defines_and_inc_dirs(self, target, compiler, generated_files_includ # Compile args added from the env or cross file: CFLAGS/CXXFLAGS, etc. We want these # to override all the defaults, but not the per-target compile args. for lang in file_args.keys(): - file_args[lang] += target.get_option(OptionKey(f'{lang}_args', machine=target.for_machine)) + file_args[lang] += target.get_option(OptionKey.factory(f'{lang}_args', machine=target.for_machine)) for args in file_args.values(): # This is where Visual Studio will insert target_args, target_defines, # etc, which are added later from external deps (see below). @@ -1302,7 +1302,7 @@ def add_non_makefile_vcxproj_elements( if True in ((dep.name == 'openmp') for dep in target.get_external_deps()): ET.SubElement(clconf, 'OpenMPSupport').text = 'true' # CRT type; debug or release - vscrt_type = target.get_option(OptionKey('b_vscrt')) + vscrt_type = target.get_option(OptionKey.factory('b_vscrt')) vscrt_val = compiler.get_crt_val(vscrt_type, self.buildtype) if vscrt_val == 'mdd': ET.SubElement(type_config, 'UseDebugLibraries').text = 'true' @@ -1340,7 +1340,7 @@ def add_non_makefile_vcxproj_elements( # Exception handling has to be set in the xml in addition to the "AdditionalOptions" because otherwise # cl will give warning D9025: overriding '/Ehs' with cpp_eh value if 'cpp' in target.compilers: - eh = target.get_option(OptionKey('cpp_eh', machine=target.for_machine)) + eh = target.get_option(OptionKey.factory('cpp_eh', machine=target.for_machine)) if eh == 'a': ET.SubElement(clconf, 'ExceptionHandling').text = 'Async' elif eh == 's': @@ -1358,10 +1358,10 @@ def add_non_makefile_vcxproj_elements( ET.SubElement(clconf, 'PreprocessorDefinitions').text = ';'.join(target_defines) ET.SubElement(clconf, 'FunctionLevelLinking').text = 'true' # Warning level - warning_level = T.cast('str', target.get_option(OptionKey('warning_level'))) + warning_level = T.cast('str', target.get_option(OptionKey.factory('warning_level'))) warning_level = 'EnableAllWarnings' if warning_level == 'everything' else 'Level' + str(1 + int(warning_level)) ET.SubElement(clconf, 'WarningLevel').text = warning_level - if target.get_option(OptionKey('werror')): + if target.get_option(OptionKey.factory('werror')): ET.SubElement(clconf, 'TreatWarningAsError').text = 'true' # Optimization flags o_flags = split_o_flags_args(build_args) @@ -1534,7 +1534,7 @@ def add_non_makefile_vcxproj_elements( # /nologo ET.SubElement(link, 'SuppressStartupBanner').text = 'true' # /release - if not target.get_option(OptionKey('debug')): + if not target.get_option(OptionKey.factory('debug')): ET.SubElement(link, 'SetChecksum').text = 'true' # Visual studio doesn't simply allow the src files of a project to be added with the 'Condition=...' attribute, @@ -1789,7 +1789,7 @@ def path_normalize_add(path, lis): # build system as possible. self.add_target_deps(root, target) self._prettyprint_vcxproj_xml(ET.ElementTree(root), ofname) - if self.environment.coredata.get_option(OptionKey('layout')) == 'mirror': + if self.environment.coredata.get_option(OptionKey.factory('layout')) == 'mirror': self.gen_vcxproj_filters(target, ofname) return True @@ -1958,9 +1958,9 @@ def gen_testproj(self): meson_build_dir_for_buildtype = build_dir_tail[:-2] + buildtype # Get the buildtype suffixed 'builddir_[debug/release/etc]' from 'builddir_vs', for example. proj_to_build_dir_for_buildtype = str(os.path.join(proj_to_multiconfigured_builds_parent_dir, meson_build_dir_for_buildtype)) test_cmd = f'{nmake_base_meson_command} test -C "{proj_to_build_dir_for_buildtype}" --no-rebuild' - if not self.environment.coredata.get_option(OptionKey('stdsplit')): + if not self.environment.coredata.get_option(OptionKey.factory('stdsplit')): test_cmd += ' --no-stdsplit' - if self.environment.coredata.get_option(OptionKey('errorlogs')): + if self.environment.coredata.get_option(OptionKey.factory('errorlogs')): test_cmd += ' --print-errorlogs' condition = f'\'$(Configuration)|$(Platform)\'==\'{buildtype}|{self.platform}\'' prop_group = ET.SubElement(root, 'PropertyGroup', Condition=condition) @@ -1982,9 +1982,9 @@ def gen_testproj(self): ET.SubElement(midl, 'ProxyFileName').text = '%(Filename)_p.c' # FIXME: No benchmarks? test_command = self.environment.get_build_command() + ['test', '--no-rebuild'] - if not self.environment.coredata.get_option(OptionKey('stdsplit')): + if not self.environment.coredata.get_option(OptionKey.factory('stdsplit')): test_command += ['--no-stdsplit'] - if self.environment.coredata.get_option(OptionKey('errorlogs')): + if self.environment.coredata.get_option(OptionKey.factory('errorlogs')): test_command += ['--print-errorlogs'] self.serialize_tests() self.add_custom_build(root, 'run_tests', '"%s"' % ('" "'.join(test_command))) diff --git a/mesonbuild/backend/xcodebackend.py b/mesonbuild/backend/xcodebackend.py index 0e40d0239e5a..67939bfb9862 100644 --- a/mesonbuild/backend/xcodebackend.py +++ b/mesonbuild/backend/xcodebackend.py @@ -230,7 +230,7 @@ class XCodeBackend(backends.Backend): def __init__(self, build: T.Optional[build.Build], interpreter: T.Optional[Interpreter]): super().__init__(build, interpreter) self.project_uid = self.environment.coredata.lang_guids['default'].replace('-', '')[:24] - self.buildtype = T.cast('str', self.environment.coredata.get_option(OptionKey('buildtype'))) + self.buildtype = T.cast('str', self.environment.coredata.get_option(OptionKey.factory('buildtype'))) self.project_conflist = self.gen_id() self.maingroup_id = self.gen_id() self.all_id = self.gen_id() @@ -272,7 +272,7 @@ def gen_id(self) -> str: @functools.lru_cache(maxsize=None) def get_target_dir(self, target: T.Union[build.Target, build.CustomTargetIndex]) -> str: - dirname = os.path.join(target.get_subdir(), T.cast('str', self.environment.coredata.get_option(OptionKey('buildtype')))) + dirname = os.path.join(target.get_subdir(), T.cast('str', self.environment.coredata.get_option(OptionKey.factory('buildtype')))) #os.makedirs(os.path.join(self.environment.get_build_dir(), dirname), exist_ok=True) return dirname @@ -1686,7 +1686,7 @@ def generate_single_build_target(self, objects_dict, target_name, target) -> Non if compiler is None: continue # Start with warning args - warn_args = compiler.get_warn_args(target.get_option(OptionKey('warning_level'))) + warn_args = compiler.get_warn_args(target.get_option(OptionKey.factory('warning_level'))) copt_proxy = target.get_options() std_args = compiler.get_option_compile_args(copt_proxy) # Add compile args added using add_project_arguments() @@ -1736,9 +1736,9 @@ def generate_single_build_target(self, objects_dict, target_name, target) -> Non if target.suffix: suffix = '.' + target.suffix settings_dict.add_item('EXECUTABLE_SUFFIX', suffix) - settings_dict.add_item('GCC_GENERATE_DEBUGGING_SYMBOLS', BOOL2XCODEBOOL[target.get_option(OptionKey('debug'))]) + settings_dict.add_item('GCC_GENERATE_DEBUGGING_SYMBOLS', BOOL2XCODEBOOL[target.get_option(OptionKey.factory('debug'))]) settings_dict.add_item('GCC_INLINES_ARE_PRIVATE_EXTERN', 'NO') - opt_flag = OPT2XCODEOPT[target.get_option(OptionKey('optimization'))] + opt_flag = OPT2XCODEOPT[target.get_option(OptionKey.factory('optimization'))] if opt_flag is not None: settings_dict.add_item('GCC_OPTIMIZATION_LEVEL', opt_flag) if target.has_pch: diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 82d97fd2db10..226e7b65ae24 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -834,7 +834,7 @@ def __str__(self): @property def is_unity(self) -> bool: - unity_opt = self.get_option(OptionKey('unity')) + unity_opt = self.get_option(OptionKey.factory('unity')) return unity_opt == 'on' or (unity_opt == 'subprojects' and self.subproject != '') def validate_install(self): @@ -1019,7 +1019,7 @@ def process_compilers(self) -> T.List[str]: if 'vala' in self.compilers and 'c' not in self.compilers: self.compilers['c'] = self.all_compilers['c'] if 'cython' in self.compilers: - key = OptionKey('cython_language', machine=self.for_machine) + key = OptionKey.factory('cython_language', machine=self.for_machine) value = self.get_option(key) try: @@ -1258,7 +1258,7 @@ def _extract_pic_pie(self, kwargs: T.Dict[str, T.Any], arg: str, option: str) -> mlog.warning(f"Use the '{arg}' kwarg instead of passing '-f{arg}' manually to {self.name!r}") return True - k = OptionKey(option) + k = OptionKey.factory(option) if kwargs.get(arg) is not None: val = T.cast('bool', kwargs[arg]) elif k in self.environment.coredata.optstore: @@ -1740,7 +1740,7 @@ def process_vs_module_defs_kw(self, kwargs: T.Dict[str, T.Any]) -> None: self.process_link_depends(path) def extract_targets_as_list(self, kwargs: T.Dict[str, T.Union[LibTypes, T.Sequence[LibTypes]]], key: T.Literal['link_with', 'link_whole']) -> T.List[LibTypes]: - bl_type = self.environment.coredata.get_option(OptionKey('default_both_libraries')) + bl_type = self.environment.coredata.get_option(OptionKey.factory('default_both_libraries')) if bl_type == 'auto': if isinstance(self, StaticLibrary): bl_type = 'static' @@ -1971,7 +1971,7 @@ def __init__( environment: environment.Environment, compilers: T.Dict[str, 'Compiler'], kwargs): - key = OptionKey('b_pie') + key = OptionKey.factory('b_pie') if 'pie' not in kwargs and key in environment.coredata.optstore: kwargs['pie'] = environment.coredata.optstore.get_value(key) super().__init__(name, subdir, subproject, for_machine, sources, structured_sources, objects, @@ -2048,7 +2048,7 @@ def post_init(self) -> None: machine.is_windows() and ('cs' in self.compilers or self.uses_rust() or self.get_using_msvc()) # .pdb file is created only when debug symbols are enabled - and self.environment.coredata.get_option(OptionKey("debug")) + and self.environment.coredata.get_option(OptionKey.factory("debug")) ) if create_debug_file: # If the target is has a standard exe extension (i.e. 'foo.exe'), @@ -2330,14 +2330,14 @@ def determine_filenames(self): # Import library is called foo.dll.lib import_filename_tpl = '{0.prefix}{0.name}.dll.lib' # .pdb file is only created when debug symbols are enabled - create_debug_file = self.environment.coredata.get_option(OptionKey("debug")) + create_debug_file = self.environment.coredata.get_option(OptionKey.factory("debug")) elif self.get_using_msvc(): # Shared library is of the form foo.dll prefix = '' # Import library is called foo.lib import_filename_tpl = '{0.prefix}{0.name}.lib' # .pdb file is only created when debug symbols are enabled - create_debug_file = self.environment.coredata.get_option(OptionKey("debug")) + create_debug_file = self.environment.coredata.get_option(OptionKey.factory("debug")) # Assume GCC-compatible naming else: # Shared library is of the form libfoo.dll diff --git a/mesonbuild/cmake/common.py b/mesonbuild/cmake/common.py index d9ff559971f7..e13814f2131c 100644 --- a/mesonbuild/cmake/common.py +++ b/mesonbuild/cmake/common.py @@ -52,14 +52,14 @@ ] def cmake_is_debug(env: 'Environment') -> bool: - if OptionKey('b_vscrt') in env.coredata.optstore: - is_debug = env.coredata.get_option(OptionKey('buildtype')) == 'debug' + if OptionKey.factory('b_vscrt') in env.coredata.optstore: + is_debug = env.coredata.get_option(OptionKey.factory('buildtype')) == 'debug' if env.coredata.optstore.get_value('b_vscrt') in {'mdd', 'mtd'}: is_debug = True return is_debug else: # Don't directly assign to is_debug to make mypy happy - debug_opt = env.coredata.get_option(OptionKey('debug')) + debug_opt = env.coredata.get_option(OptionKey.factory('debug')) assert isinstance(debug_opt, bool) return debug_opt @@ -105,7 +105,7 @@ def _flags_to_list(raw: str) -> T.List[str]: return res def cmake_get_generator_args(env: 'Environment') -> T.List[str]: - backend_name = env.coredata.get_option(OptionKey('backend')) + backend_name = env.coredata.get_option(OptionKey.factory('backend')) assert isinstance(backend_name, str) assert backend_name in backend_generator_map return ['-G', backend_generator_map[backend_name]] diff --git a/mesonbuild/cmake/executor.py b/mesonbuild/cmake/executor.py index cbe75f36c688..c8e187db2d78 100644 --- a/mesonbuild/cmake/executor.py +++ b/mesonbuild/cmake/executor.py @@ -52,7 +52,7 @@ def __init__(self, environment: 'Environment', version: str, for_machine: Machin self.cmakebin = None return - self.prefix_paths = self.environment.coredata.optstore.get_value(OptionKey('cmake_prefix_path', machine=self.for_machine)) + self.prefix_paths = self.environment.coredata.optstore.get_value(OptionKey.factory('cmake_prefix_path', machine=self.for_machine)) if self.prefix_paths: self.extra_cmake_args += ['-DCMAKE_PREFIX_PATH={}'.format(';'.join(self.prefix_paths))] diff --git a/mesonbuild/cmake/interpreter.py b/mesonbuild/cmake/interpreter.py index 27ce54e2074d..a97e3b8b1412 100644 --- a/mesonbuild/cmake/interpreter.py +++ b/mesonbuild/cmake/interpreter.py @@ -534,7 +534,7 @@ def _all_source_suffixes(self) -> 'ImmutableListProtocol[str]': @lru_cache(maxsize=None) def _all_lang_stds(self, lang: str) -> 'ImmutableListProtocol[str]': try: - opt = self.env.coredata.optstore.get_value_object(OptionKey(f'{lang}_std', machine=MachineChoice.BUILD)) + opt = self.env.coredata.optstore.get_value_object(OptionKey.factory(f'{lang}_std', machine=MachineChoice.BUILD)) assert isinstance(opt, (options.UserStdOption, options.UserComboOption)), 'for mypy' return opt.choices or [] except KeyError: @@ -828,7 +828,7 @@ def configure(self, extra_cmake_options: T.List[str]) -> CMakeExecutor: cmake_args += extra_cmake_options if not any(arg.startswith('-DCMAKE_BUILD_TYPE=') for arg in cmake_args): # Our build type is favored over any CMAKE_BUILD_TYPE environment variable - buildtype = T.cast('str', self.env.coredata.get_option(OptionKey('buildtype'))) + buildtype = T.cast('str', self.env.coredata.get_option(OptionKey.factory('buildtype'))) if buildtype in BUILDTYPE_MAP: cmake_args += [f'-DCMAKE_BUILD_TYPE={BUILDTYPE_MAP[buildtype]}'] trace_args = self.trace.trace_args() diff --git a/mesonbuild/compilers/asm.py b/mesonbuild/compilers/asm.py index d358ca992a17..aea91c63e40f 100644 --- a/mesonbuild/compilers/asm.py +++ b/mesonbuild/compilers/asm.py @@ -46,7 +46,7 @@ def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, super().__init__(ccache, exelist, version, for_machine, info, linker, full_version, is_cross) self.links_with_msvc = False if 'link' in self.linker.id: - self.base_options.add(OptionKey('b_vscrt')) + self.base_options.add(OptionKey.factory('b_vscrt')) self.links_with_msvc = True def needs_static_linker(self) -> bool: diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py index 0f7ef172f5a6..c2acae594929 100644 --- a/mesonbuild/compilers/compilers.py +++ b/mesonbuild/compilers/compilers.py @@ -230,28 +230,28 @@ def init_option(self, name: OptionKey) -> options.UserOption[_T]: BASE_OPTIONS: T.Mapping[OptionKey, BaseOption] = { - OptionKey('b_pch'): BaseOption(options.UserBooleanOption, 'Use precompiled headers', True), - OptionKey('b_lto'): BaseOption(options.UserBooleanOption, 'Use link time optimization', False), - OptionKey('b_lto_threads'): BaseOption(options.UserIntegerOption, 'Use multiple threads for Link Time Optimization', 0), - OptionKey('b_lto_mode'): BaseOption(options.UserComboOption, 'Select between different LTO modes.', 'default', - choices=['default', 'thin']), - OptionKey('b_thinlto_cache'): BaseOption(options.UserBooleanOption, 'Use LLVM ThinLTO caching for faster incremental builds', False), - OptionKey('b_thinlto_cache_dir'): BaseOption(options.UserStringOption, 'Directory to store ThinLTO cache objects', ''), - OptionKey('b_sanitize'): BaseOption(options.UserComboOption, 'Code sanitizer to use', 'none', - choices=['none', 'address', 'thread', 'undefined', 'memory', 'leak', 'address,undefined']), - OptionKey('b_lundef'): BaseOption(options.UserBooleanOption, 'Use -Wl,--no-undefined when linking', True), - OptionKey('b_asneeded'): BaseOption(options.UserBooleanOption, 'Use -Wl,--as-needed when linking', True), - OptionKey('b_pgo'): BaseOption(options.UserComboOption, 'Use profile guided optimization', 'off', - choices=['off', 'generate', 'use']), - OptionKey('b_coverage'): BaseOption(options.UserBooleanOption, 'Enable coverage tracking.', False), - OptionKey('b_colorout'): BaseOption(options.UserComboOption, 'Use colored output', 'always', - choices=['auto', 'always', 'never']), - OptionKey('b_ndebug'): BaseOption(options.UserComboOption, 'Disable asserts', 'false', choices=['true', 'false', 'if-release']), - OptionKey('b_staticpic'): BaseOption(options.UserBooleanOption, 'Build static libraries as position independent', True), - OptionKey('b_pie'): BaseOption(options.UserBooleanOption, 'Build executables as position independent', False), - OptionKey('b_bitcode'): BaseOption(options.UserBooleanOption, 'Generate and embed bitcode (only macOS/iOS/tvOS)', False), - OptionKey('b_vscrt'): BaseOption(options.UserComboOption, 'VS run-time library type to use.', 'from_buildtype', - choices=MSCRT_VALS + ['from_buildtype', 'static_from_buildtype']), + OptionKey.factory('b_pch'): BaseOption(options.UserBooleanOption, 'Use precompiled headers', True), + OptionKey.factory('b_lto'): BaseOption(options.UserBooleanOption, 'Use link time optimization', False), + OptionKey.factory('b_lto_threads'): BaseOption(options.UserIntegerOption, 'Use multiple threads for Link Time Optimization', 0), + OptionKey.factory('b_lto_mode'): BaseOption(options.UserComboOption, 'Select between different LTO modes.', 'default', + choices=['default', 'thin']), + OptionKey.factory('b_thinlto_cache'): BaseOption(options.UserBooleanOption, 'Use LLVM ThinLTO caching for faster incremental builds', False), + OptionKey.factory('b_thinlto_cache_dir'): BaseOption(options.UserStringOption, 'Directory to store ThinLTO cache objects', ''), + OptionKey.factory('b_sanitize'): BaseOption(options.UserComboOption, 'Code sanitizer to use', 'none', + choices=['none', 'address', 'thread', 'undefined', 'memory', 'leak', 'address,undefined']), + OptionKey.factory('b_lundef'): BaseOption(options.UserBooleanOption, 'Use -Wl,--no-undefined when linking', True), + OptionKey.factory('b_asneeded'): BaseOption(options.UserBooleanOption, 'Use -Wl,--as-needed when linking', True), + OptionKey.factory('b_pgo'): BaseOption(options.UserComboOption, 'Use profile guided optimization', 'off', + choices=['off', 'generate', 'use']), + OptionKey.factory('b_coverage'): BaseOption(options.UserBooleanOption, 'Enable coverage tracking.', False), + OptionKey.factory('b_colorout'): BaseOption(options.UserComboOption, 'Use colored output', 'always', + choices=['auto', 'always', 'never']), + OptionKey.factory('b_ndebug'): BaseOption(options.UserComboOption, 'Disable asserts', 'false', choices=['true', 'false', 'if-release']), + OptionKey.factory('b_staticpic'): BaseOption(options.UserBooleanOption, 'Build static libraries as position independent', True), + OptionKey.factory('b_pie'): BaseOption(options.UserBooleanOption, 'Build executables as position independent', False), + OptionKey.factory('b_bitcode'): BaseOption(options.UserBooleanOption, 'Generate and embed bitcode (only macOS/iOS/tvOS)', False), + OptionKey.factory('b_vscrt'): BaseOption(options.UserComboOption, 'VS run-time library type to use.', 'from_buildtype', + choices=MSCRT_VALS + ['from_buildtype', 'static_from_buildtype']), } base_options = {key: base_opt.init_option(key) for key, base_opt in BASE_OPTIONS.items()} @@ -294,22 +294,22 @@ def are_asserts_disabled(options: KeyedOptionDictType) -> bool: def get_base_compile_args(options: 'KeyedOptionDictType', compiler: 'Compiler', env: 'Environment') -> T.List[str]: args: T.List[str] = [] try: - if options.get_value(OptionKey('b_lto')): + if options.get_value(OptionKey.factory('b_lto')): 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=get_option_value(options, OptionKey.factory('b_lto_threads'), 0), + mode=get_option_value(options, OptionKey.factory('b_lto_mode'), 'default'))) except (KeyError, AttributeError): pass try: - args += compiler.get_colorout_args(options.get_value(OptionKey('b_colorout'))) + args += compiler.get_colorout_args(options.get_value(OptionKey.factory('b_colorout'))) except (KeyError, AttributeError): pass try: - args += compiler.sanitizer_compile_args(options.get_value(OptionKey('b_sanitize'))) + args += compiler.sanitizer_compile_args(options.get_value(OptionKey.factory('b_sanitize'))) except (KeyError, AttributeError): pass try: - pgo_val = options.get_value(OptionKey('b_pgo')) + pgo_val = options.get_value(OptionKey.factory('b_pgo')) if pgo_val == 'generate': args.extend(compiler.get_profile_generate_args()) elif pgo_val == 'use': @@ -317,7 +317,7 @@ def get_base_compile_args(options: 'KeyedOptionDictType', compiler: 'Compiler', except (KeyError, AttributeError): pass try: - if options.get_value(OptionKey('b_coverage')): + if options.get_value(OptionKey.factory('b_coverage')): args += compiler.get_coverage_args() except (KeyError, AttributeError): pass @@ -326,12 +326,12 @@ def get_base_compile_args(options: 'KeyedOptionDictType', compiler: 'Compiler', except (KeyError, AttributeError): pass # This does not need a try...except - if option_enabled(compiler.base_options, options, OptionKey('b_bitcode')): + if option_enabled(compiler.base_options, options, OptionKey.factory('b_bitcode')): args.append('-fembed-bitcode') try: try: - crt_val = options.get_value(OptionKey('b_vscrt')) - buildtype = options.get_value(OptionKey('buildtype')) + crt_val = options.get_value(OptionKey.factory('b_vscrt')) + buildtype = options.get_value(OptionKey.factory('buildtype')) args += compiler.get_crt_compile_args(crt_val, buildtype) except AttributeError: pass @@ -348,13 +348,13 @@ def get_base_link_args(options: 'KeyedOptionDictType', linker: 'Compiler', 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'), '') + if get_option_value(options, OptionKey.factory('b_thinlto_cache'), False): + thinlto_cache_dir = get_option_value(options, OptionKey.factory('b_thinlto_cache_dir'), '') if thinlto_cache_dir == '': thinlto_cache_dir = os.path.join(build_dir, 'meson-private', 'thinlto-cache') 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=get_option_value(options, OptionKey.factory('b_lto_threads'), 0), + mode=get_option_value(options, OptionKey.factory('b_lto_mode'), 'default'), thinlto_cache_dir=thinlto_cache_dir)) except (KeyError, AttributeError): pass @@ -376,8 +376,8 @@ def get_base_link_args(options: 'KeyedOptionDictType', linker: 'Compiler', 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, options, OptionKey.factory('b_asneeded')) + bitcode = option_enabled(linker.base_options, options, OptionKey.factory('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: @@ -391,15 +391,15 @@ def get_base_link_args(options: 'KeyedOptionDictType', linker: 'Compiler', if not bitcode: args.extend(linker.headerpad_args()) if (not is_shared_module and - option_enabled(linker.base_options, options, OptionKey('b_lundef'))): + option_enabled(linker.base_options, options, OptionKey.factory('b_lundef'))): args.extend(linker.no_undefined_link_args()) else: args.extend(linker.get_allow_undefined_link_args()) try: try: - crt_val = options.get_value(OptionKey('b_vscrt')) - buildtype = options.get_value(OptionKey('buildtype')) + crt_val = options.get_value(OptionKey.factory('b_vscrt')) + buildtype = options.get_value(OptionKey.factory('buildtype')) args += linker.get_crt_link_args(crt_val, buildtype) except AttributeError: pass @@ -1356,7 +1356,7 @@ def get_preprocessor(self) -> Compiler: raise EnvironmentException(f'{self.get_id()} does not support preprocessor') def form_compileropt_key(self, basename: str) -> OptionKey: - return OptionKey(f'{self.language}_{basename}', machine=self.for_machine) + return OptionKey.factory(f'{self.language}_{basename}', machine=self.for_machine) def _update_language_stds(self, opts: MutableKeyedOptionDictType, value: T.List[str]) -> None: key = self.form_compileropt_key('std') @@ -1373,7 +1373,7 @@ def get_global_options(lang: str, env: 'Environment') -> dict[OptionKey, options.UserOption[T.Any]]: """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) + argkey = OptionKey.factory(f'{lang}_args', machine=for_machine) largkey = argkey.evolve(f'{lang}_link_args') envkey = argkey.evolve(f'{lang}_env_args') diff --git a/mesonbuild/compilers/cuda.py b/mesonbuild/compilers/cuda.py index 6a49d95aeb6d..e902f483f6bb 100644 --- a/mesonbuild/compilers/cuda.py +++ b/mesonbuild/compilers/cuda.py @@ -671,7 +671,7 @@ def _to_host_compiler_options(self, master_options: 'KeyedOptionDictType') -> 'K # We must strip the -std option from the host compiler option set, as NVCC has # its own -std flag that may not agree with the host compiler's. host_options = {key: master_options.get(key, opt) for key, opt in self.host_compiler.get_options().items()} - std_key = OptionKey(f'{self.host_compiler.language}_std', machine=self.for_machine) + std_key = OptionKey.factory(f'{self.host_compiler.language}_std', machine=self.for_machine) overrides = {std_key: 'none'} # To shut up mypy. return coredata.OptionsView(host_options, overrides=overrides) diff --git a/mesonbuild/compilers/d.py b/mesonbuild/compilers/d.py index 8ee6ebf651c5..3a02948bb5ae 100644 --- a/mesonbuild/compilers/d.py +++ b/mesonbuild/compilers/d.py @@ -665,7 +665,7 @@ def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoic self.supported_warn_args(gnu_common_warning_args))} self.base_options = { - OptionKey(o) for o in [ + OptionKey.factory(o) for o in [ 'b_colorout', 'b_sanitize', 'b_staticpic', 'b_vscrt', 'b_coverage', 'b_pgo', 'b_ndebug']} @@ -739,7 +739,7 @@ def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoic linker=linker, full_version=full_version, is_cross=is_cross) DmdLikeCompilerMixin.__init__(self, dmd_frontend_version=find_ldc_dmd_frontend_version(version_output)) - self.base_options = {OptionKey(o) for o in ['b_coverage', 'b_colorout', 'b_vscrt', 'b_ndebug']} + self.base_options = {OptionKey.factory(o) for o in ['b_coverage', 'b_colorout', 'b_vscrt', 'b_ndebug']} def get_colorout_args(self, colortype: str) -> T.List[str]: if colortype == 'always': @@ -802,7 +802,7 @@ def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoic linker=linker, full_version=full_version, is_cross=is_cross) DmdLikeCompilerMixin.__init__(self, version) - self.base_options = {OptionKey(o) for o in ['b_coverage', 'b_colorout', 'b_vscrt', 'b_ndebug']} + self.base_options = {OptionKey.factory(o) for o in ['b_coverage', 'b_colorout', 'b_vscrt', 'b_ndebug']} def get_colorout_args(self, colortype: str) -> T.List[str]: if colortype == 'always': diff --git a/mesonbuild/compilers/detect.py b/mesonbuild/compilers/detect.py index d4ad4badeefd..c1dfdef704ae 100644 --- a/mesonbuild/compilers/detect.py +++ b/mesonbuild/compilers/detect.py @@ -669,7 +669,7 @@ def detect_cuda_compiler(env: 'Environment', for_machine: MachineChoice) -> Comp cpp_compiler = detect_cpp_compiler(env, for_machine) cls = CudaCompiler env.coredata.add_lang_args(cls.language, cls, for_machine, env) - key = OptionKey('cuda_link_args', machine=for_machine) + key = OptionKey.factory('cuda_link_args', machine=for_machine) if key in env.options: # To fix LDFLAGS issue val = env.options[key] diff --git a/mesonbuild/compilers/mixins/arm.py b/mesonbuild/compilers/mixins/arm.py index a70ec4ff95fb..93ef3ac9a441 100644 --- a/mesonbuild/compilers/mixins/arm.py +++ b/mesonbuild/compilers/mixins/arm.py @@ -126,7 +126,7 @@ def __init__(self) -> None: if not mesonlib.version_compare(self.version, '==' + self.linker.version): raise mesonlib.EnvironmentException('armlink version does not match with compiler version') self.base_options = { - OptionKey(o) for o in + OptionKey.factory(o) for o in ['b_pch', 'b_lto', 'b_pgo', 'b_sanitize', 'b_coverage', 'b_ndebug', 'b_staticpic', 'b_colorout']} # Assembly diff --git a/mesonbuild/compilers/mixins/clang.py b/mesonbuild/compilers/mixins/clang.py index 867b58680209..e5f213ec6443 100644 --- a/mesonbuild/compilers/mixins/clang.py +++ b/mesonbuild/compilers/mixins/clang.py @@ -58,15 +58,15 @@ def __init__(self, defines: T.Optional[T.Dict[str, str]]): super().__init__() self.defines = defines or {} self.base_options.update( - {OptionKey('b_colorout'), OptionKey('b_lto_threads'), OptionKey('b_lto_mode'), OptionKey('b_thinlto_cache'), - OptionKey('b_thinlto_cache_dir')}) + {OptionKey.factory('b_colorout'), OptionKey.factory('b_lto_threads'), OptionKey.factory('b_lto_mode'), OptionKey.factory('b_thinlto_cache'), + OptionKey.factory('b_thinlto_cache_dir')}) # TODO: this really should be part of the linker base_options, but # linkers don't have base_options. if isinstance(self.linker, AppleDynamicLinker): - self.base_options.add(OptionKey('b_bitcode')) + self.base_options.add(OptionKey.factory('b_bitcode')) elif isinstance(self.linker, MSVCDynamicLinker): - self.base_options.add(OptionKey('b_vscrt')) + self.base_options.add(OptionKey.factory('b_vscrt')) # All Clang backends can also do LLVM IR self.can_compile_suffixes.add('ll') diff --git a/mesonbuild/compilers/mixins/elbrus.py b/mesonbuild/compilers/mixins/elbrus.py index 5818d8dee0b5..73f45d385644 100644 --- a/mesonbuild/compilers/mixins/elbrus.py +++ b/mesonbuild/compilers/mixins/elbrus.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 -# Copyright © 2023-2024 Intel Corporation +# Copyright © 2023-2025 Intel Corporation from __future__ import annotations @@ -29,7 +29,7 @@ class ElbrusCompiler(GnuLikeCompiler): def __init__(self) -> None: super().__init__() - self.base_options = {OptionKey(o) for o in ['b_pgo', 'b_coverage', 'b_ndebug', 'b_staticpic', 'b_lundef', 'b_asneeded']} + self.base_options = {OptionKey.factory(o) for o in ['b_pgo', 'b_coverage', 'b_ndebug', 'b_staticpic', 'b_lundef', 'b_asneeded']} default_warn_args = ['-Wall'] self.warn_args = {'0': [], '1': default_warn_args, @@ -85,7 +85,7 @@ def get_pch_suffix(self) -> str: def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: args: T.List[str] = [] - std = options.get_value(OptionKey(f'{self.language}_std', machine=self.for_machine)) + std = options.get_value(OptionKey.factory(f'{self.language}_std', machine=self.for_machine)) if std != 'none': args.append('-std=' + std) return args diff --git a/mesonbuild/compilers/mixins/emscripten.py b/mesonbuild/compilers/mixins/emscripten.py index 24ffceda63ed..52366b5096f9 100644 --- a/mesonbuild/compilers/mixins/emscripten.py +++ b/mesonbuild/compilers/mixins/emscripten.py @@ -51,7 +51,7 @@ def _get_compile_output(self, dirname: str, mode: CompileCheckMode) -> str: def thread_link_flags(self, env: 'Environment') -> T.List[str]: args = ['-pthread'] - count: int = env.coredata.optstore.get_value(OptionKey(f'{self.language}_thread_count', machine=self.for_machine)) + count: int = env.coredata.optstore.get_value(OptionKey.factory(f'{self.language}_thread_count', machine=self.for_machine)) if count: args.append(f'-sPTHREAD_POOL_SIZE={count}') return args @@ -59,7 +59,7 @@ def thread_link_flags(self, env: 'Environment') -> T.List[str]: def get_options(self) -> coredata.MutableKeyedOptionDictType: opts = super().get_options() - key = OptionKey(f'{self.language}_thread_count', machine=self.for_machine) + key = OptionKey.factory(f'{self.language}_thread_count', machine=self.for_machine) opts[key] = options.UserIntegerOption( self.make_option_name(key), 'Number of threads to use in web assembly, set to 0 to disable', diff --git a/mesonbuild/compilers/mixins/gnu.py b/mesonbuild/compilers/mixins/gnu.py index 4dc344519a08..c990521840e5 100644 --- a/mesonbuild/compilers/mixins/gnu.py +++ b/mesonbuild/compilers/mixins/gnu.py @@ -359,14 +359,14 @@ class GnuLikeCompiler(Compiler, metaclass=abc.ABCMeta): def __init__(self) -> None: self.base_options = { - OptionKey(o) for o in ['b_pch', 'b_lto', 'b_pgo', 'b_coverage', - 'b_ndebug', 'b_staticpic', 'b_pie']} + OptionKey.factory(o) for o in ['b_pch', 'b_lto', 'b_pgo', 'b_coverage', + 'b_ndebug', 'b_staticpic', 'b_pie']} if not (self.info.is_windows() or self.info.is_cygwin() or self.info.is_openbsd()): - self.base_options.add(OptionKey('b_lundef')) + self.base_options.add(OptionKey.factory('b_lundef')) if not self.info.is_windows() or self.info.is_cygwin(): - self.base_options.add(OptionKey('b_asneeded')) + self.base_options.add(OptionKey.factory('b_asneeded')) if not self.info.is_hurd(): - self.base_options.add(OptionKey('b_sanitize')) + self.base_options.add(OptionKey.factory('b_sanitize')) # All GCC-like backends can do assembly self.can_compile_suffixes.add('s') self.can_compile_suffixes.add('sx') @@ -547,7 +547,7 @@ class GnuCompiler(GnuLikeCompiler): def __init__(self, defines: T.Optional[T.Dict[str, str]]): super().__init__() self.defines = defines or {} - self.base_options.update({OptionKey('b_colorout'), OptionKey('b_lto_threads')}) + self.base_options.update({OptionKey.factory('b_colorout'), OptionKey.factory('b_lto_threads')}) self._has_color_support = mesonlib.version_compare(self.version, '>=4.9.0') self._has_wpedantic_support = mesonlib.version_compare(self.version, '>=4.8.0') self._has_lto_auto_support = mesonlib.version_compare(self.version, '>=10.0') diff --git a/mesonbuild/compilers/mixins/intel.py b/mesonbuild/compilers/mixins/intel.py index 32cbdf010539..0b46fc2daed9 100644 --- a/mesonbuild/compilers/mixins/intel.py +++ b/mesonbuild/compilers/mixins/intel.py @@ -67,7 +67,7 @@ def __init__(self) -> None: # It does have IPO, which serves much the same purpose as LOT, but # there is an unfortunate rule for using IPO (you can't control the # name of the output file) which break assumptions meson makes - self.base_options = {OptionKey(o) for o in [ + self.base_options = {OptionKey.factory(o) for o in [ 'b_pch', 'b_lundef', 'b_asneeded', 'b_pgo', 'b_coverage', 'b_ndebug', 'b_staticpic', 'b_pie']} self.lang_header = 'none' diff --git a/mesonbuild/compilers/mixins/metrowerks.py b/mesonbuild/compilers/mixins/metrowerks.py index 60982212e241..e67d2c01baeb 100644 --- a/mesonbuild/compilers/mixins/metrowerks.py +++ b/mesonbuild/compilers/mixins/metrowerks.py @@ -177,7 +177,7 @@ def __init__(self) -> None: raise EnvironmentException(f'{id} supports only cross-compilation.') self.base_options = { - OptionKey(o) for o in ['b_pch', 'b_ndebug']} + OptionKey.factory(o) for o in ['b_pch', 'b_ndebug']} self.warn_args: T.Dict[str, T.List[str]] = { '0': ['-warnings', 'off'], diff --git a/mesonbuild/compilers/mixins/pgi.py b/mesonbuild/compilers/mixins/pgi.py index 50335c895cc5..f9fa476fd7d5 100644 --- a/mesonbuild/compilers/mixins/pgi.py +++ b/mesonbuild/compilers/mixins/pgi.py @@ -28,7 +28,7 @@ class PGICompiler(Compiler): id = 'pgi' def __init__(self) -> None: - self.base_options = {OptionKey('b_pch')} + self.base_options = {OptionKey.factory('b_pch')} default_warn_args = ['-Minform=inform'] self.warn_args: T.Dict[str, T.List[str]] = { diff --git a/mesonbuild/compilers/mixins/tasking.py b/mesonbuild/compilers/mixins/tasking.py index 082cff073908..369e8b1e11fd 100644 --- a/mesonbuild/compilers/mixins/tasking.py +++ b/mesonbuild/compilers/mixins/tasking.py @@ -55,7 +55,7 @@ def __init__(self) -> None: raise EnvironmentException(f'{id} supports only cross-compilation.') self.base_options = { - OptionKey(o) for o in [ + OptionKey.factory(o) for o in [ 'b_lto', 'b_staticpic', 'b_ndebug' diff --git a/mesonbuild/compilers/mixins/visualstudio.py b/mesonbuild/compilers/mixins/visualstudio.py index 30127eca479c..2b8aea9f072d 100644 --- a/mesonbuild/compilers/mixins/visualstudio.py +++ b/mesonbuild/compilers/mixins/visualstudio.py @@ -112,7 +112,7 @@ class VisualStudioLikeCompiler(Compiler, metaclass=abc.ABCMeta): INVOKES_LINKER = False def __init__(self, target: str): - self.base_options = {OptionKey(o) for o in ['b_pch', 'b_ndebug', 'b_vscrt']} # FIXME add lto, pgo and the like + self.base_options = {OptionKey.factory(o) for o in ['b_pch', 'b_ndebug', 'b_vscrt']} # FIXME add lto, pgo and the like self.target = target self.is_64 = ('x64' in target) or ('x86_64' in target) # do some canonicalization of target machine @@ -127,7 +127,7 @@ def __init__(self, target: str): else: self.machine = target if mesonlib.version_compare(self.version, '>=19.28.29910'): # VS 16.9.0 includes cl 19.28.29910 - self.base_options.add(OptionKey('b_sanitize')) + self.base_options.add(OptionKey.factory('b_sanitize')) assert self.linker is not None self.linker.machine = self.machine @@ -447,8 +447,8 @@ def __init__(self, target: str): super().__init__(target) self.base_options.update( - {OptionKey('b_lto_threads'), OptionKey('b_lto'), OptionKey('b_lto_mode'), OptionKey('b_thinlto_cache'), - OptionKey('b_thinlto_cache_dir')}) + {OptionKey.factory('b_lto_threads'), OptionKey.factory('b_lto'), OptionKey.factory('b_lto_mode'), OptionKey.factory('b_thinlto_cache'), + OptionKey.factory('b_thinlto_cache_dir')}) # Assembly self.can_compile_suffixes.add('s') diff --git a/mesonbuild/compilers/objc.py b/mesonbuild/compilers/objc.py index 262a4c484f2e..97d4e0931bc5 100644 --- a/mesonbuild/compilers/objc.py +++ b/mesonbuild/compilers/objc.py @@ -53,7 +53,7 @@ def sanity_check(self, work_dir: str, environment: 'Environment') -> None: def form_compileropt_key(self, basename: str) -> OptionKey: if basename == 'std': - return OptionKey(f'c_{basename}', machine=self.for_machine) + return OptionKey.factory(f'c_{basename}', machine=self.for_machine) return super().form_compileropt_key(basename) @@ -101,7 +101,7 @@ def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_ def form_compileropt_key(self, basename: str) -> OptionKey: if basename == 'std': - return OptionKey('c_std', machine=self.for_machine) + return OptionKey.factory('c_std', machine=self.for_machine) return super().form_compileropt_key(basename) def make_option_name(self, key: OptionKey) -> str: diff --git a/mesonbuild/compilers/objcpp.py b/mesonbuild/compilers/objcpp.py index 104d0cb82ebe..aa24828ea8cf 100644 --- a/mesonbuild/compilers/objcpp.py +++ b/mesonbuild/compilers/objcpp.py @@ -37,7 +37,7 @@ def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_ def form_compileropt_key(self, basename: str) -> OptionKey: if basename == 'std': - return OptionKey('cpp_std', machine=self.for_machine) + return OptionKey.factory('cpp_std', machine=self.for_machine) return super().form_compileropt_key(basename) def make_option_name(self, key: OptionKey) -> str: diff --git a/mesonbuild/compilers/rust.py b/mesonbuild/compilers/rust.py index aacdc07d7ccc..1b4aae44b23a 100644 --- a/mesonbuild/compilers/rust.py +++ b/mesonbuild/compilers/rust.py @@ -95,9 +95,9 @@ def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoic is_cross=is_cross, full_version=full_version, linker=linker) self.rustup_run_and_args: T.Optional[T.Tuple[T.List[str], T.List[str]]] = get_rustup_run_and_args(exelist) - self.base_options.update({OptionKey(o) for o in ['b_colorout', 'b_ndebug']}) + self.base_options.update({OptionKey.factory(o) for o in ['b_colorout', 'b_ndebug']}) if 'link' in self.linker.id: - self.base_options.add(OptionKey('b_vscrt')) + self.base_options.add(OptionKey.factory('b_vscrt')) self.native_static_libs: T.List[str] = [] def needs_static_linker(self) -> bool: diff --git a/mesonbuild/compilers/vala.py b/mesonbuild/compilers/vala.py index 35c7a682e013..6cf70b40bcde 100644 --- a/mesonbuild/compilers/vala.py +++ b/mesonbuild/compilers/vala.py @@ -29,7 +29,7 @@ def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoic is_cross: bool, info: 'MachineInfo'): super().__init__([], exelist, version, for_machine, info, is_cross=is_cross) self.version = version - self.base_options = {OptionKey('b_colorout')} + self.base_options = {OptionKey.factory('b_colorout')} self.force_link = False self._has_color_support = version_compare(self.version, '>=0.37.1') diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index fcf93a7e665b..21bed0468aee 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -149,8 +149,8 @@ class DependencyCache: def __init__(self, builtins: 'KeyedOptionDictType', for_machine: MachineChoice): self.__cache: T.MutableMapping[TV_DepID, DependencySubCache] = OrderedDict() self.__builtins = builtins - self.__pkg_conf_key = OptionKey('pkg_config_path', machine=for_machine) - self.__cmake_key = OptionKey('cmake_prefix_path', machine=for_machine) + self.__pkg_conf_key = OptionKey.factory('pkg_config_path', machine=for_machine) + self.__cmake_key = OptionKey.factory('cmake_prefix_path', machine=for_machine) def __calculate_subkey(self, type_: DependencyCacheType) -> T.Tuple[str, ...]: data: T.Dict[DependencyCacheType, T.List[str]] = { @@ -353,7 +353,7 @@ def builtin_options_libdir_cross_fixup(self) -> None: # getting the "system default" is always wrong on multiarch # platforms as it gets a value like lib/x86_64-linux-gnu. if self.cross_files: - options.BUILTIN_OPTIONS[OptionKey('libdir')].default = 'lib' + options.BUILTIN_OPTIONS[OptionKey.factory('libdir')].default = 'lib' def sanitize_prefix(self, prefix: str) -> str: prefix = os.path.expanduser(prefix) @@ -580,12 +580,12 @@ def is_per_machine_option(self, optname: OptionKey) -> bool: def get_external_args(self, for_machine: MachineChoice, lang: str) -> T.List[str]: # mypy cannot analyze type of OptionKey - key = OptionKey(f'{lang}_args', machine=for_machine) + key = OptionKey.factory(f'{lang}_args', machine=for_machine) return T.cast('T.List[str]', self.optstore.get_value(key)) def get_external_link_args(self, for_machine: MachineChoice, lang: str) -> T.List[str]: # mypy cannot analyze type of OptionKey - key = OptionKey(f'{lang}_link_args', machine=for_machine) + key = OptionKey.factory(f'{lang}_link_args', machine=for_machine) return T.cast('T.List[str]', self.optstore.get_value(key)) def update_project_options(self, project_options: 'MutableKeyedOptionDictType', subproject: SubProject) -> None: @@ -642,7 +642,7 @@ def set_options(self, opts_to_set: T.Dict[OptionKey, T.Any], subproject: str = ' if not self.is_cross_build(): opts_to_set = {k: v for k, v in opts_to_set.items() if k.machine is not MachineChoice.BUILD} # Set prefix first because it's needed to sanitize other options - pfk = OptionKey('prefix') + pfk = OptionKey.factory('prefix') if pfk in opts_to_set: prefix = self.sanitize_prefix(opts_to_set[pfk]) dirty |= self.optstore.set_value('prefix', prefix) @@ -778,7 +778,7 @@ def process_compiler_options(self, lang: str, comp: Compiler, env: Environment, self.emit_base_options_warnings(enabled_opts) def emit_base_options_warnings(self, enabled_opts: T.List[OptionKey]) -> None: - if OptionKey('b_bitcode') in enabled_opts: + if OptionKey.factory('b_bitcode') in enabled_opts: mlog.warning('Base option \'b_bitcode\' is enabled, which is incompatible with many linker options. Incompatible options such as \'b_asneeded\' have been disabled.', fatal=False) mlog.warning('Please see https://mesonbuild.com/Builtin-options.html#Notes_about_Apple_Bitcode_support for more details.', fatal=False) @@ -957,12 +957,12 @@ def __getitem__(self, key: OptionKey) -> options.UserOption: def get_value(self, key: T.Union[str, OptionKey]): if isinstance(key, str): - key = OptionKey(key) + key = OptionKey.factory(key) return self[key].value def set_value(self, key: T.Union[str, OptionKey], value: ElementaryOptionValues): if isinstance(key, str): - key = OptionKey(key) + key = OptionKey.factory(key) self.overrides[key] = value def __iter__(self) -> T.Iterator[OptionKey]: diff --git a/mesonbuild/dependencies/__init__.py b/mesonbuild/dependencies/__init__.py index 95e606975a5e..36dc5b239785 100644 --- a/mesonbuild/dependencies/__init__.py +++ b/mesonbuild/dependencies/__init__.py @@ -114,7 +114,7 @@ def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T. return get_option = environment.coredata.get_option - static_opt = kwargs.get('static', get_option(Mesonlib.OptionKey('prefer_static')) + static_opt = kwargs.get('static', get_option(Mesonlib.OptionKey.factory('prefer_static')) static = Mesonlib.LibType.STATIC if static_opt else Mesonlib.LibType.SHARED lib = self.clib_compiler.find_library( 'foo', environment, [os.path.join(root, 'lib')], libtype=static) diff --git a/mesonbuild/dependencies/base.py b/mesonbuild/dependencies/base.py index af370955770e..23f28a0921a0 100644 --- a/mesonbuild/dependencies/base.py +++ b/mesonbuild/dependencies/base.py @@ -1,6 +1,6 @@ # SPDX-License-Identifier: Apache-2.0 # Copyright 2013-2018 The Meson development team -# Copyright © 2024 Intel Corporation +# Copyright © 2024-2025 Intel Corporation # This file contains the detection logic for external dependencies. # Custom logic for several other packages are in separate files. @@ -403,7 +403,7 @@ def __init__(self, type_name: DependencyTypeName, environment: 'Environment', kw self.version_reqs: T.Optional[T.List[str]] = version_reqs self.required = kwargs.get('required', True) self.silent = kwargs.get('silent', False) - self.static = kwargs.get('static', self.env.coredata.get_option(OptionKey('prefer_static'))) + self.static = kwargs.get('static', self.env.coredata.get_option(OptionKey.factory('prefer_static'))) self.libtype = LibType.STATIC if self.static else LibType.PREFER_SHARED if not isinstance(self.static, bool): raise DependencyException('Static keyword must be boolean') diff --git a/mesonbuild/dependencies/boost.py b/mesonbuild/dependencies/boost.py index 870c0b16b2c3..ecbee6b0b5c3 100644 --- a/mesonbuild/dependencies/boost.py +++ b/mesonbuild/dependencies/boost.py @@ -341,7 +341,7 @@ def get_link_args(self) -> T.List[str]: class BoostDependency(SystemDependency): def __init__(self, environment: Environment, kwargs: T.Dict[str, T.Any]) -> None: super().__init__('boost', environment, kwargs, language='cpp') - buildtype = environment.coredata.get_option(OptionKey('buildtype')) + buildtype = environment.coredata.get_option(OptionKey.factory('buildtype')) assert isinstance(buildtype, str) self.debug = buildtype.startswith('debug') self.multithreading = kwargs.get('threading', 'multi') == 'multi' diff --git a/mesonbuild/dependencies/dub.py b/mesonbuild/dependencies/dub.py index 009e4f46ffbb..5ac3576fc0fc 100644 --- a/mesonbuild/dependencies/dub.py +++ b/mesonbuild/dependencies/dub.py @@ -126,7 +126,7 @@ def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T. dub_arch = self.compiler.arch # we need to know the build type as well - dub_buildtype = str(environment.coredata.get_option(OptionKey('buildtype'))) + dub_buildtype = str(environment.coredata.get_option(OptionKey.factory('buildtype'))) # MESON types: choices=['plain', 'debug', 'debugoptimized', 'release', 'minsize', 'custom'])), # DUB types: debug (default), plain, release, release-debug, release-nobounds, unittest, profile, profile-gc, # docs, ddox, cov, unittest-cov, syntax and custom diff --git a/mesonbuild/dependencies/misc.py b/mesonbuild/dependencies/misc.py index 6a2a73f2f0e8..3ca58089048b 100644 --- a/mesonbuild/dependencies/misc.py +++ b/mesonbuild/dependencies/misc.py @@ -572,7 +572,7 @@ def shaderc_factory(env: 'Environment', shared_libs = ['shaderc'] static_libs = ['shaderc_combined', 'shaderc_static'] - if kwargs.get('static', env.coredata.get_option(OptionKey('prefer_static'))): + if kwargs.get('static', env.coredata.get_option(OptionKey.factory('prefer_static'))): c = [functools.partial(PkgConfigDependency, name, env, kwargs) for name in static_libs + shared_libs] else: diff --git a/mesonbuild/dependencies/pkgconfig.py b/mesonbuild/dependencies/pkgconfig.py index 447b69ea070f..d9d1b03daa8b 100644 --- a/mesonbuild/dependencies/pkgconfig.py +++ b/mesonbuild/dependencies/pkgconfig.py @@ -255,7 +255,7 @@ def _check_pkgconfig(self, pkgbin: ExternalProgram) -> T.Optional[str]: def _get_env(self, uninstalled: bool = False) -> EnvironmentVariables: env = EnvironmentVariables() - key = OptionKey('pkg_config_path', machine=self.for_machine) + key = OptionKey.factory('pkg_config_path', machine=self.for_machine) extra_paths: T.List[str] = self.env.coredata.optstore.get_value(key)[:] if uninstalled: bpath = self.env.get_build_dir() @@ -419,7 +419,7 @@ def _search_libs(self, libs_in: ImmutableListProtocol[str], raw_libs_in: Immutab # # Only prefix_libpaths are reordered here because there should not be # too many system_libpaths to cause library version issues. - pkg_config_path: T.List[str] = self.env.coredata.optstore.get_value(OptionKey('pkg_config_path', machine=self.for_machine)) + pkg_config_path: T.List[str] = self.env.coredata.optstore.get_value(OptionKey.factory('pkg_config_path', machine=self.for_machine)) pkg_config_path = self._convert_mingw_paths(pkg_config_path) prefix_libpaths = OrderedSet(sort_libpaths(list(prefix_libpaths), pkg_config_path)) system_libpaths: OrderedSet[str] = OrderedSet() diff --git a/mesonbuild/dependencies/python.py b/mesonbuild/dependencies/python.py index f7417717e175..e5ae19c0d7a9 100644 --- a/mesonbuild/dependencies/python.py +++ b/mesonbuild/dependencies/python.py @@ -244,13 +244,13 @@ def get_windows_link_args(self, limited_api: bool) -> T.Optional[T.List[str]]: # Python itself (except with pybind11, which has an ugly # hack to work around this) - so emit a warning to explain # the cause of the expected link error. - buildtype = self.env.coredata.get_option(OptionKey('buildtype')) + buildtype = self.env.coredata.get_option(OptionKey.factory('buildtype')) assert isinstance(buildtype, str) - debug = self.env.coredata.get_option(OptionKey('debug')) + debug = self.env.coredata.get_option(OptionKey.factory('debug')) # `debugoptimized` buildtype may not set debug=True currently, see gh-11645 is_debug_build = debug or buildtype == 'debug' vscrt_debug = False - if OptionKey('b_vscrt') in self.env.coredata.optstore: + if OptionKey.factory('b_vscrt') in self.env.coredata.optstore: vscrt = self.env.coredata.optstore.get_value('b_vscrt') if vscrt in {'mdd', 'mtd', 'from_buildtype', 'static_from_buildtype'}: vscrt_debug = True diff --git a/mesonbuild/dependencies/qt.py b/mesonbuild/dependencies/qt.py index 1b60deb8afd2..6e9ca6be4e14 100644 --- a/mesonbuild/dependencies/qt.py +++ b/mesonbuild/dependencies/qt.py @@ -1,6 +1,6 @@ # SPDX-License-Identifier: Apache-2.0 # Copyright 2013-2017 The Meson development team -# Copyright © 2021-2023 Intel Corporation +# Copyright © 2021-2025 Intel Corporation from __future__ import annotations @@ -297,8 +297,8 @@ def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]): # Use the buildtype by default, but look at the b_vscrt option if the # compiler supports it. - is_debug = self.env.coredata.get_option(OptionKey('buildtype')) == 'debug' - if OptionKey('b_vscrt') in self.env.coredata.optstore: + is_debug = self.env.coredata.get_option(OptionKey.factory('buildtype')) == 'debug' + if OptionKey.factory('b_vscrt') in self.env.coredata.optstore: if self.env.coredata.optstore.get_value('b_vscrt') in {'mdd', 'mtd'}: is_debug = True modules_lib_suffix = _get_modules_lib_suffix(self.version, self.env.machines[self.for_machine], is_debug) diff --git a/mesonbuild/dependencies/scalapack.py b/mesonbuild/dependencies/scalapack.py index e50338710dd3..3970348c1e6e 100644 --- a/mesonbuild/dependencies/scalapack.py +++ b/mesonbuild/dependencies/scalapack.py @@ -28,7 +28,7 @@ def scalapack_factory(env: 'Environment', for_machine: 'MachineChoice', candidates: T.List['DependencyGenerator'] = [] if DependencyMethods.PKGCONFIG in methods: - static_opt = kwargs.get('static', env.coredata.get_option(OptionKey('prefer_static'))) + static_opt = kwargs.get('static', env.coredata.get_option(OptionKey.factory('prefer_static'))) mkl = 'mkl-static-lp64-iomp' if static_opt else 'mkl-dynamic-lp64-iomp' candidates.append(functools.partial( MKLPkgConfigDependency, mkl, env, kwargs)) diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index c09d7e312ab7..8ad2498cf515 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -1,6 +1,6 @@ # SPDX-License-Identifier: Apache-2.0 # Copyright 2012-2020 The Meson development team -# Copyright © 2023 Intel Corporation +# Copyright © 2023-2025 Intel Corporation from __future__ import annotations @@ -670,9 +670,9 @@ def __init__(self, source_dir: str, build_dir: str, cmd_options: coredata.Shared # Warn if the user is using two different ways of setting build-type # options that override each other - bt = OptionKey('buildtype') - db = OptionKey('debug') - op = OptionKey('optimization') + bt = OptionKey.factory('buildtype') + db = OptionKey.factory('debug') + op = OptionKey.factory('optimization') if bt in self.options and (db in self.options or op in self.options): mlog.warning('Recommend using either -Dbuildtype or -Doptimization + -Ddebug. ' 'Using both is redundant since they override each other. ' @@ -779,11 +779,11 @@ def _set_default_options_from_env(self) -> None: if self.first_invocation: if keyname == 'ldflags': for lang in compilers.compilers.LANGUAGES_USING_LDFLAGS: - key = OptionKey(name=f'{lang}_link_args', machine=for_machine) + key = OptionKey.factory(name=f'{lang}_link_args', machine=for_machine) env_opts[key].extend(p_list) elif keyname == 'cppflags': for lang in compilers.compilers.LANGUAGES_USING_CPPFLAGS: - key = OptionKey(f'{lang}_env_args', machine=for_machine) + key = OptionKey.factory(f'{lang}_env_args', machine=for_machine) env_opts[key].extend(p_list) else: key = OptionKey.from_string(keyname).evolve(machine=for_machine) @@ -936,25 +936,25 @@ def get_static_lib_dir(self) -> str: return self.get_libdir() def get_prefix(self) -> str: - return self.coredata.get_option(OptionKey('prefix')) + return self.coredata.get_option(OptionKey.factory('prefix')) def get_libdir(self) -> str: - return self.coredata.get_option(OptionKey('libdir')) + return self.coredata.get_option(OptionKey.factory('libdir')) def get_libexecdir(self) -> str: - return self.coredata.get_option(OptionKey('libexecdir')) + return self.coredata.get_option(OptionKey.factory('libexecdir')) def get_bindir(self) -> str: - return self.coredata.get_option(OptionKey('bindir')) + return self.coredata.get_option(OptionKey.factory('bindir')) def get_includedir(self) -> str: - return self.coredata.get_option(OptionKey('includedir')) + return self.coredata.get_option(OptionKey.factory('includedir')) def get_mandir(self) -> str: - return self.coredata.get_option(OptionKey('mandir')) + return self.coredata.get_option(OptionKey.factory('mandir')) def get_datadir(self) -> str: - return self.coredata.get_option(OptionKey('datadir')) + return self.coredata.get_option(OptionKey.factory('datadir')) def get_compiler_system_lib_dirs(self, for_machine: MachineChoice) -> T.List[str]: for comp in self.coredata.compilers[for_machine].values(): diff --git a/mesonbuild/interpreter/compiler.py b/mesonbuild/interpreter/compiler.py index 6f52c0e07ecc..2e5334571d1b 100644 --- a/mesonbuild/interpreter/compiler.py +++ b/mesonbuild/interpreter/compiler.py @@ -1,6 +1,6 @@ # SPDX-License-Identifier: Apache-2.0 # Copyright 2012-2021 The Meson development team -# Copyright © 2021-2024 Intel Corporation +# Copyright © 2021-2025 Intel Corporation from __future__ import annotations import collections @@ -718,7 +718,7 @@ def find_library_method(self, args: T.Tuple[str], kwargs: 'FindLibraryKW') -> 'd search_dirs = extract_search_dirs(kwargs) - prefer_static = self.environment.coredata.get_option(OptionKey('prefer_static')) + prefer_static = self.environment.coredata.get_option(OptionKey.factory('prefer_static')) if kwargs['static'] is True: libtype = mesonlib.LibType.STATIC elif kwargs['static'] is False: diff --git a/mesonbuild/interpreter/dependencyfallbacks.py b/mesonbuild/interpreter/dependencyfallbacks.py index f7a1b99fe783..e873e3000473 100644 --- a/mesonbuild/interpreter/dependencyfallbacks.py +++ b/mesonbuild/interpreter/dependencyfallbacks.py @@ -1,6 +1,6 @@ # SPDX-License-Identifier: Apache-2.0 # Copyright 2021-2024 The Meson Developers -# Copyright © 2021-2024 Intel Corporation +# Copyright © 2021-2025 Intel Corporation from __future__ import annotations @@ -123,7 +123,7 @@ def _do_subproject(self, kwargs: TYPE_nkwargs, func_args: TYPE_nvar, func_kwargs if static is not None and 'default_library' not in default_options: default_library = 'static' if static else 'shared' mlog.log(f'Building fallback subproject with default_library={default_library}') - default_options[OptionKey('default_library')] = default_library + default_options[OptionKey.factory('default_library')] = default_library func_kwargs['default_options'] = default_options # Configure the subproject @@ -320,8 +320,8 @@ def lookup(self, kwargs: TYPE_nkwargs, force_fallback: bool = False) -> Dependen return self._notfound_dependency() # Check if usage of the subproject fallback is forced - wrap_mode = WrapMode.from_string(self.coredata.get_option(OptionKey('wrap_mode'))) - force_fallback_for = self.coredata.get_option(OptionKey('force_fallback_for')) + wrap_mode = WrapMode.from_string(self.coredata.get_option(OptionKey.factory('wrap_mode'))) + force_fallback_for = self.coredata.get_option(OptionKey.factory('force_fallback_for')) assert isinstance(force_fallback_for, list), 'for mypy' self.nofallback = wrap_mode == WrapMode.nofallback self.forcefallback = (force_fallback or diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index f6e1bfa0145d..b4b78edeff7a 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -1138,13 +1138,13 @@ def set_backend(self) -> None: return from ..backend import backends - if OptionKey('genvslite') in self.user_defined_options.cmd_line_options: + if OptionKey.factory('genvslite') in self.user_defined_options.cmd_line_options: # Use of the '--genvslite vsxxxx' option ultimately overrides any '--backend xxx' # option the user may specify. - backend_name = self.coredata.get_option(OptionKey('genvslite')) + backend_name = self.coredata.get_option(OptionKey.factory('genvslite')) self.backend = backends.get_genvslite_backend(backend_name, self.build, self) else: - backend_name = self.coredata.get_option(OptionKey('backend')) + backend_name = self.coredata.get_option(OptionKey.factory('backend')) self.backend = backends.get_backend_from_name(backend_name, self.build, self) if self.backend is None: @@ -1154,7 +1154,7 @@ def set_backend(self) -> None: mlog.log('Auto detected Visual Studio backend:', mlog.bold(self.backend.name)) if not self.environment.first_invocation: raise MesonBugException(f'Backend changed from {backend_name} to {self.backend.name}') - self.coredata.set_option(OptionKey('backend'), self.backend.name, first_invocation=True) + self.coredata.set_option(OptionKey.factory('backend'), self.backend.name, first_invocation=True) # Only init backend options on first invocation otherwise it would # override values previously set from command line. @@ -1303,7 +1303,7 @@ def func_project(self, node: mparser.FunctionNode, args: T.Tuple[str, T.List[str # Load wrap files from this (sub)project. subprojects_dir = os.path.join(self.subdir, spdirname) if not self.is_subproject(): - wrap_mode = WrapMode.from_string(self.coredata.get_option(OptionKey('wrap_mode'))) + wrap_mode = WrapMode.from_string(self.coredata.get_option(OptionKey.factory('wrap_mode'))) self.environment.wrap_resolver = wrap.Resolver(self.environment.get_source_dir(), subprojects_dir, self.subproject, wrap_mode) else: assert self.environment.wrap_resolver is not None, 'for mypy' @@ -1318,9 +1318,9 @@ def func_project(self, node: mparser.FunctionNode, args: T.Tuple[str, T.List[str # self.set_backend() otherwise it wouldn't be able to detect which # vs backend version we need. But after setting default_options in case # the project sets vs backend by default. - backend = self.coredata.get_option(OptionKey('backend')) + backend = self.coredata.get_option(OptionKey.factory('backend')) assert backend is None or isinstance(backend, str), 'for mypy' - vsenv = self.coredata.get_option(OptionKey('vsenv')) + vsenv = self.coredata.get_option(OptionKey.factory('vsenv')) assert isinstance(vsenv, bool), 'for mypy' force_vsenv = vsenv or backend.startswith('vs') mesonlib.setup_vsenv(force_vsenv) @@ -1716,7 +1716,7 @@ def program_lookup(self, args: T.List[mesonlib.FileOrString], for_machine: Machi return ExternalProgram('meson', self.environment.get_build_command(), silent=True) fallback = None - wrap_mode = WrapMode.from_string(self.coredata.get_option(OptionKey('wrap_mode'))) + wrap_mode = WrapMode.from_string(self.coredata.get_option(OptionKey.factory('wrap_mode'))) if wrap_mode != WrapMode.nofallback and self.environment.wrap_resolver: fallback = self.environment.wrap_resolver.find_program_provider(args) if fallback and wrap_mode == WrapMode.forcefallback: @@ -3108,9 +3108,9 @@ def print_extra_warnings(self) -> None: break def check_clang_asan_lundef(self) -> None: - if OptionKey('b_lundef') not in self.coredata.optstore: + if OptionKey.factory('b_lundef') not in self.coredata.optstore: return - if OptionKey('b_sanitize') not in self.coredata.optstore: + if OptionKey.factory('b_sanitize') not in self.coredata.optstore: return if (self.coredata.optstore.get_value('b_lundef') and self.coredata.optstore.get_value('b_sanitize') != 'none'): @@ -3281,9 +3281,9 @@ def add_target(self, name: str, tobj: build.Target) -> None: def build_both_libraries(self, node: mparser.BaseNode, args: T.Tuple[str, SourcesVarargsType], kwargs: kwtypes.Library) -> build.BothLibraries: shared_lib = self.build_target(node, args, kwargs, build.SharedLibrary) static_lib = self.build_target(node, args, kwargs, build.StaticLibrary) - preferred_library = self.coredata.get_option(OptionKey('default_both_libraries')) + preferred_library = self.coredata.get_option(OptionKey.factory('default_both_libraries')) if preferred_library == 'auto': - preferred_library = self.coredata.get_option(OptionKey('default_library')) + preferred_library = self.coredata.get_option(OptionKey.factory('default_library')) if preferred_library == 'both': preferred_library = 'shared' @@ -3324,7 +3324,7 @@ def build_both_libraries(self, node: mparser.BaseNode, args: T.Tuple[str, Source return build.BothLibraries(shared_lib, static_lib, preferred_library) def build_library(self, node: mparser.BaseNode, args: T.Tuple[str, SourcesVarargsType], kwargs: kwtypes.Library): - default_library = self.coredata.get_option(OptionKey('default_library', subproject=self.subproject)) + default_library = self.coredata.get_option(OptionKey.factory('default_library', subproject=self.subproject)) assert isinstance(default_library, str), 'for mypy' if default_library == 'shared': return self.build_target(node, args, T.cast('kwtypes.SharedLibrary', kwargs), build.SharedLibrary) diff --git a/mesonbuild/interpreter/mesonmain.py b/mesonbuild/interpreter/mesonmain.py index c82f933450c1..17f5fbf63cae 100644 --- a/mesonbuild/interpreter/mesonmain.py +++ b/mesonbuild/interpreter/mesonmain.py @@ -1,6 +1,6 @@ # SPDX-License-Identifier: Apache-2.0 # Copyright 2012-2021 The Meson development team -# Copyright © 2021-2024 Intel Corporation +# Copyright © 2021-2025 Intel Corporation from __future__ import annotations import copy @@ -311,7 +311,7 @@ def get_compiler_method(self, args: T.Tuple[str], kwargs: 'NativeKW') -> 'Compil @noPosargs @noKwargs def is_unity_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> bool: - optval = self.interpreter.environment.coredata.get_option(OptionKey('unity')) + optval = self.interpreter.environment.coredata.get_option(OptionKey.factory('unity')) return optval == 'on' or (optval == 'subprojects' and self.interpreter.is_subproject()) @noPosargs @@ -359,7 +359,7 @@ def override_dependency_method(self, args: T.Tuple[str, dependencies.Dependency] dep = copy.copy(dep) dep.name = name - optkey = OptionKey('default_library', subproject=self.interpreter.subproject) + optkey = OptionKey.factory('default_library', subproject=self.interpreter.subproject) default_library = self.interpreter.coredata.get_option(optkey) assert isinstance(default_library, str), 'for mypy' static = kwargs['static'] diff --git a/mesonbuild/mcompile.py b/mesonbuild/mcompile.py index 2f5708c86521..2a41a625c8ae 100644 --- a/mesonbuild/mcompile.py +++ b/mesonbuild/mcompile.py @@ -355,14 +355,14 @@ def run(options: 'argparse.Namespace') -> int: b = build.load(options.wd) cdata = b.environment.coredata - need_vsenv = T.cast('bool', cdata.get_option(OptionKey('vsenv'))) + need_vsenv = T.cast('bool', cdata.get_option(OptionKey.factory('vsenv'))) if setup_vsenv(need_vsenv): mlog.log(mlog.green('INFO:'), 'automatically activated MSVC compiler environment') cmd: T.List[str] = [] env: T.Optional[T.Dict[str, str]] = None - backend = cdata.get_option(OptionKey('backend')) + backend = cdata.get_option(OptionKey.factory('backend')) assert isinstance(backend, str) mlog.log(mlog.green('INFO:'), 'autodetecting backend as', backend) if backend == 'ninja': diff --git a/mesonbuild/mconf.py b/mesonbuild/mconf.py index 9d65cc26fa21..98dc5ec1b542 100644 --- a/mesonbuild/mconf.py +++ b/mesonbuild/mconf.py @@ -1,6 +1,6 @@ # SPDX-License-Identifier: Apache-2.0 # Copyright 2014-2016 The Meson development team -# Copyright © 2023-2024 Intel Corporation +# Copyright © 2023-2025 Intel Corporation from __future__ import annotations @@ -258,8 +258,8 @@ def print_default_values_warning() -> None: mlog.log(' Build dir ', self.build_dir) dir_option_names = set(options.BUILTIN_DIR_OPTIONS) - test_option_names = {OptionKey('errorlogs'), - OptionKey('stdsplit')} + test_option_names = {OptionKey.factory('errorlogs'), + OptionKey.factory('stdsplit')} dir_options: 'coredata.MutableKeyedOptionDictType' = {} test_options: 'coredata.MutableKeyedOptionDictType' = {} diff --git a/mesonbuild/mdevenv.py b/mesonbuild/mdevenv.py index 8c6ce2031d45..aaa2421e1dc9 100644 --- a/mesonbuild/mdevenv.py +++ b/mesonbuild/mdevenv.py @@ -84,9 +84,9 @@ def bash_completion_files(b: build.Build, install_data: 'InstallData') -> T.List dep = PkgConfigDependency('bash-completion', b.environment, {'required': False, 'silent': True, 'version': '>=2.10'}) if dep.found(): - prefix = b.environment.coredata.get_option(OptionKey('prefix')) + prefix = b.environment.coredata.get_option(OptionKey.factory('prefix')) assert isinstance(prefix, str), 'for mypy' - datadir = b.environment.coredata.get_option(OptionKey('datadir')) + datadir = b.environment.coredata.get_option(OptionKey.factory('datadir')) assert isinstance(datadir, str), 'for mypy' datadir_abs = os.path.join(prefix, datadir) completionsdir = dep.get_variable(pkgconfig='completionsdir', pkgconfig_define=(('datadir', datadir_abs),)) @@ -164,7 +164,7 @@ def run(options: argparse.Namespace) -> int: b = build.load(options.builddir) workdir = options.workdir or options.builddir - need_vsenv = T.cast('bool', b.environment.coredata.get_option(OptionKey('vsenv'))) + need_vsenv = T.cast('bool', b.environment.coredata.get_option(OptionKey.factory('vsenv'))) setup_vsenv(need_vsenv) # Call it before get_env to get vsenv vars as well dump_fmt = options.dump_format if options.dump else None devenv, varnames = get_env(b, dump_fmt) diff --git a/mesonbuild/mdist.py b/mesonbuild/mdist.py index 17329009b40a..11bb467fa9fc 100644 --- a/mesonbuild/mdist.py +++ b/mesonbuild/mdist.py @@ -1,6 +1,6 @@ # SPDX-License-Identifier: Apache-2.0 # Copyright 2017 The Meson development team -# Copyright © 2023-2024 Intel Corporation +# Copyright © 2023-2025 Intel Corporation from __future__ import annotations @@ -356,7 +356,7 @@ def create_cmdline_args(bld_root: str) -> T.List[str]: args = T.cast('coredata.SharedCMDOptions', parser.parse_args([])) coredata.parse_cmd_line_options(args) coredata.read_cmd_line_file(bld_root, args) - args.cmd_line_options.pop(OptionKey('backend'), '') + args.cmd_line_options.pop(OptionKey.factory('backend'), '') return shlex.split(coredata.format_cmd_line_options(args)) def determine_archives_to_generate(options: argparse.Namespace) -> T.List[str]: @@ -374,7 +374,7 @@ def run(options: argparse.Namespace) -> int: if not buildfile.is_file(): raise MesonException(f'Directory {options.wd!r} does not seem to be a Meson build directory.') b = build.load(options.wd) - need_vsenv = T.cast('bool', b.environment.coredata.get_option(OptionKey('vsenv'))) + need_vsenv = T.cast('bool', b.environment.coredata.get_option(OptionKey.factory('vsenv'))) setup_vsenv(need_vsenv) src_root = b.environment.source_dir bld_root = b.environment.build_dir diff --git a/mesonbuild/minit.py b/mesonbuild/minit.py index 70f184d02ebd..4644d5e2ccf8 100644 --- a/mesonbuild/minit.py +++ b/mesonbuild/minit.py @@ -193,7 +193,7 @@ def run(options: Arguments) -> int: raise SystemExit b = build.load(options.builddir) - need_vsenv = T.cast('bool', b.environment.coredata.get_option(OptionKey('vsenv'))) + need_vsenv = T.cast('bool', b.environment.coredata.get_option(OptionKey.factory('vsenv'))) vsenv_active = mesonlib.setup_vsenv(need_vsenv) if vsenv_active: mlog.log(mlog.green('INFO:'), 'automatically activated MSVC compiler environment') diff --git a/mesonbuild/minstall.py b/mesonbuild/minstall.py index 2db4472d160c..46998e69fd84 100644 --- a/mesonbuild/minstall.py +++ b/mesonbuild/minstall.py @@ -869,9 +869,9 @@ def run(opts: 'ArgumentType') -> int: sys.exit('Install data not found. Run this command in build directory root.') if not opts.no_rebuild: b = build.load(opts.wd) - need_vsenv = T.cast('bool', b.environment.coredata.get_option(OptionKey('vsenv'))) + need_vsenv = T.cast('bool', b.environment.coredata.get_option(OptionKey.factory('vsenv'))) setup_vsenv(need_vsenv) - backend = T.cast('str', b.environment.coredata.get_option(OptionKey('backend'))) + backend = T.cast('str', b.environment.coredata.get_option(OptionKey.factory('backend'))) if not rebuild_all(opts.wd, backend): sys.exit(-1) os.chdir(opts.wd) diff --git a/mesonbuild/mintro.py b/mesonbuild/mintro.py index 383f15473eea..03e5d71b0eee 100644 --- a/mesonbuild/mintro.py +++ b/mesonbuild/mintro.py @@ -164,7 +164,7 @@ def list_install_plan(installdata: backends.InstallData) -> T.Dict[str, T.Dict[s return plan def get_target_dir(coredata: cdata.CoreData, subdir: str) -> str: - if coredata.get_option(OptionKey('layout')) == 'flat': + if coredata.get_option(OptionKey.factory('layout')) == 'flat': return 'meson-out' else: return subdir @@ -287,8 +287,8 @@ def list_buildoptions(coredata: cdata.CoreData, subprojects: T.Optional[T.List[s subprojects = subprojects or [] dir_option_names = set(options.BUILTIN_DIR_OPTIONS) - test_option_names = {OptionKey('errorlogs'), - OptionKey('stdsplit')} + test_option_names = {OptionKey.factory('errorlogs'), + OptionKey.factory('stdsplit')} dir_options: 'cdata.MutableKeyedOptionDictType' = {} test_options: 'cdata.MutableKeyedOptionDictType' = {} diff --git a/mesonbuild/modules/__init__.py b/mesonbuild/modules/__init__.py index f9374cc1d48c..24e2dbd050d6 100644 --- a/mesonbuild/modules/__init__.py +++ b/mesonbuild/modules/__init__.py @@ -133,12 +133,12 @@ def test(self, args: T.Tuple[str, T.Union[build.Executable, build.Jar, 'External def get_option(self, name: str, subproject: str = '', machine: MachineChoice = MachineChoice.HOST) -> T.Union[T.List[str], str, int, bool]: - return self.environment.coredata.get_option(OptionKey(name, subproject, machine)) + return self.environment.coredata.get_option(OptionKey.factory(name, subproject, machine)) def is_user_defined_option(self, name: str, subproject: str = '', machine: MachineChoice = MachineChoice.HOST, lang: T.Optional[str] = None) -> bool: - key = OptionKey(name, subproject, machine) + key = OptionKey.factory(name, subproject, machine) return key in self._interpreter.user_defined_options.cmd_line_options def process_include_dirs(self, dirs: T.Iterable[T.Union[str, IncludeDirs]]) -> T.Iterable[IncludeDirs]: diff --git a/mesonbuild/modules/cmake.py b/mesonbuild/modules/cmake.py index 2168aaa516c0..2765ee9bdca2 100644 --- a/mesonbuild/modules/cmake.py +++ b/mesonbuild/modules/cmake.py @@ -305,7 +305,7 @@ def write_basic_package_version_file(self, state: ModuleState, args: TYPE_var, k pkgroot = pkgroot_name = kwargs['install_dir'] if pkgroot is None: - pkgroot = os.path.join(state.environment.coredata.get_option(OptionKey('libdir')), 'cmake', name) + pkgroot = os.path.join(state.environment.coredata.get_option(OptionKey.factory('libdir')), 'cmake', name) pkgroot_name = os.path.join('{libdir}', 'cmake', name) template_file = os.path.join(self.cmake_root, 'Modules', f'BasicConfigVersion-{compatibility}.cmake.in') @@ -376,14 +376,14 @@ def configure_package_config_file(self, state: ModuleState, args: TYPE_var, kwar install_dir = kwargs['install_dir'] if install_dir is None: - install_dir = os.path.join(state.environment.coredata.get_option(OptionKey('libdir')), 'cmake', name) + install_dir = os.path.join(state.environment.coredata.get_option(OptionKey.factory('libdir')), 'cmake', name) conf = kwargs['configuration'] if isinstance(conf, dict): FeatureNew.single_use('cmake.configure_package_config_file dict as configuration', '0.62.0', state.subproject, location=state.current_node) conf = build.ConfigurationData(conf) - prefix = state.environment.coredata.get_option(OptionKey('prefix')) + prefix = state.environment.coredata.get_option(OptionKey.factory('prefix')) abs_install_dir = install_dir if not os.path.isabs(abs_install_dir): abs_install_dir = os.path.join(prefix, install_dir) diff --git a/mesonbuild/modules/external_project.py b/mesonbuild/modules/external_project.py index 57a1819a3e9c..872fb2fb03e9 100644 --- a/mesonbuild/modules/external_project.py +++ b/mesonbuild/modules/external_project.py @@ -75,16 +75,16 @@ def __init__(self, self.src_dir = Path(self.env.get_source_dir(), self.subdir) self.build_dir = Path(self.env.get_build_dir(), self.subdir, 'build') self.install_dir = Path(self.env.get_build_dir(), self.subdir, 'dist') - _p = self.env.coredata.get_option(OptionKey('prefix')) + _p = self.env.coredata.get_option(OptionKey.factory('prefix')) assert isinstance(_p, str), 'for mypy' self.prefix = Path(_p) - _l = self.env.coredata.get_option(OptionKey('libdir')) + _l = self.env.coredata.get_option(OptionKey.factory('libdir')) assert isinstance(_l, str), 'for mypy' self.libdir = Path(_l) - _l = self.env.coredata.get_option(OptionKey('bindir')) + _l = self.env.coredata.get_option(OptionKey.factory('bindir')) assert isinstance(_l, str), 'for mypy' self.bindir = Path(_l) - _i = self.env.coredata.get_option(OptionKey('includedir')) + _i = self.env.coredata.get_option(OptionKey.factory('includedir')) assert isinstance(_i, str), 'for mypy' self.includedir = Path(_i) self.name = self.src_dir.name diff --git a/mesonbuild/modules/gnome.py b/mesonbuild/modules/gnome.py index e0c1214d0851..6fca1552080f 100644 --- a/mesonbuild/modules/gnome.py +++ b/mesonbuild/modules/gnome.py @@ -520,7 +520,7 @@ def compile_resources(self, state: 'ModuleState', args: T.Tuple[str, 'FileOrStri if gresource: # Only one target for .gresource files return ModuleReturnValue(target_c, [target_c]) - install_dir = kwargs['install_dir'] or state.environment.coredata.get_option(OptionKey('includedir')) + install_dir = kwargs['install_dir'] or state.environment.coredata.get_option(OptionKey.factory('includedir')) assert isinstance(install_dir, str), 'for mypy' target_h = GResourceHeaderTarget( f'{target_name}_h', @@ -909,7 +909,7 @@ def _get_langs_compilers_flags(state: 'ModuleState', langs_compilers: T.List[T.T cflags += state.global_args[lang] if state.project_args.get(lang): cflags += state.project_args[lang] - if OptionKey('b_sanitize') in compiler.base_options: + if OptionKey.factory('b_sanitize') in compiler.base_options: sanitize = state.environment.coredata.optstore.get_value('b_sanitize') cflags += compiler.sanitizer_compile_args(sanitize) sanitize = sanitize.split(',') @@ -1649,7 +1649,7 @@ def gdbus_codegen(self, state: 'ModuleState', args: T.Tuple[str, T.Optional[T.Un targets = [] install_header = kwargs['install_header'] - install_dir = kwargs['install_dir'] or state.environment.coredata.get_option(OptionKey('includedir')) + install_dir = kwargs['install_dir'] or state.environment.coredata.get_option(OptionKey.factory('includedir')) assert isinstance(install_dir, str), 'for mypy' output = namebase + '.c' @@ -1961,7 +1961,7 @@ def _make_mkenum_impl( ) -> build.CustomTarget: real_cmd: T.List[T.Union[str, 'ToolType']] = [self._find_tool(state, 'glib-mkenums')] real_cmd.extend(cmd) - _install_dir = install_dir or state.environment.coredata.get_option(OptionKey('includedir')) + _install_dir = install_dir or state.environment.coredata.get_option(OptionKey.factory('includedir')) assert isinstance(_install_dir, str), 'for mypy' return CustomTarget( @@ -2173,7 +2173,7 @@ def generate_vapi(self, state: 'ModuleState', args: T.Tuple[str], kwargs: 'Gener cmd.append(gir_file) vapi_output = library + '.vapi' - datadir = state.environment.coredata.get_option(OptionKey('datadir')) + datadir = state.environment.coredata.get_option(OptionKey.factory('datadir')) assert isinstance(datadir, str), 'for mypy' install_dir = kwargs['install_dir'] or os.path.join(datadir, 'vala', 'vapi') diff --git a/mesonbuild/modules/hotdoc.py b/mesonbuild/modules/hotdoc.py index 50b5fe6f2fed..2d3b920fa5de 100644 --- a/mesonbuild/modules/hotdoc.py +++ b/mesonbuild/modules/hotdoc.py @@ -331,7 +331,7 @@ def make_targets(self) -> T.Tuple[HotdocTarget, mesonlib.ExecutableSerialisation for path in self.include_paths: self.cmd.extend(['--include-path', path]) - if self.state.environment.coredata.get_option(OptionKey('werror', subproject=self.state.subproject)): + if self.state.environment.coredata.get_option(OptionKey.factory('werror', subproject=self.state.subproject)): self.cmd.append('--fatal-warnings') self.generate_hotdoc_config() diff --git a/mesonbuild/modules/i18n.py b/mesonbuild/modules/i18n.py index 551e0b36fab6..079c68a671b3 100644 --- a/mesonbuild/modules/i18n.py +++ b/mesonbuild/modules/i18n.py @@ -278,7 +278,7 @@ def gettext(self, state: 'ModuleState', args: T.Tuple[str], kwargs: 'Gettext') - targets.append(pottarget) install = kwargs['install'] - install_dir = kwargs['install_dir'] or state.environment.coredata.get_option(OptionKey('localedir')) + install_dir = kwargs['install_dir'] or state.environment.coredata.get_option(OptionKey.factory('localedir')) assert isinstance(install_dir, str), 'for mypy' if not languages: languages = read_linguas(path.join(state.environment.source_dir, state.subdir)) diff --git a/mesonbuild/modules/pkgconfig.py b/mesonbuild/modules/pkgconfig.py index 974d2521d52e..daec8d955c4a 100644 --- a/mesonbuild/modules/pkgconfig.py +++ b/mesonbuild/modules/pkgconfig.py @@ -490,7 +490,7 @@ def _generate_pkgconfig_file(self, state: ModuleState, deps: DependenciesHelper, srcdir = PurePath(state.environment.get_source_dir()) else: outdir = state.environment.scratch_dir - prefix = PurePath(_as_str(coredata.get_option(OptionKey('prefix')))) + prefix = PurePath(_as_str(coredata.get_option(OptionKey.factory('prefix')))) if pkgroot: pkgroot_ = PurePath(pkgroot) if not pkgroot_.is_absolute(): @@ -507,7 +507,7 @@ def _generate_pkgconfig_file(self, state: ModuleState, deps: DependenciesHelper, if optname == 'prefix': ofile.write('prefix={}\n'.format(self._escape(prefix))) else: - dirpath = PurePath(_as_str(coredata.get_option(OptionKey(optname)))) + dirpath = PurePath(_as_str(coredata.get_option(OptionKey.factory(optname)))) ofile.write('{}={}\n'.format(optname, self._escape('${prefix}' / dirpath))) if uninstalled and not dataonly: ofile.write('srcdir={}\n'.format(self._escape(srcdir))) @@ -703,13 +703,13 @@ def parse_variable_list(vardict: T.Dict[str, str]) -> T.List[T.Tuple[str, str]]: if pkgroot is None: m = state.environment.machines.host if m.is_freebsd(): - pkgroot = os.path.join(_as_str(state.environment.coredata.get_option(OptionKey('prefix'))), 'libdata', 'pkgconfig') + pkgroot = os.path.join(_as_str(state.environment.coredata.get_option(OptionKey.factory('prefix'))), 'libdata', 'pkgconfig') pkgroot_name = os.path.join('{prefix}', 'libdata', 'pkgconfig') elif m.is_haiku(): - pkgroot = os.path.join(_as_str(state.environment.coredata.get_option(OptionKey('prefix'))), 'develop', 'lib', 'pkgconfig') + pkgroot = os.path.join(_as_str(state.environment.coredata.get_option(OptionKey.factory('prefix'))), 'develop', 'lib', 'pkgconfig') pkgroot_name = os.path.join('{prefix}', 'develop', 'lib', 'pkgconfig') else: - pkgroot = os.path.join(_as_str(state.environment.coredata.get_option(OptionKey('libdir'))), 'pkgconfig') + pkgroot = os.path.join(_as_str(state.environment.coredata.get_option(OptionKey.factory('libdir'))), 'pkgconfig') pkgroot_name = os.path.join('{libdir}', 'pkgconfig') relocatable = state.get_option('pkgconfig.relocatable') self._generate_pkgconfig_file(state, deps, subdirs, name, description, url, diff --git a/mesonbuild/modules/python.py b/mesonbuild/modules/python.py index 1b7a05640374..1f2442ceb46b 100644 --- a/mesonbuild/modules/python.py +++ b/mesonbuild/modules/python.py @@ -113,7 +113,7 @@ class PythonInstallation(_ExternalProgramHolder['PythonExternalProgram']): def __init__(self, python: 'PythonExternalProgram', interpreter: 'Interpreter'): _ExternalProgramHolder.__init__(self, python, interpreter) info = python.info - prefix = self.interpreter.environment.coredata.get_option(OptionKey('prefix')) + prefix = self.interpreter.environment.coredata.get_option(OptionKey.factory('prefix')) assert isinstance(prefix, str), 'for mypy' self.variables = info['variables'] self.suffix = info['suffix'] @@ -169,7 +169,7 @@ def extension_module_method(self, args: T.Tuple[str, T.List[BuildTargetSource]], self.current_node) limited_api_version = kwargs.pop('limited_api') - allow_limited_api = self.interpreter.environment.coredata.get_option(OptionKey('python.allow_limited_api')) + allow_limited_api = self.interpreter.environment.coredata.get_option(OptionKey.factory('python.allow_limited_api')) if limited_api_version != '' and allow_limited_api: target_suffix = self.limited_api_suffix @@ -374,7 +374,7 @@ def __init__(self, interpreter: 'Interpreter') -> None: def _get_install_scripts(self) -> T.List[mesonlib.ExecutableSerialisation]: backend = self.interpreter.backend ret = [] - optlevel = self.interpreter.environment.coredata.get_option(OptionKey('python.bytecompile')) + optlevel = self.interpreter.environment.coredata.get_option(OptionKey.factory('python.bytecompile')) if optlevel == -1: return ret if not any(PythonExternalProgram.run_bytecompile.values()): diff --git a/mesonbuild/msetup.py b/mesonbuild/msetup.py index e634c05ab5aa..4591688560e5 100644 --- a/mesonbuild/msetup.py +++ b/mesonbuild/msetup.py @@ -1,6 +1,6 @@ # SPDX-License-Identifier: Apache-2.0 # Copyright 2016-2018 The Meson development team -# Copyright © 2023-2024 Intel Corporation +# Copyright © 2023-2025 Intel Corporation from __future__ import annotations @@ -321,10 +321,10 @@ def run_genvslite_setup(options: CMDOptions) -> None: # invoke the appropriate 'meson compile ...' build commands upon the normal visual studio build/rebuild/clean actions, instead of using # the native VS/msbuild system. builddir_prefix = options.builddir - genvsliteval = options.cmd_line_options.pop(OptionKey('genvslite')) + genvsliteval = options.cmd_line_options.pop(OptionKey.factory('genvslite')) # The command line may specify a '--backend' option, which doesn't make sense in conjunction with # '--genvslite', where we always want to use a ninja back end - - k_backend = OptionKey('backend') + k_backend = OptionKey.factory('backend') if k_backend in options.cmd_line_options.keys(): if options.cmd_line_options[k_backend] != 'ninja': raise MesonException('Explicitly specifying a backend option with \'genvslite\' is not necessary ' @@ -337,12 +337,12 @@ def run_genvslite_setup(options: CMDOptions) -> None: for buildtypestr in buildtypes_list: options.builddir = f'{builddir_prefix}_{buildtypestr}' # E.g. builddir_release - options.cmd_line_options[OptionKey('buildtype')] = buildtypestr + options.cmd_line_options[OptionKey.factory('buildtype')] = buildtypestr app = MesonApp(options) vslite_ctx[buildtypestr] = app.generate(capture=True) #Now for generating the 'lite' solution and project files, which will use these builds we've just set up, above. options.builddir = f'{builddir_prefix}_vs' - options.cmd_line_options[OptionKey('genvslite')] = genvsliteval + options.cmd_line_options[OptionKey.factory('genvslite')] = genvsliteval app = MesonApp(options) app.generate(capture=False, vslite_ctx=vslite_ctx) @@ -358,7 +358,7 @@ def run(options: T.Union[CMDOptions, T.List[str]]) -> int: # lie options.pager = False - if OptionKey('genvslite') in options.cmd_line_options.keys(): + if OptionKey.factory('genvslite') in options.cmd_line_options.keys(): run_genvslite_setup(options) else: app = MesonApp(options) diff --git a/mesonbuild/mtest.py b/mesonbuild/mtest.py index bb58f617cca5..f874ad0bbe91 100644 --- a/mesonbuild/mtest.py +++ b/mesonbuild/mtest.py @@ -2216,11 +2216,11 @@ def run(options: argparse.Namespace) -> int: return 1 b = build.load(options.wd) - need_vsenv = T.cast('bool', b.environment.coredata.get_option(OptionKey('vsenv'))) + need_vsenv = T.cast('bool', b.environment.coredata.get_option(OptionKey.factory('vsenv'))) setup_vsenv(need_vsenv) if not options.no_rebuild: - backend = b.environment.coredata.get_option(OptionKey('backend')) + backend = b.environment.coredata.get_option(OptionKey.factory('backend')) if backend == 'none': # nothing to build... options.no_rebuild = True diff --git a/mesonbuild/munstable_coredata.py b/mesonbuild/munstable_coredata.py index 409b514b608e..11af50861c44 100644 --- a/mesonbuild/munstable_coredata.py +++ b/mesonbuild/munstable_coredata.py @@ -53,7 +53,7 @@ def run(options): print('') coredata = cdata.load(options.builddir) - backend = coredata.get_option(OptionKey('backend')) + backend = coredata.get_option(OptionKey.factory('backend')) for k, v in sorted(coredata.__dict__.items()): if k in {'backend_options', 'base_options', 'builtins', 'compiler_options', 'user_options'}: # use `meson configure` to view these diff --git a/mesonbuild/options.py b/mesonbuild/options.py index c31254d232d4..725697ad1ff5 100644 --- a/mesonbuild/options.py +++ b/mesonbuild/options.py @@ -5,7 +5,7 @@ from __future__ import annotations from collections import OrderedDict from itertools import chain -from functools import total_ordering +from functools import lru_cache import argparse import dataclasses import typing as T @@ -98,7 +98,8 @@ class ArgparseKWs(TypedDict, total=False): 'vsenv', } -@total_ordering +_OPTIONS_CACHE: T.Dict[int, OptionKey] = {} + class OptionKey: """Represents an option key in the various option dictionaries. @@ -108,15 +109,16 @@ class OptionKey: internally easier to reason about and produce. """ - __slots__ = ['name', 'subproject', 'machine', '_hash'] + __slots__ = ['name', 'subproject', 'machine', '_hash', '_as_tuple'] name: str subproject: str machine: MachineChoice _hash: int + _as_tuple: T.Tuple[str, MachineChoice, str] - def __init__(self, name: str, subproject: str = '', - machine: MachineChoice = MachineChoice.HOST): + def __init__(self, name: str, subproject: str, + machine: MachineChoice, hash_: int): # the _type option to the constructor is kinda private. We want to be # able to save the state and avoid the lookup function when # pickling/unpickling, but we need to be able to calculate it when @@ -124,7 +126,8 @@ def __init__(self, name: str, subproject: str = '', object.__setattr__(self, 'name', name) object.__setattr__(self, 'subproject', subproject) object.__setattr__(self, 'machine', machine) - object.__setattr__(self, '_hash', hash((name, subproject, machine))) + object.__setattr__(self, '_hash', hash_) + object.__setattr__(self, '_as_tuple', (self.subproject, self.machine, self.name)) def __setattr__(self, key: str, value: T.Any) -> None: raise AttributeError('OptionKey instances do not support mutation.') @@ -134,6 +137,7 @@ def __getstate__(self) -> T.Dict[str, T.Any]: 'name': self.name, 'subproject': self.subproject, 'machine': self.machine, + 'hash_': self._hash, } def __setstate__(self, state: T.Dict[str, T.Any]) -> None: @@ -150,17 +154,34 @@ def __setstate__(self, state: T.Dict[str, T.Any]) -> None: def __hash__(self) -> int: return self._hash - def _to_tuple(self) -> T.Tuple[str, MachineChoice, str]: - return (self.subproject, self.machine, self.name) + def __lt__(self, other: object) -> bool: + if isinstance(other, OptionKey): + return self._as_tuple < other._as_tuple + return NotImplemented + + def __le__(self, other: object) -> bool: + if isinstance(other, OptionKey): + return self._as_tuple <= other._as_tuple + return NotImplemented def __eq__(self, other: object) -> bool: if isinstance(other, OptionKey): - return self._to_tuple() == other._to_tuple() + return self._as_tuple == other._as_tuple return NotImplemented - def __lt__(self, other: object) -> bool: + def __ne__(self, other: object) -> bool: + if isinstance(other, OptionKey): + return self._as_tuple != other._as_tuple + return NotImplemented + + def __ge__(self, other: object) -> bool: if isinstance(other, OptionKey): - return self._to_tuple() < other._to_tuple() + return self._as_tuple >= other._as_tuple + return NotImplemented + + def __gt__(self, other: object) -> bool: + if isinstance(other, OptionKey): + return self._as_tuple > other._as_tuple return NotImplemented def __str__(self) -> str: @@ -172,9 +193,29 @@ def __str__(self) -> str: return out def __repr__(self) -> str: - return f'OptionKey({self.name!r}, {self.subproject!r}, {self.machine!r})' + return f'OptionKey.factory({self.name!r}, {self.subproject!r}, {self.machine!r})' + + @classmethod + def factory(cls, name: str, subproject: str = '', machine: MachineChoice = MachineChoice.HOST) -> OptionKey: + """A cached initializer for OptionKeys + + :param name: The name of the option + :param subproject: the subproject the option belongs to, defaults to '' + :param machine: the machine the subproject belongs to, defaults to MachineChoice.HOST + :return: An OptionKey + """ + # This doesn't use lru_cache so that we can re-use the calculated hash + # in a cache miss situation. + _hash = hash((name, subproject, machine)) + try: + return _OPTIONS_CACHE[_hash] + except KeyError: + inst = cls(name, subproject, machine, _hash) + _OPTIONS_CACHE[_hash] = inst + return inst @classmethod + @lru_cache(None) def from_string(cls, raw: str) -> 'OptionKey': """Parse the raw command line format into a three part tuple. @@ -200,21 +241,21 @@ def from_string(cls, raw: str) -> 'OptionKey': assert ':' not in opt assert opt.count('.') < 2 - return cls(opt, subproject, for_machine) + return cls.factory(opt, subproject, for_machine) def evolve(self, name: T.Optional[str] = None, subproject: T.Optional[str] = None, machine: T.Optional[MachineChoice] = None) -> 'OptionKey': """Create a new copy of this key, but with altered members. For example: - >>> a = OptionKey('foo', '', MachineChoice.Host) - >>> b = OptionKey('foo', 'bar', MachineChoice.Host) + >>> a = OptionKey.factory('foo', '', MachineChoice.Host) + >>> b = OptionKey.factory('foo', 'bar', MachineChoice.Host) >>> b == a.evolve(subproject='bar') True """ # We have to be a little clever with lang here, because lang is valid # as None, for non-compiler options - return OptionKey( + return OptionKey.factory( name if name is not None else self.name, subproject if subproject is not None else self.subproject, machine if machine is not None else self.machine, @@ -654,27 +695,27 @@ def add_to_argparse(self, name: OptionKey, parser: argparse.ArgumentParser, help # Also update mesonlib._BUILTIN_NAMES. See the comment there for why this is required. # Please also update completion scripts in $MESONSRC/data/shell-completions/ BUILTIN_DIR_OPTIONS: T.Dict['OptionKey', 'BuiltinOption'] = OrderedDict([ - (OptionKey('prefix'), BuiltinOption(UserStringOption, 'Installation prefix', default_prefix())), - (OptionKey('bindir'), BuiltinOption(UserStringOption, 'Executable directory', 'bin')), - (OptionKey('datadir'), BuiltinOption(UserStringOption, 'Data file directory', default_datadir())), - (OptionKey('includedir'), BuiltinOption(UserStringOption, 'Header file directory', default_includedir())), - (OptionKey('infodir'), BuiltinOption(UserStringOption, 'Info page directory', default_infodir())), - (OptionKey('libdir'), BuiltinOption(UserStringOption, 'Library directory', default_libdir())), - (OptionKey('licensedir'), BuiltinOption(UserStringOption, 'Licenses directory', '')), - (OptionKey('libexecdir'), BuiltinOption(UserStringOption, 'Library executable directory', default_libexecdir())), - (OptionKey('localedir'), BuiltinOption(UserStringOption, 'Locale data directory', default_localedir())), - (OptionKey('localstatedir'), BuiltinOption(UserStringOption, 'Localstate data directory', 'var')), - (OptionKey('mandir'), BuiltinOption(UserStringOption, 'Manual page directory', default_mandir())), - (OptionKey('sbindir'), BuiltinOption(UserStringOption, 'System executable directory', default_sbindir())), - (OptionKey('sharedstatedir'), BuiltinOption(UserStringOption, 'Architecture-independent data directory', 'com')), - (OptionKey('sysconfdir'), BuiltinOption(UserStringOption, 'Sysconf data directory', default_sysconfdir())), + (OptionKey.factory('prefix'), BuiltinOption(UserStringOption, 'Installation prefix', default_prefix())), + (OptionKey.factory('bindir'), BuiltinOption(UserStringOption, 'Executable directory', 'bin')), + (OptionKey.factory('datadir'), BuiltinOption(UserStringOption, 'Data file directory', default_datadir())), + (OptionKey.factory('includedir'), BuiltinOption(UserStringOption, 'Header file directory', default_includedir())), + (OptionKey.factory('infodir'), BuiltinOption(UserStringOption, 'Info page directory', default_infodir())), + (OptionKey.factory('libdir'), BuiltinOption(UserStringOption, 'Library directory', default_libdir())), + (OptionKey.factory('licensedir'), BuiltinOption(UserStringOption, 'Licenses directory', '')), + (OptionKey.factory('libexecdir'), BuiltinOption(UserStringOption, 'Library executable directory', default_libexecdir())), + (OptionKey.factory('localedir'), BuiltinOption(UserStringOption, 'Locale data directory', default_localedir())), + (OptionKey.factory('localstatedir'), BuiltinOption(UserStringOption, 'Localstate data directory', 'var')), + (OptionKey.factory('mandir'), BuiltinOption(UserStringOption, 'Manual page directory', default_mandir())), + (OptionKey.factory('sbindir'), BuiltinOption(UserStringOption, 'System executable directory', default_sbindir())), + (OptionKey.factory('sharedstatedir'), BuiltinOption(UserStringOption, 'Architecture-independent data directory', 'com')), + (OptionKey.factory('sysconfdir'), BuiltinOption(UserStringOption, 'Sysconf data directory', default_sysconfdir())), ]) BUILTIN_CORE_OPTIONS: T.Dict['OptionKey', 'BuiltinOption'] = OrderedDict([ - (OptionKey('auto_features'), BuiltinOption(UserFeatureOption, "Override value of all 'auto' features", 'auto')), - (OptionKey('backend'), BuiltinOption(UserComboOption, 'Backend to use', 'ninja', choices=backendlist, - readonly=True)), - (OptionKey('genvslite'), + (OptionKey.factory('auto_features'), BuiltinOption(UserFeatureOption, "Override value of all 'auto' features", 'auto')), + (OptionKey.factory('backend'), BuiltinOption(UserComboOption, 'Backend to use', 'ninja', choices=backendlist, + readonly=True)), + (OptionKey.factory('genvslite'), BuiltinOption( UserComboOption, 'Setup multiple buildtype-suffixed ninja-backend build directories, ' @@ -682,59 +723,59 @@ def add_to_argparse(self, name: OptionKey, parser: argparse.ArgumentParser, help 'vs2022', choices=genvslitelist) ), - (OptionKey('buildtype'), BuiltinOption(UserComboOption, 'Build type to use', 'debug', - choices=buildtypelist)), - (OptionKey('debug'), BuiltinOption(UserBooleanOption, 'Enable debug symbols and other information', True)), - (OptionKey('default_library'), BuiltinOption(UserComboOption, 'Default library type', 'shared', choices=['shared', 'static', 'both'], - yielding=False)), - (OptionKey('default_both_libraries'), BuiltinOption(UserComboOption, 'Default library type for both_libraries', 'shared', choices=['shared', 'static', 'auto'])), - (OptionKey('errorlogs'), BuiltinOption(UserBooleanOption, "Whether to print the logs from failing tests", True)), - (OptionKey('install_umask'), BuiltinOption(UserUmaskOption, 'Default umask to apply on permissions of installed files', '022')), - (OptionKey('layout'), BuiltinOption(UserComboOption, 'Build directory layout', 'mirror', choices=['mirror', 'flat'])), - (OptionKey('optimization'), BuiltinOption(UserComboOption, 'Optimization level', '0', choices=['plain', '0', 'g', '1', '2', '3', 's'])), - (OptionKey('prefer_static'), BuiltinOption(UserBooleanOption, 'Whether to try static linking before shared linking', False)), - (OptionKey('stdsplit'), BuiltinOption(UserBooleanOption, 'Split stdout and stderr in test logs', True)), - (OptionKey('strip'), BuiltinOption(UserBooleanOption, 'Strip targets on install', False)), - (OptionKey('unity'), BuiltinOption(UserComboOption, 'Unity build', 'off', choices=['on', 'off', 'subprojects'])), - (OptionKey('unity_size'), BuiltinOption(UserIntegerOption, 'Unity block size', 4, min_value=2)), - (OptionKey('warning_level'), BuiltinOption(UserComboOption, 'Compiler warning level to use', '1', choices=['0', '1', '2', '3', 'everything'], yielding=False)), - (OptionKey('werror'), BuiltinOption(UserBooleanOption, 'Treat warnings as errors', False, yielding=False)), - (OptionKey('wrap_mode'), BuiltinOption(UserComboOption, 'Wrap mode', 'default', choices=['default', 'nofallback', 'nodownload', 'forcefallback', 'nopromote'])), - (OptionKey('force_fallback_for'), BuiltinOption(UserStringArrayOption, 'Force fallback for those subprojects', [])), - (OptionKey('vsenv'), BuiltinOption(UserBooleanOption, 'Activate Visual Studio environment', False, readonly=True)), + (OptionKey.factory('buildtype'), BuiltinOption(UserComboOption, 'Build type to use', 'debug', + choices=buildtypelist)), + (OptionKey.factory('debug'), BuiltinOption(UserBooleanOption, 'Enable debug symbols and other information', True)), + (OptionKey.factory('default_library'), BuiltinOption(UserComboOption, 'Default library type', 'shared', choices=['shared', 'static', 'both'], + yielding=False)), + (OptionKey.factory('default_both_libraries'), BuiltinOption(UserComboOption, 'Default library type for both_libraries', 'shared', choices=['shared', 'static', 'auto'])), + (OptionKey.factory('errorlogs'), BuiltinOption(UserBooleanOption, "Whether to print the logs from failing tests", True)), + (OptionKey.factory('install_umask'), BuiltinOption(UserUmaskOption, 'Default umask to apply on permissions of installed files', '022')), + (OptionKey.factory('layout'), BuiltinOption(UserComboOption, 'Build directory layout', 'mirror', choices=['mirror', 'flat'])), + (OptionKey.factory('optimization'), BuiltinOption(UserComboOption, 'Optimization level', '0', choices=['plain', '0', 'g', '1', '2', '3', 's'])), + (OptionKey.factory('prefer_static'), BuiltinOption(UserBooleanOption, 'Whether to try static linking before shared linking', False)), + (OptionKey.factory('stdsplit'), BuiltinOption(UserBooleanOption, 'Split stdout and stderr in test logs', True)), + (OptionKey.factory('strip'), BuiltinOption(UserBooleanOption, 'Strip targets on install', False)), + (OptionKey.factory('unity'), BuiltinOption(UserComboOption, 'Unity build', 'off', choices=['on', 'off', 'subprojects'])), + (OptionKey.factory('unity_size'), BuiltinOption(UserIntegerOption, 'Unity block size', 4, min_value=2)), + (OptionKey.factory('warning_level'), BuiltinOption(UserComboOption, 'Compiler warning level to use', '1', choices=['0', '1', '2', '3', 'everything'], yielding=False)), + (OptionKey.factory('werror'), BuiltinOption(UserBooleanOption, 'Treat warnings as errors', False, yielding=False)), + (OptionKey.factory('wrap_mode'), BuiltinOption(UserComboOption, 'Wrap mode', 'default', choices=['default', 'nofallback', 'nodownload', 'forcefallback', 'nopromote'])), + (OptionKey.factory('force_fallback_for'), BuiltinOption(UserStringArrayOption, 'Force fallback for those subprojects', [])), + (OptionKey.factory('vsenv'), BuiltinOption(UserBooleanOption, 'Activate Visual Studio environment', False, readonly=True)), # Pkgconfig module - (OptionKey('pkgconfig.relocatable'), + (OptionKey.factory('pkgconfig.relocatable'), BuiltinOption(UserBooleanOption, 'Generate pkgconfig files as relocatable', False)), # Python module - (OptionKey('python.bytecompile'), + (OptionKey.factory('python.bytecompile'), BuiltinOption(UserIntegerOption, 'Whether to compile bytecode', 0, min_value=-1, max_value=2)), - (OptionKey('python.install_env'), + (OptionKey.factory('python.install_env'), BuiltinOption(UserComboOption, 'Which python environment to install to', 'prefix', choices=['auto', 'prefix', 'system', 'venv'])), - (OptionKey('python.platlibdir'), + (OptionKey.factory('python.platlibdir'), BuiltinOption(UserStringOption, 'Directory for site-specific, platform-specific files.', '')), - (OptionKey('python.purelibdir'), + (OptionKey.factory('python.purelibdir'), BuiltinOption(UserStringOption, 'Directory for site-specific, non-platform-specific files.', '')), - (OptionKey('python.allow_limited_api'), + (OptionKey.factory('python.allow_limited_api'), BuiltinOption(UserBooleanOption, 'Whether to allow use of the Python Limited API', True)), ]) BUILTIN_OPTIONS = OrderedDict(chain(BUILTIN_DIR_OPTIONS.items(), BUILTIN_CORE_OPTIONS.items())) BUILTIN_OPTIONS_PER_MACHINE: T.Dict['OptionKey', 'BuiltinOption'] = OrderedDict([ - (OptionKey('pkg_config_path'), BuiltinOption(UserStringArrayOption, 'List of additional paths for pkg-config to search', [])), - (OptionKey('cmake_prefix_path'), BuiltinOption(UserStringArrayOption, 'List of additional prefixes for cmake to search', [])), + (OptionKey.factory('pkg_config_path'), BuiltinOption(UserStringArrayOption, 'List of additional paths for pkg-config to search', [])), + (OptionKey.factory('cmake_prefix_path'), BuiltinOption(UserStringArrayOption, 'List of additional prefixes for cmake to search', [])), ]) # Special prefix-dependent defaults for installation directories that reside in # a path outside of the prefix in FHS and common usage. BUILTIN_DIR_NOPREFIX_OPTIONS: T.Dict[OptionKey, T.Dict[str, str]] = { - OptionKey('sysconfdir'): {'/usr': '/etc'}, - OptionKey('localstatedir'): {'/usr': '/var', '/usr/local': '/var/local'}, - OptionKey('sharedstatedir'): {'/usr': '/var/lib', '/usr/local': '/var/local/lib'}, - OptionKey('python.platlibdir'): {}, - OptionKey('python.purelibdir'): {}, + OptionKey.factory('sysconfdir'): {'/usr': '/etc'}, + OptionKey.factory('localstatedir'): {'/usr': '/var', '/usr/local': '/var/local'}, + OptionKey.factory('sharedstatedir'): {'/usr': '/var/lib', '/usr/local': '/var/local/lib'}, + OptionKey.factory('python.platlibdir'): {}, + OptionKey.factory('python.purelibdir'): {}, } class OptionStore: @@ -750,7 +791,7 @@ def __len__(self) -> int: def ensure_key(self, key: T.Union[OptionKey, str]) -> OptionKey: if isinstance(key, str): - return OptionKey(key) + return OptionKey.factory(key) return key def get_value_object(self, key: T.Union[OptionKey, str]) -> AnyOptionType: diff --git a/mesonbuild/scripts/regen_checker.py b/mesonbuild/scripts/regen_checker.py index fc69ed7d50a1..08ab2eeb7e86 100644 --- a/mesonbuild/scripts/regen_checker.py +++ b/mesonbuild/scripts/regen_checker.py @@ -44,7 +44,7 @@ def run(args: T.List[str]) -> int: with open(coredata_file, 'rb') as f: coredata = pickle.load(f) assert isinstance(coredata, CoreData) - backend = coredata.get_option(OptionKey('backend')) + backend = coredata.get_option(OptionKey.factory('backend')) assert isinstance(backend, str) regen_timestamp = os.stat(dumpfile).st_mtime if need_regen(regeninfo, regen_timestamp): diff --git a/run_tests.py b/run_tests.py index 4e22028b830c..d6edbea374f9 100755 --- a/run_tests.py +++ b/run_tests.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # SPDX-License-Identifier: Apache-2.0 # Copyright 2012-2021 The Meson development team -# Copyright © 2023-2024 Intel Corporation +# Copyright © 2023-2025 Intel Corporation from __future__ import annotations @@ -153,7 +153,7 @@ def get_fake_env(sdir: str = '', bdir: T.Optional[str] = None, prefix: str = '', if opts is None: opts = get_fake_options(prefix) env = Environment(sdir, bdir, opts) - env.coredata.optstore.set_value_object(OptionKey('c_args'), FakeCompilerOptions()) + env.coredata.optstore.set_value_object(OptionKey.factory('c_args'), FakeCompilerOptions()) env.machines.host.cpu_family = 'x86_64' # Used on macOS inside find_library # Invalidate cache when using a different Environment object. clear_meson_configure_class_caches() diff --git a/unittests/allplatformstests.py b/unittests/allplatformstests.py index 7c2d3ba61ac3..864135bc8fe9 100644 --- a/unittests/allplatformstests.py +++ b/unittests/allplatformstests.py @@ -2628,7 +2628,7 @@ def test_command_line(self): self.assertEqual(obj.optstore.get_value('default_library'), 'static') self.assertEqual(obj.optstore.get_value('warning_level'), '1') self.assertEqual(obj.optstore.get_value('set_sub_opt'), True) - self.assertEqual(obj.optstore.get_value(OptionKey('subp_opt', 'subp')), 'default3') + self.assertEqual(obj.optstore.get_value(OptionKey.factory('subp_opt', 'subp')), 'default3') self.wipe() # warning_level is special, it's --warnlevel instead of --warning-level @@ -2722,17 +2722,17 @@ def test_command_line(self): # Test we can set subproject option self.init(testdir, extra_args=['-Dsubp:subp_opt=foo', '--fatal-meson-warnings']) obj = mesonbuild.coredata.load(self.builddir) - self.assertEqual(obj.optstore.get_value(OptionKey('subp_opt', 'subp')), 'foo') + self.assertEqual(obj.optstore.get_value(OptionKey.factory('subp_opt', 'subp')), 'foo') self.wipe() # c_args value should be parsed with split_args self.init(testdir, extra_args=['-Dc_args=-Dfoo -Dbar "-Dthird=one two"', '--fatal-meson-warnings']) obj = mesonbuild.coredata.load(self.builddir) - self.assertEqual(obj.optstore.get_value(OptionKey('c_args')), ['-Dfoo', '-Dbar', '-Dthird=one two']) + self.assertEqual(obj.optstore.get_value(OptionKey.factory('c_args')), ['-Dfoo', '-Dbar', '-Dthird=one two']) self.setconf('-Dc_args="foo bar" one two') obj = mesonbuild.coredata.load(self.builddir) - self.assertEqual(obj.optstore.get_value(OptionKey('c_args')), ['foo bar', 'one', 'two']) + self.assertEqual(obj.optstore.get_value(OptionKey.factory('c_args')), ['foo bar', 'one', 'two']) self.wipe() self.init(testdir, extra_args=['-Dset_percent_opt=myoption%', '--fatal-meson-warnings']) @@ -2751,7 +2751,7 @@ def test_command_line(self): self.assertEqual(obj.optstore.get_value('bindir'), 'bar') self.assertEqual(obj.optstore.get_value('buildtype'), 'release') self.assertEqual(obj.optstore.get_value('b_sanitize'), 'thread') - self.assertEqual(obj.optstore.get_value(OptionKey('c_args')), ['-Dbar']) + self.assertEqual(obj.optstore.get_value(OptionKey.factory('c_args')), ['-Dbar']) self.setconf(['--bindir=bar', '--bindir=foo', '-Dbuildtype=release', '-Dbuildtype=plain', '-Db_sanitize=thread', '-Db_sanitize=address', @@ -2760,7 +2760,7 @@ def test_command_line(self): self.assertEqual(obj.optstore.get_value('bindir'), 'foo') self.assertEqual(obj.optstore.get_value('buildtype'), 'plain') self.assertEqual(obj.optstore.get_value('b_sanitize'), 'address') - self.assertEqual(obj.optstore.get_value(OptionKey('c_args')), ['-Dfoo']) + self.assertEqual(obj.optstore.get_value(OptionKey.factory('c_args')), ['-Dfoo']) self.wipe() except KeyError: # Ignore KeyError, it happens on CI for compilers that does not diff --git a/unittests/datatests.py b/unittests/datatests.py index cb6542db8f71..ae5b7a991443 100644 --- a/unittests/datatests.py +++ b/unittests/datatests.py @@ -161,7 +161,7 @@ def test_builtin_options_documented(self): debug = False else: raise RuntimeError(f'Invalid debug value {debug!r} in row:\n{m.group()}') - env.coredata.set_option(OptionKey('buildtype'), buildtype) + env.coredata.set_option(OptionKey.factory('buildtype'), buildtype) self.assertEqual(env.coredata.optstore.get_value('buildtype'), buildtype) self.assertEqual(env.coredata.optstore.get_value('optimization'), opt) self.assertEqual(env.coredata.optstore.get_value('debug'), debug) diff --git a/unittests/helpers.py b/unittests/helpers.py index 5cf8845b21b5..30a9db86d926 100644 --- a/unittests/helpers.py +++ b/unittests/helpers.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 -# Copyright © 2024 Intel Corporation +# Copyright © 2024-2025 Intel Corporation from __future__ import annotations import subprocess @@ -43,7 +43,7 @@ def actual(f: T.Callable[P, R]) -> T.Callable[P, R]: def wrapped(*args: P.args, **kwargs: P.kwargs) -> R: env = get_fake_env() cc = detect_c_compiler(env, MachineChoice.HOST) - key = OptionKey(feature) + key = OptionKey.factory(feature) if key not in cc.base_options: raise unittest.SkipTest( f'{feature} not available with {cc.id}') diff --git a/unittests/internaltests.py b/unittests/internaltests.py index d7994ee085f9..765e7baa793a 100644 --- a/unittests/internaltests.py +++ b/unittests/internaltests.py @@ -629,7 +629,7 @@ def create_static_lib(name): env = get_fake_env() compiler = detect_c_compiler(env, MachineChoice.HOST) env.coredata.compilers.host = {'c': compiler} - env.coredata.optstore.set_value_object(OptionKey('c_link_args'), FakeCompilerOptions()) + env.coredata.optstore.set_value_object(OptionKey.factory('c_link_args'), FakeCompilerOptions()) p1 = Path(tmpdir) / '1' p2 = Path(tmpdir) / '2' p1.mkdir() @@ -1731,16 +1731,16 @@ def test_major_versions_differ(self) -> None: def test_option_key_from_string(self) -> None: cases = [ - ('c_args', OptionKey('c_args')), - ('build.cpp_args', OptionKey('cpp_args', machine=MachineChoice.BUILD)), - ('prefix', OptionKey('prefix')), - ('made_up', OptionKey('made_up')), + ('c_args', OptionKey.factory('c_args')), + ('build.cpp_args', OptionKey.factory('cpp_args', machine=MachineChoice.BUILD)), + ('prefix', OptionKey.factory('prefix')), + ('made_up', OptionKey.factory('made_up')), # TODO: the from_String method should be splitting the prefix off of # these, as we have the type already, but it doesn't. For now have a # test so that we don't change the behavior un-intentionally - ('b_lto', OptionKey('b_lto')), - ('backend_startup_project', OptionKey('backend_startup_project')), + ('b_lto', OptionKey.factory('b_lto')), + ('backend_startup_project', OptionKey.factory('backend_startup_project')), ] for raw, expected in cases: diff --git a/unittests/linuxliketests.py b/unittests/linuxliketests.py index a8608c2b123e..a752048a43df 100644 --- a/unittests/linuxliketests.py +++ b/unittests/linuxliketests.py @@ -499,7 +499,7 @@ def _test_stds_impl(self, testdir: str, compiler: 'Compiler') -> None: # Check that all the listed -std=xxx options for this compiler work just fine when used # https://en.wikipedia.org/wiki/Xcode#Latest_versions # https://www.gnu.org/software/gcc/projects/cxx-status.html - key = OptionKey(f'{compiler.language}_std') + key = OptionKey.factory(f'{compiler.language}_std') for v in compiler.get_options()[key].choices: # we do it like this to handle gnu++17,c++17 and gnu17,c17 cleanly # thus, C++ first @@ -1116,7 +1116,7 @@ def test_pkgconfig_relative_paths(self): self.assertPathExists(os.path.join(pkg_dir, 'librelativepath.pc')) env = get_fake_env(testdir, self.builddir, self.prefix) - env.coredata.set_options({OptionKey('pkg_config_path'): pkg_dir}, subproject='') + env.coredata.set_options({OptionKey.factory('pkg_config_path'): pkg_dir}, subproject='') kwargs = {'required': True, 'silent': True} relative_path_dep = PkgConfigDependency('librelativepath', env, kwargs) self.assertTrue(relative_path_dep.found()) @@ -1132,7 +1132,7 @@ def test_pkgconfig_duplicate_path_entries(self): pkg_dir = os.path.join(testdir, 'pkgconfig') env = get_fake_env(testdir, self.builddir, self.prefix) - env.coredata.set_options({OptionKey('pkg_config_path'): pkg_dir}, subproject='') + env.coredata.set_options({OptionKey.factory('pkg_config_path'): pkg_dir}, subproject='') # Regression test: This used to modify the value of `pkg_config_path` # option, adding the meson-uninstalled directory to it. @@ -1167,7 +1167,7 @@ def test_pkgconfig_uninstalled_env_prepended(self): env = get_fake_env(testdir, self.builddir, self.prefix) - env.coredata.set_options({OptionKey('pkg_config_path'): external_pkg_config_path_dir}, + env.coredata.set_options({OptionKey.factory('pkg_config_path'): external_pkg_config_path_dir}, subproject='') newEnv = PkgConfigInterface.setup_env({}, env, MachineChoice.HOST, uninstalled=True) diff --git a/unittests/windowstests.py b/unittests/windowstests.py index f602d5f2ef83..f22331f793c0 100644 --- a/unittests/windowstests.py +++ b/unittests/windowstests.py @@ -363,7 +363,7 @@ def test_qt5dependency_vscrt(self): # Verify that the `b_vscrt` option is available env = get_fake_env() cc = detect_c_compiler(env, MachineChoice.HOST) - if OptionKey('b_vscrt') not in cc.base_options: + if OptionKey.factory('b_vscrt') not in cc.base_options: raise SkipTest('Compiler does not support setting the VS CRT') # Verify that qmake is for Qt5 if not shutil.which('qmake-qt5'): @@ -389,7 +389,7 @@ def test_compiler_checks_vscrt(self): # Verify that the `b_vscrt` option is available env = get_fake_env() cc = detect_c_compiler(env, MachineChoice.HOST) - if OptionKey('b_vscrt') not in cc.base_options: + if OptionKey.factory('b_vscrt') not in cc.base_options: raise SkipTest('Compiler does not support setting the VS CRT') def sanitycheck_vscrt(vscrt):