# SPDX-License-Identifier: Apache-2.0
# Copyright 2014-2016 The Meson development team

from __future__ import annotations

"""This is a helper script for IDE developers. It allows you to
extract information such as list of targets, files, compiler flags,
tests and so on. All output is in JSON for simple parsing.

Currently only works for the Ninja backend. Others use generated
project files and don't need this info."""

from contextlib import redirect_stdout
import collections
import dataclasses
import json
import os
from pathlib import Path, PurePath
import sys
import typing as T

from . import build, mesonlib, options, coredata as cdata
from .ast import IntrospectionInterpreter, BUILD_TARGET_FUNCTIONS, AstConditionLevel, AstIDGenerator, AstIndentationGenerator, AstJSONPrinter
from .backend import backends
from .dependencies import Dependency
from . import environment
from .interpreterbase import ObjectHolder
from .mesonlib import OptionKey
from .mparser import FunctionNode, ArrayNode, ArgumentNode, StringNode

if T.TYPE_CHECKING:
    import argparse

    from .interpreter import Interpreter
    from .mparser import BaseNode

def get_meson_info_file(info_dir: str) -> str:
    return os.path.join(info_dir, 'meson-info.json')

def get_meson_introspection_version() -> str:
    return '1.0.0'

def get_meson_introspection_required_version() -> T.List[str]:
    return ['>=1.0', '<2.0']

class IntroCommand:
    def __init__(self,
                 desc: str,
                 func: T.Optional[T.Callable[[], T.Union[dict, list]]] = None,
                 no_bd: T.Optional[T.Callable[[IntrospectionInterpreter], T.Union[dict, list]]] = None) -> None:
        self.desc = desc + '.'
        self.func = func
        self.no_bd = no_bd

def get_meson_introspection_types(coredata: T.Optional[cdata.CoreData] = None,
                                  builddata: T.Optional[build.Build] = None,
                                  backend: T.Optional[backends.Backend] = None) -> 'T.Mapping[str, IntroCommand]':
    if backend and builddata:
        benchmarkdata = backend.create_test_serialisation(builddata.get_benchmarks())
        testdata = backend.create_test_serialisation(builddata.get_tests())
        installdata = backend.create_install_data()
        interpreter = backend.interpreter
    else:
        benchmarkdata = testdata = installdata = None

    # Enforce key order for argparse
    return collections.OrderedDict([
        ('ast', IntroCommand('Dump the AST of the meson file', no_bd=dump_ast)),
        ('benchmarks', IntroCommand('List all benchmarks', func=lambda: list_benchmarks(benchmarkdata))),
        ('buildoptions', IntroCommand('List all build options', func=lambda: list_buildoptions(coredata), no_bd=list_buildoptions_from_source)),
        ('buildsystem_files', IntroCommand('List files that make up the build system', func=lambda: list_buildsystem_files(builddata, interpreter))),
        ('compilers', IntroCommand('List used compilers', func=lambda: list_compilers(coredata))),
        ('dependencies', IntroCommand('List external dependencies', func=lambda: list_deps(coredata, backend), no_bd=list_deps_from_source)),
        ('scan_dependencies', IntroCommand('Scan for dependencies used in the meson.build file', no_bd=list_deps_from_source)),
        ('installed', IntroCommand('List all installed files and directories', func=lambda: list_installed(installdata))),
        ('install_plan', IntroCommand('List all installed files and directories with their details', func=lambda: list_install_plan(installdata))),
        ('machines', IntroCommand('Information about host, build, and target machines', func=lambda: list_machines(builddata))),
        ('projectinfo', IntroCommand('Information about projects', func=lambda: list_projinfo(builddata), no_bd=list_projinfo_from_source)),
        ('targets', IntroCommand('List top level targets', func=lambda: list_targets(builddata, installdata, backend), no_bd=list_targets_from_source)),
        ('tests', IntroCommand('List all unit tests', func=lambda: list_tests(testdata))),
    ])

