From 08da3873ddf81a97cdce782d8cde4b904280d8f5 Mon Sep 17 00:00:00 2001 From: Daniel Mensinger Date: Sun, 20 Jan 2019 19:27:42 +0100 Subject: [PATCH] Added target AST Interpreter support --- mesonbuild/ast/interpreter.py | 29 +++++++--- mesonbuild/ast/introspection.py | 94 ++++++++++++++++++++++++++++++++- 2 files changed, 115 insertions(+), 8 deletions(-) diff --git a/mesonbuild/ast/interpreter.py b/mesonbuild/ast/interpreter.py index 032337833..28f115039 100644 --- a/mesonbuild/ast/interpreter.py +++ b/mesonbuild/ast/interpreter.py @@ -170,16 +170,33 @@ class AstInterpreter(interpreterbase.InterpreterBase): def assignment(self, node): pass - def flatten_args(self, args): + def flatten_args(self, args, include_unknown_args: bool = False): # Resolve mparser.ArrayNode if needed flattend_args = [] + temp_args = [] if isinstance(args, mparser.ArrayNode): - args = [x.value for x in args.args.arguments] + args = [x for x in args.args.arguments] + elif isinstance(args, mparser.ArgumentNode): + args = [x for x in args.arguments] for i in args: if isinstance(i, mparser.ArrayNode): - flattend_args += [x.value for x in i.args.arguments] - elif isinstance(i, str): - flattend_args += [i] + temp_args += [x for x in i.args.arguments] else: - pass + temp_args += [i] + for i in temp_args: + if isinstance(i, mparser.ElementaryNode): + flattend_args += [i.value] + elif isinstance(i, (str, bool, int, float)) or include_unknown_args: + flattend_args += [i] return flattend_args + + def flatten_kwargs(self, kwargs: object, include_unknown_args: bool = False): + flattend_kwargs = {} + for key, val in kwargs.items(): + if isinstance(val, mparser.ElementaryNode): + flattend_kwargs[key] = val.value + elif isinstance(val, (mparser.ArrayNode, mparser.ArgumentNode)): + flattend_kwargs[key] = self.flatten_args(val, include_unknown_args) + elif isinstance(val, (str, bool, int, float)) or include_unknown_args: + flattend_kwargs[key] = val + return flattend_kwargs diff --git a/mesonbuild/ast/introspection.py b/mesonbuild/ast/introspection.py index f21788c44..fde9cc176 100644 --- a/mesonbuild/ast/introspection.py +++ b/mesonbuild/ast/introspection.py @@ -19,8 +19,9 @@ from . import AstInterpreter from .. import compilers, environment, mesonlib, mparser, optinterpreter from .. import coredata as cdata from ..interpreterbase import InvalidArguments +from ..build import Executable, CustomTarget, Jar, RunTarget, SharedLibrary, SharedModule, StaticLibrary -import os +import sys, os class IntrospectionHelper: # mimic an argparse namespace @@ -48,10 +49,18 @@ class IntrospectionInterpreter(AstInterpreter): self.backend = backend self.default_options = {'backend': self.backend} self.project_data = {} + self.targets = [] self.funcs.update({ + 'add_languages': self.func_add_languages, + 'executable': self.func_executable, + 'jar': self.func_jar, + 'library': self.func_library, 'project': self.func_project, - 'add_languages': self.func_add_languages + 'shared_library': self.func_shared_lib, + 'shared_module': self.func_shared_module, + 'static_library': self.func_static_lib, + 'both_libraries': self.func_both_lib, }) def func_project(self, node, args, kwargs): @@ -115,6 +124,87 @@ class IntrospectionInterpreter(AstInterpreter): if lang not in self.coredata.compilers: self.environment.detect_compilers(lang, need_cross_compiler) + def build_target(self, node, args, kwargs, targetclass): + if not args: + return + args = self.flatten_args(args, True) + kwargs = self.flatten_kwargs(kwargs, True) + name = args[0] + sources = args[1:] + if 'sources' in kwargs: + sources += self.flatten_args(kwargs['sources']) + + # Filter out kwargs from other target types. For example 'soversion' + # passed to library() when default_library == 'static'. + kwargs = {k: v for k, v in kwargs.items() if k in targetclass.known_kwargs} + + is_cross = False + objects = [] + target = targetclass(name, self.subdir, self.subproject, is_cross, sources, objects, self.environment, kwargs) + + self.targets += [{ + 'name': target.get_basename(), + 'id': target.get_id(), + 'type': target.get_typename(), + 'defined_in': os.path.normpath(os.path.join(self.source_root, self.subdir, environment.build_filename)), + 'subdir': self.subdir, + 'build_by_default': target.build_by_default, + 'sources': sources, + 'kwargs': kwargs, + 'node': node, + }] + + return + + def build_library(self, node, args, kwargs): + default_library = self.coredata.get_builtin_option('default_library') + if default_library == 'shared': + return self.build_target(node, args, kwargs, SharedLibrary) + elif default_library == 'static': + return self.build_target(node, args, kwargs, StaticLibrary) + elif default_library == 'both': + return self.build_target(node, args, kwargs, SharedLibrary) + + def func_executable(self, node, args, kwargs): + return self.build_target(node, args, kwargs, Executable) + + def func_static_lib(self, node, args, kwargs): + return self.build_target(node, args, kwargs, StaticLibrary) + + def func_shared_lib(self, node, args, kwargs): + return self.build_target(node, args, kwargs, SharedLibrary) + + def func_both_lib(self, node, args, kwargs): + return self.build_target(node, args, kwargs, SharedLibrary) + + def func_shared_module(self, node, args, kwargs): + return self.build_target(node, args, kwargs, SharedModule) + + def func_library(self, node, args, kwargs): + return self.build_library(node, args, kwargs) + + def func_jar(self, node, args, kwargs): + return self.build_target(node, args, kwargs, Jar) + + def func_build_target(self, node, args, kwargs): + if 'target_type' not in kwargs: + return + target_type = kwargs.pop('target_type') + if isinstance(target_type, mparser.ElementaryNode): + target_type = target_type.value + if target_type == 'executable': + return self.build_target(node, args, kwargs, Executable) + elif target_type == 'shared_library': + return self.build_target(node, args, kwargs, SharedLibrary) + elif target_type == 'static_library': + return self.build_target(node, args, kwargs, StaticLibrary) + elif target_type == 'both_libraries': + return self.build_target(node, args, kwargs, SharedLibrary) + elif target_type == 'library': + return self.build_library(node, args, kwargs) + elif target_type == 'jar': + return self.build_target(node, args, kwargs, Jar) + def is_subproject(self): return self.subproject != ''