# SPDX-License-Identifier: Apache-2.0
# Copyright 2012-2020 The Meson development team
# Copyright © 2023 Intel Corporation

from __future__ import annotations

import itertools
import os, platform, re, sys, shutil
import typing as T
import collections

from . import coredata
from . import mesonlib
from . import machinefile

CmdLineFileParser = machinefile.CmdLineFileParser

from .mesonlib import (
    MesonException, MachineChoice, Popen_safe, PerMachine,
    PerMachineDefaultable, PerThreeMachineDefaultable, split_args, quote_arg, OptionKey,
    search_version, MesonBugException
)
from . import mlog
from .programs import ExternalProgram

from .envconfig import (
    BinaryTable, MachineInfo, Properties, known_cpu_families, CMakeVariables,
)
from . import compilers
from .compilers import (
    is_assembly,
    is_header,
    is_library,
    is_llvm_ir,
    is_object,
    is_source,
)

from functools import lru_cache
from mesonbuild import envconfig

if T.TYPE_CHECKING:
    from configparser import ConfigParser

    from .compilers import Compiler
    from .wrap.wrap import Resolver

    CompilersDict = T.Dict[str, Compiler]


build_filename = 'meson.build'


def _get_env_var(for_machine: MachineChoice, is_cross: bool, var_name: str) -> T.Optional[str]:
    """
    Returns the exact env var and the value.
    """
    candidates = PerMachine(
        # The prefixed build version takes priority, but if we are native
        # compiling we fall back on the unprefixed host version. This
        # allows native builds to never need to worry about the 'BUILD_*'
        # ones.
        ([var_name + '_FOR_BUILD'] if is_cross else [var_name]),
        # Always just the unprefixed host versions
        [var_name]
    )[for_machine]
    for var in candidates:
        value = os.environ.get(var)
        if value is not None:
            break
    else:
        formatted = ', '.join([f'{var!r}' for var in candidates])
        mlog.debug(f'None of {formatted} are defined in the environment, not changing global flags.')
        return None
    mlog.debug(f'Using {var!r} from environment with value: {value!r}')
    return value


def detect_gcovr(gcovr_exe: str = 'gcovr', min_version: str = '3.3', log: bool = False):
    try:
        p, found = Popen_safe([gcovr_exe, '--version'])[0:2]
    except (FileNotFoundError, PermissionError):
        # Doesn't exist in PATH or isn't executable
        return None, None
    found = search_version(found)
    if p.returncode == 0 and mesonlib.version_compare(found, '>=' + min_version):
        if log:
            mlog.log('Found gcovr-{} at {}'.format(found, quote_arg(shutil.which(gcovr_exe))))
        return gcovr_exe, found
    return None, None

def detect_lcov(lcov_exe: str = 'lcov', log: bool = False):
    try:
        p, found = Popen_safe([lcov_exe, '--version'])[0:2]
    except (FileNotFoundError, PermissionError):
        # Doesn't exist in PATH or isn't executable
        return None, None
    found = search_version(found)
    if p.returncode == 0 and found:
        if log:
            mlog.log('Found lcov-{} at {}'.format(found, quote_arg(shutil.which(lcov_exe))))
        return lcov_exe, found
    return None, None

def detect_llvm_cov(suffix: T.Optional[str] = None):
    # If there's a known suffix or forced lack of suffix, use that
    if suffix is not None:
        if suffix == '':
            tool = 'llvm-cov'
        else:
            tool = f'llvm-cov-{suffix}'
        if mesonlib.exe_exists([tool, '--version']):
            return tool
    else:
        # Otherwise guess in the dark
        tools = get_llvm_tool_names('llvm-cov')
        for tool in tools:
            if mesonlib.exe_exists([tool, '--version']):
                return tool
    return None

def compute_llvm_suffix(coredata: coredata.CoreData):
    # Check to see if the user is trying to do coverage for either a C or C++ project
    compilers = coredata.compilers[MachineChoice.BUILD]
    cpp_compiler_is_clang = 'cpp' in compilers and compilers['cpp'].id == 'clang'
    c_compiler_is_clang = 'c' in compilers and compilers['c'].id == 'clang'
    # Extract first the C++ compiler if available. If it's a Clang of some kind, compute the suffix if possible
    if cpp_compiler_is_clang:
        suffix = compilers['cpp'].version.split('.')[0]
        return suffix

    # Then the C compiler, again checking if it's some kind of Clang and computing the suffix
    if c_compiler_is_clang:
        suffix = compilers['c'].version.split('.')[0]
        return suffix

    # Neither compiler is a Clang, or no compilers are for C or C++
    return None

def detect_lcov_genhtml(lcov_exe: str = 'lcov', genhtml_exe: str = 'genhtml'):
    lcov_exe, lcov_version = detect_lcov(lcov_exe)
    if not mesonlib.exe_exists([genhtml_exe, '--version']):
        genhtml_exe = None

    return lcov_exe, lcov_version, genhtml_exe