# Note: when adding arguments, please also add them to the completion
# scripts in $MESONSRC/data/shell-completions/
def add_arguments(parser: argparse.ArgumentParser) -> None:
    intro_types = get_meson_introspection_types()
    for key, val in intro_types.items():
        flag = '--' + key.replace('_', '-')
        parser.add_argument(flag, action='store_true', dest=key, default=False, help=val.desc)

    parser.add_argument('--backend', choices=sorted(options.backendlist), dest='backend', default='ninja',
                        help='The backend to use for the --buildoptions introspection.')
    parser.add_argument('-a', '--all', action='store_true', dest='all', default=False,
                        help='Print all available information.')
    parser.add_argument('-i', '--indent', action='store_true', dest='indent', default=False,
                        help='Enable pretty printed JSON.')
    parser.add_argument('-f', '--force-object-output', action='store_true', dest='force_dict', default=False,
                        help='Always use the new JSON format for multiple entries (even for 0 and 1 introspection commands)')
    parser.add_argument('builddir', nargs='?', default='.', help='The build directory')

def dump_ast(intr: IntrospectionInterpreter) -> T.Dict[str, T.Any]:
    printer = AstJSONPrinter()
    intr.ast.accept(printer)
    return printer.result

def list_installed(installdata: backends.InstallData) -> T.Dict[str, str]:
    res = {}
    if installdata is not None:
        for t in installdata.targets:
            res[os.path.join(installdata.build_dir, t.fname)] = \
                os.path.join(installdata.prefix, t.outdir, os.path.basename(t.fname))
        for i in installdata.data:
            res[i.path] = os.path.join(installdata.prefix, i.install_path)
        for i in installdata.headers:
            res[i.path] = os.path.join(installdata.prefix, i.install_path, os.path.basename(i.path))
        for i in installdata.man:
            res[i.path] = os.path.join(installdata.prefix, i.install_path)
        for i in installdata.install_subdirs:
            res[i.path] = os.path.join(installdata.prefix, i.install_path)
        for s in installdata.symlinks:
            basename = os.path.basename(s.name)
            res[basename] = os.path.join(installdata.prefix, s.install_path, basename)
    return res

def list_install_plan(installdata: backends.InstallData) -> T.Dict[str, T.Dict[str, T.Dict[str, T.Optional[str]]]]:
    plan: T.Dict[str, T.Dict[str, T.Dict[str, T.Optional[str]]]] = {
        'targets': {
            os.path.join(installdata.build_dir, target.fname): {
                'destination': target.out_name,
                'tag': target.tag or None,
                'subproject': target.subproject or None,
            }
            for target in installdata.targets
        },
    }
    for key, data_list in {
        'data': installdata.data,
        'man': installdata.man,
        'headers': installdata.headers,
        'install_subdirs': installdata.install_subdirs
    }.items():
        # Mypy doesn't recognize SubdirInstallData as a subclass of InstallDataBase
        for data in data_list: # type: ignore[attr-defined]
            data_type = data.data_type or key
            install_path_name = data.install_path_name
            if key == 'headers':  # in the headers, install_path_name is the directory
                install_path_name = os.path.join(install_path_name, os.path.basename(data.path))

            entry = {
                'destination': install_path_name,
                'tag': data.tag or None,
                'subproject': data.subproject or None,
            }

            if key == 'install_subdirs':
                exclude_files, exclude_dirs = data.exclude or ([], [])
                entry['exclude_dirs'] = list(exclude_dirs)
                entry['exclude_files'] = list(exclude_files)

            plan[data_type] = plan.get(data_type, {})
            plan[data_type][data.path] = entry

    return plan

def get_target_dir(coredata: cdata.CoreData, subdir: str) -> str:
    if coredata.get_option(OptionKey('layout')) == 'flat':
        return 'meson-out'
    else:
        return subdir

