# SPDX-License-Identifier: Apache-2.0
# Copyright 2013-2024 The Meson development team
# Copyright © 2023-2025 Intel Corporation

from __future__ import annotations

import copy

from . import mlog, options
import pickle, os, uuid
import sys
from itertools import chain
from collections import OrderedDict, abc
import dataclasses
import textwrap

from .mesonlib import (
    MesonBugException,
    MesonException, MachineChoice, PerMachine,
    PerMachineDefaultable,
    stringlistify,
    pickle_load
)

from .options import OptionKey

from .machinefile import CmdLineFileParser

import ast
import enum
import shlex
import typing as T

if T.TYPE_CHECKING:
    import argparse
    from typing_extensions import Protocol

    from . import dependencies
    from .compilers.compilers import Compiler, CompileResult, RunResult, CompileCheckMode
    from .dependencies.detect import TV_DepID
    from .environment import Environment
    from .mesonlib import FileOrString
    from .cmake.traceparser import CMakeCacheEntry
    from .interpreterbase import SubProject
    from .options import ElementaryOptionValues
    from .build import BuildTarget

    class SharedCMDOptions(Protocol):

        """Representation of command line options from Meson setup, configure,
        and dist.

        :param projectoptions: The raw list of command line options given
        :param cmd_line_options: command line options parsed into an OptionKey:
            str mapping
        """

        cmd_line_options: T.Dict[OptionKey, str]
        projectoptions: T.List[str]
        cross_file: T.List[str]
        native_file: T.List[str]

    OptionDictType = T.Union[T.Dict[str, options.AnyOptionType], 'OptionsView']
    MutableKeyedOptionDictType = T.Dict['OptionKey', options.AnyOptionType]
    KeyedOptionDictType = T.Union['options.OptionStore', 'OptionsView']
    CompilerCheckCacheKey = T.Tuple[T.Tuple[str, ...], str, FileOrString, T.Tuple[str, ...], CompileCheckMode]
    # code, args
    RunCheckCacheKey = T.Tuple[str, T.Tuple[str, ...]]

    # typeshed
    StrOrBytesPath = T.Union[str, bytes, os.PathLike[str], os.PathLike[bytes]]

# Check major_versions_differ() if changing versioning scheme.
#
# Pip requires that RCs are named like this: '0.1.0.rc1'
# But the corresponding Git tag needs to be '0.1.0rc1'
version = '1.7.99'

# The next stable version when we are in dev. This is used to allow projects to
# require meson version >=1.2.0 when using 1.1.99. FeatureNew won't warn when
# using a feature introduced in 1.2.0 when using Meson 1.1.99.
stable_version = version
if stable_version.endswith('.99'):
    stable_version_array = stable_version.split('.')
    stable_version_array[-1] = '0'
    stable_version_array[-2] = str(int(stable_version_array[-2]) + 1)
    stable_version = '.'.join(stable_version_array)


def get_genvs_default_buildtype_list() -> list[str]:
    # just debug, debugoptimized, and release for now
    # but this should probably be configurable through some extra option, alongside --genvslite.
    return options.buildtypelist[1:-2]


class MesonVersionMismatchException(MesonException):
    '''Build directory generated with Meson version is incompatible with current version'''
    def __init__(self, old_version: str, current_version: str, extra_msg: str = '') -> None:
        super().__init__(f'Build directory has been generated with Meson version {old_version}, '
                         f'which is incompatible with the current version {current_version}.'
                         + extra_msg)
        self.old_version = old_version
        self.current_version = current_version


class DependencyCacheType(enum.Enum):

    OTHER = 0
    PKG_CONFIG = 1
    CMAKE = 2

    @classmethod
    def from_type(cls, dep: 'dependencies.Dependency') -> 'DependencyCacheType':
        # As more types gain search overrides they'll need to be added here
        if dep.type_name == 'pkgconfig':
            return cls.PKG_CONFIG
        if dep.type_name == 'cmake':
            return cls.CMAKE
        return cls.OTHER


class DependencySubCache:

    def __init__(self, type_: DependencyCacheType):
        self.types = [type_]
        self.__cache: T.Dict[T.Tuple[str, ...], 'dependencies.Dependency'] = {}

    def __getitem__(self, key: T.Tuple[str, ...]) -> 'dependencies.Dependency':
        return self.__cache[key]

    def __setitem__(self, key: T.Tuple[str, ...], value: 'dependencies.Dependency') -> None:
        self.__cache[key] = value

    def __contains__(self, key: T.Tuple[str, ...]) -> bool:
        return key in self.__cache

    def values(self) -> T.Iterable['dependencies.Dependency']:
        return self.__cache.values()