def find_coverage_tools(coredata: coredata.CoreData) -> T.Tuple[T.Optional[str], T.Optional[str], T.Optional[str], T.Optional[str], T.Optional[str], T.Optional[str]]:
    gcovr_exe, gcovr_version = detect_gcovr()

    llvm_cov_exe = detect_llvm_cov(compute_llvm_suffix(coredata))

    lcov_exe, lcov_version, genhtml_exe = detect_lcov_genhtml()

    return gcovr_exe, gcovr_version, lcov_exe, lcov_version, genhtml_exe, llvm_cov_exe

def detect_ninja(version: str = '1.8.2', log: bool = False) -> T.List[str]:
    r = detect_ninja_command_and_version(version, log)
    return r[0] if r else None

def detect_ninja_command_and_version(version: str = '1.8.2', log: bool = False) -> T.Tuple[T.List[str], str]:
    env_ninja = os.environ.get('NINJA', None)
    for n in [env_ninja] if env_ninja else ['ninja', 'ninja-build', 'samu']:
        prog = ExternalProgram(n, silent=True)
        if not prog.found():
            continue
        try:
            p, found = Popen_safe(prog.command + ['--version'])[0:2]
        except (FileNotFoundError, PermissionError):
            # Doesn't exist in PATH or isn't executable
            continue
        found = found.strip()
        # Perhaps we should add a way for the caller to know the failure mode
        # (not found or too old)
        if p.returncode == 0 and mesonlib.version_compare(found, '>=' + version):
            if log:
                name = os.path.basename(n)
                if name.endswith('-' + found):
                    name = name[0:-1 - len(found)]
                if name == 'ninja-build':
                    name = 'ninja'
                if name == 'samu':
                    name = 'samurai'
                mlog.log('Found {}-{} at {}'.format(name, found,
                         ' '.join([quote_arg(x) for x in prog.command])))
            return (prog.command, found)

def get_llvm_tool_names(tool: str) -> T.List[str]:
    # Ordered list of possible suffixes of LLVM executables to try. Start with
    # base, then try newest back to oldest (3.5 is arbitrary), and finally the
    # devel version. Please note that the development snapshot in Debian does
    # not have a distinct name. Do not move it to the beginning of the list
    # unless it becomes a stable release.
    suffixes = [
        '', # base (no suffix)
        '-18.1', '18.1',
        '-18',  '18',
        '-17',  '17',
        '-16',  '16',
        '-15',  '15',
        '-14',  '14',
        '-13',  '13',
        '-12',  '12',
        '-11',  '11',
        '-10',  '10',
        '-9',   '90',
        '-8',   '80',
        '-7',   '70',
        '-6.0', '60',
        '-5.0', '50',
        '-4.0', '40',
        '-3.9', '39',
        '-3.8', '38',
        '-3.7', '37',
        '-3.6', '36',
        '-3.5', '35',
        '-19',    # Debian development snapshot
        '-devel', # FreeBSD development snapshot
    ]
    names: T.List[str] = []
    for suffix in suffixes:
        names.append(tool + suffix)
    return names

def detect_scanbuild() -> T.List[str]:
    """ Look for scan-build binary on build platform

    First, if a SCANBUILD env variable has been provided, give it precedence
    on all platforms.

    For most platforms, scan-build is found is the PATH contains a binary
    named "scan-build". However, some distribution's package manager (FreeBSD)
    don't. For those, loop through a list of candidates to see if one is
    available.

    Return: a single-element list of the found scan-build binary ready to be
        passed to Popen()
    """
    exelist: T.List[str] = []
    if 'SCANBUILD' in os.environ:
        exelist = split_args(os.environ['SCANBUILD'])

    else:
        tools = get_llvm_tool_names('scan-build')
        for tool in tools:
            which = shutil.which(tool)
            if which is not None:
                exelist = [which]
                break

    if exelist:
        tool = exelist[0]
        if os.path.isfile(tool) and os.access(tool, os.X_OK):
            return [tool]
    return []

def detect_clangformat() -> T.List[str]:
    """ Look for clang-format binary on build platform

    Do the same thing as detect_scanbuild to find clang-format except it
    currently does not check the environment variable.

    Return: a single-element list of the found clang-format binary ready to be
        passed to Popen()
    """
    tools = get_llvm_tool_names('clang-format')
    for tool in tools:
        path = shutil.which(tool)
        if path is not None:
            return [path]
    return []