def list_targets_from_source(intr: IntrospectionInterpreter) -> T.List[T.Dict[str, T.Union[bool, str, T.List[T.Union[str, T.Dict[str, T.Union[str, T.List[str], bool]]]]]]]:
    tlist: T.List[T.Dict[str, T.Union[bool, str, T.List[T.Union[str, T.Dict[str, T.Union[str, T.List[str], bool]]]]]]] = []
    root_dir = Path(intr.source_root)

    def nodes_to_paths(node_list: T.List[BaseNode]) -> T.List[Path]:
        res: T.List[Path] = []
        for n in node_list:
            args: T.List[BaseNode] = []
            if isinstance(n, FunctionNode):
                args = list(n.args.arguments)
                if n.func_name.value 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):
                    assert isinstance(j.value, str)
                    res += [Path(j.value)]
                elif isinstance(j, str):
                    res += [Path(j)]
        res = [root_dir / i['subdir'] / x for x in res]
        res = [x.resolve() for x in res]
        return res

    for i in intr.targets:
        sources = nodes_to_paths(i['sources'])
        extra_f = nodes_to_paths(i['extra_files'])
        outdir = get_target_dir(intr.coredata, i['subdir'])

        tlist += [{
            'name': i['name'],
            'id': i['id'],
            'type': i['type'],
            'defined_in': i['defined_in'],
            'filename': [os.path.join(outdir, x) for x in i['outputs']],
            'build_by_default': i['build_by_default'],
            'target_sources': [{
                'language': 'unknown',
                'compiler': [],
                'parameters': [],
                'sources': [str(x) for x in sources],
                'generated_sources': []
            }],
            'depends': [],
            'extra_files': [str(x) for x in extra_f],
            'subproject': None, # Subprojects are not supported
            'installed': i['installed']
        }]

    return tlist

def list_targets(builddata: build.Build, installdata: backends.InstallData, backend: backends.Backend) -> T.List[T.Any]:
    tlist: T.List[T.Any] = []
    build_dir = builddata.environment.get_build_dir()
    src_dir = builddata.environment.get_source_dir()

    # Fast lookup table for installation files
    install_lookuptable = {}
    for i in installdata.targets:
        basename = os.path.basename(i.fname)
        install_lookuptable[basename] = [str(PurePath(installdata.prefix, i.outdir, basename))]
    for s in installdata.symlinks:
        # Symlink's target must already be in the table. They share the same list
        # to support symlinks to symlinks recursively, such as .so -> .so.0 -> .so.1.2.3
        basename = os.path.basename(s.name)
        try:
            install_lookuptable[basename] = install_lookuptable[os.path.basename(s.target)]
            install_lookuptable[basename].append(str(PurePath(installdata.prefix, s.install_path, basename)))
        except KeyError:
            pass

    for (idname, target) in builddata.get_targets().items():
        if not isinstance(target, build.Target):
            raise RuntimeError('The target object in `builddata.get_targets()` is not of type `build.Target`. Please file a bug with this error message.')

        outdir = get_target_dir(builddata.environment.coredata, target.subdir)
        t = {
            'name': target.get_basename(),
            'id': idname,
            'type': target.get_typename(),
            'defined_in': os.path.normpath(os.path.join(src_dir, target.subdir, environment.build_filename)),
            'filename': [os.path.join(build_dir, outdir, x) for x in target.get_outputs()],
            'build_by_default': target.build_by_default,
            'target_sources': backend.get_introspection_data(idname, target),
            'extra_files': [os.path.normpath(os.path.join(src_dir, x.subdir, x.fname)) for x in target.extra_files],
            'subproject': target.subproject or None,
            'dependencies': [d.name for d in getattr(target, 'external_deps', [])],
            'depends': [lib.get_id() for lib in getattr(target, 'dependencies', [])]
        }

        vs_module_defs = getattr(target, 'vs_module_defs', None)
        if vs_module_defs is not None:
            t['vs_module_defs'] = vs_module_defs.relative_name()
        win_subsystem = getattr(target, 'win_subsystem', None)
        if win_subsystem is not None:
            t['win_subsystem'] = win_subsystem

        if installdata and target.should_install():
            t['installed'] = True
            ifn = [install_lookuptable.get(x, [None]) for x in target.get_outputs()]
            t['install_filename'] = [x for sublist in ifn for x in sublist]  # flatten the list
        else:
            t['installed'] = False
        tlist.append(t)
    return tlist

