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

from __future__ import annotations

import dataclasses
import itertools
import os, re
import typing as T
import collections

from . import cmdline
from . import coredata
from . import mesonlib
from . import machinefile
from . import options

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

from .envconfig import (
    BinaryTable, MachineInfo, Properties, CMakeVariables,
    detect_machine_info, machine_info_can_run
)
from . import compilers

from mesonbuild import envconfig

if T.TYPE_CHECKING:
    from .compilers.compilers import Compiler, CompilerDict, Language
    from .options import OptionDict, ElementaryOptionValues
    from .wrap.wrap import Resolver

    import enum


NON_LANG_ENV_OPTIONS = [
    ('PKG_CONFIG_PATH', 'pkg_config_path'),
    ('CMAKE_PREFIX_PATH', 'cmake_prefix_path'),
    ('LDFLAGS', 'ldflags'),
    ('CPPFLAGS', 'cppflags'),
]

build_filename = 'meson.build'


def _as_str(val: object) -> str:
    assert isinstance(val, str), 'for mypy'
    return val


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


@dataclasses.dataclass
class MachineMap:
    # BUILD if cross compiling, HOST if not cross compiling
    build: MachineChoice
    # This is not entirely correct: it is possible in principle for
    # the host machine to be originally configured as a target, and
    # switched to be the host for a single subproject.  Ultimately,
    # Environment should include N arbitrarily-named configurations,
    # and kwargs['native'] would be supplanted by kwargs['for_machine']
    # of type T.NewType('MachineChoice', str) after parameter parsing.
    host: MachineChoice
    target: ThreeMachineChoice

    @T.overload
    def __getitem__(self, machine: MachineChoice) -> MachineChoice:
        ...

    @T.overload
    def __getitem__(self, machine: ThreeMachineChoice) -> ThreeMachineChoice:
        ...

    def __getitem__(self, machine: MachineChoice | ThreeMachineChoice) -> enum.IntEnum:
        return [self.build, self.host, self.target][machine.value]


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

    exe_wrapper: ExternalProgram | None

    def __init__(self, source_dir: str, build_dir: T.Optional[str], cmd_options: cmdline.SharedCMDOptions) -> None:
        self.source_dir = source_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.build_dir = build_dir
            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))
                cmdline.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(cmdline.get_cmd_line_file(self.build_dir)):
                    mlog.warning('Regenerating configuration from scratch.', fatal=False)
                    mlog.log('Reason:', mlog.red(str(e)))
                    cmdline.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.build_dir = ''
            self.scratch_dir = ''
            self.create_new_coredata(cmd_options)

        # Store which machine is actually returned by self.machines after
        # taking into account defaults
        if self.coredata.cross_files:
            self.machine_map = MachineMap(MachineChoice.BUILD, MachineChoice.HOST, ThreeMachineChoice.HOST)
        else:
            self.machine_map = MachineMap(MachineChoice.HOST, MachineChoice.HOST, ThreeMachineChoice.HOST)

        ## 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: OptionDict = collections.OrderedDict()

        # Environment variables with the name converted into an OptionKey type.
        # These have subtly different behavior compared to machine files, so do
        # not store them in self.options.  See _set_default_options_from_env.
        self.env_opts: OptionDict = {}

        self.machinestore = machinefile.MachineFileStore(self.coredata.config_files, self.coredata.cross_files, self.source_dir)

        ## 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, self.machine_map.build)

        ## 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'])
                self.machine_map.target = ThreeMachineChoice.TARGET
            # 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.optstore.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()

        # Set host machine info for machine-aware handling of directory options
        self.coredata.optstore.set_host_machine(self.machines.host)

        # 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)

        # Filter out build machine options that are not valid per-project.
        # We allow this in the file because it makes the machine files more
        # useful (ie, the same file can be used for host == build configuration
        # a host != build configuration)
        self.options = {k: v for k, v in self.options.items()
                        if k.machine is MachineChoice.HOST or self.coredata.optstore.is_per_machine_option(k)}

        exe_wrapper = self.lookup_binary_entry(MachineChoice.HOST, 'exe_wrapper')
        self.exe_wrapper: ExternalProgram | None
        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 mfilestr2key(self, machine_file_string: str, section: T.Optional[str], section_subproject: T.Optional[str], machine: MachineChoice) -> OptionKey:
        key = OptionKey.from_string(machine_file_string)
        if key.subproject:
            suggestion = section if section == 'project options' else 'built-in options'
            raise MesonException(f'Do not set subproject options in [{section}] section, use [subproject:{suggestion}] instead.')
        if section_subproject:
            key = key.evolve(subproject=section_subproject)
        if machine == MachineChoice.BUILD:
            if key.machine == MachineChoice.BUILD:
                mlog.deprecation('Setting build machine options in the native file does not need the "build." prefix', once=True)
            return key.evolve(machine=machine)
        return key

    def _load_machine_file_options(self, config: T.Mapping[str, T.Mapping[str, ElementaryOptionValues]],
                                   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 strk, v in paths.items():
                k = self.mfilestr2key(strk, 'paths', None, machine)
                self.options[k] = 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 strk, v in properties.properties.copy().items():
            if strk in deprecated_properties:
                mlog.deprecation(f'{strk} in the [properties] section of the machine file is deprecated, use the [built-in options] section.')
                k = self.mfilestr2key(strk, 'properties', None, machine)
                self.options[k] = v
                del properties.properties[strk]

        for section, values in config.items():
            if ':' in section:
                section_subproject, section = section.split(':', 1)
            else:
                section_subproject = ''
            if section == 'built-in options':
                for strk, v in values.items():
                    key = self.mfilestr2key(strk, section, section_subproject, machine)
                    # 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 2.0', once=True)
                    self.options[key] = 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 strk, v in values.items():
                    # Project options are always for the host machine
                    key = self.mfilestr2key(strk, section, section_subproject, machine)
                    self.options[key] = v
            elif ':' in section:
                correct_subproject, correct_section = section.split(':')[-2:]
                raise MesonException(
                    'Subproject options should always be set as '
                    '`[subproject:section]`, even if the options are from a '
                    'nested subproject. '
                    f'Replace `[{section_subproject}:{section}]` with `[{correct_subproject}:{correct_section}]`')

    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()] +
            NON_LANG_ENV_OPTIONS
        )

        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':
                        for lang in compilers.compilers.LANGUAGES_USING_LDFLAGS:
                            key = OptionKey(name=f'{lang}_link_args', machine=for_machine)
                            env_opts[key].extend(p_list)
                    elif keyname == 'cppflags':
                        for lang in compilers.compilers.LANGUAGES_USING_CPPFLAGS:
                            key = OptionKey(f'{lang}_args', machine=for_machine)
                            env_opts[key].extend(p_list)
                    else:
                        key = OptionKey.from_string(keyname).evolve(machine=for_machine)
                        env_opts[key].extend(p_list)

        # 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.
        for (_, keyname), for_machine in itertools.product(NON_LANG_ENV_OPTIONS, MachineChoice):
            key = OptionKey.from_string(keyname).evolve(machine=for_machine)
            # Only store options that are not already in self.options,
            # otherwise we'd override the machine files
            if key in env_opts and key not in self.options:
                self.options[key] = env_opts[key]
                del env_opts[key]

        self.env_opts.update(env_opts)

    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, evars), 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 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))
                    break

    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: cmdline.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
        try:
            meson_command = mesonlib.get_meson_command().copy()
        except MesonBugException:
            meson_command = []
        self.coredata = coredata.CoreData(options, self.scratch_dir, meson_command)
        self.first_invocation = True

    def init_backend_options(self, backend_name: str) -> None:
        # Only init backend options on first invocation otherwise it would
        # override values previously set from command line.
        if not self.first_invocation:
            return

        self.coredata.init_backend_options(backend_name)
        for k, v in self.options.items():
            if self.coredata.optstore.is_backend_option(k):
                self.coredata.optstore.set_option(k, v)

    def is_cross_build(self, when_building_for: MachineChoice = MachineChoice.HOST) -> bool:
        return self.machine_map[when_building_for] is not self.machine_map.build

    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().copy()
        if unbuffered and 'python' in os.path.basename(cmd[0]):
            cmd.insert(1, '-u')
        return cmd

    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 _as_str(self.coredata.optstore.get_value_for(OptionKey('prefix')))

    def get_libdir(self) -> str:
        return _as_str(self.coredata.optstore.get_value_for(OptionKey('libdir')))

    def get_libexecdir(self) -> str:
        return _as_str(self.coredata.optstore.get_value_for(OptionKey('libexecdir')))

    def get_bindir(self) -> str:
        return _as_str(self.coredata.optstore.get_value_for(OptionKey('bindir')))

    def get_sbindir(self) -> str:
        return _as_str(self.coredata.optstore.get_value_for(OptionKey('sbindir')))

    def get_includedir(self) -> str:
        return _as_str(self.coredata.optstore.get_value_for(OptionKey('includedir')))

    def get_mandir(self) -> str:
        return _as_str(self.coredata.optstore.get_value_for(OptionKey('mandir')))

    def get_datadir(self) -> str:
        return _as_str(self.coredata.optstore.get_value_for(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')
        split = out.split('\n')[index].lstrip('libraries: =').split(':')
        return [os.path.normpath(p) for p in split]

    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) -> bool:
        value = self.properties[for_machine].get('needs_exe_wrapper', None)
        if value is not None:
            assert isinstance(value, bool), 'for mypy'
            return value
        if not self.is_cross_build():
            return False
        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 is not None and self.exe_wrapper.found()

    def get_env_for_paths(self, library_paths: T.Set[str], extra_paths: T.Set[str]) -> mesonlib.EnvironmentVariables:
        env = mesonlib.EnvironmentVariables()
        need_wine = not self.machines.build.is_windows() and self.machines.host.is_windows()
        if need_wine:
            # Executable paths should be in both PATH and WINEPATH.
            # - Having them in PATH makes bash completion find it,
            #   and make running "foo.exe" find it when wine-binfmt is installed.
            # - Having them in WINEPATH makes "wine foo.exe" find it.
            library_paths.update(extra_paths)
        if library_paths:
            if need_wine:
                env.prepend('WINEPATH', list(library_paths), separator=';')
            elif self.machines.host.is_windows() or self.machines.host.is_cygwin():
                extra_paths.update(library_paths)
            elif self.machines.host.is_darwin():
                env.prepend('DYLD_LIBRARY_PATH', list(library_paths))
            else:
                env.prepend('LD_LIBRARY_PATH', list(library_paths))
        if extra_paths:
            env.prepend('PATH', list(extra_paths))
        return env

    def add_lang_args(self, lang: Language, comp: T.Type['Compiler'],
                      for_machine: MachineChoice) -> None:
        """Add global language arguments that are needed before compiler/linker detection."""
        description = f'Extra arguments passed to the {lang}'
        argkey = OptionKey(f'{lang}_args', machine=for_machine)
        largkey = OptionKey(f'{lang}_link_args', machine=for_machine)

        comp_args_from_envvar = False
        comp_options = self.coredata.optstore.get_pending_value(argkey)
        if comp_options is None:
            comp_args_from_envvar = True
            comp_options = self.env_opts.get(argkey, [])

        link_options = self.coredata.optstore.get_pending_value(largkey)
        if link_options is None:
            link_options = self.env_opts.get(largkey, [])

        assert isinstance(comp_options, (str, list)), 'for mypy'
        assert isinstance(link_options, (str, list)), 'for mypy'

        cargs = options.UserStringArrayOption(
            argkey.name,
            description + ' compiler',
            comp_options, split_args=True, allow_dups=True)

        largs = options.UserStringArrayOption(
            largkey.name,
            description + ' linker',
            link_options, split_args=True, allow_dups=True)

        self.coredata.optstore.add_compiler_option(lang, argkey, cargs)
        self.coredata.optstore.add_compiler_option(lang, largkey, largs)

        if comp.USED_FOR_SEPARATE_LINKING_STEP and comp_args_from_envvar:
            # If the compiler acts as a linker driver, and we're using the
            # environment variable flags for both the compiler and linker
            # arguments, then put the compiler flags in the linker flags as well.
            # This is how autotools works, and the env vars feature is for
            # autotools compatibility.
            largs.extend_value(comp_options)

    def update_build_machine(self, compilers: T.Optional[CompilerDict] = None) -> None:
        """Redetect the build machine and update the machine definitions

        :compilers: An optional dictionary of compilers to use instead of the coredata dict.
        """
        compilers = compilers or self.coredata.compilers.build

        machines = self.machines.miss_defaulting()
        machines.build = detect_machine_info(compilers)
        self.machines = machines.default_missing()