def detect_windows_arch(compilers: CompilersDict) -> str:
    """
    Detecting the 'native' architecture of Windows is not a trivial task. We
    cannot trust that the architecture that Python is built for is the 'native'
    one because you can run 32-bit apps on 64-bit Windows using WOW64 and
    people sometimes install 32-bit Python on 64-bit Windows.

    We also can't rely on the architecture of the OS itself, since it's
    perfectly normal to compile and run 32-bit applications on Windows as if
    they were native applications. It's a terrible experience to require the
    user to supply a cross-info file to compile 32-bit applications on 64-bit
    Windows. Thankfully, the only way to compile things with Visual Studio on
    Windows is by entering the 'msvc toolchain' environment, which can be
    easily detected.

    In the end, the sanest method is as follows:
    1. Check environment variables that are set by Windows and WOW64 to find out
       if this is x86 (possibly in WOW64), if so use that as our 'native'
       architecture.
    2. If the compiler toolchain target architecture is x86, use that as our
      'native' architecture.
    3. Otherwise, use the actual Windows architecture

    """
    os_arch = mesonlib.windows_detect_native_arch()
    if os_arch == 'x86':
        return os_arch
    # If we're on 64-bit Windows, 32-bit apps can be compiled without
    # cross-compilation. So if we're doing that, just set the native arch as
    # 32-bit and pretend like we're running under WOW64. Else, return the
    # actual Windows architecture that we deduced above.
    for compiler in compilers.values():
        if compiler.id == 'msvc' and (compiler.target in {'x86', '80x86'}):
            return 'x86'
        if compiler.id == 'clang-cl' and compiler.target == 'x86':
            return 'x86'
        if compiler.id == 'gcc' and compiler.has_builtin_define('__i386__'):
            return 'x86'
    return os_arch

def any_compiler_has_define(compilers: CompilersDict, define: str) -> bool:
    for c in compilers.values():
        try:
            if c.has_builtin_define(define):
                return True
        except mesonlib.MesonException:
            # Ignore compilers that do not support has_builtin_define.
            pass
    return False

def detect_cpu_family(compilers: CompilersDict) -> str:
    """
    Python is inconsistent in its platform module.
    It returns different values for the same cpu.
    For x86 it might return 'x86', 'i686' or somesuch.
    Do some canonicalization.
    """
    if mesonlib.is_windows():
        trial = detect_windows_arch(compilers)
    elif mesonlib.is_freebsd() or mesonlib.is_netbsd() or mesonlib.is_openbsd() or mesonlib.is_qnx() or mesonlib.is_aix():
        trial = platform.processor().lower()
    else:
        trial = platform.machine().lower()
    if trial.startswith('i') and trial.endswith('86'):
        trial = 'x86'
    elif trial == 'bepc':
        trial = 'x86'
    elif trial == 'arm64':
        trial = 'aarch64'
    elif trial.startswith('aarch64'):
        # This can be `aarch64_be`
        trial = 'aarch64'
    elif trial.startswith('arm') or trial.startswith('earm'):
        trial = 'arm'
    elif trial.startswith(('powerpc64', 'ppc64')):
        trial = 'ppc64'
    elif trial.startswith(('powerpc', 'ppc')) or trial in {'macppc', 'power macintosh'}:
        trial = 'ppc'
    elif trial in {'amd64', 'x64', 'i86pc'}:
        trial = 'x86_64'
    elif trial in {'sun4u', 'sun4v'}:
        trial = 'sparc64'
    elif trial.startswith('mips'):
        if '64' not in trial:
            trial = 'mips'
        else:
            trial = 'mips64'
    elif trial in {'ip30', 'ip35'}:
        trial = 'mips64'

    # On Linux (and maybe others) there can be any mixture of 32/64 bit code in
    # the kernel, Python, system, 32-bit chroot on 64-bit host, etc. The only
    # reliable way to know is to check the compiler defines.
    if trial == 'x86_64':
        if any_compiler_has_define(compilers, '__i386__'):
            trial = 'x86'
    elif trial == 'aarch64':
        if any_compiler_has_define(compilers, '__arm__'):
            trial = 'arm'
    # Add more quirks here as bugs are reported. Keep in sync with detect_cpu()
    # below.
    elif trial == 'parisc64':
        # ATM there is no 64 bit userland for PA-RISC. Thus always
        # report it as 32 bit for simplicity.
        trial = 'parisc'
    elif trial == 'ppc':
        # AIX always returns powerpc, check here for 64-bit
        if any_compiler_has_define(compilers, '__64BIT__'):
            trial = 'ppc64'
    # MIPS64 is able to run MIPS32 code natively, so there is a chance that
    # such mixture mentioned above exists.
    elif trial == 'mips64':
        if compilers and not any_compiler_has_define(compilers, '__mips64'):
            trial = 'mips'

    if trial not in known_cpu_families:
        mlog.warning(f'Unknown CPU family {trial!r}, please report this at '
                     'https://github.com/mesonbuild/meson/issues/new with the '
                     'output of `uname -a` and `cat /proc/cpuinfo`')

    return trial