def list_buildoptions_from_source(intr: IntrospectionInterpreter) -> T.List[T.Dict[str, T.Union[str, bool, int, T.List[str]]]]:
    subprojects = [i['name'] for i in intr.project_data['subprojects']]
    return list_buildoptions(intr.coredata, subprojects)

def list_buildoptions(coredata: cdata.CoreData, subprojects: T.Optional[T.List[str]] = None) -> T.List[T.Dict[str, T.Union[str, bool, int, T.List[str]]]]:
    optlist: T.List[T.Dict[str, T.Union[str, bool, int, T.List[str]]]] = []
    subprojects = subprojects or []

    dir_option_names = set(options.BUILTIN_DIR_OPTIONS)
    test_option_names = {OptionKey('errorlogs'),
                         OptionKey('stdsplit')}

    dir_options: 'cdata.MutableKeyedOptionDictType' = {}
    test_options: 'cdata.MutableKeyedOptionDictType' = {}
    core_options: 'cdata.MutableKeyedOptionDictType' = {}
    for k, v in coredata.optstore.items():
        if k in dir_option_names:
            dir_options[k] = v
        elif k in test_option_names:
            test_options[k] = v
        elif k.is_builtin():
            core_options[k] = v
            if not v.yielding:
                for s in subprojects:
                    core_options[k.evolve(subproject=s)] = v

    def add_keys(opts: 'cdata.KeyedOptionDictType', section: str) -> None:
        for key, opt in sorted(opts.items()):
            optdict = {'name': str(key), 'value': opt.value, 'section': section,
                       'machine': key.machine.get_lower_case_name() if coredata.is_per_machine_option(key) else 'any'}
            if isinstance(opt, options.UserStringOption):
                typestr = 'string'
            elif isinstance(opt, options.UserBooleanOption):
                typestr = 'boolean'
            elif isinstance(opt, options.UserComboOption):
                optdict['choices'] = opt.choices
                typestr = 'combo'
            elif isinstance(opt, options.UserIntegerOption):
                typestr = 'integer'
            elif isinstance(opt, options.UserArrayOption):
                typestr = 'array'
                if opt.choices:
                    optdict['choices'] = opt.choices
            else:
                raise RuntimeError("Unknown option type")
            optdict['type'] = typestr
            optdict['description'] = opt.description
            optlist.append(optdict)

    add_keys(core_options, 'core')
    add_keys({k: v for k, v in coredata.optstore.items() if k.is_backend()}, 'backend')
    add_keys({k: v for k, v in coredata.optstore.items() if k.is_base()}, 'base')
    add_keys(
        {k: v for k, v in sorted(coredata.optstore.items(), key=lambda i: i[0].machine) if k.is_compiler()},
        'compiler',
    )
    add_keys(dir_options, 'directory')
    add_keys({k: v for k, v in coredata.optstore.items() if k.is_project()}, 'user')
    add_keys(test_options, 'test')
    return optlist

def find_buildsystem_files_list(src_dir: str) -> T.List[str]:
    build_files = frozenset({'meson.build', 'meson.options', 'meson_options.txt'})
    # I feel dirty about this. But only slightly.
    filelist: T.List[str] = []
    for root, _, files in os.walk(src_dir):
        filelist.extend(os.path.relpath(os.path.join(root, f), src_dir)
                        for f in build_files.intersection(files))
    return filelist

def list_buildsystem_files(builddata: build.Build, interpreter: Interpreter) -> T.List[str]:
    src_dir = builddata.environment.get_source_dir()
    filelist = list(interpreter.get_build_def_files())
    filelist = [PurePath(src_dir, x).as_posix() for x in filelist]
    return filelist

def list_compilers(coredata: cdata.CoreData) -> T.Dict[str, T.Dict[str, T.Dict[str, str]]]:
    compilers: T.Dict[str, T.Dict[str, T.Dict[str, str]]] = {}
    for machine in ('host', 'build'):
        compilers[machine] = {}
        for language, compiler in getattr(coredata.compilers, machine).items():
            compilers[machine][language] = {
                'id': compiler.get_id(),
                'exelist': compiler.get_exelist(),
                'linker_exelist': compiler.get_linker_exelist(),
                'file_suffixes': compiler.file_suffixes,
                'default_suffix': compiler.get_default_suffix(),
                'version': compiler.version,
                'full_version': compiler.full_version,
                'linker_id': compiler.get_linker_id(),
            }
    return compilers