class DependencyCache:

    """Class that stores a cache of dependencies.

    This class is meant to encapsulate the fact that we need multiple keys to
    successfully lookup by providing a simple get/put interface.
    """

    def __init__(self, builtins: 'KeyedOptionDictType', for_machine: MachineChoice):
        self.__cache: T.MutableMapping[TV_DepID, DependencySubCache] = OrderedDict()
        self.__builtins = builtins
        self.__pkg_conf_key = options.OptionKey('pkg_config_path')
        self.__cmake_key = options.OptionKey('cmake_prefix_path')

    def __calculate_subkey(self, type_: DependencyCacheType) -> T.Tuple[str, ...]:
        data: T.Dict[DependencyCacheType, T.List[str]] = {
            DependencyCacheType.PKG_CONFIG: stringlistify(self.__builtins.get_value_for(self.__pkg_conf_key)),
            DependencyCacheType.CMAKE: stringlistify(self.__builtins.get_value_for(self.__cmake_key)),
            DependencyCacheType.OTHER: [],
        }
        assert type_ in data, 'Someone forgot to update subkey calculations for a new type'
        return tuple(data[type_])

    def __iter__(self) -> T.Iterator['TV_DepID']:
        return self.keys()

    def put(self, key: 'TV_DepID', dep: 'dependencies.Dependency') -> None:
        t = DependencyCacheType.from_type(dep)
        if key not in self.__cache:
            self.__cache[key] = DependencySubCache(t)
        subkey = self.__calculate_subkey(t)
        self.__cache[key][subkey] = dep

    def get(self, key: 'TV_DepID') -> T.Optional['dependencies.Dependency']:
        """Get a value from the cache.

        If there is no cache entry then None will be returned.
        """
        try:
            val = self.__cache[key]
        except KeyError:
            return None

        for t in val.types:
            subkey = self.__calculate_subkey(t)
            try:
                return val[subkey]
            except KeyError:
                pass
        return None

    def values(self) -> T.Iterator['dependencies.Dependency']:
        for c in self.__cache.values():
            yield from c.values()

    def keys(self) -> T.Iterator['TV_DepID']:
        return iter(self.__cache.keys())

    def items(self) -> T.Iterator[T.Tuple['TV_DepID', T.List['dependencies.Dependency']]]:
        for k, v in self.__cache.items():
            vs: T.List[dependencies.Dependency] = []
            for t in v.types:
                subkey = self.__calculate_subkey(t)
                if subkey in v:
                    vs.append(v[subkey])
            yield k, vs

    def clear(self) -> None:
        self.__cache.clear()


class CMakeStateCache:
    """Class that stores internal CMake compiler states.

    This cache is used to reduce the startup overhead of CMake by caching
    all internal CMake compiler variables.
    """

    def __init__(self) -> None:
        self.__cache: T.Dict[str, T.Dict[str, T.List[str]]] = {}
        self.cmake_cache: T.Dict[str, 'CMakeCacheEntry'] = {}

    def __iter__(self) -> T.Iterator[T.Tuple[str, T.Dict[str, T.List[str]]]]:
        return iter(self.__cache.items())

    def items(self) -> T.Iterator[T.Tuple[str, T.Dict[str, T.List[str]]]]:
        return iter(self.__cache.items())

    def update(self, language: str, variables: T.Dict[str, T.List[str]]):
        if language not in self.__cache:
            self.__cache[language] = {}
        self.__cache[language].update(variables)

    @property
    def languages(self) -> T.Set[str]:
        return set(self.__cache.keys())


# Can't bind this near the class method it seems, sadly.
_V = T.TypeVar('_V')

# This class contains all data that must persist over multiple
# invocations of Meson. It is roughly the same thing as
# cmakecache.