def detect_cpu(compilers: CompilersDict) -> str:
    if mesonlib.is_windows():
        trial = detect_windows_arch(compilers)
    elif mesonlib.is_freebsd() or mesonlib.is_netbsd() or mesonlib.is_openbsd() or mesonlib.is_aix():
        trial = platform.processor().lower()
    else:
        trial = platform.machine().lower()

    if trial in {'amd64', 'x64', 'i86pc'}:
        trial = 'x86_64'
    if trial == 'x86_64':
        # Same check as above for cpu_family
        if any_compiler_has_define(compilers, '__i386__'):
            trial = 'i686' # All 64 bit cpus have at least this level of x86 support.
    elif trial.startswith('aarch64') or trial.startswith('arm64'):
        # Same check as above for cpu_family
        if any_compiler_has_define(compilers, '__arm__'):
            trial = 'arm'
        else:
            # for aarch64_be
            trial = 'aarch64'
    elif trial.startswith('earm'):
        trial = 'arm'
    elif trial == 'e2k':
        # Make more precise CPU detection for Elbrus platform.
        trial = platform.processor().lower()
    elif trial.startswith('mips'):
        if '64' not in trial:
            trial = 'mips'
        else:
            if compilers and not any_compiler_has_define(compilers, '__mips64'):
                trial = 'mips'
            else:
                trial = 'mips64'
    elif trial == 'ppc':
        # AIX always returns powerpc, check here for 64-bit
        if any_compiler_has_define(compilers, '__64BIT__'):
            trial = 'ppc64'

    # Add more quirks here as bugs are reported. Keep in sync with
    # detect_cpu_family() above.
    return trial

KERNEL_MAPPINGS: T.Mapping[str, str] = {'freebsd': 'freebsd',
                                        'openbsd': 'openbsd',
                                        'netbsd': 'netbsd',
                                        'windows': 'nt',
                                        'android': 'linux',
                                        'linux': 'linux',
                                        'cygwin': 'nt',
                                        'darwin': 'xnu',
                                        'dragonfly': 'dragonfly',
                                        'haiku': 'haiku',
                                        }

def detect_kernel(system: str) -> T.Optional[str]:
    if system == 'sunos':
        # Solaris 5.10 uname doesn't support the -o switch, and illumos started
        # with version 5.11 so shortcut the logic to report 'solaris' in such
        # cases where the version is 5.10 or below.
        if mesonlib.version_compare(platform.uname().release, '<=5.10'):
            return 'solaris'
        # This needs to be /usr/bin/uname because gnu-uname could be installed and
        # won't provide the necessary information
        p, out, _ = Popen_safe(['/usr/bin/uname', '-o'])
        if p.returncode != 0:
            raise MesonException('Failed to run "/usr/bin/uname -o"')
        out = out.lower().strip()
        if out not in {'illumos', 'solaris'}:
            mlog.warning(f'Got an unexpected value for kernel on a SunOS derived platform, expcted either "illumos" or "solaris", but got "{out}".'
                         "Please open a Meson issue with the OS you're running and the value detected for your kernel.")
            return None
        return out
    return KERNEL_MAPPINGS.get(system, None)

def detect_subsystem(system: str) -> T.Optional[str]:
    if system == 'darwin':
        return 'macos'
    return system

def detect_system() -> str:
    if sys.platform == 'cygwin':
        return 'cygwin'
    return platform.system().lower()

def detect_msys2_arch() -> T.Optional[str]:
    return os.environ.get('MSYSTEM_CARCH', None)

def detect_machine_info(compilers: T.Optional[CompilersDict] = None) -> MachineInfo:
    """Detect the machine we're running on

    If compilers are not provided, we cannot know as much. None out those
    fields to avoid accidentally depending on partial knowledge. The
    underlying ''detect_*'' method can be called to explicitly use the
    partial information.
    """
    system = detect_system()
    return MachineInfo(
        system,
        detect_cpu_family(compilers) if compilers is not None else None,
        detect_cpu(compilers) if compilers is not None else None,
        sys.byteorder,
        detect_kernel(system),
        detect_subsystem(system))

# TODO make this compare two `MachineInfo`s purely. How important is the
# `detect_cpu_family({})` distinction? It is the one impediment to that.
def machine_info_can_run(machine_info: MachineInfo):
    """Whether we can run binaries for this machine on the current machine.

    Can almost always run 32-bit binaries on 64-bit natively if the host
    and build systems are the same. We don't pass any compilers to
    detect_cpu_family() here because we always want to know the OS
    architecture, not what the compiler environment tells us.
    """
    if machine_info.system != detect_system():
        return False
    true_build_cpu_family = detect_cpu_family({})
    return \
        (machine_info.cpu_family == true_build_cpu_family) or \
        ((true_build_cpu_family == 'x86_64') and (machine_info.cpu_family == 'x86')) or \
        ((true_build_cpu_family == 'mips64') and (machine_info.cpu_family == 'mips')) or \
        ((true_build_cpu_family == 'aarch64') and (machine_info.cpu_family == 'arm'))

