diff options
| author | Charles Brunet <charles.brunet@optelgroup.com> | 2025-03-12 17:27:36 -0400 |
|---|---|---|
| committer | Dylan Baker <dylan@pnwbakers.com> | 2025-03-14 12:58:28 -0700 |
| commit | e65c879925219685cbcbb9a8367006b8c687167e (patch) | |
| tree | 2deac14448d7bf8b1efa70df3954ee62fa6f52eb | |
| parent | fa3816a2eeecf4c2ee86bff0c1d92f9a4354c98b (diff) | |
| download | meson-e65c879925219685cbcbb9a8367006b8c687167e.tar.gz | |
Extract common func_subdir functions to InterpreterBase
| -rw-r--r-- | mesonbuild/ast/interpreter.py | 28 | ||||
| -rw-r--r-- | mesonbuild/interpreter/interpreter.py | 36 | ||||
| -rw-r--r-- | mesonbuild/interpreterbase/interpreterbase.py | 40 |
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 |