def list_deps_from_source(intr: IntrospectionInterpreter) -> T.List[T.Dict[str, T.Union[str, bool]]]:
    result: T.List[T.Dict[str, T.Union[str, bool]]] = []
    for i in intr.dependencies:
        keys = [
            'name',
            'required',
            'version',
            'has_fallback',
            'conditional',
        ]
        result += [{k: v for k, v in i.items() if k in keys}]
    return result

def list_deps(coredata: cdata.CoreData, backend: backends.Backend) -> T.List[T.Dict[str, T.Union[str, T.List[str]]]]:
    result: T.Dict[str, T.Dict[str, T.Union[str, T.List[str]]]] = {}

    def _src_to_str(src_file: T.Union[mesonlib.FileOrString, build.CustomTarget, build.StructuredSources, build.CustomTargetIndex, build.GeneratedList]) -> T.List[str]:
        if isinstance(src_file, str):
            return [src_file]
        if isinstance(src_file, mesonlib.File):
            return [src_file.absolute_path(backend.source_dir, backend.build_dir)]
        if isinstance(src_file, (build.CustomTarget, build.CustomTargetIndex, build.GeneratedList)):
            return src_file.get_outputs()
        if isinstance(src_file, build.StructuredSources):
            return [f for s in src_file.as_list() for f in _src_to_str(s)]
        raise mesonlib.MesonBugException(f'Invalid file type {type(src_file)}.')

    def _create_result(d: Dependency, varname: T.Optional[str] = None) -> T.Dict[str, T.Any]:
        return {
            'name': d.name,
            'type': d.type_name,
            'version': d.get_version(),
            'compile_args': d.get_compile_args(),
            'link_args': d.get_link_args(),
            'include_directories': [i for idirs in d.get_include_dirs() for i in idirs.to_string_list(backend.source_dir, backend.build_dir)],
            'sources': [f for s in d.get_sources() for f in _src_to_str(s)],
            'extra_files': [f for s in d.get_extra_files() for f in _src_to_str(s)],
            'dependencies': [e.name for e in d.ext_deps],
            'depends': [lib.get_id() for lib in getattr(d, 'libraries', [])],
            'meson_variables': [varname] if varname else [],
        }

    for d in coredata.deps.host.values():
        if d.found():
            result[d.name] = _create_result(d)

    for varname, holder in backend.interpreter.variables.items():
        if isinstance(holder, ObjectHolder):
            d = holder.held_object
            if isinstance(d, Dependency) and d.found():
                if d.name in result:
                    T.cast('T.List[str]', result[d.name]['meson_variables']).append(varname)
                else:
                    result[d.name] = _create_result(d, varname)

    return list(result.values())

def get_test_list(testdata: T.List[backends.TestSerialisation]) -> T.List[T.Dict[str, T.Union[str, int, T.List[str], T.Dict[str, str]]]]:
    result: T.List[T.Dict[str, T.Union[str, int, T.List[str], T.Dict[str, str]]]] = []
    for t in testdata:
        to: T.Dict[str, T.Union[str, int, T.List[str], T.Dict[str, str]]] = {}
        if isinstance(t.fname, str):
            fname = [t.fname]
        else:
            fname = t.fname
        to['cmd'] = fname + t.cmd_args
        if isinstance(t.env, mesonlib.EnvironmentVariables):
            to['env'] = t.env.get_env({})
        else:
            to['env'] = t.env
        to['name'] = t.name
        to['workdir'] = t.workdir
        to['timeout'] = t.timeout
        to['suite'] = t.suite
        to['is_parallel'] = t.is_parallel
        to['priority'] = t.priority
        to['protocol'] = str(t.protocol)
        to['depends'] = t.depends
        to['extra_paths'] = t.extra_paths
        result.append(to)
    return result

def list_tests(testdata: T.List[backends.TestSerialisation]) -> T.List[T.Dict[str, T.Union[str, int, T.List[str], T.Dict[str, str]]]]:
    return get_test_list(testdata)

