From 7784539a1ae439ce91d6255e24a72fd556a513a2 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 1 Nov 2024 10:45:12 -0700 Subject: [PATCH 1/9] interpreter: remove current_lineno This was only used in a couple of places, and requires extra tracking to ensure it is correct, while we already have `current_node.lineno`, which is always accurate and up to date. I have also fixed a potential strict-null issue by using a sentinel node for `current_node` --- mesonbuild/interpreter/interpreter.py | 4 ++-- mesonbuild/interpreterbase/interpreterbase.py | 3 +-- mesonbuild/modules/__init__.py | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index 7bb2337425c5..7ae1d93f2b80 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -2686,11 +2686,11 @@ def func_configure_file(self, node: mparser.BaseNode, args: T.List[TYPE_var], ofile_rpath = os.path.join(self.subdir, output) if ofile_rpath in self.configure_file_outputs: mesonbuildfile = os.path.join(self.subdir, 'meson.build') - current_call = f"{mesonbuildfile}:{self.current_lineno}" + current_call = f"{mesonbuildfile}:{self.current_node.lineno}" first_call = "{}:{}".format(mesonbuildfile, self.configure_file_outputs[ofile_rpath]) mlog.warning('Output file', mlog.bold(ofile_rpath, True), 'for configure_file() at', current_call, 'overwrites configure_file() output at', first_call) else: - self.configure_file_outputs[ofile_rpath] = self.current_lineno + self.configure_file_outputs[ofile_rpath] = self.current_node.lineno (ofile_path, ofile_fname) = os.path.split(os.path.join(self.subdir, output)) ofile_abs = os.path.join(self.environment.build_dir, ofile_path, ofile_fname) diff --git a/mesonbuild/interpreterbase/interpreterbase.py b/mesonbuild/interpreterbase/interpreterbase.py index 525d5d6c54a0..5f9df4cb5bcc 100644 --- a/mesonbuild/interpreterbase/interpreterbase.py +++ b/mesonbuild/interpreterbase/interpreterbase.py @@ -82,7 +82,7 @@ def __init__(self, source_root: str, subdir: str, subproject: 'SubProject'): self.current_lineno = -1 # Current node set during a function call. This can be used as location # when printing a warning message during a method call. - self.current_node: mparser.BaseNode = None + self.current_node = mparser.BaseNode(-1, -1, 'sentinel') # This is set to `version_string` when this statement is evaluated: # meson.version().compare_version(version_string) # If it was part of a if-clause, it is used to temporally override the @@ -183,7 +183,6 @@ def evaluate_codeblock(self, node: mparser.CodeBlockNode, start: int = 0, end: T while i < len(statements): cur = statements[i] try: - self.current_lineno = cur.lineno self.evaluate_statement(cur) except Exception as e: if getattr(e, 'lineno', None) is None: diff --git a/mesonbuild/modules/__init__.py b/mesonbuild/modules/__init__.py index 86dc8762e65a..f9374cc1d48c 100644 --- a/mesonbuild/modules/__init__.py +++ b/mesonbuild/modules/__init__.py @@ -38,7 +38,7 @@ def __init__(self, interpreter: 'Interpreter') -> None: self.subproject = interpreter.subproject self.subdir = interpreter.subdir self.root_subdir = interpreter.root_subdir - self.current_lineno = interpreter.current_lineno + self.current_lineno = interpreter.current_node.lineno self.environment = interpreter.environment self.project_name = interpreter.build.project_name self.project_version = interpreter.build.dep_manifest[interpreter.active_projectname].version From 3dbd3514394a32f749f24f817e3953b026e19ac5 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 26 Jan 2024 13:39:17 -0800 Subject: [PATCH 2/9] interperter: Remove unused Interpreter.subproject_directory_name --- mesonbuild/interpreter/interpreter.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index 7ae1d93f2b80..ec946d480c96 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -281,9 +281,6 @@ def __init__( self.backend = backend self.summary: T.Dict[str, 'Summary'] = {} self.modules: T.Dict[str, NewExtensionModule] = {} - # Subproject directory is usually the name of the subproject, but can - # be different for dependencies provided by wrap files. - self.subproject_directory_name = subdir.split(os.path.sep)[-1] self.subproject_dir = subproject_dir self.relaxations = relaxations or set() if ast is None: From 81e4fbe7ff63d7fdd8cd55d3ce81eebfdffd1786 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 26 Jan 2024 13:59:30 -0800 Subject: [PATCH 3/9] interpreter: only calculate build_filename if we're actually going to use it --- mesonbuild/interpreter/interpreter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index ec946d480c96..c4d57e7c9d98 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -313,8 +313,8 @@ def __init__( # exist we don't want to add a dependency on it, it's autogenerated # from the actual build files, and is just for reference. self.build_def_files: mesonlib.OrderedSet[str] = mesonlib.OrderedSet() - build_filename = os.path.join(self.subdir, environment.build_filename) if not is_translated: + build_filename = os.path.join(self.subdir, environment.build_filename) self.build_def_files.add(build_filename) self.parse_project() self._redetect_machines() From a876ae0a126cdf427a851eec57e408786de66c3a Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Mon, 29 Jan 2024 10:30:18 -0800 Subject: [PATCH 4/9] interpreter: remove Interpreter.generators Which is built, but never used --- mesonbuild/interpreter/interpreter.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index c4d57e7c9d98..65ba2ae6c009 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -289,7 +289,6 @@ def __init__( self.ast = ast self.sanity_check_ast() self.builtin.update({'meson': MesonMain(self.build, self)}) - self.generators: T.List[build.Generator] = [] self.processed_buildfiles: T.Set[str] = set() self.project_args_frozen = False self.global_args_frozen = False # implies self.project_args_frozen @@ -2200,9 +2199,7 @@ def func_generator(self, node: mparser.FunctionNode, if '@OUTPUT@' in o: raise InvalidArguments('Tried to use @OUTPUT@ in a rule with more than one output.') - gen = build.Generator(args[0], **kwargs) - self.generators.append(gen) - return gen + return build.Generator(args[0], **kwargs) @typed_pos_args('benchmark', str, (build.Executable, build.Jar, ExternalProgram, mesonlib.File, build.CustomTarget, build.CustomTargetIndex)) @typed_kwargs('benchmark', *TEST_KWS) From ea6a857bbbf946563263c2a887018133db36358f Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Mon, 29 Jan 2024 11:39:47 -0800 Subject: [PATCH 5/9] interpreter/dependencyfallbacks: Add copyright header --- mesonbuild/interpreter/dependencyfallbacks.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mesonbuild/interpreter/dependencyfallbacks.py b/mesonbuild/interpreter/dependencyfallbacks.py index fd8a025ea220..f7a1b99fe783 100644 --- a/mesonbuild/interpreter/dependencyfallbacks.py +++ b/mesonbuild/interpreter/dependencyfallbacks.py @@ -1,3 +1,7 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright 2021-2024 The Meson Developers +# Copyright © 2021-2024 Intel Corporation + from __future__ import annotations from .interpreterobjects import extract_required_kwarg From e1df461e5e115e17dd9fab86ca8a3747e1cb43f4 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Mon, 29 Jan 2024 13:13:56 -0800 Subject: [PATCH 6/9] build: store Build.modules as a set Since it's only used to check membership, a set makes more sense. Also add some documentation to the attribute --- mesonbuild/build.py | 6 +++++- mesonbuild/interpreter/interpreter.py | 4 ++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 460ed549be92..0d9374d40170 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -275,7 +275,11 @@ def __init__(self, environment: environment.Environment): self.dependency_overrides: PerMachine[T.Dict[T.Tuple, DependencyOverride]] = PerMachineDefaultable.default( environment.is_cross_build(), {}, {}) self.devenv: T.List[EnvironmentVariables] = [] - self.modules: T.List[str] = [] + self.modules: T.Set[str] = set() + """Used to track which modules are enabled in all subprojects. + + Needed for tracking whether a modules options needs to be exposed to the user. + """ def get_build_targets(self): build_targets = OrderedDict() diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index 65ba2ae6c009..f4f3f4af67fb 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -632,8 +632,8 @@ def func_import(self, node: mparser.BaseNode, args: T.Tuple[str], ext_module = NotFoundExtensionModule(real_modname) else: ext_module = module.initialize(self) - assert isinstance(ext_module, (ExtensionModule, NewExtensionModule)), 'for mypy' - self.build.modules.append(real_modname) + assert isinstance(ext_module, (ExtensionModule, NewExtensionModule)) + self.build.modules.add(real_modname) if ext_module.INFO.added: FeatureNew.single_use(f'module {ext_module.INFO.name}', ext_module.INFO.added, self.subproject, location=node) if ext_module.INFO.deprecated: From 659be974123abf87a8bff17108d77e7722de3af5 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Mon, 29 Jan 2024 14:36:48 -0800 Subject: [PATCH 7/9] interpreter: don't use `in dict.keys()` use `in dict` The former performs a linear search, which is slower than the set based search. --- mesonbuild/interpreter/interpreter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index f4f3f4af67fb..ec95b659eabe 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -1127,7 +1127,7 @@ def set_backend(self) -> None: return from ..backend import backends - if OptionKey('genvslite') in self.user_defined_options.cmd_line_options.keys(): + if OptionKey('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')) From 488cae147a4f937979ea0683ceb0dd40d24b8dfd Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 2 Feb 2024 09:54:52 -0800 Subject: [PATCH 8/9] interpreter: remove is_translated It's not actually useful, we can just add the root meson.build file to the depfiles when we translate the meson.build into ast. If there's a provided ast then we don't go down that path anyway. --- mesonbuild/interpreter/interpreter.py | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index ec95b659eabe..3d5d3da3b2a7 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -269,7 +269,6 @@ def __init__( subproject_dir: str = 'subprojects', default_project_options: T.Optional[T.Dict[OptionKey, str]] = None, ast: T.Optional[mparser.CodeBlockNode] = None, - is_translated: bool = False, relaxations: T.Optional[T.Set[InterpreterRuleRelaxation]] = None, user_defined_options: T.Optional[coredata.SharedCMDOptions] = None, ) -> None: @@ -283,6 +282,7 @@ def __init__( self.modules: T.Dict[str, NewExtensionModule] = {} self.subproject_dir = subproject_dir self.relaxations = relaxations or set() + self.build_def_files: mesonlib.OrderedSet[str] = mesonlib.OrderedSet() if ast is None: self.load_root_meson_file() else: @@ -305,16 +305,6 @@ def __init__( self.build_holder_map() self.user_defined_options = user_defined_options self.compilers: PerMachine[T.Dict[str, 'compilers.Compiler']] = PerMachine({}, {}) - - # build_def_files needs to be defined before parse_project is called - # - # For non-meson subprojects, we'll be using the ast. Even if it does - # exist we don't want to add a dependency on it, it's autogenerated - # from the actual build files, and is just for reference. - self.build_def_files: mesonlib.OrderedSet[str] = mesonlib.OrderedSet() - if not is_translated: - build_filename = os.path.join(self.subdir, environment.build_filename) - self.build_def_files.add(build_filename) self.parse_project() self._redetect_machines() @@ -339,6 +329,11 @@ def _redetect_machines(self) -> None: self.builtin['target_machine'] = \ OBJ.MachineHolder(self.build.environment.machines.target, self) + def load_root_meson_file(self) -> None: + build_filename = os.path.join(self.subdir, environment.build_filename) + self.build_def_files.add(build_filename) + super().load_root_meson_file() + def build_func_dict(self) -> None: self.funcs.update({'add_global_arguments': self.func_add_global_arguments, 'add_global_link_arguments': self.func_add_global_link_arguments, @@ -968,8 +963,7 @@ def _do_subproject_meson(self, subp_name: str, subdir: str, new_build = self.build.copy() subi = Interpreter(new_build, self.backend, subp_name, subdir, self.subproject_dir, - default_options, ast=ast, is_translated=(ast is not None), - relaxations=relaxations, + default_options, ast=ast, relaxations=relaxations, user_defined_options=self.user_defined_options) # Those lists are shared by all interpreters. That means that # even if the subproject fails, any modification that the subproject From 16746f58e273c9ecf86a4b837dc5ef7309c57cd2 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Mon, 6 May 2024 15:50:32 -0700 Subject: [PATCH 9/9] ast/introspection: Drop duplicate None check The AstInterpreter does this check as well, so don't do it twice. --- mesonbuild/ast/introspection.py | 1 - 1 file changed, 1 deletion(-) diff --git a/mesonbuild/ast/introspection.py b/mesonbuild/ast/introspection.py index b2eb1f8cd633..3e8d564e2fbf 100644 --- a/mesonbuild/ast/introspection.py +++ b/mesonbuild/ast/introspection.py @@ -55,7 +55,6 @@ def __init__(self, subproject: SubProject = SubProject(''), subproject_dir: str = 'subprojects', env: T.Optional[environment.Environment] = None): - visitors = visitors if visitors is not None else [] super().__init__(source_root, subdir, subproject, visitors=visitors) options = IntrospectionHelper(cross_file)