diff options
author | Daniel Schulte <trilader@schroedingers-bit.net> | 2018-09-16 17:42:57 +0200 |
---|---|---|
committer | Daniel Schulte <trilader@schroedingers-bit.net> | 2018-11-26 23:12:00 +0100 |
commit | 0e621937306575b9c1a2f5b07e6dd8d9e6c27ee7 (patch) | |
tree | be82e3b81b18205edc18b0f71d9683c88920ed9a /mesonbuild | |
parent | 8c9c5199f9c2c08190e424ffcaed6d54b8c47184 (diff) | |
download | meson-0e621937306575b9c1a2f5b07e6dd8d9e6c27ee7.zip meson-0e621937306575b9c1a2f5b07e6dd8d9e6c27ee7.tar.gz meson-0e621937306575b9c1a2f5b07e6dd8d9e6c27ee7.tar.bz2 |
mintro: Allow introspect --projectinfo without build directory.
This variant was added to allow introspection before configuring a build
directory. This is useful for IDE integration to allow displaying and/or
setting options for the initial configuration of the build directory.
It also allows showing basic information about the project even if it's
not yet configured or configuring failed.
The project 'name' field in --projectinfo is used inconsistently:
For the top level project it always shows the name configured in
the top level meson.build file. For subprojects it's referring to the
name of the directory the subproject's meson.build is contained in.
To have a consistent output and preserve the existing behavior this adds
the 'descriptive_name' field which always shows the name set in the
project.
To be consistent the 'descriptive_name' field was also added to the
--projectfiles variant that uses an already configured build.
It also extends the information shown with the list of buildsystem-files.
This is currently only implemented in the variant for unconfigured
projects.
Diffstat (limited to 'mesonbuild')
-rw-r--r-- | mesonbuild/mintro.py | 70 |
1 files changed, 68 insertions, 2 deletions
diff --git a/mesonbuild/mintro.py b/mesonbuild/mintro.py index 98bd16a..6cadd1e 100644 --- a/mesonbuild/mintro.py +++ b/mesonbuild/mintro.py @@ -22,6 +22,9 @@ project files and don't need this info.""" import json from . import build, mtest, coredata as cdata from . import mesonlib +from . import astinterpreter +from . import mparser +from .interpreterbase import InvalidArguments from .backend import ninjabackend import sys, os import pathlib @@ -223,19 +226,82 @@ def list_tests(testdata): print(json.dumps(result)) def list_projinfo(builddata): - result = {'name': builddata.project_name, 'version': builddata.project_version} + result = {'name': builddata.project_name, + 'version': builddata.project_version, + 'descriptive_name': builddata.project_name} subprojects = [] for k, v in builddata.subprojects.items(): c = {'name': k, - 'version': v} + 'version': v, + 'descriptive_name': builddata.projects.get(k)} subprojects.append(c) result['subprojects'] = subprojects print(json.dumps(result)) +class ProjectInfoInterperter(astinterpreter.AstInterpreter): + def __init__(self, source_root, subdir): + super().__init__(source_root, subdir) + self.funcs.update({'project': self.func_project}) + self.project_name = None + self.project_version = None + + def func_project(self, node, args, kwargs): + if len(args) < 1: + raise InvalidArguments('Not enough arguments to project(). Needs at least the project name.') + self.project_name = args[0] + self.project_version = kwargs.get('version', 'undefined') + if isinstance(self.project_version, mparser.ElementaryNode): + self.project_version = self.project_version.value + + def set_variable(self, varname, variable): + pass + + def analyze(self): + self.load_root_meson_file() + self.sanity_check_ast() + self.parse_project() + self.run() + +def list_projinfo_from_source(sourcedir): + files = find_buildsystem_files_list(sourcedir) + + result = {'buildsystem_files': []} + subprojects = {} + + for f in files: + f = f.replace('\\', '/') + if f == 'meson.build': + interpreter = ProjectInfoInterperter(sourcedir, '') + interpreter.analyze() + version = None + if interpreter.project_version is str: + version = interpreter.project_version + result.update({'name': interpreter.project_name, 'version': version, 'descriptive_name': interpreter.project_name}) + result['buildsystem_files'].append(f) + elif f.startswith('subprojects/'): + subproject_id = f.split('/')[1] + subproject = subprojects.setdefault(subproject_id, {'buildsystem_files': []}) + subproject['buildsystem_files'].append(f) + if f.count('/') == 2 and f.endswith('meson.build'): + interpreter = ProjectInfoInterperter(os.path.join(sourcedir, 'subprojects', subproject_id), '') + interpreter.analyze() + subproject.update({'name': subproject_id, 'version': interpreter.project_version, 'descriptive_name': interpreter.project_name}) + else: + result['buildsystem_files'].append(f) + + subprojects = [obj for name, obj in subprojects.items()] + result['subprojects'] = subprojects + print(json.dumps(result)) + def run(options): datadir = 'meson-private' if options.builddir is not None: datadir = os.path.join(options.builddir, datadir) + if options.builddir.endswith('/meson.build') or options.builddir.endswith('\\meson.build') or options.builddir == 'meson.build': + if options.projectinfo: + sourcedir = '.' if options.builddir == 'meson.build' else options.builddir[:-11] + list_projinfo_from_source(sourcedir) + return 0 if not os.path.isdir(datadir): print('Current directory is not a build dir. Please specify it or ' 'change the working directory to it.') |