def list_benchmarks(benchdata: T.List[backends.TestSerialisation]) -> T.List[T.Dict[str, T.Union[str, int, T.List[str], T.Dict[str, str]]]]:
    return get_test_list(benchdata)

def list_machines(builddata: build.Build) -> T.Dict[str, T.Dict[str, T.Union[str, bool]]]:
    machines: T.Dict[str, T.Dict[str, T.Union[str, bool]]] = {}
    for m in ('host', 'build', 'target'):
        machine = getattr(builddata.environment.machines, m)
        machines[m] = dataclasses.asdict(machine)
        machines[m]['is_64_bit'] = machine.is_64_bit
        machines[m]['exe_suffix'] = machine.get_exe_suffix()
        machines[m]['object_suffix'] = machine.get_object_suffix()
    return machines

def list_projinfo(builddata: build.Build) -> T.Dict[str, T.Union[str, T.List[T.Dict[str, str]]]]:
    result: T.Dict[str, T.Union[str, T.List[T.Dict[str, str]]]] = {
        'version': builddata.project_version,
        'descriptive_name': builddata.project_name,
        'subproject_dir': builddata.subproject_dir,
    }
    subprojects = []
    for k, v in builddata.subprojects.items():
        c: T.Dict[str, str] = {
            'name': k,
            'version': v,
            'descriptive_name': builddata.projects.get(k),
        }
        subprojects.append(c)
    result['subprojects'] = subprojects
    return result

def list_projinfo_from_source(intr: IntrospectionInterpreter) -> T.Dict[str, T.Union[str, T.List[T.Dict[str, str]]]]:
    sourcedir = intr.source_root
    files = find_buildsystem_files_list(sourcedir)
    files = [os.path.normpath(x) for x in files]

    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)]
        files = [x for x in files if not x.startswith(basedir)]

    intr.project_data['buildsystem_files'] = files
    intr.project_data['subproject_dir'] = intr.subproject_dir
    return intr.project_data

def print_results(options: argparse.Namespace, results: T.Sequence[T.Tuple[str, T.Union[dict, T.List[T.Any]]]], indent: T.Optional[int]) -> int:
    if not results 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 get_infodir(builddir: T.Optional[str] = None) -> str:
    infodir = 'meson-info'
    if builddir is not None:
        infodir = os.path.join(builddir, infodir)
    return infodir

def get_info_file(infodir: str, kind: T.Optional[str] = None) -> str:
    return os.path.join(infodir,
                        'meson-info.json' if not kind else f'intro-{kind}.json')

def load_info_file(infodir: str, kind: T.Optional[str] = None) -> T.Any:
    with open(get_info_file(infodir, kind), encoding='utf-8') as fp:
        return json.load(fp)

def run(options: argparse.Namespace) -> int:
    datadir = 'meson-private'
    infodir = get_infodir(options.builddir)
    if options.builddir is not None:
        datadir = os.path.join(options.builddir, datadir)
    indent = 4 if options.indent else None
    results: T.List[T.Tuple[str, T.Union[dict, T.List[T.Any]]]] = []
    sourcedir = '.' if options.builddir == 'meson.build' else options.builddir[:-11]
    intro_types = get_meson_introspection_types()

    if 'meson.build' in [os.path.basename(options.builddir), options.builddir]:
        # Make sure that log entries in other parts of meson don't interfere with the JSON output
        with redirect_stdout(sys.stderr):
            backend = backends.get_backend_from_name(options.backend)
            assert backend is not None
            intr = IntrospectionInterpreter(sourcedir, '', backend.name, visitors = [AstIDGenerator(), AstIndentationGenerator(), AstConditionLevel()])
            intr.analyze()

        for key, val in intro_types.items():
            if (not options.all and not getattr(options, key, False)) or not val.no_bd:
                continue
            results += [(key, val.no_bd(intr))]
        return print_results(options, results, indent)

    try:
        raw = load_info_file(infodir)
        intro_vers = raw.get('introspection', {}).get('version', {}).get('full', '0.0.0')
    except FileNotFoundError:
        if not os.path.isdir(datadir) or not os.path.isdir(infodir):
            print('Current directory is not a meson build directory.\n'
                  'Please specify a valid build dir or change the working directory to it.')
        else:
            print('Introspection file {} does not exist.\n'
                  'It is also possible that the build directory was generated with an old\n'
                  'meson version. Please regenerate it in this case.'.format(get_info_file(infodir)))
        return 1

    vers_to_check = get_meson_introspection_required_version()
    for i in vers_to_check:
        if not mesonlib.version_compare(intro_vers, i):
            print('Introspection version {} is not supported. '
                  'The required version is: {}'
                  .format(intro_vers, ' and '.join(vers_to_check)))
            return 1

    # Extract introspection information from JSON
    for i, v in intro_types.items():
        if not v.func:
            continue
        if not options.all and not getattr(options, i, False):
            continue
        try:
            results += [(i, load_info_file(infodir, i))]
        except FileNotFoundError:
            print('Introspection file {} does not exist.'.format(get_info_file(infodir, i)))
            return 1

    return print_results(options, results, indent)