class Environment:
    private_dir = 'meson-private'
    log_dir = 'meson-logs'
    info_dir = 'meson-info'

    def __init__(self, source_dir: str, build_dir: str, cmd_options: coredata.SharedCMDOptions) -> None:
        self.source_dir = source_dir
        self.build_dir = build_dir
        # Do not try to create build directories when build_dir is none.
        # This reduced mode is used by the --buildoptions introspector
        if build_dir is not None:
            self.scratch_dir = os.path.join(build_dir, Environment.private_dir)
            self.log_dir = os.path.join(build_dir, Environment.log_dir)
            self.info_dir = os.path.join(build_dir, Environment.info_dir)
            os.makedirs(self.scratch_dir, exist_ok=True)
            os.makedirs(self.log_dir, exist_ok=True)
            os.makedirs(self.info_dir, exist_ok=True)
            try:
                self.coredata: coredata.CoreData = coredata.load(self.get_build_dir(), suggest_reconfigure=False)
                self.first_invocation = False
            except FileNotFoundError:
                self.create_new_coredata(cmd_options)
            except coredata.MesonVersionMismatchException as e:
                # This is routine, but tell the user the update happened
                mlog.log('Regenerating configuration from scratch:', str(e))
                coredata.read_cmd_line_file(self.build_dir, cmd_options)
                self.create_new_coredata(cmd_options)
            except MesonException as e:
                # If we stored previous command line options, we can recover from
                # a broken/outdated coredata.
                if os.path.isfile(coredata.get_cmd_line_file(self.build_dir)):
                    mlog.warning('Regenerating configuration from scratch.', fatal=False)
                    mlog.log('Reason:', mlog.red(str(e)))
                    coredata.read_cmd_line_file(self.build_dir, cmd_options)
                    self.create_new_coredata(cmd_options)
                else:
                    raise MesonException(f'{str(e)} Try regenerating using "meson setup --wipe".')
        else:
            # Just create a fresh coredata in this case
            self.scratch_dir = ''
            self.create_new_coredata(cmd_options)

        ## locally bind some unfrozen configuration

        # Stores machine infos, the only *three* machine one because we have a
        # target machine info on for the user (Meson never cares about the
        # target machine.)
        machines: PerThreeMachineDefaultable[MachineInfo] = PerThreeMachineDefaultable()

        # Similar to coredata.compilers, but lower level in that there is no
        # meta data, only names/paths.
        binaries: PerMachineDefaultable[BinaryTable] = PerMachineDefaultable()

        # Misc other properties about each machine.
        properties: PerMachineDefaultable[Properties] = PerMachineDefaultable()

        # CMake toolchain variables
        cmakevars: PerMachineDefaultable[CMakeVariables] = PerMachineDefaultable()

        ## Setup build machine defaults

        # Will be fully initialized later using compilers later.
        machines.build = detect_machine_info()

        # Just uses hard-coded defaults and environment variables. Might be
        # overwritten by a native file.
        binaries.build = BinaryTable()
        properties.build = Properties()

        # Options with the key parsed into an OptionKey type.
        #
        # Note that order matters because of 'buildtype', if it is after
        # 'optimization' and 'debug' keys, it override them.
        self.options: T.MutableMapping[OptionKey, T.Union[str, T.List[str]]] = collections.OrderedDict()

        ## Read in native file(s) to override build machine configuration

        if self.coredata.config_files is not None:
            config = machinefile.parse_machine_files(self.coredata.config_files, self.source_dir)
            binaries.build = BinaryTable(config.get('binaries', {}))
            properties.build = Properties(config.get('properties', {}))
            cmakevars.build = CMakeVariables(config.get('cmake', {}))
            self._load_machine_file_options(
                config, properties.build,
                MachineChoice.BUILD if self.coredata.cross_files else MachineChoice.HOST)

        ## Read in cross file(s) to override host machine configuration

        if self.coredata.cross_files:
            config = machinefile.parse_machine_files(self.coredata.cross_files, self.source_dir)
            properties.host = Properties(config.get('properties', {}))
            binaries.host = BinaryTable(config.get('binaries', {}))
            cmakevars.host = CMakeVariables(config.get('cmake', {}))
            if 'host_machine' in config:
                machines.host = MachineInfo.from_literal(config['host_machine'])
            if 'target_machine' in config:
                machines.target = MachineInfo.from_literal(config['target_machine'])
            # Keep only per machine options from the native file. The cross
            # file takes precedence over all other options.
            for key, value in list(self.options.items()):
                if self.coredata.is_per_machine_option(key):
                    self.options[key.as_build()] = value
            self._load_machine_file_options(config, properties.host, MachineChoice.HOST)

        ## "freeze" now initialized configuration, and "save" to the class.

        self.machines = machines.default_missing()
        self.binaries = binaries.default_missing()
        self.properties = properties.default_missing()
        self.cmakevars = cmakevars.default_missing()

        # Command line options override those from cross/native files
        self.options.update(cmd_options.cmd_line_options)

        # Take default value from env if not set in cross/native files or command line.
        self._set_default_options_from_env()
        self._set_default_binaries_from_env()
        self._set_default_properties_from_env()

        # Warn if the user is using two different ways of setting build-type
        # options that override each other
        bt = OptionKey('buildtype')
        db = OptionKey('debug')
        op = OptionKey('optimization')
        if bt in self.options and (db in self.options or op in self.options):
            mlog.warning('Recommend using either -Dbuildtype or -Doptimization + -Ddebug. '
                         'Using both is redundant since they override each other. '
                         'See: https://mesonbuild.com/Builtin-options.html#build-type-options',
                         fatal=False)

        exe_wrapper = self.lookup_binary_entry(MachineChoice.HOST, 'exe_wrapper')
        if exe_wrapper is not None:
            self.exe_wrapper = ExternalProgram.from_bin_list(self, MachineChoice.HOST, 'exe_wrapper')
        else:
            self.exe_wrapper = None

        self.default_cmake = ['cmake']
        self.default_pkgconfig = ['pkg-config']
        self.wrap_resolver: T.Optional['Resolver'] = None

    def _load_machine_file_options(self, config: 'ConfigParser', properties: Properties, machine: MachineChoice) -> None:
        """Read the contents of a Machine file and put it in the options store."""

        # Look for any options in the deprecated paths section, warn about
        # those, then assign them. They will be overwritten by the ones in the
        # "built-in options" section if they're in both sections.
        paths = config.get('paths')
        if paths:
            mlog.deprecation('The [paths] section is deprecated, use the [built-in options] section instead.')
            for k, v in paths.items():
                self.options[OptionKey.from_string(k).evolve(machine=machine)] = v

        # Next look for compiler options in the "properties" section, this is
        # also deprecated, and these will also be overwritten by the "built-in
        # options" section. We need to remove these from this section, as well.
        deprecated_properties: T.Set[str] = set()
        for lang in compilers.all_languages:
            deprecated_properties.add(lang + '_args')
            deprecated_properties.add(lang + '_link_args')
        for k, v in properties.properties.copy().items():
            if k in deprecated_properties:
                mlog.deprecation(f'{k} in the [properties] section of the machine file is deprecated, use the [built-in options] section.')
                self.options[OptionKey.from_string(k).evolve(machine=machine)] = v
                del properties.properties[k]

        for section, values in config.items():
            if ':' in section:
                subproject, section = section.split(':')
            else:
                subproject = ''
            if section == 'built-in options':
                for k, v in values.items():
                    key = OptionKey.from_string(k)
                    # If we're in the cross file, and there is a `build.foo` warn about that. Later we'll remove it.
                    if machine is MachineChoice.HOST and key.machine is not machine:
                        mlog.deprecation('Setting build machine options in cross files, please use a native file instead, this will be removed in meson 0.60', once=True)
                    if key.subproject:
                        raise MesonException('Do not set subproject options in [built-in options] section, use [subproject:built-in options] instead.')
                    self.options[key.evolve(subproject=subproject, machine=machine)] = v
            elif section == 'project options' and machine is MachineChoice.HOST:
                # Project options are only for the host machine, we don't want
                # to read these from the native file
                for k, v in values.items():
                    # Project options are always for the host machine
                    key = OptionKey.from_string(k)
                    if key.subproject:
                        raise MesonException('Do not set subproject options in [built-in options] section, use [subproject:built-in options] instead.')
                    self.options[key.evolve(subproject=subproject)] = v

    def _set_default_options_from_env(self) -> None:
        opts: T.List[T.Tuple[str, str]] = (
            [(v, f'{k}_args') for k, v in compilers.compilers.CFLAGS_MAPPING.items()] +
            [
                ('PKG_CONFIG_PATH', 'pkg_config_path'),
                ('CMAKE_PREFIX_PATH', 'cmake_prefix_path'),
                ('LDFLAGS', 'ldflags'),
                ('CPPFLAGS', 'cppflags'),
            ]
        )

        env_opts: T.DefaultDict[OptionKey, T.List[str]] = collections.defaultdict(list)

        for (evar, keyname), for_machine in itertools.product(opts, MachineChoice):
            p_env = _get_env_var(for_machine, self.is_cross_build(), evar)
            if p_env is not None:
                # these may contain duplicates, which must be removed, else
                # a duplicates-in-array-option warning arises.
                if keyname == 'cmake_prefix_path':
                    if self.machines[for_machine].is_windows():
                        # Cannot split on ':' on Windows because its in the drive letter
                        _p_env = p_env.split(os.pathsep)
                    else:
                        # https://github.com/mesonbuild/meson/issues/7294
                        _p_env = re.split(r':|;', p_env)
                    p_list = list(mesonlib.OrderedSet(_p_env))
                elif keyname == 'pkg_config_path':
                    p_list = list(mesonlib.OrderedSet(p_env.split(os.pathsep)))
                else:
                    p_list = split_args(p_env)
                p_list = [e for e in p_list if e]  # filter out any empty elements

                # Take env vars only on first invocation, if the env changes when
                # reconfiguring it gets ignored.
                # FIXME: We should remember if we took the value from env to warn
                # if it changes on future invocations.
                if self.first_invocation:
                    if keyname == 'ldflags':
                        key = OptionKey('link_args', machine=for_machine, lang='c')  # needs a language to initialize properly
                        for lang in compilers.compilers.LANGUAGES_USING_LDFLAGS:
                            key = key.evolve(lang=lang)
                            env_opts[key].extend(p_list)
                    elif keyname == 'cppflags':
                        key = OptionKey('env_args', machine=for_machine, lang='c')
                        for lang in compilers.compilers.LANGUAGES_USING_CPPFLAGS:
                            key = key.evolve(lang=lang)
                            env_opts[key].extend(p_list)
                    else:
                        key = OptionKey.from_string(keyname).evolve(machine=for_machine)
                        if evar in compilers.compilers.CFLAGS_MAPPING.values():
                            # If this is an environment variable, we have to
                            # store it separately until the compiler is
                            # instantiated, as we don't know whether the
                            # compiler will want to use these arguments at link
                            # time and compile time (instead of just at compile
                            # time) until we're instantiating that `Compiler`
                            # object. This is required so that passing
                            # `-Dc_args=` on the command line and `$CFLAGS`
                            # have subtly different behavior. `$CFLAGS` will be
                            # added to the linker command line if the compiler
                            # acts as a linker driver, `-Dc_args` will not.
                            #
                            # We still use the original key as the base here, as
                            # we want to inherit the machine and the compiler
                            # language
                            key = key.evolve('env_args')
                        env_opts[key].extend(p_list)

        # Only store options that are not already in self.options,
        # otherwise we'd override the machine files
        for k, v in env_opts.items():
            if k not in self.options:
                self.options[k] = v

    def _set_default_binaries_from_env(self) -> None:
        """Set default binaries from the environment.

        For example, pkg-config can be set via PKG_CONFIG, or in the machine
        file. We want to set the default to the env variable.
        """
        opts = itertools.chain(envconfig.DEPRECATED_ENV_PROG_MAP.items(),
                               envconfig.ENV_VAR_PROG_MAP.items())

        for (name, evar), for_machine in itertools.product(opts, MachineChoice):
            p_env = _get_env_var(for_machine, self.is_cross_build(), evar)
            if p_env is not None:
                if os.path.exists(p_env):
                    self.binaries[for_machine].binaries.setdefault(name, [p_env])
                else:
                    self.binaries[for_machine].binaries.setdefault(name, mesonlib.split_args(p_env))

    def _set_default_properties_from_env(self) -> None:
        """Properties which can also be set from the environment."""
        # name, evar, split
        opts: T.List[T.Tuple[str, T.List[str], bool]] = [
            ('boost_includedir', ['BOOST_INCLUDEDIR'], False),
            ('boost_librarydir', ['BOOST_LIBRARYDIR'], False),
            ('boost_root', ['BOOST_ROOT', 'BOOSTROOT'], True),
            ('java_home', ['JAVA_HOME'], False),
        ]

        for (name, evars, split), for_machine in itertools.product(opts, MachineChoice):
            for evar in evars:
                p_env = _get_env_var(for_machine, self.is_cross_build(), evar)
                if p_env is not None:
                    if split:
                        self.properties[for_machine].properties.setdefault(name, p_env.split(os.pathsep))
                    else:
                        self.properties[for_machine].properties.setdefault(name, p_env)
                    break

    def create_new_coredata(self, options: coredata.SharedCMDOptions) -> None:
        # WARNING: Don't use any values from coredata in __init__. It gets
        # re-initialized with project options by the interpreter during
        # build file parsing.
        # meson_command is used by the regenchecker script, which runs meson
        self.coredata = coredata.CoreData(options, self.scratch_dir, mesonlib.get_meson_command())
        self.first_invocation = True

    def is_cross_build(self, when_building_for: MachineChoice = MachineChoice.HOST) -> bool:
        return self.coredata.is_cross_build(when_building_for)

    def dump_coredata(self) -> str:
        return coredata.save(self.coredata, self.get_build_dir())

    def get_log_dir(self) -> str:
        return self.log_dir

    def get_coredata(self) -> coredata.CoreData:
        return self.coredata

    @staticmethod
    def get_build_command(unbuffered: bool = False) -> T.List[str]:
        cmd = mesonlib.get_meson_command()
        if cmd is None:
            raise MesonBugException('No command?')
        cmd = cmd.copy()
        if unbuffered and 'python' in os.path.basename(cmd[0]):
            cmd.insert(1, '-u')
        return cmd

    def is_header(self, fname: 'mesonlib.FileOrString') -> bool:
        return is_header(fname)

    def is_source(self, fname: 'mesonlib.FileOrString') -> bool:
        return is_source(fname)

    def is_assembly(self, fname: 'mesonlib.FileOrString') -> bool:
        return is_assembly(fname)

    def is_llvm_ir(self, fname: 'mesonlib.FileOrString') -> bool:
        return is_llvm_ir(fname)

    def is_object(self, fname: 'mesonlib.FileOrString') -> bool:
        return is_object(fname)

    @lru_cache(maxsize=None)
    def is_library(self, fname: mesonlib.FileOrString):
        return is_library(fname)

    def lookup_binary_entry(self, for_machine: MachineChoice, name: str) -> T.Optional[T.List[str]]:
        return self.binaries[for_machine].lookup_entry(name)

    def get_scratch_dir(self) -> str:
        return self.scratch_dir

    def get_source_dir(self) -> str:
        return self.source_dir

    def get_build_dir(self) -> str:
        return self.build_dir

    def get_import_lib_dir(self) -> str:
        "Install dir for the import library (library used for linking)"
        return self.get_libdir()

    def get_shared_module_dir(self) -> str:
        "Install dir for shared modules that are loaded at runtime"
        return self.get_libdir()

    def get_shared_lib_dir(self) -> str:
        "Install dir for the shared library"
        m = self.machines.host
        # Windows has no RPATH or similar, so DLLs must be next to EXEs.
        if m.is_windows() or m.is_cygwin():
            return self.get_bindir()
        return self.get_libdir()

    def get_jar_dir(self) -> str:
        """Install dir for JAR files"""
        return f"{self.get_datadir()}/java"

    def get_static_lib_dir(self) -> str:
        "Install dir for the static library"
        return self.get_libdir()

    def get_prefix(self) -> str:
        return self.coredata.get_option(OptionKey('prefix'))

    def get_libdir(self) -> str:
        return self.coredata.get_option(OptionKey('libdir'))

    def get_libexecdir(self) -> str:
        return self.coredata.get_option(OptionKey('libexecdir'))

    def get_bindir(self) -> str:
        return self.coredata.get_option(OptionKey('bindir'))

    def get_includedir(self) -> str:
        return self.coredata.get_option(OptionKey('includedir'))

    def get_mandir(self) -> str:
        return self.coredata.get_option(OptionKey('mandir'))

    def get_datadir(self) -> str:
        return self.coredata.get_option(OptionKey('datadir'))

    def get_compiler_system_lib_dirs(self, for_machine: MachineChoice) -> T.List[str]:
        for comp in self.coredata.compilers[for_machine].values():
            if comp.id == 'clang':
                index = 1
                break
            elif comp.id == 'gcc':
                index = 2
                break
        else:
            # This option is only supported by gcc and clang. If we don't get a
            # GCC or Clang compiler return and empty list.
            return []

        p, out, _ = Popen_safe(comp.get_exelist() + ['-print-search-dirs'])
        if p.returncode != 0:
            raise mesonlib.MesonException('Could not calculate system search dirs')
        out = out.split('\n')[index].lstrip('libraries: =').split(':')
        return [os.path.normpath(p) for p in out]

    def get_compiler_system_include_dirs(self, for_machine: MachineChoice) -> T.List[str]:
        for comp in self.coredata.compilers[for_machine].values():
            if comp.id == 'clang':
                break
            elif comp.id == 'gcc':
                break
        else:
            # This option is only supported by gcc and clang. If we don't get a
            # GCC or Clang compiler return and empty list.
            return []
        return comp.get_default_include_dirs()

    def need_exe_wrapper(self, for_machine: MachineChoice = MachineChoice.HOST):
        value = self.properties[for_machine].get('needs_exe_wrapper', None)
        if value is not None:
            return value
        return not machine_info_can_run(self.machines[for_machine])

    def get_exe_wrapper(self) -> T.Optional[ExternalProgram]:
        if not self.need_exe_wrapper():
            return None
        return self.exe_wrapper

    def has_exe_wrapper(self) -> bool:
        return self.exe_wrapper and self.exe_wrapper.found()