class CoreData:

    def __init__(self, cmd_options: SharedCMDOptions, scratch_dir: str, meson_command: T.List[str]):
        self.lang_guids = {
            'default': '8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942',
            'c': '8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942',
            'cpp': '8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942',
            'test': '3AC096D0-A1C2-E12C-1390-A8335801FDAB',
            'directory': '2150E333-8FDC-42A3-9474-1A3956D46DE8',
        }
        self.test_guid = str(uuid.uuid4()).upper()
        self.regen_guid = str(uuid.uuid4()).upper()
        self.install_guid = str(uuid.uuid4()).upper()
        self.meson_command = meson_command
        self.target_guids = {}
        self.version = version
        self.sp_option_overrides: T.Dict[str, str] = {}
        self.cross_files = self.__load_config_files(cmd_options, scratch_dir, 'cross')
        self.compilers: PerMachine[T.Dict[str, Compiler]] = PerMachine(OrderedDict(), OrderedDict())
        self.optstore = options.OptionStore(self.is_cross_build())

        # Stores the (name, hash) of the options file, The name will be either
        # "meson_options.txt" or "meson.options".
        # This is used by mconf to reload the option file if it's changed.
        self.options_files: T.Dict[SubProject, T.Optional[T.Tuple[str, str]]] = {}

        # Set of subprojects that have already been initialized once, this is
        # required to be stored and reloaded with the coredata, as we don't
        # want to overwrite options for such subprojects.
        self.initialized_subprojects: T.Set[str] = set()

        # For host == build configurations these caches should be the same.
        self.deps: PerMachine[DependencyCache] = PerMachineDefaultable.default(
            self.is_cross_build(),
            DependencyCache(self.optstore, MachineChoice.BUILD),
            DependencyCache(self.optstore, MachineChoice.HOST))

        self.compiler_check_cache: T.Dict['CompilerCheckCacheKey', 'CompileResult'] = OrderedDict()
        self.run_check_cache: T.Dict['RunCheckCacheKey', 'RunResult'] = OrderedDict()

        # CMake cache
        self.cmake_cache: PerMachine[CMakeStateCache] = PerMachine(CMakeStateCache(), CMakeStateCache())

        # Only to print a warning if it changes between Meson invocations.
        self.config_files = self.__load_config_files(cmd_options, scratch_dir, 'native')
        self.builtin_options_libdir_cross_fixup()
        self.init_builtins()

    @staticmethod
    def __load_config_files(cmd_options: SharedCMDOptions, scratch_dir: str, ftype: str) -> T.List[str]:
        # Need to try and make the passed filenames absolute because when the
        # files are parsed later we'll have chdir()d.
        if ftype == 'cross':
            filenames = cmd_options.cross_file
        else:
            filenames = cmd_options.native_file

        if not filenames:
            return []

        found_invalid: T.List[str] = []
        missing: T.List[str] = []
        real: T.List[str] = []
        for i, f in enumerate(filenames):
            f = os.path.expanduser(os.path.expandvars(f))
            if os.path.exists(f):
                if os.path.isfile(f):
                    real.append(os.path.abspath(f))
                    continue
                elif os.path.isdir(f):
                    found_invalid.append(os.path.abspath(f))
                else:
                    # in this case we've been passed some kind of pipe, copy
                    # the contents of that file into the meson private (scratch)
                    # directory so that it can be re-read when wiping/reconfiguring
                    fcopy = os.path.join(scratch_dir, f'{uuid.uuid4()}.{ftype}.ini')
                    with open(f, encoding='utf-8') as rf:
                        with open(fcopy, 'w', encoding='utf-8') as wf:
                            wf.write(rf.read())
                    real.append(fcopy)

                    # Also replace the command line argument, as the pipe
                    # probably won't exist on reconfigure
                    filenames[i] = fcopy
                    continue
            if sys.platform != 'win32':
                paths = [
                    os.environ.get('XDG_DATA_HOME', os.path.expanduser('~/.local/share')),
                ] + os.environ.get('XDG_DATA_DIRS', '/usr/local/share:/usr/share').split(':')
                for path in paths:
                    path_to_try = os.path.join(path, 'meson', ftype, f)
                    if os.path.isfile(path_to_try):
                        real.append(path_to_try)
                        break
                else:
                    missing.append(f)
            else:
                missing.append(f)

        if missing:
            if found_invalid:
                mlog.log('Found invalid candidates for', ftype, 'file:', *found_invalid)
            mlog.log('Could not find any valid candidate for', ftype, 'files:', *missing)
            raise MesonException(f'Cannot find specified {ftype} file: {f}')
        return real

    def builtin_options_libdir_cross_fixup(self) -> None:
        # By default set libdir to "lib" when cross compiling since
        # getting the "system default" is always wrong on multiarch
        # platforms as it gets a value like lib/x86_64-linux-gnu.
        if self.cross_files:
            options.BUILTIN_OPTIONS[OptionKey('libdir')].default = 'lib'

    def init_builtins(self) -> None:
        # Create builtin options with default values
        for key, opt in options.BUILTIN_OPTIONS.items():
            self.add_builtin_option(self.optstore, key, opt)
        for for_machine in iter(MachineChoice):
            for key, opt in options.BUILTIN_OPTIONS_PER_MACHINE.items():
                self.add_builtin_option(self.optstore, key.evolve(machine=for_machine), opt)

    @staticmethod
    def add_builtin_option(opts_map: 'MutableKeyedOptionDictType', key: OptionKey,
                           opt: 'options.BuiltinOption') -> None:
        if key.subproject:
            if opt.yielding:
                # This option is global and not per-subproject
                return
            value = opts_map.get_value(key.as_root())
        else:
            value = None
        if key.has_module_prefix():
            modulename = key.get_module_prefix()
            opts_map.add_module_option(modulename, key, opt.init_option(key, value, options.default_prefix()))
        else:
            opts_map.add_system_option(key, opt.init_option(key, value, options.default_prefix()))

    def init_backend_options(self, backend_name: str) -> None:
        if backend_name == 'ninja':
            self.optstore.add_system_option('backend_max_links', options.UserIntegerOption(
                'backend_max_links',
                'Maximum number of linker processes to run or 0 for no '
                'limit',
                0,
                min_value=0))
        elif backend_name.startswith('vs'):
            self.optstore.add_system_option('backend_startup_project', options.UserStringOption(
                'backend_startup_project',
                'Default project to execute in Visual Studio',
                ''))

    def get_option(self, key: OptionKey) -> ElementaryOptionValues:
        return self.optstore.get_value_for(key.name, key.subproject)

    def get_option_object_for_target(self, target: 'BuildTarget', key: T.Union[str, OptionKey]) -> options.AnyOptionType:
        return self.get_option_for_subproject(key, target.subproject)

    def get_option_for_target(self, target: 'BuildTarget', key: T.Union[str, OptionKey]) -> ElementaryOptionValues:
        if isinstance(key, str):
            assert ':' not in key
            newkey = OptionKey(key, target.subproject)
        else:
            newkey = key
        if newkey.subproject != target.subproject:
            # FIXME: this should be an error. The caller needs to ensure that
            # key and target have the same subproject for consistency.
            # Now just do this to get things going.
            newkey = newkey.evolve(subproject=target.subproject)
        (option_object, value) = self.optstore.get_value_object_and_value_for(newkey)
        override = target.get_override(newkey.name)
        if override is not None:
            return option_object.validate_value(override)
        return value

    def get_option_for_subproject(self, key: T.Union[str, OptionKey], subproject) -> ElementaryOptionValues:
        if isinstance(key, str):
            key = OptionKey(key, subproject=subproject)
        if key.subproject != subproject:
            # This should be an error, fix before merging.
            key = key.evolve(subproject=subproject)
        return self.optstore.get_value_for(key)

    def get_option_object_for_subproject(self, key: T.Union[str, OptionKey], subproject) -> options.AnyOptionType:
        #keyname = key.name
        if key.subproject != subproject:
            # This should be an error, fix before merging.
            key = key.evolve(subproject=subproject)
        return self.optstore.get_value_object_for(key)

    def set_option(self, key: OptionKey, value, first_invocation: bool = False) -> bool:
        dirty = False
        try:
            changed = self.optstore.set_value(key, value, first_invocation)
        except KeyError:
            raise MesonException(f'Tried to set unknown builtin option {str(key)}')
        dirty |= changed

        if key.name == 'buildtype':
            dirty |= self._set_others_from_buildtype(value)

        return dirty

    def clear_cache(self) -> None:
        self.deps.host.clear()
        self.deps.build.clear()
        self.compiler_check_cache.clear()
        self.run_check_cache.clear()

    def get_nondefault_buildtype_args(self) -> T.List[T.Union[T.Tuple[str, str, str], T.Tuple[str, bool, bool]]]:
        result: T.List[T.Union[T.Tuple[str, str, str], T.Tuple[str, bool, bool]]] = []
        value = self.optstore.get_value_for('buildtype')
        if value == 'plain':
            opt = 'plain'
            debug = False
        elif value == 'debug':
            opt = '0'
            debug = True
        elif value == 'debugoptimized':
            opt = '2'
            debug = True
        elif value == 'release':
            opt = '3'
            debug = False
        elif value == 'minsize':
            opt = 's'
            debug = True
        else:
            assert value == 'custom'
            return []
        actual_opt = self.optstore.get_value_for('optimization')
        actual_debug = self.optstore.get_value_for('debug')
        if actual_opt != opt:
            result.append(('optimization', actual_opt, opt))
        if actual_debug != debug:
            result.append(('debug', actual_debug, debug))
        return result

    def _set_others_from_buildtype(self, value: str) -> bool:
        dirty = False

        if value == 'plain':
            opt = 'plain'
            debug = False
        elif value == 'debug':
            opt = '0'
            debug = True
        elif value == 'debugoptimized':
            opt = '2'
            debug = True
        elif value == 'release':
            opt = '3'
            debug = False
        elif value == 'minsize':
            opt = 's'
            debug = True
        else:
            assert value == 'custom'
            return False

        dirty |= self.optstore.set_value('optimization', opt)
        dirty |= self.optstore.set_value('debug', debug)

        return dirty

    def is_per_machine_option(self, optname: OptionKey) -> bool:
        if isinstance(optname, str):
            optname = OptionKey.from_string(optname)
        if optname.as_host() in options.BUILTIN_OPTIONS_PER_MACHINE:
            return True
        return self.optstore.is_compiler_option(optname)

    def get_external_args(self, for_machine: MachineChoice, lang: str) -> T.List[str]:
        # mypy cannot analyze type of OptionKey
        key = OptionKey(f'{lang}_args', machine=for_machine)
        return T.cast('T.List[str]', self.optstore.get_value(key))

    def get_external_link_args(self, for_machine: MachineChoice, lang: str) -> T.List[str]:
        # mypy cannot analyze type of OptionKey
        linkkey = OptionKey(f'{lang}_link_args', machine=for_machine)
        return T.cast('T.List[str]', self.optstore.get_value_for(linkkey))

    def update_project_options(self, project_options: 'MutableKeyedOptionDictType', subproject: SubProject) -> None:
        for key, value in project_options.items():
            if key not in self.optstore:
                self.optstore.add_project_option(key, value)
                continue
            if key.subproject != subproject:
                raise MesonBugException(f'Tried to set an option for subproject {key.subproject} from {subproject}!')

            oldval = self.optstore.get_value_object(key)
            if type(oldval) is not type(value):
                self.optstore.set_value(key, value.value)
            elif options.choices_are_different(oldval, value):
                # If the choices have changed, use the new value, but attempt
                # to keep the old options. If they are not valid keep the new
                # defaults but warn.
                self.optstore.set_value_object(key, value)
                try:
                    value.set_value(oldval.value)
                except MesonException:
                    mlog.warning(f'Old value(s) of {key} are no longer valid, resetting to default ({value.value}).',
                                 fatal=False)

        # Find any extranious keys for this project and remove them
        potential_removed_keys = self.optstore.keys() - project_options.keys()
        for key in potential_removed_keys:
            if self.optstore.is_project_option(key) and key.subproject == subproject:
                self.optstore.remove(key)

    def is_cross_build(self, when_building_for: MachineChoice = MachineChoice.HOST) -> bool:
        if when_building_for == MachineChoice.BUILD:
            return False
        return len(self.cross_files) > 0

    def copy_build_options_from_regular_ones(self, shut_up_pylint: bool = True) -> bool:
        # FIXME, needs cross compilation support.
        if shut_up_pylint:
            return False
        dirty = False
        assert not self.is_cross_build()
        for k in options.BUILTIN_OPTIONS_PER_MACHINE:
            o = self.optstore.get_value_object_for(k.name)
            dirty |= self.optstore.set_value(k, True, o.value)
        for bk, bv in self.optstore.items():
            if bk.machine is MachineChoice.BUILD:
                hk = bk.as_host()
                try:
                    hv = self.optstore.get_value_object(hk)
                    dirty |= bv.set_value(hv.value)
                except KeyError:
                    continue

        return dirty

    def set_options(self, opts_to_set: T.Dict[OptionKey, T.Any], subproject: str = '', first_invocation: bool = False) -> bool:
        dirty = False
        if not self.is_cross_build():
            opts_to_set = {k: v for k, v in opts_to_set.items() if k.machine is not MachineChoice.BUILD}
        # Set prefix first because it's needed to sanitize other options
        pfk = OptionKey('prefix')
        if pfk in opts_to_set:
            prefix = self.sanitize_prefix(opts_to_set[pfk])
            for key in options.BUILTIN_DIR_NOPREFIX_OPTIONS:
                if key not in opts_to_set:
                    val = options.BUILTIN_OPTIONS[key].prefixed_default(key, prefix)
                    tmpkey = options.convert_oldkey(key)
                    dirty |= self.optstore.set_option(tmpkey, val)

        unknown_options: T.List[OptionKey] = []
        for k, v in opts_to_set.items():
            if k == pfk:
                continue
            elif k.evolve(subproject=None) in self.optstore:
                dirty |= self.set_option(k, v, first_invocation)
            elif k.machine != MachineChoice.BUILD and not self.optstore.is_compiler_option(k):
                unknown_options.append(k)
        if unknown_options:
            if subproject:
                # The subproject may have top-level options that should be used
                # when it is not a subproject. Ignore those for now. With option
                # refactor they will get per-subproject values.
                really_unknown = []
                for uo in unknown_options:
                    topkey = uo.evolve(subproject='')
                    if topkey not in self.optstore:
                        really_unknown.append(uo)
                unknown_options = really_unknown
            if unknown_options:
                unknown_options_str = ', '.join(sorted(str(s) for s in unknown_options))
                sub = f'In subproject {subproject}: ' if subproject else ''
                raise MesonException(f'{sub}Unknown options: "{unknown_options_str}"')

        if not self.is_cross_build():
            dirty |= self.copy_build_options_from_regular_ones()

        return dirty

    def can_set_per_sb(self, keystr):
        return True

    def set_options_from_configure_strings(self, D_args) -> bool:
        dirty = False
        for entry in D_args:
            if '=' not in entry:
                raise MesonException(f'A -D argument must be of form "name=value" instead of {entry}')
            key, val = entry.split('=', 1)
            if key in self.sp_option_overrides:
                self.sp_option_overrides[key] = val
                dirty = True
            else:
                dirty |= self.set_options({OptionKey(key): val})
        return dirty

    def create_sp_options(self, A_args) -> bool:
        if A_args is None:
            return False
        dirty = False
        for entry in A_args:
            keystr, valstr = entry.split('=', 1)
            if ':' not in keystr:
                raise MesonException(f'Option to add override has no subproject: {entry}')
            if not self.can_set_per_sb(keystr):
                raise MesonException(f'Option {keystr} can not be set per subproject.')
            if keystr in self.sp_option_overrides:
                raise MesonException(f'Override {keystr} already exists.')
            key = self.optstore.split_keystring(keystr)
            original_key = key.copy_with(subproject=None)
            if not self.optstore.has_option(original_key):
                raise MesonException('Tried to override a nonexisting key.')
            self.sp_option_overrides[keystr] = valstr
            dirty = True
        return dirty

    def remove_sp_options(self, U_args) -> bool:
        dirty = False
        if U_args is None:
            return False
        for entry in U_args:
            if entry in self.sp_option_overrides:
                del self.sp_option_overrides[entry]
                dirty = True
            else:
                pass # Deleting a non-existing key ok, I guess?
        return dirty

    def set_default_options(self, default_options: T.MutableMapping[OptionKey, str], subproject: str, env: 'Environment') -> None:
        from .compilers import base_options

        # Main project can set default options on subprojects, but subprojects
        # can only set default options on themselves.
        # Preserve order: if env.options has 'buildtype' it must come after
        # 'optimization' if it is in default_options.
        options: T.MutableMapping[OptionKey, T.Any] = OrderedDict()
        for k, v in default_options.items():
            if isinstance(k, str):
                k = OptionKey.from_string(k)
            if not subproject or k.subproject == subproject:
                options[k] = v
        options.update(env.options)
        env.options = options

        # Create a subset of options, keeping only project and builtin
        # options for this subproject.
        # Language and backend specific options will be set later when adding
        # languages and setting the backend (builtin options must be set first
        # to know which backend we'll use).
        options = OrderedDict()

        for k, v in env.options.items():
            if isinstance(k, str):
                k = OptionKey.from_string(k)
            # If this is a subproject, don't use other subproject options
            if k.subproject and k.subproject != subproject:
                continue
            # If the option is a builtin and is yielding then it's not allowed per subproject.
            #
            # Always test this using the HOST machine, as many builtin options
            # are not valid for the BUILD machine, but the yielding value does
            # not differ between them even when they are valid for both.
            if subproject and self.optstore.is_builtin_option(k) and self.optstore.get_value_object(k.evolve(subproject=None, machine=MachineChoice.HOST)).yielding:
                continue
            # Skip base, compiler, and backend options, they are handled when
            # adding languages and setting backend.
            if self.optstore.is_compiler_option(k) or self.optstore.is_backend_option(k):
                continue
            if self.optstore.is_base_option(k) and k.as_root() in base_options:
                # set_options will report unknown base options
                continue
            options[k] = v

        self.set_options(options, subproject=subproject, first_invocation=env.first_invocation)

    def add_compiler_options(self, c_options: MutableKeyedOptionDictType, lang: str, for_machine: MachineChoice,
                             env: Environment, subproject: str) -> None:
        for k, o in c_options.items():
            value = env.options.get(k)
            if value is not None:
                o.set_value(value)
                if not subproject:
                    # FIXME, add augment
                    #self.optstore[k] = o  # override compiler option on reconfigure
                    pass

            comp_key = OptionKey(f'{k.name}', None, for_machine)
            if lang == 'objc' and k.name == 'c_std':
                # For objective C, always fall back to c_std.
                self.optstore.add_compiler_option('c', comp_key, o)
            elif lang == 'objcpp' and k.name == 'cpp_std':
                self.optstore.add_compiler_option('cpp', comp_key, o)
            else:
                self.optstore.add_compiler_option(lang, comp_key, o)

    def add_lang_args(self, lang: str, comp: T.Type['Compiler'],
                      for_machine: MachineChoice, env: 'Environment') -> None:
        """Add global language arguments that are needed before compiler/linker detection."""
        from .compilers import compilers
        # These options are all new at this point, because the compiler is
        # responsible for adding its own options, thus calling
        # `self.optstore.update()`` is perfectly safe.
        for gopt_key, gopt_valobj in compilers.get_global_options(lang, comp, for_machine, env).items():
            self.optstore.add_compiler_option(lang, gopt_key, gopt_valobj)

    def process_compiler_options(self, lang: str, comp: Compiler, env: Environment, subproject: str) -> None:
        from . import compilers

        self.add_compiler_options(comp.get_options(), lang, comp.for_machine, env, subproject)

        for key in comp.base_options:
            if subproject:
                skey = key.evolve(subproject=subproject)
            else:
                skey = key
            if skey not in self.optstore:
                self.optstore.add_system_option(skey, copy.deepcopy(compilers.base_options[key]))
                if skey in env.options:
                    self.optstore.set_value(skey, env.options[skey])
                elif subproject and key in env.options:
                    self.optstore.set_value(skey, env.options[key])
                # FIXME
                #if subproject and not self.optstore.has_option(key):
                #    self.optstore[key] = copy.deepcopy(self.optstore[skey])
            elif skey in env.options:
                self.optstore.set_value(skey, env.options[skey])
            elif subproject and key in env.options:
                self.optstore.set_value(skey, env.options[key])
        self.emit_base_options_warnings()

    def emit_base_options_warnings(self) -> None:
        bcodekey = OptionKey('b_bitcode')
        if bcodekey in self.optstore and self.optstore.get_value(bcodekey):
            msg = textwrap.dedent('''Base option 'b_bitcode' is enabled, which is incompatible with many linker options.
                                     Incompatible options such as \'b_asneeded\' have been disabled.'
                                     Please see https://mesonbuild.com/Builtin-options.html#Notes_about_Apple_Bitcode_support for more details.''')
            mlog.warning(msg, once=True, fatal=False)

