From 98e60f59acf9bf2c74bc38cb8d0285a5d76293a7 Mon Sep 17 00:00:00 2001 From: Daniel Mensinger Date: Mon, 18 Feb 2019 14:37:30 +0100 Subject: Minor introspection refactoring --- mesonbuild/mintro.py | 80 ++++++++++++++++++++++++++-------------------------- 1 file changed, 40 insertions(+), 40 deletions(-) (limited to 'mesonbuild/mintro.py') diff --git a/mesonbuild/mintro.py b/mesonbuild/mintro.py index b1e6509..f7e5358 100644 --- a/mesonbuild/mintro.py +++ b/mesonbuild/mintro.py @@ -37,7 +37,7 @@ def get_meson_introspection_version(): def get_meson_introspection_required_version(): return ['>=1.0', '<2.0'] -def get_meson_introspection_types(coredata: cdata.CoreData = None, builddata: build.Build = None, backend: backends.Backend = None): +def get_meson_introspection_types(coredata: cdata.CoreData = None, builddata: build.Build = None, backend: backends.Backend = None, sourcedir: str = None): if backend and builddata: benchmarkdata = backend.create_test_serialisation(builddata.get_benchmarks()) testdata = backend.create_test_serialisation(builddata.get_tests()) @@ -52,6 +52,7 @@ def get_meson_introspection_types(coredata: cdata.CoreData = None, builddata: bu }, 'buildoptions': { 'func': lambda: list_buildoptions(coredata), + 'no_bd': lambda intr: list_buildoptions_from_source(intr), 'desc': 'List all build options.', }, 'buildsystem_files': { @@ -69,6 +70,7 @@ def get_meson_introspection_types(coredata: cdata.CoreData = None, builddata: bu }, 'projectinfo': { 'func': lambda: list_projinfo(builddata), + 'no_bd': lambda intr: list_projinfo_from_source(sourcedir, intr), 'desc': 'Information about projects.', }, 'targets': { @@ -147,15 +149,8 @@ def list_targets(builddata: build.Build, installdata, backend: backends.Backend) tlist.append(t) return tlist -def list_buildoptions_from_source(sourcedir, backend, indent): - # Make sure that log entries in other parts of meson don't interfere with the JSON output - mlog.disable() - backend = backends.get_backend_from_name(backend, None) - intr = IntrospectionInterpreter(sourcedir, '', backend.name) - intr.analyze() - # Reenable logging just in case - mlog.enable() - print(json.dumps(list_buildoptions(intr.coredata), indent=indent)) +def list_buildoptions_from_source(intr: IntrospectionInterpreter): + return list_buildoptions(intr.coredata) def list_target_files(target_name: str, targets: list, source_dir: str): sys.stderr.write("WARNING: The --target-files introspection API is deprecated. Use --targets instead.\n") @@ -299,15 +294,10 @@ def list_projinfo(builddata: build.Build): result['subprojects'] = subprojects return result -def list_projinfo_from_source(sourcedir, indent): +def list_projinfo_from_source(sourcedir: str, intr: IntrospectionInterpreter): files = find_buildsystem_files_list(sourcedir) files = [os.path.normpath(x) for x in files] - mlog.disable() - intr = IntrospectionInterpreter(sourcedir, '', 'ninja') - intr.analyze() - mlog.enable() - for i in intr.project_data['subprojects']: basedir = os.path.join(intr.subproject_dir, i['name']) i['buildsystem_files'] = [x for x in files if x.startswith(basedir)] @@ -315,23 +305,47 @@ def list_projinfo_from_source(sourcedir, indent): intr.project_data['buildsystem_files'] = files intr.project_data['subproject_dir'] = intr.subproject_dir - print(json.dumps(intr.project_data, indent=indent)) + return intr.project_data + +def print_results(options, results, indent): + if len(results) == 0 and not options.force_dict: + print('No command specified') + return 1 + elif len(results) == 1 and not options.force_dict: + # Make to keep the existing output format for a single option + print(json.dumps(results[0][1], indent=indent)) + else: + out = {} + for i in results: + out[i[0]] = i[1] + print(json.dumps(out, indent=indent)) + return 0 def run(options): datadir = 'meson-private' infodir = 'meson-info' - indent = 4 if options.indent else None if options.builddir is not None: datadir = os.path.join(options.builddir, datadir) infodir = os.path.join(options.builddir, infodir) + indent = 4 if options.indent else None + results = [] + sourcedir = '.' if options.builddir == 'meson.build' else options.builddir[:-11] + intro_types = get_meson_introspection_types(sourcedir=sourcedir) + if 'meson.build' in [os.path.basename(options.builddir), options.builddir]: - sourcedir = '.' if options.builddir == 'meson.build' else options.builddir[:-11] - if options.projectinfo: - list_projinfo_from_source(sourcedir, indent) - return 0 - if options.buildoptions: - list_buildoptions_from_source(sourcedir, options.backend, indent) - return 0 + # Make sure that log entries in other parts of meson don't interfere with the JSON output + mlog.disable() + backend = backends.get_backend_from_name(options.backend, None) + intr = IntrospectionInterpreter(sourcedir, '', backend.name) + intr.analyze() + # Reenable logging just in case + mlog.enable() + for key, val in intro_types.items(): + if (not options.all and not getattr(options, key, False)) or 'no_bd' not in val: + continue + results += [(key, val['no_bd'](intr))] + return print_results(options, results, indent) + infofile = get_meson_info_file(infodir) if not os.path.isdir(datadir) or not os.path.isdir(infodir) or not os.path.isfile(infofile): print('Current directory is not a meson build directory.' @@ -355,9 +369,6 @@ def run(options): .format(intro_vers, ' and '.join(vers_to_check))) return 1 - results = [] - intro_types = get_meson_introspection_types() - # Handle the one option that does not have its own JSON file (meybe deprecate / remove this?) if options.target_files is not None: targets_file = os.path.join(infodir, 'intro-targets.json') @@ -376,18 +387,7 @@ def run(options): with open(curr, 'r') as fp: results += [(i, json.load(fp))] - if len(results) == 0 and not options.force_dict: - print('No command specified') - return 1 - elif len(results) == 1 and not options.force_dict: - # Make to keep the existing output format for a single option - print(json.dumps(results[0][1], indent=indent)) - else: - out = {} - for i in results: - out[i[0]] = i[1] - print(json.dumps(out, indent=indent)) - return 0 + return print_results(options, results, indent) updated_introspection_files = [] -- cgit v1.1 From 8a1411a1e8a8a2c37de0d25ec129aba65703616e Mon Sep 17 00:00:00 2001 From: Daniel Mensinger Date: Mon, 18 Feb 2019 15:51:40 +0100 Subject: Target introspection from source --- mesonbuild/mintro.py | 43 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) (limited to 'mesonbuild/mintro.py') diff --git a/mesonbuild/mintro.py b/mesonbuild/mintro.py index f7e5358..ed74781 100644 --- a/mesonbuild/mintro.py +++ b/mesonbuild/mintro.py @@ -22,9 +22,10 @@ project files and don't need this info.""" import json from . import build, coredata as cdata from . import mesonlib -from .ast import IntrospectionInterpreter +from .ast import IntrospectionInterpreter, build_target_functions from . import mlog from .backend import backends +from .mparser import FunctionNode, ArrayNode, ArgumentNode, StringNode import sys, os import pathlib @@ -75,6 +76,7 @@ def get_meson_introspection_types(coredata: cdata.CoreData = None, builddata: bu }, 'targets': { 'func': lambda: list_targets(builddata, installdata, backend), + 'no_bd': lambda intr: list_targets_from_source(intr), 'desc': 'List top level targets.', }, 'tests': { @@ -115,6 +117,45 @@ def list_installed(installdata): res[path] = os.path.join(installdata.prefix, installpath) return res +def list_targets_from_source(intr: IntrospectionInterpreter): + tlist = [] + for i in intr.targets: + sources = [] + for n in i['sources']: + args = [] + if isinstance(n, FunctionNode): + args = list(n.args.arguments) + if n.func_name in build_target_functions: + args.pop(0) + elif isinstance(n, ArrayNode): + args = n.args.arguments + elif isinstance(n, ArgumentNode): + args = n.arguments + for j in args: + if isinstance(j, StringNode): + sources += [j.value] + elif isinstance(j, str): + sources += [j] + + tlist += [{ + 'name': i['name'], + 'id': i['id'], + 'type': i['type'], + 'defined_in': i['defined_in'], + 'filename': [os.path.join(i['subdir'], x) for x in i['outputs']], + 'build_by_default': i['build_by_default'], + 'target_sources': [{ + 'language': 'unknown', + 'compiler': [], + 'parameters': [], + 'sources': [os.path.normpath(os.path.join(os.path.abspath(intr.source_root), i['subdir'], x)) for x in sources], + 'generated_sources': [] + }], + 'installed': i['installed'] + }] + + return tlist + def list_targets(builddata: build.Build, installdata, backend: backends.Backend): tlist = [] build_dir = builddata.environment.get_build_dir() -- cgit v1.1 From f9b41d5ecbed3adabb6a0433892ea801b531c412 Mon Sep 17 00:00:00 2001 From: Daniel Mensinger Date: Mon, 18 Feb 2019 16:43:48 +0100 Subject: mintro: Dependencies from source --- mesonbuild/mintro.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'mesonbuild/mintro.py') diff --git a/mesonbuild/mintro.py b/mesonbuild/mintro.py index ed74781..349a399 100644 --- a/mesonbuild/mintro.py +++ b/mesonbuild/mintro.py @@ -22,7 +22,7 @@ project files and don't need this info.""" import json from . import build, coredata as cdata from . import mesonlib -from .ast import IntrospectionInterpreter, build_target_functions +from .ast import IntrospectionInterpreter, build_target_functions, AstConditionLevel, AstIDGenerator, AstIndentationGenerator from . import mlog from .backend import backends from .mparser import FunctionNode, ArrayNode, ArgumentNode, StringNode @@ -63,6 +63,7 @@ def get_meson_introspection_types(coredata: cdata.CoreData = None, builddata: bu }, 'dependencies': { 'func': lambda: list_deps(coredata), + 'no_bd': lambda intr: list_deps_from_source(intr), 'desc': 'List external dependencies.', }, 'installed': { @@ -286,6 +287,12 @@ def list_buildsystem_files(builddata: build.Build): filelist = [os.path.join(src_dir, x) for x in filelist] return filelist +def list_deps_from_source(intr: IntrospectionInterpreter): + result = [] + for i in intr.dependencies: + result += [{k: v for k, v in i.items() if k in ['name', 'required', 'has_fallback', 'conditional']}] + return result + def list_deps(coredata: cdata.CoreData): result = [] for d in coredata.deps.values(): @@ -377,7 +384,7 @@ def run(options): # Make sure that log entries in other parts of meson don't interfere with the JSON output mlog.disable() backend = backends.get_backend_from_name(options.backend, None) - intr = IntrospectionInterpreter(sourcedir, '', backend.name) + intr = IntrospectionInterpreter(sourcedir, '', backend.name, visitors = [AstIDGenerator(), AstIndentationGenerator(), AstConditionLevel()]) intr.analyze() # Reenable logging just in case mlog.enable() -- cgit v1.1 From f9da03fb7bbc73630ccad2cc505acbd9490f1d5c Mon Sep 17 00:00:00 2001 From: Daniel Mensinger Date: Fri, 1 Mar 2019 09:35:47 +0100 Subject: mintro: Address code review --- mesonbuild/mintro.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'mesonbuild/mintro.py') diff --git a/mesonbuild/mintro.py b/mesonbuild/mintro.py index 349a399..2d9bd9f 100644 --- a/mesonbuild/mintro.py +++ b/mesonbuild/mintro.py @@ -26,6 +26,7 @@ from .ast import IntrospectionInterpreter, build_target_functions, AstConditionL from . import mlog from .backend import backends from .mparser import FunctionNode, ArrayNode, ArgumentNode, StringNode +from typing import List, Optional import sys, os import pathlib @@ -38,7 +39,10 @@ def get_meson_introspection_version(): def get_meson_introspection_required_version(): return ['>=1.0', '<2.0'] -def get_meson_introspection_types(coredata: cdata.CoreData = None, builddata: build.Build = None, backend: backends.Backend = None, sourcedir: str = None): +def get_meson_introspection_types(coredata: Optional[cdata.CoreData] = None, + builddata: Optional[build.Build] = None, + backend: Optional[backends.Backend] = None, + sourcedir: Optional[str] = None): if backend and builddata: benchmarkdata = backend.create_test_serialisation(builddata.get_benchmarks()) testdata = backend.create_test_serialisation(builddata.get_tests()) @@ -191,7 +195,7 @@ def list_targets(builddata: build.Build, installdata, backend: backends.Backend) tlist.append(t) return tlist -def list_buildoptions_from_source(intr: IntrospectionInterpreter): +def list_buildoptions_from_source(intr: IntrospectionInterpreter) -> List[dict]: return list_buildoptions(intr.coredata) def list_target_files(target_name: str, targets: list, source_dir: str): @@ -215,7 +219,7 @@ def list_target_files(target_name: str, targets: list, source_dir: str): return result -def list_buildoptions(coredata: cdata.CoreData): +def list_buildoptions(coredata: cdata.CoreData) -> List[dict]: optlist = [] dir_option_names = ['bindir', -- cgit v1.1 From 185dc8c2e5d8e429f5d55d18800d6a4487194f09 Mon Sep 17 00:00:00 2001 From: Daniel Mensinger Date: Sat, 2 Mar 2019 10:54:11 +0100 Subject: mintro: Fix unit test --- mesonbuild/mintro.py | 1 + 1 file changed, 1 insertion(+) (limited to 'mesonbuild/mintro.py') diff --git a/mesonbuild/mintro.py b/mesonbuild/mintro.py index 2d9bd9f..b3cc4f5 100644 --- a/mesonbuild/mintro.py +++ b/mesonbuild/mintro.py @@ -156,6 +156,7 @@ def list_targets_from_source(intr: IntrospectionInterpreter): 'sources': [os.path.normpath(os.path.join(os.path.abspath(intr.source_root), i['subdir'], x)) for x in sources], 'generated_sources': [] }], + 'subproject': None, # Subprojects are not supported 'installed': i['installed'] }] -- cgit v1.1 From 7074f12644ae0ddc7f8d7471f776bce3375934d4 Mon Sep 17 00:00:00 2001 From: Daniel Mensinger Date: Sun, 3 Mar 2019 22:12:31 +0100 Subject: mintro: Renamed --dependencies --> --scan-dependencies --- mesonbuild/mintro.py | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'mesonbuild/mintro.py') diff --git a/mesonbuild/mintro.py b/mesonbuild/mintro.py index b3cc4f5..243dc5d 100644 --- a/mesonbuild/mintro.py +++ b/mesonbuild/mintro.py @@ -70,6 +70,11 @@ def get_meson_introspection_types(coredata: Optional[cdata.CoreData] = None, 'no_bd': lambda intr: list_deps_from_source(intr), 'desc': 'List external dependencies.', }, + 'scan_dependencies': { + 'no_bd': lambda intr: list_deps_from_source(intr), + 'desc': 'Scan for dependencies used in the meson.build file.', + 'key': 'scan-dependencies', + }, 'installed': { 'func': lambda: list_installed(installdata), 'desc': 'List all installed files and directories.', @@ -431,6 +436,8 @@ def run(options): # Extract introspection information from JSON for i in intro_types.keys(): + if 'func' not in intro_types[i]: + continue if not options.all and not getattr(options, i, False): continue curr = os.path.join(infodir, 'intro-{}.json'.format(i)) @@ -461,6 +468,8 @@ def generate_introspection_file(builddata: build.Build, backend: backends.Backen intro_info = [] for key, val in intro_types.items(): + if 'func' not in val: + continue intro_info += [(key, val['func']())] write_intro_info(intro_info, builddata.environment.info_dir) @@ -489,6 +498,8 @@ def write_meson_info_file(builddata: build.Build, errors: list, build_files_upda intro_info = {} for i in intro_types.keys(): + if 'func' not in intro_types[i]: + continue intro_info[i] = { 'file': 'intro-{}.json'.format(i), 'updated': i in updated_introspection_files -- cgit v1.1