summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCharles Brunet <charles.brunet@optelgroup.com>2025-03-12 17:27:36 -0400
committerDylan Baker <dylan@pnwbakers.com>2025-03-14 12:58:28 -0700
commite65c879925219685cbcbb9a8367006b8c687167e (patch)
tree2deac14448d7bf8b1efa70df3954ee62fa6f52eb
parentfa3816a2eeecf4c2ee86bff0c1d92f9a4354c98b (diff)
downloadmeson-e65c879925219685cbcbb9a8367006b8c687167e.tar.gz
Extract common func_subdir functions to InterpreterBase
-rw-r--r--mesonbuild/ast/interpreter.py28
-rw-r--r--mesonbuild/interpreter/interpreter.py36
-rw-r--r--mesonbuild/interpreterbase/interpreterbase.py40
3 files changed, 52 insertions, 52 deletions
diff --git a/mesonbuild/ast/interpreter.py b/mesonbuild/ast/interpreter.py
index 30fc52183..878fb34ed 100644
--- a/mesonbuild/ast/interpreter.py
+++ b/mesonbuild/ast/interpreter.py
@@ -89,7 +89,6 @@ class AstInterpreter(InterpreterBase):
def __init__(self, source_root: str, subdir: str, subproject: SubProject, visitors: T.Optional[T.List[AstVisitor]] = None):
super().__init__(source_root, subdir, subproject)
self.visitors = visitors if visitors is not None else []
- self.processed_buildfiles: T.Set[str] = set()
self.assignments: T.Dict[str, BaseNode] = {}
self.assign_vals: T.Dict[str, T.Any] = {}
self.reverse_assignment: T.Dict[str, BaseNode] = {}
@@ -174,33 +173,14 @@ class AstInterpreter(InterpreterBase):
sys.stderr.write(f'Unable to evaluate subdir({args}) in AstInterpreter --> Skipping\n')
return
- prev_subdir = self.subdir
- subdir = os.path.join(prev_subdir, args[0])
- absdir = os.path.join(self.source_root, subdir)
- buildfilename = os.path.join(subdir, environment.build_filename)
- absname = os.path.join(self.source_root, buildfilename)
- symlinkless_dir = os.path.realpath(absdir)
- build_file = os.path.join(symlinkless_dir, 'meson.build')
- if build_file in self.processed_buildfiles:
+ subdir, is_new = self._resolve_subdir(self.source_root, args[0])
+ if not is_new:
sys.stderr.write('Trying to enter {} which has already been visited --> Skipping\n'.format(args[0]))
return
- self.processed_buildfiles.add(build_file)
- if not os.path.isfile(absname):
+ if not self._evaluate_subdir(self.source_root, subdir, self.visitors):
+ buildfilename = os.path.join(subdir, environment.build_filename)
sys.stderr.write(f'Unable to find build file {buildfilename} --> Skipping\n')
- return
- code = self.read_buildfile(absname, buildfilename)
- try:
- codeblock = mparser.Parser(code, absname).parse()
- except mesonlib.MesonException as me:
- me.file = absname
- raise me
-
- self.subdir = subdir
- for i in self.visitors:
- codeblock.accept(i)
- self.evaluate_codeblock(codeblock)
- self.subdir = prev_subdir
def method_call(self, node: BaseNode) -> bool:
return True
diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py
index 14de76888..1b378e304 100644
--- a/mesonbuild/interpreter/interpreter.py
+++ b/mesonbuild/interpreter/interpreter.py
@@ -284,14 +284,12 @@ class Interpreter(InterpreterBase, HoldableObject):
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:
self.ast = ast
self.sanity_check_ast()
self.builtin.update({'meson': MesonMain(self.build, self)})
- self.processed_buildfiles: T.Set[str] = set()
self.validated_cache: T.Set[str] = set()
self.project_args_frozen = False
self.global_args_frozen = False # implies self.project_args_frozen
@@ -2461,39 +2459,21 @@ class Interpreter(InterpreterBase, HoldableObject):
raise InvalidArguments('The "meson-" prefix is reserved and cannot be used for top-level subdir().')
if args[0] == '':
raise InvalidArguments("The argument given to subdir() is the empty string ''. This is prohibited.")
+ if os.path.isabs(args[0]):
+ raise InvalidArguments('Subdir argument must be a relative path.')
for i in kwargs['if_found']:
if not i.found():
return
- prev_subdir = self.subdir
- subdir = os.path.join(prev_subdir, args[0])
- if os.path.isabs(subdir):
- raise InvalidArguments('Subdir argument must be a relative path.')
- absdir = os.path.join(self.environment.get_source_dir(), subdir)
- symlinkless_dir = os.path.realpath(absdir)
- build_file = os.path.join(symlinkless_dir, 'meson.build')
- if build_file in self.processed_buildfiles:
+ subdir, is_new = self._resolve_subdir(self.environment.get_source_dir(), args[0])
+ if not is_new:
raise InvalidArguments(f'Tried to enter directory "{subdir}", which has already been visited.')
- self.processed_buildfiles.add(build_file)
- self.subdir = subdir
+
os.makedirs(os.path.join(self.environment.build_dir, subdir), exist_ok=True)
- buildfilename = os.path.join(self.subdir, environment.build_filename)
- self.build_def_files.add(buildfilename)
- absname = os.path.join(self.environment.get_source_dir(), buildfilename)
- if not os.path.isfile(absname):
- self.subdir = prev_subdir
+
+ if not self._evaluate_subdir(self.environment.get_source_dir(), subdir):
+ buildfilename = os.path.join(subdir, environment.build_filename)
raise InterpreterException(f"Nonexistent build file '{buildfilename!s}'")
- code = self.read_buildfile(absname, buildfilename)
- try:
- codeblock = mparser.Parser(code, absname).parse()
- except mesonlib.MesonException as me:
- me.file = absname
- raise me
- try:
- self.evaluate_codeblock(codeblock)
- except SubdirDoneRequest:
- pass
- self.subdir = prev_subdir
# This is either ignored on basically any OS nowadays, or silently gets
# ignored (Solaris) or triggers an "illegal operation" error (FreeBSD).
diff --git a/mesonbuild/interpreterbase/interpreterbase.py b/mesonbuild/interpreterbase/interpreterbase.py
index 5849e9ca9..e94ba70dc 100644
--- a/mesonbuild/interpreterbase/interpreterbase.py
+++ b/mesonbuild/interpreterbase/interpreterbase.py
@@ -39,6 +39,7 @@ import textwrap
if T.TYPE_CHECKING:
from .baseobjects import InterpreterObjectTypeVar, SubProject, TYPE_kwargs, TYPE_var
+ from ..ast import AstVisitor
from ..interpreter import Interpreter
HolderMapType = T.Dict[
@@ -74,6 +75,8 @@ class InterpreterBase:
# Holder maps store a mapping from an HoldableObject to a class ObjectHolder
self.holder_map: HolderMapType = {}
self.bound_holder_map: HolderMapType = {}
+ self.build_def_files: mesonlib.OrderedSet[str] = mesonlib.OrderedSet()
+ self.processed_buildfiles: T.Set[str] = set()
self.subdir = subdir
self.root_subdir = subdir
self.subproject = subproject
@@ -668,3 +671,40 @@ class InterpreterBase:
def validate_extraction(self, buildtarget: mesonlib.HoldableObject) -> None:
raise InterpreterException('validate_extraction is not implemented in this context (please file a bug)')
+
+ def _resolve_subdir(self, rootdir: str, new_subdir: str) -> T.Tuple[str, bool]:
+ subdir = os.path.join(self.subdir, new_subdir)
+ absdir = os.path.join(rootdir, subdir)
+ symlinkless_dir = os.path.realpath(absdir)
+ build_file = os.path.join(symlinkless_dir, environment.build_filename)
+ if build_file in self.processed_buildfiles:
+ return subdir, False
+ self.processed_buildfiles.add(build_file)
+ return subdir, True
+
+ def _evaluate_subdir(self, rootdir: str, subdir: str, visitors: T.Optional[T.Iterable[AstVisitor]] = None) -> bool:
+ buildfilename = os.path.join(subdir, environment.build_filename)
+ self.build_def_files.add(buildfilename)
+
+ absname = os.path.join(rootdir, buildfilename)
+ if not os.path.isfile(absname):
+ return False
+
+ code = self.read_buildfile(absname, buildfilename)
+ try:
+ codeblock = mparser.Parser(code, absname).parse()
+ except mesonlib.MesonException as me:
+ me.file = absname
+ raise me
+ try:
+ prev_subdir = self.subdir
+ self.subdir = subdir
+ if visitors:
+ for visitor in visitors:
+ codeblock.accept(visitor)
+ self.evaluate_codeblock(codeblock)
+ except SubdirDoneRequest:
+ pass
+ finally:
+ self.subdir = prev_subdir
+ return True