def get_cmd_line_file(build_dir: str) -> str:
    return os.path.join(build_dir, 'meson-private', 'cmd_line.txt')

def read_cmd_line_file(build_dir: str, options: SharedCMDOptions) -> None:
    filename = get_cmd_line_file(build_dir)
    if not os.path.isfile(filename):
        return

    config = CmdLineFileParser()
    config.read(filename)

    # Do a copy because config is not really a dict. options.cmd_line_options
    # overrides values from the file.
    d = {OptionKey.from_string(k): v for k, v in config['options'].items()}
    d.update(options.cmd_line_options)
    options.cmd_line_options = d

    properties = config['properties']
    if not options.cross_file:
        options.cross_file = ast.literal_eval(properties.get('cross_file', '[]'))
    if not options.native_file:
        # This will be a string in the form: "['first', 'second', ...]", use
        # literal_eval to get it into the list of strings.
        options.native_file = ast.literal_eval(properties.get('native_file', '[]'))

def write_cmd_line_file(build_dir: str, options: SharedCMDOptions) -> None:
    filename = get_cmd_line_file(build_dir)
    config = CmdLineFileParser()

    properties: OrderedDict[str, str] = OrderedDict()
    if options.cross_file:
        properties['cross_file'] = options.cross_file
    if options.native_file:
        properties['native_file'] = options.native_file

    config['options'] = {str(k): str(v) for k, v in options.cmd_line_options.items()}
    config['properties'] = properties
    with open(filename, 'w', encoding='utf-8') as f:
        config.write(f)