updated_introspection_files: T.List[str] = []

def write_intro_info(intro_info: T.Sequence[T.Tuple[str, T.Union[dict, T.List[T.Any]]]], info_dir: str) -> None:
    for kind, data in intro_info:
        out_file = os.path.join(info_dir, f'intro-{kind}.json')
        tmp_file = os.path.join(info_dir, 'tmp_dump.json')
        with open(tmp_file, 'w', encoding='utf-8') as fp:
            json.dump(data, fp, indent=2)
            fp.flush() # Not sure if this is needed
        os.replace(tmp_file, out_file)
        updated_introspection_files.append(kind)

def generate_introspection_file(builddata: build.Build, backend: backends.Backend) -> None:
    coredata = builddata.environment.get_coredata()
    intro_types = get_meson_introspection_types(coredata=coredata, builddata=builddata, backend=backend)
    intro_info: T.List[T.Tuple[str, T.Union[dict, T.List[T.Any]]]] = []

    for key, val in intro_types.items():
        if not val.func:
            continue
        intro_info += [(key, val.func())]

    write_intro_info(intro_info, builddata.environment.info_dir)

def update_build_options(coredata: cdata.CoreData, info_dir: str) -> None:
    intro_info = [
        ('buildoptions', list_buildoptions(coredata))
    ]

    write_intro_info(intro_info, info_dir)

def split_version_string(version: str) -> T.Dict[str, T.Union[str, int]]:
    vers_list = version.split('.')
    return {
        'full': version,
        'major': int(vers_list[0] if len(vers_list) > 0 else 0),
        'minor': int(vers_list[1] if len(vers_list) > 1 else 0),
        'patch': int(vers_list[2] if len(vers_list) > 2 else 0)
    }

def write_meson_info_file(builddata: build.Build, errors: list, build_files_updated: bool = False) -> None:
    info_dir = builddata.environment.info_dir
    info_file = get_meson_info_file(info_dir)
    intro_types = get_meson_introspection_types()
    intro_info = {}

    for i, v in intro_types.items():
        if not v.func:
            continue
        intro_info[i] = {
            'file': f'intro-{i}.json',
            'updated': i in updated_introspection_files
        }

    info_data = {
        'meson_version': split_version_string(cdata.version),
        'directories': {
            'source': builddata.environment.get_source_dir(),
            'build': builddata.environment.get_build_dir(),
            'info': info_dir,
        },
        'introspection': {
            'version': split_version_string(get_meson_introspection_version()),
            'information': intro_info,
        },
        'build_files_updated': build_files_updated,
    }

    if errors:
        info_data['error'] = True
        info_data['error_list'] = [x if isinstance(x, str) else str(x) for x in errors]
    else:
        info_data['error'] = False

    # Write the data to disc
    tmp_file = os.path.join(info_dir, 'tmp_dump.json')
    with open(tmp_file, 'w', encoding='utf-8') as fp:
        json.dump(info_data, fp)
        fp.flush()
    os.replace(tmp_file, info_file)