def update_cmd_line_file(build_dir: str, options: SharedCMDOptions) -> None:
    filename = get_cmd_line_file(build_dir)
    config = CmdLineFileParser()
    config.read(filename)
    config['options'].update({str(k): str(v) for k, v in options.cmd_line_options.items()})
    with open(filename, 'w', encoding='utf-8') as f:
        config.write(f)

def format_cmd_line_options(options: SharedCMDOptions) -> str:
    cmdline = ['-D{}={}'.format(str(k), v) for k, v in options.cmd_line_options.items()]
    if options.cross_file:
        cmdline += [f'--cross-file={f}' for f in options.cross_file]
    if options.native_file:
        cmdline += [f'--native-file={f}' for f in options.native_file]
    return ' '.join([shlex.quote(x) for x in cmdline])

def major_versions_differ(v1: str, v2: str) -> bool:
    v1_major, v1_minor = v1.rsplit('.', 1)
    v2_major, v2_minor = v2.rsplit('.', 1)
    # Major version differ, or one is development version but not the other.
    return v1_major != v2_major or ('99' in {v1_minor, v2_minor} and v1_minor != v2_minor)

def load(build_dir: str, suggest_reconfigure: bool = True) -> CoreData:
    filename = os.path.join(build_dir, 'meson-private', 'coredata.dat')
    return pickle_load(filename, 'Coredata', CoreData, suggest_reconfigure)


def save(obj: CoreData, build_dir: str) -> str:
    filename = os.path.join(build_dir, 'meson-private', 'coredata.dat')
    prev_filename = filename + '.prev'
    tempfilename = filename + '~'
    if major_versions_differ(obj.version, version):
        raise MesonException('Fatal version mismatch corruption.')
    if os.path.exists(filename):
        import shutil
        shutil.copyfile(filename, prev_filename)
    with open(tempfilename, 'wb') as f:
        pickle.dump(obj, f)
        f.flush()
        os.fsync(f.fileno())
    os.replace(tempfilename, filename)
    return filename


def register_builtin_arguments(parser: argparse.ArgumentParser) -> None:
    for n, b in options.BUILTIN_OPTIONS.items():
        b.add_to_argparse(n, parser, '')
    for n, b in options.BUILTIN_OPTIONS_PER_MACHINE.items():
        b.add_to_argparse(n, parser, ' (just for host machine)')
        b.add_to_argparse(n.as_build(), parser, ' (just for build machine)')
    parser.add_argument('-D', action='append', dest='projectoptions', default=[], metavar="option",
                        help='Set the value of an option, can be used several times to set multiple options.')

def create_options_dict(options: T.List[str], subproject: str = '') -> T.Dict[str, str]:
    result: T.OrderedDict[OptionKey, str] = OrderedDict()
    for o in options:
        try:
            (key, value) = o.split('=', 1)
        except ValueError:
            raise MesonException(f'Option {o!r} must have a value separated by equals sign.')
        result[key] = value
    return result

def parse_cmd_line_options(args: SharedCMDOptions) -> None:
    args.cmd_line_options = create_options_dict(args.projectoptions)

    # Merge builtin options set with --option into the dict.
    for key in chain(
            options.BUILTIN_OPTIONS.keys(),
            (k.as_build() for k in options.BUILTIN_OPTIONS_PER_MACHINE.keys()),
            options.BUILTIN_OPTIONS_PER_MACHINE.keys(),
    ):
        name = str(key)
        value = getattr(args, name, None)
        if value is not None:
            if key in args.cmd_line_options:
                cmdline_name = options.BuiltinOption.argparse_name_to_arg(name)
                raise MesonException(
                    f'Got argument {name} as both -D{name} and {cmdline_name}. Pick one.')
            args.cmd_line_options[key.name] = value
            delattr(args, name)

@dataclasses.dataclass
class OptionsView(abc.Mapping):
    '''A view on an options dictionary for a given subproject and with overrides.
    '''

    # TODO: the typing here could be made more explicit using a TypeDict from
    # python 3.8 or typing_extensions
    original_options: T.Union[KeyedOptionDictType, 'dict[OptionKey, options.AnyOptionType]']
    subproject: T.Optional[str] = None
    overrides: T.Optional[T.Mapping[OptionKey, ElementaryOptionValues]] = dataclasses.field(default_factory=dict)

    def __getitem__(self, key: OptionKey) -> options.UserOption:
        # FIXME: This is fundamentally the same algorithm than interpreter.get_option_internal().
        # We should try to share the code somehow.
        key = key.evolve(subproject=self.subproject)
        if not isinstance(self.original_options, options.OptionStore):
            # This is only used by CUDA currently.
            # This entire class gets removed when option refactor
            # is finished.
            if '_' in key.name or key.lang is not None:
                is_project_option = False
            else:
                sys.exit(f'FAIL {key}.')
        else:
            is_project_option = self.original_options.is_project_option(key)
        if not is_project_option:
            opt = self.original_options.get(key)
            if opt is None or opt.yielding:
                key2 = key.as_root()
                # This hack goes away once wi start using OptionStore
                # to hold overrides.
                if isinstance(self.original_options, options.OptionStore):
                    if key2 not in self.original_options:
                        raise KeyError(f'{key} {key2}')
                    opt = self.original_options.get_value_object(key2)
                else:
                    opt = self.original_options[key2]
        else:
            opt = self.original_options[key]
            if opt.yielding:
                opt = self.original_options.get(key.as_root(), opt)
        if self.overrides:
            override_value = self.overrides.get(key.as_root())
            if override_value is not None:
                opt = copy.copy(opt)
                opt.set_value(override_value)
        return opt

    def get_value(self, key: T.Union[str, OptionKey]):
        if isinstance(key, str):
            key = OptionKey(key)
        return self[key].value

    def set_value(self, key: T.Union[str, OptionKey], value: ElementaryOptionValues):
        if isinstance(key, str):
            key = OptionKey(key)
        self.overrides[key] = value

    def __iter__(self) -> T.Iterator[OptionKey]:
        return iter(self.original_options)

    def __len__(self) -> int:
        return len(self.original_options)

FORBIDDEN_TARGET_NAMES = frozenset({
    'clean',
    'clean-ctlist',
    'clean-gcno',
    'clean-gcda',
    'coverage',
    'coverage-text',
    'coverage-xml',
    'coverage-html',
    'phony',
    'PHONY',
    'all',
    'test',
    'benchmark',
    'install',
    'uninstall',
    'build.ninja',
    'scan-build',
    'reconfigure',
    'dist',
    'distcheck',
})
