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

from __future__ import annotations

import io, sys, traceback
import dataclasses
import functools

from .. import mparser
from .. import environment
from .. import coredata
from .. import dependencies
from .. import mlog
from .. import options
from .. import build
from .. import compilers
from .. import envconfig
from ..wrap import wrap, WrapMode
from .. import mesonlib
from ..mesonlib import (EnvironmentVariables, ExecutableSerialisation, MesonBugException, MesonException, HoldableObject,
                        FileMode, InstallScriptFailure, MachineChoice, PerMachine, PerMachineDefaultable, is_parent_path,
                        listify, has_path_sep, path_has_root, path_is_in_root)
from ..options import OptionKey
from ..programs import ExternalProgram, NonExistingExternalProgram, Program
from ..dependencies import Dependency
from ..depfile import DepFile
from ..interpreterbase import ContainerTypeInfo, InterpreterBase, KwargInfo, typed_kwargs, typed_pos_args
from ..interpreterbase import noPosargs, noKwargs, noArgsFlattening, noSecondLevelHolderResolving, unholder_return
from .decorators import apply_machine_map
from ..interpreterbase import InterpreterException, InvalidArguments, InvalidCode, SubdirDoneRequest
from ..interpreterbase import Disabler, disablerIfNotFound
from ..interpreterbase import FeatureNew, FeatureDeprecated, FeatureBroken, FeatureNewKwargs
from ..interpreterbase import ObjectHolder, ContextManagerObject, DefaultObject
from ..interpreterbase import stringifyUserArguments, Feature, FeatureValue
from ..modules import ExtensionModule, ModuleObject, MutableModuleObject, NewExtensionModule, NotFoundExtensionModule, __path__ as modules_path
from ..optinterpreter import optname_regex

from . import interpreterobjects as OBJ
from . import compiler as compilerOBJ
from .mesonmain import MesonMain
from .dependencyfallbacks import DependencyFallbacksHolder
from .interpreterobjects import (
    SubprojectHolder,
    Test,
    RunProcess,
    extract_required_kwarg,
    extract_search_dirs,
    NullSubprojectInterpreter,
)
from .type_checking import (
    BUILD_TARGET_KWS,
    COMMAND_KW,
    CT_BUILD_ALWAYS,
    CT_BUILD_ALWAYS_STALE,
    CT_BUILD_BY_DEFAULT,
    CT_INPUT_KW,
    CT_INSTALL_DIR_KW,
    EXCLUSIVE_EXECUTABLE_KWS,
    EXECUTABLE_KWS,
    JAR_KWS,
    LIBRARY_KWS,
    MULTI_OUTPUT_KW,
    OUTPUT_KW,
    DEFAULT_OPTIONS,
    DEPENDENCIES_KW,
    DEPENDENCY_KWS,
    DEPENDS_KW,
    DEPEND_FILES_KW,
    DEPFILE_KW,
    DISABLER_KW,
    D_MODULE_VERSIONS_KW,
    ENV_KW,
    ENV_METHOD_KW,
    ENV_SEPARATOR_KW,
    INCLUDE_DIRECTORIES,
    INSTALL_KW,
    INSTALL_DIR_KW,
    INSTALL_MODE_KW,
    INSTALL_FOLLOW_SYMLINKS,
    LINK_ARGS_KW,
    LINK_WITH_KW,
    LINK_WHOLE_KW,
    CT_INSTALL_TAG_KW,
    INSTALL_TAG_KW,
    LANGUAGE_KW,
    NATIVE_KW,
    PRESERVE_PATH_KW,
    REQUIRED_KW,
    SHARED_LIB_KWS,
    SHARED_MOD_KWS,
    DEPENDENCY_SOURCES_KW,
    SOURCES_VARARGS,
    STATIC_LIB_KWS,
    VARIABLES_KW,
    TEST_KWS,
    NoneType,
    in_set_validator,
    env_convertor_with_method
)
from . import primitives as P_OBJ

from pathlib import Path
from enum import Enum
import os
import shutil
import uuid
import re
import stat
import collections
import typing as T
import textwrap
import importlib
import itertools

if T.TYPE_CHECKING:
    from typing_extensions import Literal
    import types

    from .. import cargo
    from . import kwargs as kwtypes
    from ..backend.backends import Backend
    from ..compilers.compilers import CompilerDict, Language
    from ..interpreterbase.baseobjects import InterpreterObject, TYPE_var, TYPE_kwargs
    from ..options import OptionDict
    from ..mesonlib import InstallScript, SubProject
    from ..cmdline import SharedCMDOptions
    from .type_checking import SourcesVarargsType, FullEnvInitValueType

    # Input source types passed to Targets
    SourceInputs = T.Union[str, build.TargetSources, build.BuildTarget,
                           build.BothLibraries, build.ExtractedObjects]
    # Input source types passed to the build.Target classes
    SourceOutputs = T.Union[build.TargetSources, build.BuildTarget,
                            build.ExtractedObjects, build.StructuredSources]
    # Sources for custom targets, which can also include ExternalProgram
    CustomTargetSources = T.Union[build.TargetSources, build.BuildTarget,
                                  build.ExtractedObjects, Program]

    BuildTargetSource = T.Union[str, build.TargetSources, build.StructuredSources]

    ProgramVersionFunc = T.Callable[[Program], str]

    TestClass = T.TypeVar('TestClass', bound=Test)

def _project_version_validator(value: T.Union[T.List, str, mesonlib.File, None]) -> T.Optional[str]:
    if isinstance(value, list):
        if len(value) != 1:
            return 'when passed as array must have a length of 1'
        elif not isinstance(value[0], mesonlib.File):
            return 'when passed as array must contain a File'
    return None


@dataclasses.dataclass
class SandboxViolationError(InterpreterException):

    """Exception raised when trying to use files outside of this project

    :param inputtype: The kind of thing, usually "directory" or "file"
    :param name: The name of the thing being used
    :param subproject: Is this an attempt to use a file from inside a subproject?
    """

    inputtype: str
    name: str
    subproject: bool = dataclasses.field(default=True, kw_only=True)

    def __str__(self) -> str:
        if self.subproject:
            msg = 'a nested subproject'
        else:
            msg = 'outside current (sub)project'
        return f'Sandbox violation: Tried to grab {self.inputtype} {self.name} from {msg}.'


@dataclasses.dataclass
class BuiltFileByNameError(InterpreterException):

    name: str

    def __str__(self) -> str:
        return (f'{self.name!r} is a generated file, and should be passed by reference instead of string name. '
                'This will become a hard error in Meson 2.0')


class Summary:
    def __init__(self, project_name: str, project_version: str):
        self.project_name = project_name
        self.project_version = project_version
        self.sections: collections.defaultdict[str, dict[str, tuple[mlog.TV_LoggableList, str | None]]] = collections.defaultdict(dict)
        self.max_key_len = 0

    def add_section(self, section: str, values: T.Dict[str, mlog.TV_Loggable | mlog.TV_LoggableList], bool_yn: bool,
                    list_sep: T.Optional[str], subproject: SubProject) -> None:
        for k, v in values.items():
            if k in self.sections[section]:
                raise InterpreterException(f'Summary section {section!r} already have key {k!r}')
            formatted_values: mlog.TV_LoggableList = []
            for i in listify(v):
                if isinstance(i, bool):
                    if bool_yn:
                        formatted_values.append(mlog.green('YES') if i else mlog.red('NO'))
                    else:
                        formatted_values.append('true' if i else 'false')
                elif isinstance(i, (str, int)):
                    formatted_values.append(str(i))
                elif isinstance(i, (ExternalProgram, Dependency)):
                    FeatureNew.single_use('dependency or external program in summary', '0.57.0', subproject)
                    formatted_values.append(i.summary_value())
                elif isinstance(i, Disabler):
                    FeatureNew.single_use('disabler in summary', '0.64.0', subproject)
                    formatted_values.append(mlog.red('NO'))
                elif isinstance(i, Feature):
                    FeatureNew.single_use('feature option in summary', '0.58.0', subproject)
                    formatted_values.append(str(i))
                else:
                    m = 'Summary value in section {!r}, key {!r}, must be string, integer, boolean, dependency, disabler, or external program'
                    raise InterpreterException(m.format(section, k))
            self.sections[section][k] = (formatted_values, list_sep)
            self.max_key_len = max(self.max_key_len, len(k))

    def dump(self) -> None:
        mlog.log(self.project_name, mlog.normal_cyan(self.project_version))
        for section, values in self.sections.items():
            mlog.log('')  # newline
            if section:
                mlog.log(' ', mlog.bold(section))
            for k, v in values.items():
                v, list_sep = v
                padding = self.max_key_len - len(k)
                end = ' ' if v else ''
                mlog.log(' ' * 3, k + ' ' * padding + ':', end=end)
                indent = self.max_key_len + 6
                self.dump_value(v, list_sep, indent)
        mlog.log('')  # newline

    def dump_value(self, arr: mlog.TV_LoggableList, list_sep: str | None, indent: int) -> None:
        lines_sep = '\n' + ' ' * indent
        if list_sep is None:
            mlog.log(*arr, sep=lines_sep, display_timestamp=False)
            return
        max_len = shutil.get_terminal_size().columns
        line: mlog.TV_LoggableList = []
        line_len = indent
        lines_sep = list_sep.rstrip() + lines_sep
        for v in arr:
            v_len = len(str(v)) + len(list_sep)
            if line and line_len + v_len > max_len:
                mlog.log(*line, sep=list_sep, end=lines_sep)
                line_len = indent
                line = []
            line.append(v)
            line_len += v_len
        mlog.log(*line, sep=list_sep, display_timestamp=False)


class InterpreterRuleRelaxation(Enum):
    ''' Defines specific relaxations of the Meson rules.

    This is intended to be used for automatically converted
    projects (CMake subprojects, build system mixing) that
    generate a Meson AST via introspection, etc.
    '''

    ALLOW_BUILD_DIR_FILE_REFERENCES = 1
    CARGO_SUBDIR = 2

implicit_check_false_warning = """You should add the boolean check kwarg to the run_command call.
         It currently defaults to false,
         but it will default to true in meson 2.0.
         See also: https://github.com/mesonbuild/meson/issues/9300"""
class Interpreter(InterpreterBase, HoldableObject):

    backend: mesonlib.late_property[Backend] = mesonlib.late_property()

    def __init__(
                self,
                _build: build.Build,
                backend: T.Optional[Backend] = None,
                subproject: SubProject = mesonlib.ROOT_SUBPROJECT,
                subdir: str = '',
                subproject_dir: str = 'subprojects',
                invoker_method_default_options: T.Optional[OptionDict] = None,
                ast: T.Optional[mparser.CodeBlockNode] = None,
                relaxations: T.Optional[T.Set[InterpreterRuleRelaxation]] = None,
                user_defined_options: T.Optional[SharedCMDOptions] = None,
                cargo: T.Optional[cargo.Interpreter] = None,
            ) -> None:
        super().__init__(_build.environment.get_source_dir(), subdir, subproject, subproject_dir, _build.environment)
        self.active_projectname = ''
        self.build = _build
        if backend is not None:
            self.backend = backend
        self.cargo = cargo
        self.summary: T.Dict[str, 'Summary'] = {}
        self.modules: T.Dict[str, NewExtensionModule] = {}
        self.relaxations = relaxations or set()
        if ast is None:
            self.load_root_meson_file()
        else:
            self.ast = ast
        self.sanity_check_ast()
        self.builtin.update({'meson': MesonMain(self.build, self)})
        self.validated_cache: T.Set[str] = set()
        self.project_args_frozen = False
        self.global_args_frozen = False  # implies self.project_args_frozen
        self.subprojects: PerMachine[T.Dict[str, SubprojectHolder]] = PerMachineDefaultable.default(
            self.environment.is_cross_build(), {}, {})
        self.subproject_stack: T.List[T.Tuple[str, MachineChoice]] = []
        self.configure_file_outputs: T.Dict[str, int] = {}
        # Passed from the outside, only used in subprojects.
        if invoker_method_default_options:
            assert isinstance(invoker_method_default_options, dict)
            self.invoker_method_default_options = invoker_method_default_options
        else:
            self.invoker_method_default_options = {}
        self.project_default_options: OptionDict = {}
        self.build_func_dict()
        self.build_holder_map()
        self.user_defined_options = user_defined_options
        # Languages added in the current subproject
        self.compilers: PerMachine[CompilerDict] = PerMachine({}, {})
        self.parse_project()
        self._redetect_machines()

    def __getnewargs_ex__(self) -> T.Tuple[T.Tuple[object], T.Dict[str, object]]:
        raise MesonBugException('This class is unpicklable')

    def load_root_cargo_lock_file(self) -> None:
        cargo_lock = os.path.join(self.source_root, self.subdir, 'Cargo.lock')
        if not os.path.isfile(cargo_lock):
            return
        from .. import cargo
        try:
            self.cargo = cargo.Interpreter(self.environment, self.subdir, self.subproject_dir)
        except cargo.TomlImplementationMissing as e:
            # error delayed to actual usage of a Cargo subproject
            mlog.warning(f'cannot load Cargo.lock: {e}', fatal=False)

    def _redetect_machines(self) -> None:
        # Re-initialize machine descriptions. We can do a better job now because we
        # have the compilers needed to gain more knowledge, so wipe out old
        # inference and start over.
        self.build.environment.update_build_machine()

        self.builtin['build_machine'] = \
            OBJ.MachineHolder(self.build.environment.machines[self.build.machine_map.build], self)
        self.builtin['host_machine'] = \
            OBJ.MachineHolder(self.build.environment.machines[self.build.machine_map.host], self)
        self.builtin['target_machine'] = \
            OBJ.MachineHolder(self.build.environment.machines[self.build.machine_map.target], self)

    def is_internal_machine(self, for_machine: MachineChoice) -> bool:
        # Return whether applying the caller's effect to the build and
        # host machine would duplicate the effect
        return self.build.machine_map[for_machine] is MachineChoice.BUILD

    def apply_machine_map_to_kwargs(self, kwargs: kwtypes.BaseBuildTarget | kwtypes.MachineMapArgs) -> None:
        orig_for_machine: MachineChoice | None = kwargs.get('native', None)
        if orig_for_machine is None:
            return

        for_machine = self.build.machine_map[orig_for_machine]
        if for_machine is orig_for_machine:
            return

        if 'install' in kwargs and for_machine is MachineChoice.BUILD:
            kwargs['install'] = False
        kwargs['native'] = for_machine

    def build_func_dict(self) -> None:
        self.funcs.update({'add_global_arguments': self.func_add_global_arguments,
                           'add_global_link_arguments': self.func_add_global_link_arguments,
                           'add_languages': self.func_add_languages,
                           'add_project_arguments': self.func_add_project_arguments,
                           'add_project_dependencies': self.func_add_project_dependencies,
                           'add_project_link_arguments': self.func_add_project_link_arguments,
                           'add_test_setup': self.func_add_test_setup,
                           'alias_target': self.func_alias_target,
                           'assert': self.func_assert,
                           'benchmark': self.func_benchmark,
                           'both_libraries': self.func_both_lib,
                           'build_target': self.func_build_target,
                           'configuration_data': self.func_configuration_data,
                           'configure_file': self.func_configure_file,
                           'custom_target': self.func_custom_target,
                           'debug': self.func_debug,
                           'declare_dependency': self.func_declare_dependency,
                           'dependency': self.func_dependency,
                           'disabler': self.func_disabler,
                           'default': self.func_default,
                           'environment': self.func_environment,
                           'error': self.func_error,
                           'executable': self.func_executable,
                           'files': self.func_files,
                           'find_program': self.func_find_program,
                           'generator': self.func_generator,
                           'get_option': self.func_get_option,
                           'get_variable': self.func_get_variable,
                           'import': self.func_import,
                           'include_directories': self.func_include_directories,
                           'install_data': self.func_install_data,
                           'install_emptydir': self.func_install_emptydir,
                           'install_headers': self.func_install_headers,
                           'install_man': self.func_install_man,
                           'install_subdir': self.func_install_subdir,
                           'install_symlink': self.func_install_symlink,
                           'is_disabler': self.func_is_disabler,
                           'is_variable': self.func_is_variable,
                           'jar': self.func_jar,
                           'join_paths': self.func_join_paths,
                           'library': self.func_library,
                           'message': self.func_message,
                           'option': self.func_option,
                           'project': self.func_project,
                           'range': self.func_range,
                           'run_command': self.func_run_command,
                           'run_target': self.func_run_target,
                           'set_variable': self.func_set_variable,
                           'structured_sources': self.func_structured_sources,
                           'subdir': self.func_subdir,
                           'shared_library': self.func_shared_lib,
                           'shared_module': self.func_shared_module,
                           'static_library': self.func_static_lib,
                           'subdir_done': self.func_subdir_done,
                           'subproject': self.func_subproject,
                           'summary': self.func_summary,
                           'test': self.func_test,
                           'unset_variable': self.func_unset_variable,
                           'vcs_tag': self.func_vcs_tag,
                           'warning': self.func_warning,
                           })
        if 'MESON_UNIT_TEST' in os.environ:
            self.funcs.update({'exception': self.func_exception})
        if 'MESON_RUNNING_IN_PROJECT_TESTS' in os.environ:
            self.funcs.update({'expect_error': self.func_expect_error})

    def build_holder_map(self) -> None:
        '''
            Build a mapping of `HoldableObject` types to their corresponding
            `ObjectHolder`s. This mapping is used in `InterpreterBase` to automatically
            holderify all returned values from methods and functions.
        '''
        self.holder_map.update({
            # Primitives
            list: P_OBJ.ArrayHolder,
            dict: P_OBJ.DictHolder,
            int: P_OBJ.IntegerHolder,
            bool: P_OBJ.BooleanHolder,
            str: P_OBJ.StringHolder,
            P_OBJ.MesonVersionString: P_OBJ.MesonVersionStringHolder,
            P_OBJ.DependencyVariableString: P_OBJ.DependencyVariableStringHolder,
            P_OBJ.OptionString: P_OBJ.OptionStringHolder,

            # Meson types
            mesonlib.File: OBJ.FileHolder,
            build.SharedLibrary: OBJ.SharedLibraryHolder,
            build.StaticLibrary: OBJ.StaticLibraryHolder,
            build.BothLibraries: OBJ.BothLibrariesHolder,
            build.SharedModule: OBJ.SharedModuleHolder,
            build.Executable: OBJ.ExecutableHolder,
            build.Jar: OBJ.JarHolder,
            build.CustomTarget: OBJ.CustomTargetHolder,
            build.CustomTargetIndex: OBJ.CustomTargetIndexHolder,
            build.Generator: OBJ.GeneratorHolder,
            build.GeneratedList: OBJ.GeneratedListHolder,
            build.ExtractedObjects: OBJ.GeneratedObjectsHolder,
            build.RunTarget: OBJ.RunTargetHolder,
            build.AliasTarget: OBJ.AliasTargetHolder,
            build.Headers: OBJ.HeadersHolder,
            build.Man: OBJ.ManHolder,
            build.EmptyDir: OBJ.EmptyDirHolder,
            build.Data: OBJ.DataHolder,
            build.SymlinkData: OBJ.SymlinkDataHolder,
            build.InstallDir: OBJ.InstallDirHolder,
            build.IncludeDirs: OBJ.IncludeDirsHolder,
            mesonlib.EnvironmentVariables: OBJ.EnvironmentVariablesHolder,
            build.StructuredSources: OBJ.StructuredSourcesHolder,
            compilers.RunResult: compilerOBJ.TryRunResultHolder,
            dependencies.ExternalLibrary: OBJ.ExternalLibraryHolder,
            Feature: OBJ.FeatureOptionHolder,
            envconfig.MachineInfo: OBJ.MachineHolder,
            build.ConfigurationData: OBJ.ConfigurationDataHolder,
        })

        '''
            Build a mapping of `HoldableObject` base classes to their
            corresponding `ObjectHolder`s. The difference to `self.holder_map`
            is that the keys here define an upper bound instead of requiring an
            exact match.

            The mappings defined here are only used when there was no direct hit
            found in `self.holder_map`.
        '''
        self.bound_holder_map.update({
            dependencies.Dependency: OBJ.DependencyHolder,
            Program: OBJ.ProgramHolder,
            compilers.Compiler: compilerOBJ.CompilerHolder,
            ModuleObject: OBJ.ModuleObjectHolder,
            MutableModuleObject: OBJ.MutableModuleObjectHolder,
        })

    def append_holder_map(self, held_type: T.Type[mesonlib.HoldableObject], holder_type: T.Type[ObjectHolder]) -> None:
        '''
            Adds one additional mapping to the `holder_map`.

            The intended use for this function is in the `initialize` method of
            modules to register custom object holders.
        '''
        self.holder_map.update({
            held_type: holder_type
        })

    def process_new_values(self, invalues: list[TYPE_var | InstallScript] | list[build.GeneratedTypes | mesonlib.File]) -> None:
        for v in invalues:
            if isinstance(v, ObjectHolder):
                raise InterpreterException('Modules must not return ObjectHolders')
            if isinstance(v, build.Target):
                self.add_target(v.name, v)
            elif isinstance(v, list):
                self.process_new_values(v)
            elif isinstance(v, (ExecutableSerialisation, InstallScriptFailure)):
                v.subproject = self.subproject
                self.build.install_scripts.append(v)
            elif isinstance(v, build.Data):
                self.build.data.append(v)
            elif isinstance(v, build.SymlinkData):
                self.build.symlinks.append(v)
            elif isinstance(v, dependencies.InternalDependency):
                # FIXME: This is special cased and not ideal:
                # The first source is our new VapiTarget, the rest are deps
                self.process_new_values([v.sources[0]])
            elif isinstance(v, build.InstallDir):
                self.build.install_dirs.append(v)
            elif isinstance(v, Test):
                self.build.tests.append(v)
            elif isinstance(v, (int, str, bool, Disabler, ObjectHolder, build.GeneratedList,
                                ExternalProgram, build.ConfigurationData)):
                pass
            else:
                raise InterpreterException(f'Module returned a value of unknown type {v!r}.')

    def handle_meson_version(self, pv: str, location: mparser.BaseNode) -> None:
        if not mesonlib.version_compare(coredata.stable_version, pv):
            raise InterpreterException.from_node(f'Meson version is {coredata.version} but project requires {pv}', node=location)
        mesonlib.project_meson_versions[self.subproject] = mesonlib.version_check_to_range([pv])

    def handle_meson_version_from_ast(self) -> None:
        if not self.ast.lines:
            return
        project = self.ast.lines[0]
        # first line is always project()
        if not isinstance(project, mparser.FunctionNode):
            return
        for kw, val in project.args.kwargs.items():
            assert isinstance(kw, mparser.IdNode), 'for mypy'
            if kw.value == 'meson_version':
                # mypy does not understand "and isinstance"
                if isinstance(val, mparser.StringNode):
                    self.handle_meson_version(val.value, val)

    def get_build_def_files(self) -> T.List[str]:
        if self.cargo:
            self.build_def_files.update(self.cargo.get_build_def_files())
        return list(self.build_def_files)

    def add_build_def_file(self, f: mesonlib.FileOrString) -> None:
        # Use relative path for files within source directory, and absolute path
        # for system files. Skip files within build directory. Also skip not regular
        # files (e.g. /dev/stdout) Normalize the path to avoid duplicates, this
        # is especially important to convert '/' to '\' on Windows.
        if isinstance(f, mesonlib.File):
            if f.is_built:
                return
            f = os.path.normpath(f.relative_name())
        elif os.path.isfile(f) and not f.startswith('/dev/'):
            srcdir = Path(self.environment.get_source_dir())
            builddir = Path(self.environment.get_build_dir())
            try:
                f_ = Path(f).resolve()
            except OSError:
                f_ = Path(f)
                s = f_.stat()
                # Mypy needs the `sys.platform` check to understand that this is
                # a Windows only path
                if (sys.platform == 'win32' and
                        s.st_file_attributes & stat.FILE_ATTRIBUTE_REPARSE_POINT != 0 and
                        s.st_reparse_tag == stat.IO_REPARSE_TAG_APPEXECLINK):
                    # This is a Windows Store link which we can't
                    # resolve, so just do our best otherwise.
                    f_ = f_.parent.resolve() / f_.name
                else:
                    raise
            if builddir in f_.parents:
                return
            if srcdir in f_.parents:
                f_ = f_.relative_to(srcdir)
            f = str(f_)
        else:
            return
        if f not in self.build_def_files:
            self.build_def_files.add(f)

    def get_variables(self) -> T.Dict[str, InterpreterObject]:
        return self.variables

    def check_stdlibs(self) -> None:
        machine_choices = [MachineChoice.HOST]
        if self.coredata.is_cross_build():
            machine_choices.append(MachineChoice.BUILD)
        for for_machine in machine_choices:
            props = self.build.environment.properties[for_machine]
            for l in self.coredata.compilers[for_machine].keys():
                try:
                    di = mesonlib.stringlistify(props.get_stdlib(l))
                except KeyError:
                    continue
                if len(di) == 1:
                    FeatureNew.single_use('stdlib without variable name', '0.56.0', self.subproject, location=self.current_node)
                kwargs: dependencies.base.DependencyObjectKWs = {'native': for_machine}
                name = l + '_stdlib'
                df = DependencyFallbacksHolder(self, [name], for_machine)
                df.set_fallback(di)
                dep = df.lookup(kwargs, force_fallback=True)
                self.build.stdlibs[for_machine][l] = dep

    @typed_pos_args('import', str)
    @typed_kwargs(
        'import',
        REQUIRED_KW.evolve(since='0.59.0'),
        DISABLER_KW.evolve(since='0.59.0'),
    )
    @disablerIfNotFound
    def func_import(self, node: mparser.BaseNode, args: T.Tuple[str],
                    kwargs: 'kwtypes.FuncImportModule') -> T.Union[ExtensionModule, NewExtensionModule, NotFoundExtensionModule]:
        modname = args[0]
        disabled, required, _ = extract_required_kwarg(kwargs, self.subproject)
        if disabled:
            return NotFoundExtensionModule(modname)

        # Always report implementation detail modules don't exist
        if modname.startswith('_'):
            raise InvalidArguments(f'Module "{modname}" does not exist')

        expect_unstable = False
        # Some tests use "unstable_" instead of "unstable-", and that happens to work because
        # of implementation details
        if modname.startswith(('unstable-', 'unstable_')):
            if modname.startswith('unstable_'):
                mlog.deprecation(f'Importing unstable modules as "{modname}" instead of "{modname.replace("_", "-", 1)}"',
                                 location=node)
            real_modname = modname[len('unstable') + 1:]  # + 1 to handle the - or _
            expect_unstable = True
        else:
            real_modname = modname

        if real_modname in self.modules:
            return self.modules[real_modname]
        try:
            full_module_path = f'mesonbuild.modules.{real_modname}'
            module = importlib.import_module(full_module_path)
        except ImportError as e:
            if e.name != full_module_path:
                if required:
                    raise e

                mlog.warning(f'Module "{modname}" exists but failed to import.')

                for line in traceback.format_exception(e):
                    mlog.debug(line)

            if required:
                ustr = f'Module "{modname}" does not exist.'
                from difflib import get_close_matches
                from pkgutil import iter_modules
                modnames = [mod.name for mod in iter_modules(modules_path) if not mod.name.startswith('_')]
                close_matches = get_close_matches(modname, modnames)
                if close_matches:
                    ustr += f' Did you mean "{close_matches[0]}"?'
                raise InvalidArguments(ustr)
            ext_module = NotFoundExtensionModule(real_modname)
        else:
            ext_module = module.initialize(self)
            assert isinstance(ext_module, (ExtensionModule, NewExtensionModule)), 'for mypy'
            self.build.modules.add(real_modname)
        if ext_module.INFO.added:
            FeatureNew.single_use(f'module {ext_module.INFO.name}', ext_module.INFO.added, self.subproject, location=node)
        if ext_module.INFO.deprecated:
            FeatureDeprecated.single_use(f'module {ext_module.INFO.name}', ext_module.INFO.deprecated, self.subproject, location=node)
        if expect_unstable and not ext_module.INFO.unstable and ext_module.INFO.stabilized is None:
            raise InvalidArguments(f'Module {ext_module.INFO.name} has never been unstable, remove "unstable-" prefix.')
        if ext_module.INFO.stabilized is not None:
            if expect_unstable:
                FeatureDeprecated.single_use(
                    f'module {ext_module.INFO.name} has been stabilized',
                    ext_module.INFO.stabilized, self.subproject,
                    'drop "unstable-" prefix from the module name',
                    location=node)
            else:
                FeatureNew.single_use(
                    f'module {ext_module.INFO.name} as stable module',
                    ext_module.INFO.stabilized, self.subproject,
                    f'Consider either adding "unstable-" to the module name, or updating the meson required version to ">= {ext_module.INFO.stabilized}"',
                    location=node)
        elif ext_module.INFO.unstable:
            if not expect_unstable:
                if required:
                    raise InvalidArguments(f'Module "{ext_module.INFO.name}" has not been stabilized, and must be imported as unstable-{ext_module.INFO.name}')
                ext_module = NotFoundExtensionModule(real_modname)
            else:
                mlog.warning(f'Module {ext_module.INFO.name} has no backwards or forwards compatibility and might not exist in future releases.', location=node, fatal=False)

        self.modules[real_modname] = ext_module
        return ext_module

    @typed_pos_args('files', varargs=str)
    @noKwargs
    def func_files(self, node: mparser.FunctionNode, args: T.Tuple[T.List[str]], kwargs: 'TYPE_kwargs') -> T.List[mesonlib.File]:
        return self.source_strings_to_files(args[0])

    @noPosargs
    @typed_kwargs(
        'declare_dependency',
        KwargInfo('compile_args', ContainerTypeInfo(list, str), listify=True, default=[]),
        INCLUDE_DIRECTORIES.evolve(name='d_import_dirs', since='0.62.0'),
        D_MODULE_VERSIONS_KW.evolve(since='0.62.0'),
        LINK_ARGS_KW,
        DEPENDENCIES_KW,
        INCLUDE_DIRECTORIES.evolve(since_values={ContainerTypeInfo(list, str): '0.50.0'}),
        LINK_WITH_KW,
        LINK_WHOLE_KW.evolve(since='0.46.0'),
        DEPENDENCY_SOURCES_KW,
        KwargInfo('extra_files', ContainerTypeInfo(list, (mesonlib.File, str)), listify=True, default=[], since='1.2.0'),
        VARIABLES_KW.evolve(since='0.54.0', since_values={list: '0.56.0'}),
        KwargInfo('version', (str, NoneType)),
        KwargInfo('objects', ContainerTypeInfo(list, build.ExtractedObjects), listify=True, default=[], since='1.1.0'),
    )
    def func_declare_dependency(self, node: mparser.BaseNode, args: T.List[TYPE_var],
                                kwargs: kwtypes.FuncDeclareDependency) -> dependencies.Dependency:
        deps = kwargs['dependencies']
        incs = self.extract_incdirs(kwargs['include_directories'])
        libs = kwargs['link_with']
        libs_whole = kwargs['link_whole']
        objects = kwargs['objects']
        sources = self.source_strings_to_files(kwargs['sources'])
        extra_files = self.source_strings_to_files(kwargs['extra_files'])
        compile_args = kwargs['compile_args']
        link_args = kwargs['link_args']
        variables = kwargs['variables']
        version = kwargs['version']
        if version is None:
            version = self.project_version
        d_module_versions = kwargs['d_module_versions']
        d_import_dirs = self.extract_incdirs(kwargs['d_import_dirs'], True)
        srcdir = self.environment.source_dir
        subproject_dir = os.path.abspath(os.path.join(srcdir, self.subproject_dir))
        project_root = os.path.abspath(os.path.join(srcdir, self.root_subdir))
        # convert variables which refer to an -uninstalled.pc style datadir
        for k, v in variables.items():
            if not v:
                FeatureNew.single_use('empty variable value in declare_dependency', '1.4.0', self.subproject, location=node)
            if path_has_root(v) \
                    and (self.is_subproject() or not is_parent_path(subproject_dir, v)) \
                    and is_parent_path(project_root, v) \
                    and os.path.isdir(v):
                variables[k] = P_OBJ.DependencyVariableString(v)

        dep = dependencies.InternalDependency(version, incs, compile_args,
                                              link_args, libs, libs_whole, sources, extra_files,
                                              deps, variables, d_module_versions, d_import_dirs,
                                              objects)
        return dep

    @typed_pos_args('assert', bool, optargs=[str])
    @noKwargs
    def func_assert(self, node: mparser.FunctionNode, args: T.Tuple[bool, T.Optional[str]],
                    kwargs: 'TYPE_kwargs') -> None:
        value, message = args
        if message is None:
            FeatureNew.single_use('assert function without message argument', '0.53.0', self.subproject, location=node)

        if not value:
            if message is None:
                from ..ast import AstPrinter
                printer = AstPrinter()
                node.args.arguments[0].accept(printer)
                message = printer.result
            raise InterpreterException('Assert failed: ' + message)

    # Executables aren't actually accepted, but we allow them here to allow for
    # better error messages when overridden
    @typed_pos_args(
        'run_command',
        (build.Executable, Program, compilers.Compiler, mesonlib.File, str),
        varargs=(build.Executable, Program, compilers.Compiler, mesonlib.File, str))
    @typed_kwargs(
        'run_command',
        KwargInfo('check', (bool, NoneType), since='0.47.0'),
        KwargInfo('capture', bool, default=True, since='0.47.0'),
        KwargInfo('console', bool, default=False, since='1.11.0'),
        ENV_KW.evolve(since='0.50.0'),
    )
    def func_run_command(self, node: mparser.BaseNode,
                         args: T.Tuple[T.Union[build.Executable, Program, compilers.Compiler, mesonlib.File, str],
                                       T.List[T.Union[build.Executable, Program, compilers.Compiler, mesonlib.File, str]]],
                         kwargs: 'kwtypes.RunCommand') -> RunProcess:
        return self.run_command_impl(args, kwargs)

    def _compiled_exe_error(self, cmd: T.Union[Program, build.Executable]) -> T.NoReturn:
        descr = cmd.name if isinstance(cmd, build.Executable) else cmd.description()
        for for_machine in MachineChoice:
            for name, exe in self.build.find_overrides[for_machine].items():
                if cmd == exe:
                    raise InterpreterException(f'Program {name!r} was overridden with the compiled executable {descr!r} and therefore cannot be used during configuration')
        raise InterpreterException(f'Program {descr!r} is a compiled executable and therefore cannot be used during configuration')

    def run_command_impl(self,
                         args: T.Tuple[T.Union[build.Executable, Program, compilers.Compiler, mesonlib.File, str],
                                       T.List[T.Union[build.Executable, Program, compilers.Compiler, mesonlib.File, str]]],
                         kwargs: 'kwtypes.RunCommand',
                         in_builddir: bool = False) -> RunProcess:
        cmd, cargs = args
        env = kwargs['env']
        srcdir = self.environment.get_source_dir()
        builddir = self.environment.get_build_dir()

        check = kwargs['check']
        if check is None:
            mlog.warning(implicit_check_false_warning, once=True)
            check = False

        expanded_args: T.List[str] = []
        if isinstance(cmd, build.Executable):
            self._compiled_exe_error(cmd)
        elif isinstance(cmd, Program):
            if not cmd.found():
                raise InterpreterException(f'command {cmd.get_name()!r} not found or not executable')
            if not cmd.runnable():
                self._compiled_exe_error(cmd)
        elif isinstance(cmd, compilers.Compiler):
            expanded_args = cmd.get_exe_args()
            cmd = cmd.get_exe()
            prog = ExternalProgram(cmd, silent=True)
            if not prog.found():
                raise InterpreterException(f'Program {cmd!r} not found or not executable')
            cmd = prog
        else:
            if isinstance(cmd, mesonlib.File):
                cmd = cmd.absolute_path(srcdir, builddir)
            # Prefer scripts in the current source directory
            search_dir = os.path.join(srcdir, self.subdir)
            prog = ExternalProgram(cmd, silent=True, search_dirs=[search_dir])
            if not prog.found():
                raise InterpreterException(f'Program or command {cmd!r} not found or not executable')
            cmd = prog
        for a in cargs:
            if isinstance(a, str):
                expanded_args.append(a)
            elif isinstance(a, mesonlib.File):
                expanded_args.append(a.absolute_path(srcdir, builddir))
            elif isinstance(a, Program):
                if not a.found():
                    raise InterpreterException(f'command {cmd.get_name()!r} not found or not executable')
                if not a.runnable():
                    self._compiled_exe_error(a)
                expanded_args.append(a.get_path())
            elif isinstance(a, compilers.Compiler):
                FeatureNew.single_use('Compiler object as a variadic argument to `run_command`', '0.61.0', self.subproject, location=self.current_node)
                prog = ExternalProgram(a.get_exe(), silent=True)
                if not prog.found():
                    raise InterpreterException(f'Program {cmd!r} not found or not executable')
                expanded_args.append(prog.get_path())
            else:
                self._compiled_exe_error(a)

        # If any file that was used as an argument to the command
        # changes, we must re-run the configuration step.
        self.add_build_def_file(cmd.get_path())
        for a in expanded_args:
            a = os.path.join(builddir if in_builddir else srcdir, self.subdir, a)
            self.add_build_def_file(a)

        return RunProcess(cmd, expanded_args, env, srcdir, builddir, self.subdir,
                          self.environment.get_build_command() + ['introspect'],
                          in_builddir=in_builddir, check=check, capture=kwargs['capture'],
                          console=kwargs['console'])

    def func_option(self, nodes: mparser.BaseNode, args: list[TYPE_var], kwargs: TYPE_kwargs) -> T.NoReturn:
        raise InterpreterException('Tried to call option() in build description file. All options must be in the option file.')

    @typed_pos_args('subproject', str)
    @typed_kwargs(
        'subproject',
        REQUIRED_KW,
        NATIVE_KW.evolve(since='1.12.0'),
        DEFAULT_OPTIONS.evolve(since='0.38.0'),
        KwargInfo('version', ContainerTypeInfo(list, str), default=[], listify=True),
    )
    def func_subproject(self, nodes: mparser.BaseNode, args: T.Tuple[SubProject], kwargs: kwtypes.Subproject) -> SubprojectHolder:
        # note that this does not use @apply_machine_map.  'for_machine'
        # is only used by _do_subproject_meson to decide between
        # Build.copy() and Build.copy_for_build_machine(), and copying
        # a build-only subproject provides the correct result for "native:
        # false".  This is needed so that it takes two *explicit* levels
        # of "native: true" for the target_machine to become the build_machine.
        kw: kwtypes.DoSubproject = {
            'required': kwargs['required'],
            'default_options': kwargs['default_options'],
            'version': kwargs['version'],
            'options': None,
            'cmake_options': [],
            'for_machine': kwargs['native'],
        }
        return self.do_subproject(args[0], kw)

    def disabled_subproject(self, subp_name: SubProject, disabled_feature: T.Optional[str] = None,
                            exception: T.Optional[Exception] = None,
                            for_machine: MachineChoice = MachineChoice.HOST) -> SubprojectHolder:
        sub = SubprojectHolder(NullSubprojectInterpreter(), os.path.join(self.subproject_dir, subp_name),
                               disabled_feature=disabled_feature, exception=exception)
        self.subprojects[for_machine][subp_name] = sub
        return sub

    def create_build_subdir(self, subdir: str) -> None:
        os.makedirs(os.path.join(self.build.environment.get_build_dir(), subdir), exist_ok=True)

    @staticmethod
    def format_subproject_stack(stack: T.List[T.Tuple[str, MachineChoice]], join: str = ' => ') -> str:
        prefix = ''
        result = ''
        for_build = False
        for subp_name, machine in stack:
            result += prefix + subp_name
            if machine is MachineChoice.BUILD and not for_build:
                result += ' (build)'
                for_build = True
            prefix = join
        return result

    def do_subproject(self, subp_name: SubProject, kwargs: kwtypes.DoSubproject, force_method: T.Optional[wrap.Method] = None,
                      forced_options: T.Optional[OptionDict] = None) -> SubprojectHolder:
        disabled, required, feature = extract_required_kwarg(kwargs, self.subproject)
        kwargs.setdefault('for_machine', MachineChoice.HOST)
        for_machine = self.build.machine_map[kwargs['for_machine']]

        if disabled:
            mlog.log('Subproject', mlog.bold(subp_name), ':', 'skipped: feature', mlog.bold(feature), 'disabled')
            return self.disabled_subproject(subp_name, disabled_feature=feature, for_machine=for_machine)

        default_options = kwargs['default_options']

        # This in practice is only used for default_library.  forced_options is the
        # only case in which a meson.build file overrides the machine file or the
        # command line.
        if forced_options:
            for k, v in forced_options.items():
                # FIXME: this should have no business poking at augments[],
                # but set_option() does not do what we want
                self.coredata.optstore.augments[k.evolve(subproject=subp_name)] = v
            default_options = {**forced_options, **default_options}

        if subp_name == '':
            raise InterpreterException('Subproject name must not be empty.')
        if subp_name[0] == '.':
            raise InterpreterException('Subproject name must not start with a period.')
        if '..' in subp_name:
            raise InterpreterException('Subproject name must not contain a ".." path segment.')
        if path_has_root(subp_name):
            raise InterpreterException('Subproject name must not be an absolute path.')
        if has_path_sep(subp_name):
            mlog.warning('Subproject name has a path separator. This may cause unexpected behaviour.',
                         location=self.current_node)
        fullstack = self.subproject_stack + [(subp_name, for_machine)]
        if (subp_name, for_machine) in self.subproject_stack:
            incpath = self.format_subproject_stack(fullstack)
            raise InvalidCode(f'Recursive include of subprojects: {incpath}.')
        if subp_name in self.subprojects[for_machine]:
            subproject = self.subprojects[for_machine][subp_name]
            if required and not subproject.found():
                raise InterpreterException(f'Subproject "{subproject.subdir}" required but not found.')
            if kwargs['version']:
                pv = self.build.projects[for_machine][subp_name].version
                wanted = kwargs['version']
                if pv == 'undefined' or not mesonlib.version_compare_many(pv, wanted)[0]:
                    raise InterpreterException(f'Subproject {subp_name} version is {pv} but {wanted} required.')
            return subproject

        r = self.environment.wrap_resolver
        try:
            subdir, method = r.resolve(subp_name, force_method)
        except wrap.WrapException as e:
            if force_method is not None:
                prefix = force_method.title() + ' subproject'
            else:
                prefix = 'Subproject'
            msg = [prefix, mlog.bold(subp_name), 'is buildable:', mlog.red('NO')]
            if not required:
                mlog.log(e)
                mlog.log(*msg, '(disabling)')
                return self.disabled_subproject(subp_name, exception=e)
            mlog.error(*msg)
            raise e

        self.create_build_subdir(subdir)
        self.global_args_frozen = True

        stack = self.format_subproject_stack(fullstack, ':')
        m = ['\nExecuting subproject', mlog.bold(stack)]
        if method != 'meson':
            m += ['method', mlog.bold(method)]
        m.extend(['for machine:', mlog.bold(for_machine.get_lower_case_name())])
        mlog.log(*m, '\n', nested=False)

        methods_map: T.Dict[wrap.Method, T.Callable[[SubProject, str, OptionDict, kwtypes.DoSubproject],
                                                    SubprojectHolder]] = {
            'meson': self._do_subproject_meson,
            'cmake': self._do_subproject_cmake,
            'cargo': self._do_subproject_cargo,
        }

        try:
            return methods_map[method](subp_name, subdir, default_options, kwargs)
        # Invalid code is always an error
        except InvalidCode:
            raise
        except Exception as e:
            if not required:
                with mlog.nested(subp_name):
                    # Suppress the 'ERROR:' prefix because this exception is not
                    # fatal and VS CI treat any logs with "ERROR:" as fatal.
                    mlog.exception(e, prefix=mlog.yellow('Exception:'))
                mlog.log('\nSubproject', mlog.bold(subdir), 'is buildable:', mlog.red('NO'), '(disabling)')
                return self.disabled_subproject(subp_name, exception=e)
            raise e

    def _save_ast(self, subdir: str, ast: mparser.CodeBlockNode) -> None:
        # Debug print the generated meson file
        from ..ast import AstIndentationGenerator, AstPrinter
        printer = AstPrinter(update_ast_line_nos=True)
        ast.accept(AstIndentationGenerator())
        ast.accept(printer)
        printer.post_process()
        meson_filename = os.path.join(self.build.environment.get_build_dir(), subdir, 'meson.build')
        with open(meson_filename, "w", encoding='utf-8') as f:
            f.write(printer.result)
        mlog.log('Generated Meson AST:', meson_filename)
        mlog.cmd_ci_include(meson_filename)

    def _do_subproject_meson(self, subp_name: SubProject, subdir: str,
                             default_options: OptionDict,
                             kwargs: kwtypes.DoSubproject,
                             ast: T.Optional[mparser.CodeBlockNode] = None,
                             build_def_files: T.Optional[T.List[str]] = None,
                             relaxations: T.Optional[T.Set[InterpreterRuleRelaxation]] = None,
                             cargo: T.Optional[cargo.Interpreter] = None) -> SubprojectHolder:
        for_machine = kwargs['for_machine']
        if for_machine is MachineChoice.BUILD:
            new_build = self.build.copy_for_build_machine()
        else:
            new_build = self.build.copy()

        with mlog.nested(subp_name):
            if ast:
                self._save_ast(subdir, ast)

            subi = Interpreter(new_build, self.backend, subp_name, subdir, self.subproject_dir,
                               default_options, ast=ast, relaxations=relaxations,
                               user_defined_options=self.user_defined_options,
                               cargo=cargo)
            # Those lists are shared by all interpreters. That means that
            # even if the subproject fails, any modification that the subproject
            # made to those lists will affect the parent project.
            subi.subprojects = self.subprojects
            subi.modules = self.modules
            subi.holder_map = self.holder_map
            subi.bound_holder_map = self.bound_holder_map
            subi.summary = self.summary

            subi.subproject_stack = self.subproject_stack + [(subp_name, for_machine)]
            current_active = self.active_projectname
            with mlog.nested_warnings():
                subi.run()
                subi_warnings = mlog.get_warning_count()
            mlog.log('Subproject', mlog.bold(subp_name), 'finished.')

        mlog.log()

        if kwargs['version']:
            pv = subi.project_version
            wanted = kwargs['version']
            if pv == 'undefined' or not mesonlib.version_compare_many(pv, wanted)[0]:
                raise InterpreterException(f'Subproject {subp_name} version is {pv} but {wanted} required.')
        self.active_projectname = current_active
        self.subprojects[for_machine].update(subi.subprojects[for_machine])
        self.subprojects[for_machine][subp_name] = SubprojectHolder(
            subi, subdir, warnings=subi_warnings, callstack=self.subproject_stack)
        # Duplicates are possible when subproject uses files from project root
        if build_def_files:
            self.build_def_files.update(build_def_files)
        # We always need the subi.build_def_files, to propagate sub-sub-projects
        self.build_def_files.update(subi.get_build_def_files())
        self.build.merge(subi.build)
        return self.subprojects[for_machine][subp_name]

    def _do_subproject_cmake(self, subp_name: SubProject, subdir: str,
                             default_options: OptionDict,
                             kwargs: kwtypes.DoSubproject) -> SubprojectHolder:
        from ..cmake import CMakeInterpreter
        for_machine = kwargs['for_machine']
        with mlog.nested(subp_name):
            from ..modules.cmake import CMakeSubprojectOptions
            kw_opts = kwargs.get('options') or CMakeSubprojectOptions()
            cmake_options = kwargs.get('cmake_options', []) + kw_opts.cmake_options
            cm_int = CMakeInterpreter(Path(subdir), self.build.environment, self.backend, for_machine)
            cm_int.initialise(cmake_options)
            cm_int.analyse()

            # Generate a meson ast and execute it with the normal do_subproject_meson
            ast = cm_int.pretend_to_be_meson(kw_opts.target_options)
            result = self._do_subproject_meson(
                    subp_name, subdir, default_options,
                    kwargs, ast,
                    [str(f) for f in cm_int.bs_files],
                    relaxations={
                        InterpreterRuleRelaxation.ALLOW_BUILD_DIR_FILE_REFERENCES,
                    }
            )
            result.cm_interpreter = cm_int
        return result

    def _do_subproject_cargo(self, subp_name: SubProject, subdir: str,
                             default_options: OptionDict,
                             kwargs: kwtypes.DoSubproject) -> SubprojectHolder:
        from .. import cargo
        FeatureNew.single_use('Cargo subproject', '1.3.0', self.subproject, location=self.current_node)
        mlog.warning('Cargo subproject is an experimental feature and has no backwards compatibility guarantees.',
                     once=True, location=self.current_node)
        self.add_languages(['rust'], True, MachineChoice.HOST)
        self.add_languages(['rust'], True, MachineChoice.BUILD)
        with mlog.nested(subp_name):
            try:
                cargo_int = self.cargo or cargo.Interpreter(self.environment, subdir, self.subproject_dir)
            except cargo.TomlImplementationMissing as e:
                raise MesonException(f'Failed to load Cargo.lock: {e!s}')

            if os.path.exists(os.path.join(self.environment.get_source_dir(), subdir, environment.build_filename)):
                ast = None
            else:
                ast = cargo_int.interpret(subdir)

            return self._do_subproject_meson(
                subp_name, subdir, default_options, kwargs, ast,
                relaxations={InterpreterRuleRelaxation.CARGO_SUBDIR} if ast is not None else None,
                cargo=cargo_int)

    @typed_pos_args('get_option', str)
    @noKwargs
    def func_get_option(self, node: mparser.BaseNode, args: T.Tuple[str],
                        kwargs: TYPE_kwargs) -> T.Union[options.UserOption, 'TYPE_var']:
        optname = args[0]

        if ':' in optname:
            raise InterpreterException('Having a colon in option name is forbidden, '
                                       'projects are not allowed to directly access '
                                       'options of other subprojects.')
        if optname_regex.search(optname.split('.', maxsplit=1)[-1]) is not None:
            raise InterpreterException(f'Invalid option name {optname!r}')

        option_object: T.Optional[options.AnyOptionType]

        try:
            optkey = options.OptionKey.from_string(optname).evolve(subproject=self.subproject)
            option_object, value = self.coredata.optstore.get_option_and_value_for(optkey)
        except KeyError:
            if self.coredata.optstore.is_base_option(optkey):
                # Due to backwards compatibility return the default
                # option for base options instead of erroring out.
                option_object = options.COMPILER_BASE_OPTIONS[optkey.evolve(subproject=None, machine=MachineChoice.HOST)]
                value = option_object.default
            else:
                if self.subproject:
                    raise MesonException(f'Option {optname} does not exist for subproject {self.subproject}.')
                raise MesonException(f'Option {optname} does not exist.')

        if isinstance(option_object, options.UserFeatureOption):
            return Feature(optname, FeatureValue(value))
        elif optname == 'b_sanitize':
            assert isinstance(option_object, options.UserStringArrayOption)
            # To ensure backwards compatibility this always returns a string.
            # We may eventually want to introduce a new "format" kwarg that
            # allows the user to modify this behaviour, but for now this is
            # likely good enough for most usecases.
            if not value:
                return 'none'
            assert isinstance(value, list), 'for mypy'
            return ','.join(sorted(value))

        if isinstance(value, str):
            return P_OBJ.OptionString(value, f'{{{optname}}}')
        return value

    @typed_pos_args('configuration_data', optargs=[dict])
    @noKwargs
    def func_configuration_data(self, node: mparser.BaseNode, args: T.Tuple[T.Optional[T.Dict[str, T.Any]]],
                                kwargs: 'TYPE_kwargs') -> build.ConfigurationData:
        initial_values = args[0]
        if initial_values is not None:
            FeatureNew.single_use('configuration_data dictionary', '0.49.0', self.subproject, location=node)
            for k, v in initial_values.items():
                if not isinstance(v, (str, int, bool)):
                    raise InvalidArguments(
                        f'"configuration_data": initial value dictionary key "{k!r}"" must be "str | int | bool", not "{v!r}"')
        return build.ConfigurationData(initial_values)

    @functools.lru_cache(None)
    def set_backend(self) -> None:
        from ..backend import backends

        if OptionKey('genvslite') in self.user_defined_options.cmd_line_options:
            # Use of the '--genvslite vsxxxx' option ultimately overrides any '--backend xxx'
            # option the user may specify.
            backend_name = self.coredata.optstore.get_value_for(OptionKey('genvslite'))
            assert isinstance(backend_name, str), 'for mypy'
            self.backend = backends.get_genvslite_backend(backend_name, self.build)
        else:
            backend_name = self.coredata.optstore.get_value_for(OptionKey('backend'))
            assert isinstance(backend_name, str), 'for mypy'
            self.backend = backends.get_backend_from_name(backend_name, self.build)

        if backend_name != self.backend.name:
            if self.backend.name.startswith('vs'):
                mlog.log('Auto detected Visual Studio backend:', mlog.bold(self.backend.name))
            if not self.environment.first_invocation:
                raise MesonBugException(f'Backend changed from {backend_name} to {self.backend.name}')
            self.coredata.optstore.set_option(OptionKey('backend'), self.backend.name, first_invocation=True)

        self.environment.init_backend_options(backend_name)

    def _validate_languages(self, langs: T.List[str], required: bool, node: mparser.BaseNode) -> T.List[Language]:
        valid: T.List[Language] = []

        for lang in langs:
            lang = lang.lower()
            if lang in compilers.all_languages:
                valid.append(T.cast('Language', lang))
                continue

            FeatureBroken.single_use(
                f'Adding unknown language {lang}', '1.11.0', self.subproject,
                'This language cannot be found. It could be: a typo, in which case it can be removed, or, '
                'this project might have its Meson version requirements set incorrectly.',
                node)
            if required:
                raise InterpreterException.from_node(
                    f'Attempted to add language "{lang}", which is not known to this version of Meson.',
                    node=node)

        return valid

    @typed_pos_args('project', str, varargs=str)
    @typed_kwargs(
        'project',
        DEFAULT_OPTIONS,
        KwargInfo('meson_version', (str, NoneType)),
        KwargInfo(
            'version',
            (str, mesonlib.File, list),
            default='undefined',
            validator=_project_version_validator,
            convertor=lambda x: x[0] if isinstance(x, list) else x,
        ),
        KwargInfo('license', (ContainerTypeInfo(list, str), NoneType), default=None, listify=True),
        KwargInfo('license_files', ContainerTypeInfo(list, str), default=[], listify=True, since='1.1.0'),
        KwargInfo('subproject_dir', str, default='subprojects'),
    )
    def func_project(self, node: mparser.FunctionNode, args: T.Tuple[str, T.List[str]], kwargs: 'kwtypes.Project') -> None:
        proj_name, proj_langs_ = args
        if ':' in proj_name:
            raise InvalidArguments(f"Project name {proj_name!r} must not contain ':'")

        proj_langs = self._validate_languages(proj_langs_, True, node)

        # This needs to be evaluated as early as possible, as meson uses this
        # for things like deprecation testing.
        if kwargs['meson_version']:
            self.handle_meson_version(kwargs['meson_version'], node)
        else:
            mesonlib.project_meson_versions[self.subproject] = mesonlib.NoProjectVersion()

        self._load_option_file()

        self.project_default_options = kwargs['default_options']
        if self.environment.first_invocation or (self.subproject != '' and self.subproject not in self.coredata.initialized_subprojects):
            if self.subproject == '':
                self.coredata.optstore.initialize_from_top_level_project_call(self.project_default_options,
                                                                              self.user_defined_options.cmd_line_options,
                                                                              self.environment.options)
            else:
                self.coredata.optstore.initialize_from_subproject_call(self.subproject,
                                                                       self.invoker_method_default_options,
                                                                       self.project_default_options,
                                                                       self.user_defined_options.cmd_line_options,
                                                                       self.environment.options)
                self.coredata.initialized_subprojects.add(self.subproject)

        if not self.is_subproject():
            # We have to activate VS before adding languages and before calling
            # self.set_backend() otherwise it wouldn't be able to detect which
            # vs backend version we need. But after setting default_options in case
            # the project sets vs backend by default.
            backend = self.coredata.optstore.get_value_for(OptionKey('backend'))
            assert backend is None or isinstance(backend, str), 'for mypy'
            vsenv = self.coredata.optstore.get_value_for(OptionKey('vsenv'))
            assert isinstance(vsenv, bool), 'for mypy'
            force_vsenv = vsenv or backend.startswith('vs')
            mesonlib.setup_vsenv(force_vsenv)
        self.set_backend()

        if not self.is_subproject():
            self.build.project_name = proj_name
        self.active_projectname = proj_name

        version = kwargs['version']
        if isinstance(version, mesonlib.File):
            FeatureNew.single_use('version from file', '0.57.0', self.subproject, location=node)
            self.add_build_def_file(version)
            ifname = version.absolute_path(self.environment.source_dir,
                                           self.environment.build_dir)
            try:
                ver_data = Path(ifname).read_text(encoding='utf-8').split('\n')
            except FileNotFoundError:
                raise InterpreterException('Version file not found.')
            if len(ver_data) == 2 and ver_data[1] == '':
                ver_data = ver_data[0:1]
            if len(ver_data) != 1:
                raise InterpreterException('Version file must contain exactly one line of text.')
            self.project_version = ver_data[0]
        else:
            self.project_version = version

        if self.build.project_version is None:
            self.build.project_version = self.project_version

        if kwargs['license'] is None:
            proj_license = ['unknown']
            if kwargs['license_files']:
                raise InvalidArguments('Project `license` name must be specified when `license_files` is set')
        else:
            proj_license = kwargs['license']
        proj_license_files = []
        for i in self.source_strings_to_files(kwargs['license_files']):
            ifname = i.absolute_path(self.environment.source_dir,
                                     self.environment.build_dir)
            proj_license_files.append((ifname, i))
        self.build.dep_manifest[proj_name] = build.DepManifest(self.project_version, proj_license,
                                                               proj_license_files, self.subproject)

        for_machine = self.build.machine_map.host
        if self.subproject in self.build.projects[for_machine]:
            raise InvalidCode('Second call to project().')

        # spdirname is the subproject_dir for this project, relative to self.subdir.
        # self.subproject_dir is the subproject_dir for the main project, relative to top source dir.
        spdirname = kwargs['subproject_dir']
        if not isinstance(spdirname, str):
            raise InterpreterException('Subproject_dir must be a string')
        if path_has_root(spdirname):
            raise InterpreterException('Subproject_dir must not be an absolute path.')
        if spdirname.startswith('.'):
            raise InterpreterException('Subproject_dir must not begin with a period.')
        if '..' in spdirname:
            raise InterpreterException('Subproject_dir must not contain a ".." segment.')
        if not self.is_subproject():
            self.subproject_dir = spdirname
        self.build.subproject_dir = self.subproject_dir

        # Load wrap files from this (sub)project.
        subprojects_dir = os.path.join(self.subdir, spdirname)
        if not self.is_subproject():
            wrap_mode_s = self.coredata.optstore.get_value_for(OptionKey('wrap_mode'))
            assert isinstance(wrap_mode_s, str), 'for mypy'
            wrap_mode = WrapMode.from_string(wrap_mode_s)
            self.environment.wrap_resolver = wrap.Resolver(self.environment.get_source_dir(), subprojects_dir, self.subproject, wrap_mode)
        else:
            self.environment.wrap_resolver.load_and_merge(subprojects_dir, self.subproject)

        if self.cargo is None:
            self.load_root_cargo_lock_file()

        build_project = build.BuildProject(proj_name, self.project_version, self.subproject, for_machine)
        self.build.projects[for_machine][self.subproject] = build_project

        extra_args: T.List[mlog.TV_Loggable] = []
        if self.is_subproject() and for_machine is MachineChoice.BUILD:
            extra_args.append('(for build machine)')
        mlog.log('Project name:', mlog.bold(proj_name), *extra_args)
        mlog.log('Project version:', mlog.bold(self.project_version))

        self.add_languages(proj_langs, True, MachineChoice.HOST)
        self.add_languages(proj_langs, False, MachineChoice.BUILD)

        if not self.is_subproject():
            self.check_stdlibs()

    @typed_kwargs(
        'add_languages',
        KwargInfo(
            'native',
            (bool, NoneType),
            since='0.54.0',
            convertor=lambda x: {None: None, True: MachineChoice.BUILD, False: MachineChoice.HOST}[x],
        ),
        REQUIRED_KW,
    )
    @typed_pos_args('add_languages', varargs=str)
    def func_add_languages(self, node: mparser.FunctionNode, args: T.Tuple[T.List[str]], kwargs: 'kwtypes.FuncAddLanguages') -> bool:
        disabled, required, feature = extract_required_kwarg(kwargs, self.subproject)
        for_machine = kwargs['native']

        langs = self._validate_languages(args[0], required, node)

        if disabled:
            for lang in sorted(langs, key=compilers.sort_clink):
                mlog.log('Compiler for language', mlog.bold(lang), 'skipped: feature', mlog.bold(feature), 'disabled')
            return False
        if for_machine is not None:
            for_machine = self.build.machine_map[for_machine]
            return self.add_languages(langs, required, for_machine)
        else:
            # absent 'native' means 'both' for backwards compatibility
            tv = FeatureNew.get_target_version(self.subproject)
            if FeatureNew.check_version(tv, '0.54'):
                mlog.warning('add_languages is missing native:, assuming languages are wanted for both host and build.',
                             location=node)

            # If languages were removed as invalid, then return false
            success = len(langs) == len(args[0])
            success &= self.add_languages(langs, required, MachineChoice.HOST)
            success &= self.add_languages(langs, False, MachineChoice.BUILD)
            return success

    def _stringify_user_arguments(self, args: T.List[TYPE_var], func_name: str) -> list[str]:
        try:
            return [stringifyUserArguments(i, self.subproject) for i in args]
        except InvalidArguments as e:
            raise InvalidArguments(f'{func_name}(): {str(e)}')

    @noArgsFlattening
    @noKwargs
    def func_message(self, node: mparser.BaseNode, args: list[TYPE_var], kwargs: TYPE_kwargs) -> None:
        if len(args) > 1:
            FeatureNew.single_use('message with more than one argument', '0.54.0', self.subproject, location=node)
        args_str = self._stringify_user_arguments(args, 'message')
        self.message_impl(args_str)

    def message_impl(self, args: mlog.TV_LoggableList | list[str]) -> None:
        mlog.log(mlog.bold('Message:'), *args)

    @noArgsFlattening
    @FeatureNew('summary', '0.53.0')
    @typed_pos_args('summary', (str, dict), optargs=[object])
    @typed_kwargs(
        'summary',
        KwargInfo('section', str, default=''),
        KwargInfo('bool_yn', bool, default=False),
        KwargInfo('list_sep', (str, NoneType), since='0.54.0')
    )
    def func_summary(self, node: mparser.BaseNode, args: T.Tuple[T.Union[str, T.Dict[str, T.Any]], T.Optional[T.Any]],
                     kwargs: 'kwtypes.Summary') -> None:
        if args[1] is None:
            if not isinstance(args[0], dict):
                raise InterpreterException('Summary first argument must be dictionary.')
            values = args[0]
        else:
            if not isinstance(args[0], str):
                raise InterpreterException('Summary first argument must be string.')
            values = {args[0]: args[1]}
        self.summary_impl(values=values, **kwargs)

    def summary_impl(self, section: str, values: dict[str, mlog.TV_Loggable | mlog.TV_LoggableList], bool_yn: bool, list_sep: str | None) -> None:
        if self.subproject not in self.summary:
            self.summary[self.subproject] = Summary(self.active_projectname, self.project_version)
        self.summary[self.subproject].add_section(
            section, values, bool_yn, list_sep, self.subproject)

    def _print_subprojects(self, for_machine: MachineChoice) -> None:
        # Add automatic 'Subprojects' section in main project.
        all_subprojects: dict[str, mlog.TV_Loggable | mlog.TV_LoggableList] = {}
        for name, subp in sorted(self.subprojects[for_machine].items()):
            value: mlog.TV_LoggableList = [subp.found()]
            if subp.disabled_feature:
                value += [f'Feature {subp.disabled_feature!r} disabled']
            elif subp.exception:
                value += [str(subp.exception)]
            elif subp.warnings > 0:
                value += [f'{subp.warnings} warnings']
            if subp.callstack:
                stack = self.format_subproject_stack(subp.callstack)
                value += [f'(from {stack})']
            all_subprojects[name] = value
        if all_subprojects:
            self.summary_impl(f'Subprojects (for {for_machine.get_lower_case_name()} machine)', all_subprojects,
                              bool_yn=True, list_sep=' ')

    def _print_summary(self) -> None:
        self._print_subprojects(MachineChoice.HOST)
        if self.environment.is_cross_build():
            self._print_subprojects(MachineChoice.BUILD)
        # Add automatic section with all user defined options
        if self.user_defined_options:
            values: dict[str, mlog.TV_Loggable | mlog.TV_LoggableList] = {}
            if self.user_defined_options.cross_file:
                values['Cross files'] = self.user_defined_options.cross_file
            if self.user_defined_options.native_file:
                values['Native files'] = self.user_defined_options.native_file

            sorted_options = sorted(self.user_defined_options.cmd_line_options.items(), key=lambda x: x[0].name)
            values.update({str(k): v for k, v in sorted_options})
            if values:
                self.summary_impl('User defined options', values, bool_yn=False, list_sep=None)
        # Print all summaries, main project last.
        mlog.log('')  # newline
        main_summary = self.summary.pop('', None)
        for subp_name, summary in sorted(self.summary.items()):
            if self.subprojects.host[subp_name].found():
                summary.dump()
        if main_summary:
            main_summary.dump()

    @noArgsFlattening
    @FeatureNew('warning', '0.44.0')
    @noKwargs
    def func_warning(self, node: mparser.BaseNode, args: list[TYPE_var], kwargs: TYPE_kwargs) -> None:
        if len(args) > 1:
            FeatureNew.single_use('warning with more than one argument', '0.54.0', self.subproject, location=node)
        args_str = self._stringify_user_arguments(args, 'warning')
        mlog.warning(*args_str, location=node)

    @noArgsFlattening
    @noKwargs
    def func_error(self, node: mparser.BaseNode, args: list[TYPE_var], kwargs: TYPE_kwargs) -> T.NoReturn:
        if len(args) > 1:
            FeatureNew.single_use('error with more than one argument', '0.58.0', self.subproject, location=node)
        args_str = self._stringify_user_arguments(args, 'error')
        raise InterpreterException('Problem encountered: ' + ' '.join(args_str))

    @noArgsFlattening
    @FeatureNew('debug', '0.63.0')
    @noKwargs
    def func_debug(self, node: mparser.BaseNode, args: list[TYPE_var], kwargs: TYPE_kwargs) -> None:
        args_str = self._stringify_user_arguments(args, 'debug')
        mlog.debug('Debug:', *args_str)

    @noKwargs
    @noPosargs
    def func_exception(self, node: mparser.BaseNode, args: list[TYPE_var], kwargs: TYPE_kwargs) -> T.NoReturn:
        raise RuntimeError('unit test traceback :)')

    @typed_pos_args('expect_error', str)
    @typed_kwargs(
        'expect_error',
        KwargInfo('how', str, default='literal', validator=in_set_validator({'literal', 're'})),
    )
    def func_expect_error(self, node: mparser.BaseNode, args: T.Tuple[str], kwargs: kwtypes.FuncExpectError) -> ContextManagerObject:
        class ExpectErrorObject(ContextManagerObject):
            def __init__(self, msg: str, how: str, subproject: SubProject) -> None:
                super().__init__(subproject)
                self.old_stdout = sys.stdout
                sys.stdout = self.new_stdout = io.StringIO()
                sys.stdout.colorize_console = getattr(self.old_stdout, 'colorize_console', None)  # type: ignore[attr-defined]
                self.msg = msg
                self.how = how

            def __exit__(self, exc_type: type[BaseException], exc_val: BaseException, exc_tb: types.TracebackType) -> bool:
                sys.stdout = self.old_stdout
                for l in self.new_stdout.getvalue().splitlines():
                    if 'ERROR:' in l:
                        print(l.replace('ERROR', 'ERROR (msbuild proof)'))
                    else:
                        print(l)
                if exc_val is None:
                    raise InterpreterException('Expecting an error but code block succeeded')
                if isinstance(exc_val, mesonlib.MesonException):
                    msg = str(exc_val)
                    if (self.how == 'literal' and self.msg != msg) or \
                       (self.how == 're' and not re.match(self.msg, msg)):
                        raise InterpreterException(f'Expecting error {self.msg!r} but got {msg!r}')
                    return True
                return False
        return ExpectErrorObject(args[0], kwargs['how'], self.subproject)

    def add_languages(self, args: T.List[Language], required: bool, for_machine: MachineChoice) -> bool:
        success = self.add_languages_for(args, required, for_machine)
        self._redetect_machines()
        return success

    def should_skip_sanity_check(self, for_machine: MachineChoice) -> bool:
        should = self.environment.properties.host.get('skip_sanity_check', False)
        if not isinstance(should, bool):
            raise InterpreterException('Option skip_sanity_check must be a boolean.')
        if for_machine != MachineChoice.HOST and not should:
            return False
        if not self.environment.is_cross_build() and not should:
            return False
        return should

    def add_languages_for(self, args: T.List[Language], required: bool, for_machine: MachineChoice) -> bool:
        langs = set(self.compilers[for_machine])
        langs.update(args)

        # Some languages are added only as implementation details of other
        # languages. When that happens, we don't want to add those languages to
        # the project enabled languages, as they are implementation details, not
        # something the user explicitly asked for, and we don't want to be
        # forced to keep them forever if the implementation changes.
        internal: T.Set[Language] = set()

        if 'vala' in langs and 'c' not in langs:
            FeatureNew.single_use('Adding Vala language without C', '0.59.0', self.subproject, location=self.current_node)
            args.append('c')

        # We need to initialize the default cython language here, as we need it
        # for sanity checking. We may need to initialize a different language later
        # if a target has the `cython_language` overridden. We only want to
        # initialize a default if cython is a new language, not if it's an
        # existing one from `self.compilers`.
        if 'cython' in args:
            _lang = self.coredata.optstore.get_pending_value(OptionKey('cython_language', None, for_machine), 'c')
            assert isinstance(_lang, str), 'for mypy'
            cython_lang = T.cast('Language', _lang)
            if cython_lang not in langs:
                FeatureNew.single_use(f'Adding Cython language without {cython_lang}', '1.11',
                                      self.subproject, location=self.current_node)
                args.append(cython_lang)
                internal.add(cython_lang)

        if 'cuda' in args and 'cpp' not in langs:
            # Cuda requires C++, ensure we initialize that compiler, but don't
            # add that to the project compiler list
            # No FeatureNew is required here because we always did this, we just
            # did it wrong.
            args.append('cpp')
            internal.add('cpp')

        if 'nasm' in langs:
            FeatureNew.single_use('Adding NASM language', '0.64.0', self.subproject, location=self.current_node)

        success = True
        for lang in sorted(args, key=compilers.sort_clink):
            if lang in self.compilers[for_machine]:
                continue
            machine_name = for_machine.get_lower_case_name()
            comp = self.coredata.compilers[for_machine].get(lang)
            if not comp:
                try:
                    skip_sanity_check = self.should_skip_sanity_check(for_machine)
                    if skip_sanity_check:
                        mlog.log('Cross compiler sanity tests disabled via the cross file.', once=True)
                    comp = compilers.detect_compiler_for(self.environment, lang, for_machine, skip_sanity_check, self.subproject)
                    if comp is None:
                        raise InvalidArguments(f'Tried to use unknown language "{lang}".')
                except mesonlib.MesonException:
                    if not required:
                        mlog.log('Compiler for language',
                                 mlog.bold(lang), 'for the', machine_name,
                                 'machine not found.')
                        success = False
                        continue
                    else:
                        raise
                if lang == 'cuda' and hasattr(self.backend, 'allow_thin_archives'):
                    # see NinjaBackend.__init__() why we need to disable thin archives for cuda
                    mlog.debug('added cuda as language, disabling thin archives for {}, since nvcc/nvlink cannot handle thin archives natively'.format(for_machine))
                    self.backend.allow_thin_archives[for_machine] = False
            else:
                # update new values from commandline, if it applies
                self.coredata.process_compiler_options(lang, comp, self.subproject)

            if for_machine == MachineChoice.HOST or self.environment.is_cross_build():
                logger_fun = mlog.log
            else:
                logger_fun = mlog.debug
            logger_fun(comp.get_display_language(), 'compiler for the', machine_name, 'machine:',
                       mlog.bold(' '.join(comp.get_exelist())), comp.get_version_string())
            if comp.linker is not None:
                logger_fun(comp.get_display_language(), 'linker for the', machine_name, 'machine:',
                           mlog.bold(' '.join(comp.linker.get_exelist())), comp.linker.id, comp.linker.version)
            self.build.ensure_static_linker(comp)
            if lang not in internal:
                self.compilers[for_machine][lang] = comp

        return success

    def program_from_file_for(self, for_machine: MachineChoice, prognames: T.List[mesonlib.FileOrString]
                              ) -> T.Optional[ExternalProgram]:
        for p in prognames:
            if isinstance(p, mesonlib.File):
                continue # Always points to a local (i.e. self generated) file.
            if not isinstance(p, str):
                raise InterpreterException('Executable name must be a string')
            prog = ExternalProgram.from_bin_list(self.environment, for_machine, p)
            # if the machine file specified something, it may be a regular
            # not-found program but we still want to return that
            if not isinstance(prog, NonExistingExternalProgram):
                return prog
        return None

    def program_from_system(self, args: T.List[mesonlib.FileOrString], search_dirs: T.Optional[T.List[str]],
                            extra_info: T.List[mlog.TV_Loggable]) -> T.Optional[ExternalProgram]:
        # Search for scripts relative to current subdir.
        # Do not cache found programs because find_program('foobar')
        # might give different results when run from different source dirs.
        source_dir = os.path.join(self.environment.get_source_dir(), self.subdir)
        for exename in args:
            if isinstance(exename, mesonlib.File):
                if exename.is_built:
                    search_dir = os.path.join(self.environment.get_build_dir(),
                                              exename.subdir)
                else:
                    search_dir = os.path.join(self.environment.get_source_dir(),
                                              exename.subdir)
                exename = exename.fname
                search_dirs = [search_dir]
            elif isinstance(exename, str):
                if search_dirs:
                    search_dirs = [source_dir] + search_dirs
                else:
                    search_dirs = [source_dir]
            else:
                raise InvalidArguments(f'find_program only accepts strings and files, not {exename!r}')
            extprog = ExternalProgram(exename, search_dirs=search_dirs, silent=True)
            if extprog.found():
                extra_info.append(f"({' '.join(extprog.get_command())})")
                return extprog
        return None

    def program_from_overrides(self, command_names: T.List[mesonlib.FileOrString],
                               for_machine: MachineChoice,
                               extra_info: T.List['mlog.TV_Loggable']
                               ) -> T.Optional[Program]:
        for name in command_names:
            if not isinstance(name, str):
                continue
            if name in self.build.find_overrides[for_machine]:
                exe = self.build.find_overrides[for_machine][name]
                extra_info.append(mlog.blue('(overridden)'))
                return exe
        return None

    def store_name_lookups(self, command_names: T.List[mesonlib.FileOrString], for_machine: MachineChoice) -> None:
        for name in command_names:
            if isinstance(name, str):
                self.build.searched_programs[for_machine].add(name)

    def add_find_program_override(self, name: str, exe: Program, for_machine: MachineChoice) -> None:
        if name in self.build.searched_programs[for_machine]:
            raise InterpreterException(f'Tried to override finding of executable "{name}" which has already been found.')
        if name in self.build.find_overrides[for_machine]:
            raise InterpreterException(f'Tried to override executable "{name}" which has already been overridden.')
        self.build.find_overrides[for_machine][name] = exe
        if name == 'pkg-config' and isinstance(exe, ExternalProgram):
            from ..dependencies.pkgconfig import PkgConfigInterface
            PkgConfigInterface.set_program_override(exe, for_machine)

    def notfound_program(self, args: T.List[mesonlib.FileOrString]) -> ExternalProgram:
        return NonExistingExternalProgram(' '.join(
            [a if isinstance(a, str) else a.absolute_path(self.environment.source_dir, self.environment.build_dir)
             for a in args]))

    # TODO update modules to always pass `for_machine`. It is bad-form to assume
    # the host machine.
    def find_program_impl(self, args: T.List[mesonlib.FileOrString],
                          for_machine: MachineChoice = MachineChoice.HOST,
                          default_options: T.Optional[OptionDict] = None,
                          required: bool = True, silent: bool = True,
                          wanted: T.Union[str, T.List[str]] = '',
                          search_dirs: T.Optional[T.List[str]] = None,
                          version_arg: T.Optional[str] = '',
                          version_func: T.Optional[ProgramVersionFunc] = None
                          ) -> Program:
        args = mesonlib.listify(args)

        extra_info: T.List[mlog.TV_Loggable] = []
        progobj = self.program_lookup(args, for_machine, default_options, required, search_dirs, wanted, version_arg, version_func, extra_info)
        if progobj is None or not self.check_program_version(progobj, wanted, version_func, for_machine, extra_info):
            progobj = self.notfound_program(args)

        if isinstance(progobj, ExternalProgram) and not progobj.found():
            if not silent:
                mlog.log('Program', mlog.bold(progobj.get_name()), 'found:', mlog.red('NO'), *extra_info)
            if required:
                m = 'Program {!r} not found or not executable'
                raise InterpreterException(m.format(progobj.get_name()))
            return progobj

        # Only store successful lookups
        self.store_name_lookups(args, for_machine)
        if not silent:
            mlog.log('Program', mlog.bold(progobj.name), 'found:', mlog.green('YES'), *extra_info)
        return progobj

    def program_lookup(self, args: T.List[mesonlib.FileOrString], for_machine: MachineChoice,
                       default_options: T.Optional[OptionDict],
                       required: bool,
                       search_dirs: T.Optional[T.List[str]],
                       wanted: T.Union[str, T.List[str]],
                       version_arg: T.Optional[str],
                       version_func: T.Optional[ProgramVersionFunc],
                       extra_info: T.List[mlog.TV_Loggable]
                       ) -> T.Optional[Program]:
        progobj = self.program_from_overrides(args, for_machine, extra_info)
        if progobj:
            return progobj

        if args[0] == 'meson':
            # Override find_program('meson') to return what we were invoked with
            return ExternalProgram('meson', self.environment.get_build_command(), silent=True)

        wrap_mode_s = self.coredata.optstore.get_value_for(OptionKey('wrap_mode'))
        force_fallback_for = self.coredata.optstore.get_value_for(OptionKey('force_fallback_for'))
        assert isinstance(wrap_mode_s, str), 'for mypy'
        assert isinstance(force_fallback_for, list), 'for mypy'
        wrap_mode = WrapMode.from_string(wrap_mode_s)

        fallback: SubProject | None = \
            self.environment.wrap_resolver.find_program_provider(args) \
            if self.environment.wrap_resolver is not None \
            else None
        if fallback and (wrap_mode == WrapMode.forcefallback or fallback in force_fallback_for):
            return self.find_program_fallback(fallback, args, for_machine, default_options, required, extra_info)

        progobj = self.program_from_file_for(for_machine, args)
        if progobj is None:
            progobj = self.program_from_system(args, search_dirs, extra_info)
        if progobj is None and args[0].endswith('python3'):
            prog = ExternalProgram('python3', mesonlib.python_command, silent=True)
            progobj = prog if prog.found() else None

        if isinstance(progobj, ExternalProgram) and version_arg:
            progobj.version_arg = version_arg
        if progobj and not self.check_program_version(progobj, wanted, version_func, for_machine, extra_info):
            progobj = None

        if progobj is None and fallback and required:
            progobj = self.notfound_program(args)
            mlog.log('Program', mlog.bold(progobj.get_name()), 'found:', mlog.red('NO'), *extra_info)
            extra_info.clear()
            progobj = self.find_program_fallback(fallback, args, for_machine, default_options, required, extra_info)

        return progobj

    def check_program_version(self, progobj: Program,
                              wanted: T.Union[str, T.List[str]],
                              version_func: T.Optional[ProgramVersionFunc],
                              for_machine: MachineChoice,
                              extra_info: T.List[mlog.TV_Loggable]) -> bool:
        if wanted:
            if version_func:
                version = version_func(progobj)
            elif isinstance(progobj, build.Executable):
                if progobj.subproject:
                    interp = self.subprojects[for_machine][progobj.subproject].held_object
                else:
                    interp = self
                assert isinstance(interp, Interpreter), 'for mypy'
                version = interp.project_version
            else:
                version = progobj.get_version(self)
            is_found, not_found, _ = mesonlib.version_compare_many(version, wanted)
            if not is_found:
                extra_info[:0] = ['found', mlog.normal_cyan(version), 'but need:',
                                  mlog.bold(', '.join([f"'{e}'" for e in not_found]))]
                return False
            extra_info.insert(0, mlog.normal_cyan(version))
        return True

    def find_program_fallback(self, fallback: SubProject, args: T.List[mesonlib.FileOrString],
                              for_machine: MachineChoice,
                              default_options: OptionDict,
                              required: bool, extra_info: T.List[mlog.TV_Loggable],
                              ) -> T.Optional[Program]:
        mlog.log('Fallback to subproject', mlog.bold(fallback), 'which provides program',
                 mlog.bold(' '.join(str(a) for a in args)))
        sp_kwargs: kwtypes.DoSubproject = {
            'required': required,
            'default_options': default_options or {},
            'version': [],
            'cmake_options': [],
            'options': None,
            'for_machine': for_machine,
        }
        self.do_subproject(fallback, sp_kwargs)
        return self.program_from_overrides(args, for_machine, extra_info)

    @typed_pos_args('find_program', varargs=(str, mesonlib.File), min_varargs=1)
    @typed_kwargs(
        'find_program',
        DISABLER_KW.evolve(since='0.49.0'),
        NATIVE_KW,
        REQUIRED_KW,
        KwargInfo('dirs', ContainerTypeInfo(list, str), default=[], listify=True, since='0.53.0'),
        KwargInfo('version', ContainerTypeInfo(list, str), default=[], listify=True, since='0.52.0'),
        KwargInfo('version_argument', str, default='', since='1.5.0'),
        DEFAULT_OPTIONS.evolve(since='1.3.0')
    )
    @disablerIfNotFound
    @apply_machine_map
    def func_find_program(self, node: mparser.BaseNode, args: T.Tuple[T.List[mesonlib.FileOrString]],
                          kwargs: 'kwtypes.FindProgram',
                          ) -> Program:
        disabled, required, feature = extract_required_kwarg(kwargs, self.subproject)
        if disabled:
            mlog.log('Program', mlog.bold(' '.join(str(a) for a in args[0])), 'skipped: feature', mlog.bold(feature), 'disabled')
            return self.notfound_program(args[0])

        search_dirs = extract_search_dirs(kwargs)
        default_options = kwargs['default_options']
        return self.find_program_impl(args[0], kwargs['native'], default_options=default_options, required=required,
                                      silent=False, wanted=kwargs['version'], version_arg=kwargs['version_argument'],
                                      search_dirs=search_dirs)

    # When adding kwargs, please check if they make sense in dependencies.get_dep_identifier()
    @typed_pos_args('dependency', varargs=str, min_varargs=1)
    @typed_kwargs('dependency', *DEPENDENCY_KWS)
    @disablerIfNotFound
    @apply_machine_map
    def func_dependency(self, node: mparser.BaseNode, args: T.Tuple[T.List[str]], kwargs: kwtypes.FuncDependency) -> Dependency:
        # Replace '' by empty list of names
        names = [n for n in args[0] if n]
        if len(names) > 1:
            FeatureNew('dependency with more than one name', '0.60.0').use(self.subproject)
        default_options = kwargs.get('default_options')
        for_machine = kwargs['native']
        df = DependencyFallbacksHolder(self, names, for_machine, kwargs['allow_fallback'], default_options)
        df.set_fallback(kwargs['fallback'])
        not_found_message = kwargs['not_found_message']

        disabled, required, feature = extract_required_kwarg(kwargs, self.subproject)
        if disabled:
            name = names[0]
            if kwargs['modules']:
                name = name + '(modules: {})'.format(', '.join(kwargs['modules']))
            mlog.log('Dependency', mlog.bold(name),
                     'for', mlog.bold(for_machine.get_lower_case_name()), 'machine',
                     'skipped: feature', mlog.bold(feature), 'disabled')
            return dependencies.NotFoundDependency(names[0], self.environment)

        nkwargs = T.cast('dependencies.base.DependencyObjectKWs', kwargs.copy())
        nkwargs['required'] = required  # to replace a possible Feature with a bool

        try:
            d = df.lookup(nkwargs)
        except Exception:
            if not_found_message:
                self.message_impl([not_found_message])
            raise
        assert isinstance(d, Dependency), 'for mypy'
        if not d.found() and not_found_message:
            self.message_impl([not_found_message])
        # Ensure the correct include type
        if kwargs['include_type'] != 'preserve':
            wanted = kwargs['include_type']
            actual = d.get_include_type()
            if wanted != actual:
                mlog.debug(f'Current include type of {args[0]} is {actual}. Converting to requested {wanted}')
                d = d.generate_system_dependency(wanted)
        if d.feature_since is not None:
            version, extra_msg = d.feature_since
            FeatureNew.single_use(f'dep {d.name!r} custom lookup', version, self.subproject, extra_msg, node)
        for f in d.featurechecks:
            f.use(self.subproject, node)
        return d

    @FeatureNew('default', '1.12.0')
    @noKwargs
    @noPosargs
    def func_default(self, node: mparser.BaseNode, args: list[TYPE_var], kwargs: TYPE_kwargs) -> DefaultObject:
        return DefaultObject()

    @FeatureNew('disabler', '0.44.0')
    @noKwargs
    @noPosargs
    def func_disabler(self, node: mparser.BaseNode, args: list[TYPE_var], kwargs: TYPE_kwargs) -> Disabler:
        return Disabler()

    @typed_pos_args('executable', str, varargs=SOURCES_VARARGS)
    @typed_kwargs('executable', *EXECUTABLE_KWS)
    def func_executable(self, node: mparser.BaseNode,
                        args: T.Tuple[str, SourcesVarargsType],
                        kwargs: kwtypes.Executable) -> T.Union[build.Executable, build.SharedLibrary]:
        return self.build_target(node, args, kwargs, build.Executable)

    @typed_pos_args('static_library', str, varargs=SOURCES_VARARGS)
    @typed_kwargs('static_library', *STATIC_LIB_KWS)
    def func_static_lib(self, node: mparser.BaseNode,
                        args: T.Tuple[str, SourcesVarargsType],
                        kwargs: kwtypes.StaticLibrary) -> build.StaticLibrary:
        return self.build_target(node, args, kwargs, build.StaticLibrary)

    @typed_pos_args('shared_library', str, varargs=SOURCES_VARARGS)
    @typed_kwargs('shared_library', *SHARED_LIB_KWS)
    def func_shared_lib(self, node: mparser.BaseNode,
                        args: T.Tuple[str, SourcesVarargsType],
                        kwargs: kwtypes.SharedLibrary) -> build.SharedLibrary:
        return self.build_target(node, args, kwargs, build.SharedLibrary)

    @typed_pos_args('both_libraries', str, varargs=SOURCES_VARARGS)
    @typed_kwargs('both_libraries', *LIBRARY_KWS)
    @noSecondLevelHolderResolving
    def func_both_lib(self, node: mparser.BaseNode,
                      args: T.Tuple[str, SourcesVarargsType],
                      kwargs: kwtypes.Library) -> build.BothLibraries:
        return self.build_both_libraries(node, args, kwargs)

    @FeatureNew('shared_module', '0.37.0')
    @typed_pos_args('shared_module', str, varargs=SOURCES_VARARGS)
    @typed_kwargs('shared_module', *SHARED_MOD_KWS)
    def func_shared_module(self, node: mparser.BaseNode,
                           args: T.Tuple[str, SourcesVarargsType],
                           kwargs: kwtypes.SharedModule) -> build.SharedModule:
        return self.build_target(node, args, kwargs, build.SharedModule)

    @typed_pos_args('library', str, varargs=SOURCES_VARARGS)
    @typed_kwargs('library', *LIBRARY_KWS)
    @noSecondLevelHolderResolving
    def func_library(self, node: mparser.BaseNode,
                     args: T.Tuple[str, SourcesVarargsType],
                     kwargs: kwtypes.Library) -> build.StaticLibrary | build.SharedLibrary | build.BothLibraries:
        return self.build_library(node, args, kwargs)

    @typed_pos_args('jar', str, varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList, build.ExtractedObjects, build.BuildTarget))
    @typed_kwargs('jar', *JAR_KWS)
    def func_jar(self, node: mparser.BaseNode,
                 args: T.Tuple[str, T.List[str | build.TargetSources]],
                 kwargs: kwtypes.Jar) -> build.Jar:
        return self.build_target(node, T.cast('tuple[str, SourcesVarargsType]', args), kwargs, build.Jar)

    @FeatureNewKwargs('build_target', '0.40.0', ['link_whole', 'override_options'])
    @typed_pos_args('build_target', str, varargs=SOURCES_VARARGS)
    @typed_kwargs('build_target', *BUILD_TARGET_KWS)
    def func_build_target(self, node: mparser.BaseNode,
                          args: T.Tuple[str, SourcesVarargsType],
                          kwargs: kwtypes.BuildTargetFunc,
                          ) -> T.Union[build.Executable, build.StaticLibrary, build.SharedLibrary,
                                       build.SharedModule, build.BothLibraries, build.Jar]:
        target_type = kwargs['target_type']

        if target_type == 'executable':
            return self.build_target(node, args, kwargs, build.Executable)
        elif target_type == 'shared_library':
            return self.build_target(node, args, kwargs, build.SharedLibrary)
        elif target_type == 'shared_module':
            return self.build_target(node, args, kwargs, build.SharedModule)
        elif target_type == 'static_library':
            return self.build_target(node, args, kwargs, build.StaticLibrary)
        elif target_type == 'both_libraries':
            return self.build_both_libraries(node, args, kwargs)
        elif target_type == 'library':
            return self.build_library(node, args, kwargs)
        # We can't avoid the cast here because of the mis-matched sources types
        # between Jar and BuildTarget types
        return self.build_target(node, args, T.cast('kwtypes.Jar', kwargs), build.Jar)

    @noPosargs
    @typed_kwargs(
        'vcs_tag',
        CT_INPUT_KW.evolve(required=True),
        MULTI_OUTPUT_KW,
        # Cannot use the COMMAND_KW because command is allowed to be empty
        KwargInfo(
            'command',
            ContainerTypeInfo(list, (str, build.BuildTarget, build.CustomTarget, build.CustomTargetIndex, Program, mesonlib.File)),
            listify=True,
            default=[],
        ),
        KwargInfo('fallback', (str, NoneType)),
        KwargInfo('replace_string', str, default='@VCS_TAG@'),
        INSTALL_KW.evolve(since='1.7.0'),
        INSTALL_DIR_KW.evolve(since='1.7.0'),
        INSTALL_TAG_KW.evolve(since='1.7.0'),
        INSTALL_MODE_KW.evolve(since='1.7.0'),
    )
    @apply_machine_map
    def func_vcs_tag(self, node: mparser.BaseNode, args: T.List['TYPE_var'], kwargs: 'kwtypes.VcsTag') -> build.CustomTarget:
        if kwargs['fallback'] is None:
            FeatureNew.single_use('Optional fallback in vcs_tag', '0.41.0', self.subproject, location=node)
        fallback = kwargs['fallback'] or self.project_version
        replace_string = kwargs['replace_string']
        regex_selector = '(.*)' # default regex selector for custom command: use complete output
        vcs_cmd = kwargs['command']
        source_dir = os.path.normpath(os.path.join(self.environment.get_source_dir(), self.subdir))
        if vcs_cmd:
            if isinstance(vcs_cmd[0], (str, mesonlib.File)):
                if isinstance(vcs_cmd[0], mesonlib.File):
                    FeatureNew.single_use('vcs_tag with file as the first argument', '0.62.0', self.subproject, location=node)
                maincmd = self.find_program_impl([vcs_cmd[0]], required=False)
                if maincmd.found():
                    vcs_cmd[0] = maincmd
            else:
                FeatureNew.single_use('vcs_tag with custom_tgt, program, or exe as the first argument', '0.63.0', self.subproject, location=node)
        else:
            vcs = mesonlib.detect_vcs(source_dir)
            if vcs:
                mlog.log('Found {} repository at {}'.format(vcs.name, vcs.wc_dir))
                vcs_cmd = vcs.get_rev
                regex_selector = vcs.rev_regex
            else:
                vcs_cmd = [' '] # executing this cmd will fail in vcstagger.py and force to use the fallback string
        # vcstagger.py parameters: infile, outfile, fallback, source_dir, replace_string, regex_selector, command...

        self._validate_custom_target_outputs(len(kwargs['input']) > 1, kwargs['output'], "vcs_tag")

        cmd = self.environment.get_build_command() + \
            ['--internal',
             'vcstagger',
             '@INPUT0@',
             '@OUTPUT0@',
             fallback,
             source_dir,
             replace_string,
             regex_selector] + vcs_cmd

        install = kwargs['install']
        install_mode = self._warn_kwarg_install_mode_sticky(kwargs['install_mode'])
        install_dir: T.List[T.Union[str, Literal[False]]] = [] if kwargs['install_dir'] is None else [kwargs['install_dir']]
        install_tag: T.List[T.Optional[str]] = [] if kwargs['install_tag'] is None else [kwargs['install_tag']]
        if install and not install_dir:
            raise InvalidArguments('vcs_tag: "install_dir" keyword argument must be set when "install" is true.')

        tg = build.CustomTarget(
            kwargs['output'][0],
            self.subdir,
            self.environment,
            cmd,
            self.source_strings_to_files(kwargs['input']),
            kwargs['output'],
            self.current_build_project(),
            build_by_default=True,
            build_always_stale=True,
            install=install,
            install_dir=install_dir,
            install_mode=install_mode,
            install_tag=install_tag,
        )
        self.add_target(tg.name, tg)
        return tg

    @FeatureNew('subdir_done', '0.46.0')
    @noPosargs
    @noKwargs
    def func_subdir_done(self, node: mparser.BaseNode, args: TYPE_var, kwargs: TYPE_kwargs) -> T.NoReturn:
        raise SubdirDoneRequest()

    def _validate_custom_target_outputs(self, has_multi_in: bool, outputs: T.Iterable[str], name: str) -> None:
        """Checks for additional invalid values in a custom_target output.

        This cannot be done with typed_kwargs because it requires the number of
        inputs.
        """
        inregex: T.List[str] = ['@PLAINNAME[0-9]+@', '@BASENAME[0-9]+@']
        from ..utils.universal import iter_regexin_iter
        for out in outputs:
            match = iter_regexin_iter(inregex, [out])
            if has_multi_in and ('@PLAINNAME@' in out or '@BASENAME@' in out):
                raise InvalidArguments(f'{name}: output cannot contain "@PLAINNAME@" or "@BASENAME@" '
                                       'when there is more than one input (we can\'t know which to use)')
            elif match:
                FeatureNew.single_use(
                    f'{match} in output', '1.5.0',
                    self.subproject)

    @typed_pos_args('custom_target', optargs=[str])
    @typed_kwargs(
        'custom_target',
        COMMAND_KW,
        CT_BUILD_ALWAYS,
        CT_BUILD_ALWAYS_STALE,
        CT_BUILD_BY_DEFAULT,
        CT_INPUT_KW,
        CT_INSTALL_DIR_KW,
        CT_INSTALL_TAG_KW,
        MULTI_OUTPUT_KW,
        DEPENDS_KW,
        DEPEND_FILES_KW,
        DEPFILE_KW,
        ENV_KW.evolve(since='0.57.0'),
        INSTALL_KW,
        INSTALL_MODE_KW.evolve(since='0.47.0'),
        KwargInfo('feed', bool, default=False, since='0.59.0'),
        KwargInfo('capture', bool, default=False),
        KwargInfo('console', bool, default=False, since='0.48.0'),
        KwargInfo('build_subdir', str, default='', since='1.10.0'),
    )
    @apply_machine_map
    def func_custom_target(self, node: mparser.FunctionNode, args: T.Tuple[str],
                           kwargs: 'kwtypes.CustomTarget') -> build.CustomTarget:
        if kwargs['depfile'] and ('@BASENAME@' in kwargs['depfile'] or '@PLAINNAME@' in kwargs['depfile']):
            FeatureNew.single_use('substitutions in custom_target depfile', '0.47.0', self.subproject, location=node)
        install_mode = self._warn_kwarg_install_mode_sticky(kwargs['install_mode'])

        # Don't mutate the kwargs

        build_by_default = kwargs['build_by_default']
        build_always_stale = kwargs['build_always_stale']
        # Remap build_always to build_by_default and build_always_stale
        if kwargs['build_always'] is not None and kwargs['build_always_stale'] is not None:
            raise InterpreterException('CustomTarget: "build_always" and "build_always_stale" are mutually exclusive')

        if build_by_default is None and kwargs['install']:
            build_by_default = True

        elif kwargs['build_always'] is not None:
            if build_by_default is None:
                build_by_default = kwargs['build_always']
            build_always_stale = kwargs['build_by_default']

        # These are nullable so that we can know whether they're explicitly
        # set or not. If they haven't been overwritten, set them to their true
        # default
        if build_by_default is None:
            build_by_default = False
        if build_always_stale is None:
            build_always_stale = False

        name = args[0]
        if name is None:
            # name will default to first output, but we cannot do that yet because
            # they could need substitutions (e.g. @BASENAME@) first. CustomTarget()
            # will take care of setting a proper default but name must be an empty
            # string in the meantime.
            FeatureNew.single_use('custom_target() with no name argument', '0.60.0', self.subproject, location=node)
            name = ''
        inputs = self.source_strings_to_files(kwargs['input'])
        command = kwargs['command']
        if command and isinstance(command[0], str):
            command[0] = self.find_program_impl([command[0]])

        if len(inputs) > 1 and kwargs['feed']:
            raise InvalidArguments('custom_target: "feed" keyword argument can only be used with a single input')
        if len(kwargs['output']) > 1 and kwargs['capture']:
            raise InvalidArguments('custom_target: "capture" keyword argument can only be used with a single output')
        if kwargs['capture'] and kwargs['console']:
            raise InvalidArguments('custom_target: "capture" and "console" keyword arguments are mutually exclusive')
        for c in command:
            if kwargs['capture'] and isinstance(c, str) and '@OUTPUT@' in c:
                raise InvalidArguments('custom_target: "capture" keyword argument cannot be used with "@OUTPUT@"')
            if kwargs['feed'] and isinstance(c, str) and '@INPUT@' in c:
                raise InvalidArguments('custom_target: "feed" keyword argument cannot be used with "@INPUT@"')
        if kwargs['install'] and not kwargs['install_dir']:
            raise InvalidArguments('custom_target: "install_dir" keyword argument must be set when "install" is true.')
        if len(kwargs['install_dir']) > 1:
            FeatureNew.single_use('multiple install_dir for custom_target', '0.40.0', self.subproject, location=node)
        if len(kwargs['install_tag']) not in {0, 1, len(kwargs['output'])}:
            raise InvalidArguments('custom_target: install_tag argument must have 0 or 1 outputs, '
                                   'or the same number of elements as the output keyword argument. '
                                   f'(there are {len(kwargs["install_tag"])} install_tags, '
                                   f'and {len(kwargs["output"])} outputs)')

        self._validate_custom_target_outputs(len(inputs) > 1, kwargs['output'], "custom_target")

        tg = build.CustomTarget(
            name,
            self.subdir,
            self.environment,
            command,
            inputs,
            kwargs['output'],
            self.current_build_project(),
            build_always_stale=build_always_stale,
            build_by_default=build_by_default,
            capture=kwargs['capture'],
            console=kwargs['console'],
            depend_files=self.source_strings_to_files(kwargs['depend_files']),
            depfile=kwargs['depfile'],
            extra_depends=kwargs['depends'],
            env=kwargs['env'],
            feed=kwargs['feed'],
            install=kwargs['install'],
            install_dir=kwargs['install_dir'],
            install_mode=install_mode,
            install_tag=kwargs['install_tag'],
            backend=self.backend,
            build_subdir=kwargs['build_subdir'])

        subdir = tg.get_builddir()
        for t in tg.get_outputs():
            self.validate_forbidden_targets(t, not subdir)
        self.add_target(tg.name, tg)
        return tg

    @typed_pos_args('run_target', str)
    @typed_kwargs(
        'run_target',
        COMMAND_KW,
        DEPENDS_KW,
        ENV_KW.evolve(since='0.57.0'),
    )
    def func_run_target(self, node: mparser.FunctionNode, args: T.Tuple[str],
                        kwargs: 'kwtypes.RunTarget') -> build.RunTarget:
        all_args = kwargs['command'].copy()

        for i in listify(all_args):
            if isinstance(i, ExternalProgram) and not i.found():
                raise InterpreterException(f'Tried to use non-existing executable {i.name!r}')
        if isinstance(all_args[0], str):
            all_args[0] = self.find_program_impl([all_args[0]])

        if '@DEPFILE@' in all_args:
            raise InterpreterException('run_target does not have support for @DEPFILE@')

        name = args[0]
        tg = build.RunTarget(name, all_args, kwargs['depends'], self.subdir, self.environment,
                             self.current_build_project(), kwargs['env'])
        self.add_target(name, tg)
        return tg

    @FeatureNew('alias_target', '0.52.0')
    @typed_pos_args('alias_target', str, varargs=(build.Target, build.BothLibraries), min_varargs=1)
    @noKwargs
    def func_alias_target(self, node: mparser.BaseNode, args: T.Tuple[str, T.List[T.Union[build.Target, build.BothLibraries]]],
                          kwargs: TYPE_kwargs) -> build.AliasTarget:
        name, deps = args
        if any(isinstance(d, build.RunTarget) for d in deps):
            FeatureNew.single_use('alias_target that depends on run_targets', '0.60.0', self.subproject)
        real_deps: T.List[build.Target] = []
        for d in deps:
            if isinstance(d, build.BothLibraries):
                real_deps.append(d.shared)
                real_deps.append(d.static)
            else:
                real_deps.append(d)
        tg = build.AliasTarget(name, real_deps, self.subdir, self.environment,
                               self.current_build_project())
        self.add_target(name, tg)
        return tg

    @typed_pos_args('generator', (build.Executable, Program))
    @typed_kwargs(
        'generator',
        KwargInfo('arguments', ContainerTypeInfo(list, str, allow_empty=False), required=True, listify=True),
        KwargInfo('output', ContainerTypeInfo(list, str, allow_empty=False), required=True, listify=True),
        DEPFILE_KW,
        DEPENDS_KW,
        KwargInfo('capture', bool, default=False, since='0.43.0'),
    )
    def func_generator(self, node: mparser.FunctionNode,
                       args: T.Tuple[T.Union[build.Executable, Program]],
                       kwargs: 'kwtypes.FuncGenerator') -> build.Generator:
        for rule in kwargs['output']:
            if '@BASENAME@' not in rule and '@PLAINNAME@' not in rule:
                raise InvalidArguments('Every element of "output" must contain @BASENAME@ or @PLAINNAME@.')
            if has_path_sep(rule):
                raise InvalidArguments('"output" must not contain a directory separator.')
        if len(kwargs['output']) > 1:
            for o in kwargs['output']:
                if '@OUTPUT@' in o:
                    raise InvalidArguments('Tried to use @OUTPUT@ in a rule with more than one output.')

        if isinstance(args[0], build.Executable):
            exe_prg = build.LocalProgram(args[0], self.project_version)
        else:
            exe_prg = args[0]
        return build.Generator(self.environment, exe_prg, **kwargs)

    @typed_pos_args('benchmark', str, (build.Executable, build.Jar, Program, mesonlib.File, build.CustomTarget, build.CustomTargetIndex))
    @typed_kwargs('benchmark', *TEST_KWS)
    def func_benchmark(self, node: mparser.BaseNode,
                       args: T.Tuple[str, T.Union[build.Executable, build.Jar, Program, mesonlib.File, build.CustomTarget, build.CustomTargetIndex]],
                       kwargs: 'kwtypes.FuncBenchmark') -> None:
        self.add_test(node, args, kwargs, False)

    @typed_pos_args('test', str, (build.Executable, build.Jar, Program, mesonlib.File, build.CustomTarget, build.CustomTargetIndex))
    @typed_kwargs('test', *TEST_KWS, KwargInfo('is_parallel', bool, default=True))
    def func_test(self, node: mparser.BaseNode,
                  args: T.Tuple[str, T.Union[build.Executable, build.Jar, Program, mesonlib.File, build.CustomTarget, build.CustomTargetIndex]],
                  kwargs: 'kwtypes.FuncTest') -> None:
        self.add_test(node, args, kwargs, True)

    def make_test(self, node: mparser.BaseNode,
                  args: T.Tuple[str, T.Union[build.Executable, build.Jar, Program, mesonlib.File, build.CustomTarget, build.CustomTargetIndex]],
                  kwargs: kwtypes.FuncTest | kwtypes.FuncBenchmark,
                  klass: T.Type[TestClass] = Test) -> TestClass:  # type: ignore[assignment]
        name = args[0]
        if ':' in name:
            mlog.deprecation(f'":" is not allowed in test name "{name}", it has been replaced with "_"',
                             location=node)
            name = name.replace(':', '_')
        exe = args[1]
        if isinstance(exe, Program) and not exe.found():
            raise InvalidArguments('Tried to use not-found external program as test exe')
        elif isinstance(exe, mesonlib.File):
            exe = self.find_program_impl([exe])
        if isinstance(exe, (build.Executable, build.CustomTarget, build.CustomTargetIndex)):
            kwargs.setdefault('depends', []).append(exe.get_target())

        if kwargs['timeout'] <= 0:
            FeatureNew.single_use('test() timeout <= 0', '0.57.0', self.subproject, location=node)

        expected_fail = False
        if kwargs['should_fail'] is not None and kwargs['expected_fail'] is not None:
            raise InvalidArguments("Tried to use both 'should_fail' and 'expected_fail'")
        elif kwargs['should_fail'] is not None:
            expected_fail = kwargs['should_fail']
        elif kwargs['expected_fail'] is not None:
            expected_fail = kwargs['expected_fail']

        prj = self.subproject if self.is_subproject() else self.build.project_name

        suite: T.List[str] = []
        for s in kwargs['suite']:
            if s:
                s = ':' + s
            suite.append(prj.replace(' ', '_').replace(':', '_') + s)

        return klass(name,
                     prj,
                     suite,
                     exe,
                     kwargs['depends'],
                     T.cast('bool', kwargs.get('is_parallel', False)),
                     kwargs['args'],
                     kwargs['env'],
                     expected_fail,
                     kwargs['expected_exitcode'],
                     kwargs['timeout'],
                     kwargs['workdir'],
                     kwargs['protocol'],
                     kwargs['priority'],
                     kwargs['verbose'])

    def add_test(self, node: mparser.BaseNode,
                 args: T.Tuple[str, T.Union[build.Executable, build.Jar, Program, mesonlib.File, build.CustomTarget, build.CustomTargetIndex]],
                 kwargs: kwtypes.FuncTest | kwtypes.FuncBenchmark, is_base_test: bool) -> None:
        if isinstance(args[1], (build.CustomTarget, build.CustomTargetIndex)):
            FeatureNew.single_use('test with CustomTarget as command', '1.4.0', self.subproject)
        if any(isinstance(i, ExternalProgram) for i in kwargs['args']):
            FeatureNew.single_use('test with program in args', '1.6.0', self.subproject)

        t: Test = self.make_test(node, args, kwargs)
        if is_base_test:
            self.build.tests.append(t)
            mlog.debug('Adding test', mlog.bold(t.name, True))
        else:
            self.build.benchmarks.append(t)
            mlog.debug('Adding benchmark', mlog.bold(t.name, True))

    @typed_pos_args('install_headers', varargs=(str, mesonlib.File))
    @typed_kwargs(
        'install_headers',
        PRESERVE_PATH_KW,
        KwargInfo('subdir', (str, NoneType)),
        INSTALL_MODE_KW.evolve(since='0.47.0'),
        INSTALL_DIR_KW,
        INSTALL_FOLLOW_SYMLINKS,
        INSTALL_TAG_KW.evolve(since='1.11.0'),
    )
    def func_install_headers(self, node: mparser.BaseNode,
                             args: T.Tuple[T.List['mesonlib.FileOrString']],
                             kwargs: 'kwtypes.FuncInstallHeaders') -> list[build.Headers]:
        install_mode = self._warn_kwarg_install_mode_sticky(kwargs['install_mode'])
        source_files = self.source_strings_to_files(args[0])
        install_subdir = kwargs['subdir']
        if install_subdir is not None:
            if kwargs['install_dir'] is not None:
                raise InterpreterException('install_headers: cannot specify both "install_dir" and "subdir". Use only "install_dir".')
            if path_has_root(install_subdir):
                mlog.deprecation('Subdir keyword must not be an absolute path. This will be a hard error in meson 2.0.')
        else:
            install_subdir = ''

        dirs = collections.defaultdict(list)
        ret_headers: list[build.Headers] = []
        if kwargs['preserve_path']:
            for file in source_files:
                dirname = os.path.dirname(file.fname)
                dirs[dirname].append(file)
        else:
            dirs[''].extend(source_files)

        for childdir in dirs:
            h = build.Headers(dirs[childdir], os.path.join(install_subdir, childdir), kwargs['install_dir'],
                              install_mode, self.subproject,
                              follow_symlinks=kwargs['follow_symlinks'],
                              install_tag=kwargs['install_tag'])
            ret_headers.append(h)
            if not self.is_internal_machine(MachineChoice.HOST):
                self.build.headers.append(h)

        return ret_headers

    @typed_pos_args('install_man', varargs=(str, mesonlib.File))
    @typed_kwargs(
        'install_man',
        KwargInfo('locale', (str, NoneType), since='0.58.0'),
        INSTALL_MODE_KW.evolve(since='0.47.0'),
        INSTALL_DIR_KW,
        INSTALL_TAG_KW.evolve(since='1.11.0')
    )
    def func_install_man(self, node: mparser.BaseNode,
                         args: T.Tuple[T.List['mesonlib.FileOrString']],
                         kwargs: 'kwtypes.FuncInstallMan') -> build.Man:
        install_mode = self._warn_kwarg_install_mode_sticky(kwargs['install_mode'])
        # We just need to narrow this, because the input is limited to files and
        # Strings as inputs, so only Files will be returned
        sources = self.source_strings_to_files(args[0])
        for s in sources:
            try:
                num = int(s.rsplit('.', 1)[-1])
            except (IndexError, ValueError):
                num = 0
            if not 1 <= num <= 9:
                raise InvalidArguments('Man file must have a file extension of a number between 1 and 9')

        m = build.Man(sources, kwargs['install_dir'], install_mode,
                      self.subproject, kwargs['locale'], kwargs['install_tag'])
        if not self.is_internal_machine(MachineChoice.HOST):
            self.build.man.append(m)

        return m

    @FeatureNew('install_emptydir', '0.60.0')
    @typed_kwargs(
        'install_emptydir',
        INSTALL_MODE_KW,
        KwargInfo('install_tag', (str, NoneType), since='0.62.0')
    )
    def func_install_emptydir(self, node: mparser.BaseNode, args: T.Tuple[str],
                              kwargs: kwtypes.FuncInstallEmptyDir) -> build.EmptyDir:
        d = build.EmptyDir(args[0], kwargs['install_mode'], self.subproject, kwargs['install_tag'])
        if not self.is_internal_machine(MachineChoice.HOST):
            self.build.emptydir.append(d)
        return d

    @FeatureNew('install_symlink', '0.61.0')
    @typed_pos_args('symlink_name', str)
    @typed_kwargs(
        'install_symlink',
        KwargInfo('pointing_to', str, required=True),
        KwargInfo('install_dir', str, required=True),
        INSTALL_TAG_KW,
    )
    def func_install_symlink(self, node: mparser.BaseNode,
                             args: T.Tuple[str],
                             kwargs: kwtypes.FuncInstallSymlink) -> build.SymlinkData:
        name = args[0] # Validation while creating the SymlinkData object
        target = kwargs['pointing_to']
        l = build.SymlinkData(target, name, kwargs['install_dir'],
                              self.subproject, kwargs['install_tag'])
        if not self.is_internal_machine(MachineChoice.HOST):
            self.build.symlinks.append(l)
        return l

    @FeatureNew('structured_sources', '0.62.0')
    @typed_pos_args('structured_sources', object, optargs=[dict])
    @noKwargs
    @noArgsFlattening
    def func_structured_sources(
            self, node: mparser.BaseNode,
            args: T.Tuple[object, T.Optional[T.Dict[str, object]]],
            kwargs: 'TYPE_kwargs') -> build.StructuredSources:
        valid_types = (str, mesonlib.File, build.GeneratedList, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList)
        sources: T.DefaultDict[str, T.List[T.Union[build.TargetSources]]] = collections.defaultdict(list)

        for arg in mesonlib.listify(args[0]):
            if not isinstance(arg, valid_types):
                raise InvalidArguments(f'structured_sources: type "{type(arg)}" is not valid')
            if isinstance(arg, str):
                arg = mesonlib.File.from_source_file(self.environment.source_dir, self.subdir, arg)
            sources[''].append(arg)
        if args[1]:
            if '' in args[1]:
                raise InvalidArguments('structured_sources: keys to dictionary argument may not be an empty string.')
            for k, v in args[1].items():
                for arg in mesonlib.listify(v):
                    if not isinstance(arg, valid_types):
                        raise InvalidArguments(f'structured_sources: type "{type(arg)}" is not valid')
                    if isinstance(arg, str):
                        arg = mesonlib.File.from_source_file(self.environment.source_dir, self.subdir, arg)
                    sources[k].append(arg)
        return build.StructuredSources(sources)

    @typed_pos_args('subdir', str)
    @typed_kwargs(
        'subdir',
        KwargInfo(
            'if_found',
            ContainerTypeInfo(list, object),
            validator=lambda a: 'Objects must have a found() method' if not all(hasattr(x, 'found') for x in a) else None,
            since='0.44.0',
            default=[],
            listify=True,
        ),
    )
    def func_subdir(self, node: mparser.BaseNode, args: T.Tuple[str], kwargs: 'kwtypes.Subdir') -> None:
        mesonlib.check_direntry_issues(args)
        if '..' in args[0]:
            raise InvalidArguments('Subdir contains ..')
        if self.subdir == '' and args[0] == self.subproject_dir:
            raise InvalidArguments('Must not go into subprojects dir with subdir(), use subproject() instead.')
        if self.subdir == '' and args[0].startswith('meson-'):
            raise InvalidArguments('The "meson-" prefix is reserved and cannot be used for top-level subdir().')
        if args[0] == '':
            raise InvalidArguments("The argument given to subdir() is the empty string ''. This is prohibited.")
        if path_has_root(args[0]):
            raise InvalidArguments('Subdir argument must be a relative path.')
        for i in kwargs['if_found']:
            if not i.found():
                return

        subdir, is_new = self._resolve_subdir(self.environment.get_source_dir(), args[0])
        if not is_new:
            raise InvalidArguments(f'Tried to enter directory "{subdir}", which has already been visited.')

        self.create_build_subdir(subdir)

        if InterpreterRuleRelaxation.CARGO_SUBDIR in self.relaxations and \
           os.path.exists(os.path.join(self.environment.get_source_dir(), subdir, 'Cargo.toml')):
            codeblock = self.cargo.interpret(subdir, self.root_subdir)
            self._save_ast(subdir, codeblock)
            self._evaluate_codeblock(codeblock, subdir)
        elif not self._evaluate_subdir(self.environment.get_source_dir(), subdir):
            buildfilename = os.path.join(subdir, environment.build_filename)
            raise InterpreterException(f"Nonexistent build file '{buildfilename!s}'")

    # This is either ignored on basically any OS nowadays, or silently gets
    # ignored (Solaris) or triggers an "illegal operation" error (FreeBSD).
    # It was likely added "because it exists", but should never be used. In
    # theory it is useful for directories, but we never apply modes to
    # directories other than in install_emptydir.
    def _warn_kwarg_install_mode_sticky(self, mode: FileMode) -> FileMode:
        if mode.perms > 0 and mode.perms & stat.S_ISVTX:
            mlog.deprecation('install_mode with the sticky bit on a file does not do anything and will '
                             'be ignored since Meson 0.64.0', location=self.current_node)
            perms = stat.filemode(mode.perms - stat.S_ISVTX)[1:]
            return FileMode(perms, mode.owner, mode.group)
        else:
            return mode

    @typed_pos_args('install_data', varargs=(str, mesonlib.File))
    @typed_kwargs(
        'install_data',
        KwargInfo('sources', ContainerTypeInfo(list, (str, mesonlib.File)), listify=True, default=[]),
        KwargInfo('rename', ContainerTypeInfo(list, str), default=[], listify=True, since='0.46.0'),
        INSTALL_MODE_KW.evolve(since='0.38.0'),
        INSTALL_TAG_KW.evolve(since='0.60.0'),
        INSTALL_DIR_KW,
        PRESERVE_PATH_KW.evolve(since='0.64.0'),
        INSTALL_FOLLOW_SYMLINKS,
    )
    def func_install_data(self, node: mparser.BaseNode,
                          args: T.Tuple[T.List['mesonlib.FileOrString']],
                          kwargs: 'kwtypes.FuncInstallData') -> list[build.Data]:
        sources = self.source_strings_to_files(args[0] + kwargs['sources'])
        rename = kwargs['rename'] or None
        if rename:
            if len(rename) != len(sources):
                raise InvalidArguments(
                    '"rename" and "sources" argument lists must be the same length if "rename" is given. '
                    f'Rename has {len(rename)} elements and sources has {len(sources)}.')

        install_dir = kwargs['install_dir']
        if not install_dir:
            subdir = self.active_projectname
            install_dir = P_OBJ.OptionString(os.path.join(self.environment.get_datadir(), subdir), os.path.join('{datadir}', subdir))
            if self.is_subproject():
                FeatureNew.single_use('install_data() without install_dir inside of a subproject', '1.3.0', self.subproject,
                                      'This was broken and would install to the project name of the parent project instead',
                                      node)
            if kwargs['preserve_path']:
                FeatureNew.single_use('install_data() with preserve_path and without install_dir', '1.3.0', self.subproject,
                                      'This was broken and would not add the project name to the install path',
                                      node)

        install_mode = self._warn_kwarg_install_mode_sticky(kwargs['install_mode'])
        return self.install_data_impl(sources, install_dir, install_mode, rename, kwargs['install_tag'],
                                      preserve_path=kwargs['preserve_path'],
                                      follow_symlinks=kwargs['follow_symlinks'])

    def install_data_impl(self, sources: T.List[mesonlib.File], install_dir: str,
                          install_mode: FileMode, rename: T.Optional[T.List[str]],
                          tag: T.Optional[str],
                          install_data_type: T.Optional[str] = None,
                          preserve_path: bool = False,
                          follow_symlinks: T.Optional[bool] = None) -> list[build.Data]:
        install_dir_name = install_dir.optname if isinstance(install_dir, P_OBJ.OptionString) else install_dir
        dirs = collections.defaultdict(list)
        if preserve_path:
            for file in sources:
                dirname = os.path.dirname(file.fname)
                dirs[dirname].append(file)
        else:
            dirs[''].extend(sources)

        ret_data: list[build.Data] = []
        for childdir, files in dirs.items():
            d = build.Data(files, os.path.join(install_dir, childdir), os.path.join(install_dir_name, childdir),
                           install_mode, self.subproject, rename, tag, install_data_type,
                           follow_symlinks)
            ret_data.append(d)

        if not self.is_internal_machine(MachineChoice.HOST):
            self.build.data.extend(ret_data)
        return ret_data

    @typed_pos_args('install_subdir', str)
    @typed_kwargs(
        'install_subdir',
        KwargInfo('install_dir', str, required=True),
        KwargInfo('strip_directory', bool, default=False),
        KwargInfo('exclude_files', ContainerTypeInfo(list, str),
                  default=[], listify=True, since='0.42.0',
                  validator=lambda x: 'cannot be absolute' if any(path_has_root(d) for d in x) else None),
        KwargInfo('exclude_directories', ContainerTypeInfo(list, str),
                  default=[], listify=True, since='0.42.0',
                  validator=lambda x: 'cannot be absolute' if any(path_has_root(d) for d in x) else None),
        INSTALL_MODE_KW.evolve(since='0.38.0'),
        INSTALL_TAG_KW.evolve(since='0.60.0'),
        INSTALL_FOLLOW_SYMLINKS,
    )
    def func_install_subdir(self, node: mparser.BaseNode, args: T.Tuple[str],
                            kwargs: 'kwtypes.FuncInstallSubdir') -> build.InstallDir:
        exclude = (set(kwargs['exclude_files']), set(kwargs['exclude_directories']))

        srcdir = os.path.join(self.environment.source_dir, self.subdir, args[0])
        if not os.path.isdir(srcdir) or not any(os.listdir(srcdir)):
            FeatureNew.single_use('install_subdir with empty directory', '0.47.0', self.subproject, location=node)
            FeatureDeprecated.single_use('install_subdir with empty directory', '0.60.0', self.subproject,
                                         'It worked by accident and is buggy. Use install_emptydir instead.', node)
        install_mode = self._warn_kwarg_install_mode_sticky(kwargs['install_mode'])

        idir_name = kwargs['install_dir']
        if isinstance(idir_name, P_OBJ.OptionString):
            idir_name = idir_name.optname

        idir = build.InstallDir(
            self.subdir,
            args[0],
            kwargs['install_dir'],
            idir_name,
            install_mode,
            exclude,
            kwargs['strip_directory'],
            self.subproject,
            install_tag=kwargs['install_tag'],
            follow_symlinks=kwargs['follow_symlinks'])
        if not self.is_internal_machine(MachineChoice.HOST):
            self.build.install_dirs.append(idir)
        return idir

    def validate_build_subdir(self, build_subdir: str, target: str) -> None:
        if build_subdir and build_subdir != '.':
            if os.path.exists(os.path.join(self.source_root, self.subdir, build_subdir)):
                raise InvalidArguments(f'Build subdir "{build_subdir}" in "{target}" exists in source tree.')
            if '..' in build_subdir:
                raise InvalidArguments(f'Build subdir "{build_subdir}" in "{target}" contains ..')
            self.create_build_subdir(os.path.join(self.subdir, build_subdir))

    @noPosargs
    @typed_kwargs(
        'configure_file',
        DEPFILE_KW.evolve(since='0.52.0'),
        INSTALL_MODE_KW.evolve(since='0.47.0,'),
        INSTALL_TAG_KW.evolve(since='0.60.0'),
        KwargInfo('capture', bool, default=False, since='0.41.0'),
        KwargInfo(
            'command',
            (ContainerTypeInfo(list, (build.Executable, Program, compilers.Compiler, mesonlib.File, str), allow_empty=False), NoneType),
            listify=True,
        ),
        KwargInfo(
            'configuration',
            (ContainerTypeInfo(dict, (str, int, bool)), build.ConfigurationData, NoneType),
        ),
        KwargInfo(
            'copy', bool, default=False, since='0.47.0',
        ),
        KwargInfo('encoding', str, default='utf-8', since='0.47.0'),
        KwargInfo('format', str, default='meson', since='0.46.0',
                  validator=in_set_validator({'meson', 'cmake', 'cmake@'})),
        KwargInfo(
            'input',
            ContainerTypeInfo(list, (mesonlib.File, str)),
            listify=True,
            default=[],
        ),
        # Cannot use shared implementation until None backwards compat is dropped
        KwargInfo('install', (bool, NoneType), since='0.50.0'),
        KwargInfo('install_dir', (str, bool), default='',
                  validator=lambda x: 'must be `false` if boolean' if x is True else None),
        OUTPUT_KW,
        KwargInfo('output_format', str, default='c', since='0.47.0', since_values={'json': '1.3.0'},
                  validator=in_set_validator({'c', 'json', 'nasm'})),
        KwargInfo('macro_name', (str, NoneType), default=None, since='1.3.0'),
        KwargInfo('build_subdir', str, default='', since='1.10.0'),
    )
    @apply_machine_map
    def func_configure_file(self, node: mparser.BaseNode, args: T.List[TYPE_var],
                            kwargs: kwtypes.ConfigureFile) -> mesonlib.File:
        actions = sorted(x for x in ('configuration', 'command', 'copy')
                         if kwargs[x] not in [None, False])  # type: ignore[literal-required]
        num_actions = len(actions)
        if num_actions == 0:
            raise InterpreterException('Must specify an action with one of these '
                                       'keyword arguments: \'configuration\', '
                                       '\'command\', or \'copy\'.')
        elif num_actions == 2:
            raise InterpreterException('Must not specify both {!r} and {!r} '
                                       'keyword arguments since they are '
                                       'mutually exclusive.'.format(*actions))
        elif num_actions == 3:
            raise InterpreterException('Must specify one of {!r}, {!r}, and '
                                       '{!r} keyword arguments since they are '
                                       'mutually exclusive.'.format(*actions))

        if kwargs['capture'] and not kwargs['command']:
            raise InvalidArguments('configure_file: "capture" keyword requires "command" keyword.')

        install_mode = self._warn_kwarg_install_mode_sticky(kwargs['install_mode'])

        fmt = kwargs['format']
        output_format = kwargs['output_format']
        depfile = kwargs['depfile']

        # Validate input
        inputs = self.source_strings_to_files(kwargs['input'])
        inputs_abs = []
        for f in inputs:
            if isinstance(f, mesonlib.File):
                inputs_abs.append(f.absolute_path(self.environment.source_dir,
                                                  self.environment.build_dir))
                self.add_build_def_file(f)
            else:
                raise InterpreterException('Inputs can only be strings or file objects')

        # Validate output
        output = kwargs['output']
        if inputs_abs:
            values = mesonlib.get_filenames_templates_dict(inputs_abs, None)
            outputs = mesonlib.substitute_values([output], values)
            output = outputs[0]
            if depfile:
                depfile = mesonlib.substitute_values([depfile], values)[0]

        # Validate build_subdir
        build_subdir = kwargs['build_subdir']
        self.validate_build_subdir(build_subdir, output)

        ofile_rpath = os.path.join(self.subdir, build_subdir, output)
        if ofile_rpath in self.configure_file_outputs:
            mesonbuildfile = os.path.join(self.subdir, 'meson.build')
            current_call = f"{mesonbuildfile}:{self.current_node.lineno}"
            first_call = "{}:{}".format(mesonbuildfile, self.configure_file_outputs[ofile_rpath])
            mlog.warning('Output file', mlog.bold(ofile_rpath, True), 'for configure_file() at', current_call, 'overwrites configure_file() output at', first_call)
        else:
            self.configure_file_outputs[ofile_rpath] = self.current_node.lineno

        ofile_path, ofile_fname = os.path.split(ofile_rpath)
        ofile_abs = os.path.join(self.environment.build_dir, ofile_rpath)
        os.makedirs(os.path.split(ofile_abs)[0], exist_ok=True)

        # Perform the appropriate action
        if kwargs['configuration'] is not None:
            conf = kwargs['configuration']
            if isinstance(conf, dict):
                FeatureNew.single_use('configure_file.configuration dictionary', '0.49.0', self.subproject, location=node)
                for k, v in conf.items():
                    if not isinstance(v, (str, int, bool)):
                        raise InvalidArguments(
                            f'"configuration_data": initial value dictionary key "{k!r}"" must be "str | int | bool", not "{v!r}"')
                conf = build.ConfigurationData(conf)
            mlog.log('Configuring', mlog.bold(os.path.join(build_subdir, output)), 'using configuration')
            if len(inputs) > 1:
                raise InterpreterException('At most one input file can given in configuration mode')
            if inputs:
                file_encoding = kwargs['encoding']
                missing_variables, confdata_useless = \
                    mesonlib.do_conf_file(inputs_abs[0], ofile_abs, conf,
                                          fmt, file_encoding, self.subproject)
                if missing_variables:
                    var_list = ", ".join(repr(m) for m in sorted(missing_variables))
                    mlog.warning(
                        f"The variable(s) {var_list} in the input file '{inputs[0]}' are not "
                        "present in the given configuration data.", location=node)
                if confdata_useless:
                    ifbase = os.path.basename(inputs_abs[0])
                    tv = FeatureNew.get_target_version(self.subproject)
                    if FeatureNew.check_version(tv, '0.47'):
                        mlog.warning('Got an empty configuration_data() object and found no '
                                     f'substitutions in the input file {ifbase!r}. If you want to '
                                     'copy a file to the build dir, use the \'copy:\' keyword '
                                     'argument added in 0.47.0', location=node)
            else:
                macro_name = kwargs['macro_name']
                mesonlib.dump_conf_header(ofile_abs, conf, output_format, macro_name)
            conf.used = True
        elif kwargs['command'] is not None:
            if len(inputs) > 1:
                FeatureNew.single_use('multiple inputs in configure_file()', '0.52.0', self.subproject, location=node)
            # We use absolute paths for input and output here because the cwd
            # that the command is run from is 'unspecified', so it could change.
            # Currently it's builddir/subdir for in_builddir else srcdir/subdir.
            values = mesonlib.get_filenames_templates_dict(inputs_abs, [ofile_abs])
            if depfile:
                depfile = os.path.join(self.environment.get_scratch_dir(), depfile)
                values['@DEPFILE@'] = depfile
            # Substitute @INPUT@, @OUTPUT@, etc here.
            _cmd = mesonlib.substitute_values(kwargs['command'], values)
            mlog.log('Configuring', mlog.bold(output), 'with command')
            cmd, *_args = _cmd
            res = self.run_command_impl((cmd, _args),
                                        {'capture': True,
                                         'console': False,
                                         'check': True,
                                         'env': mesonlib.EnvironmentVariables()},
                                        True)
            if kwargs['capture']:
                dst_tmp = ofile_abs + '~'
                file_encoding = kwargs['encoding']
                with open(dst_tmp, 'w', encoding=file_encoding) as f:
                    f.writelines(res.stdout)
                if inputs_abs:
                    shutil.copymode(inputs_abs[0], dst_tmp)
                mesonlib.replace_if_different(ofile_abs, dst_tmp)
            if depfile:
                mlog.log('Reading depfile:', mlog.bold(depfile))
                with open(depfile, encoding='utf-8') as f:
                    df = DepFile(f.readlines())
                    deps = df.get_all_dependencies(ofile_fname)
                    for dep in deps:
                        self.add_build_def_file(dep)

        elif kwargs['copy']:
            if len(inputs_abs) != 1:
                raise InterpreterException('Exactly one input file must be given in copy mode')
            self.create_build_subdir(self.subdir)
            shutil.copy2(inputs_abs[0], ofile_abs)

        # Install file if requested, we check for the empty string
        # for backwards compatibility. That was the behaviour before
        # 0.45.0 so preserve it.
        idir = kwargs['install_dir']
        if idir is False:
            idir = ''
            FeatureDeprecated.single_use('configure_file install_dir: false', '0.50.0',
                                         self.subproject, 'Use the `install:` kwarg instead', location=node)
        install = kwargs['install'] if kwargs['install'] is not None else idir != ''
        if install:
            if not idir:
                raise InterpreterException(
                    '"install_dir" must be specified when "install" in a configure_file is true')
            idir_name = idir
            if isinstance(idir_name, P_OBJ.OptionString):
                idir_name = idir_name.optname
            cfile = mesonlib.File.from_built_file(ofile_path, ofile_fname)
            install_tag = kwargs['install_tag']
            self.build.data.append(build.Data([cfile], idir, idir_name, install_mode, self.subproject,
                                              install_tag=install_tag, data_type='configure'))
        return mesonlib.File.from_built_file(self.subdir, output)

    def extract_incdirs(self, prospectives: T.List[T.Union[str, build.IncludeDirs]],
                        is_d_import_dirs: bool = False
                        ) -> T.List[build.IncludeDirs]:
        result: T.List[build.IncludeDirs] = []
        for p in prospectives:
            if isinstance(p, build.IncludeDirs):
                result.append(p)
            else:
                if is_d_import_dirs and os.path.normpath(p).startswith(self.environment.get_source_dir()):
                    FeatureDeprecated.single_use('Building absolute path to source dir is not supported',
                                                 '0.45', self.subproject,
                                                 'Use a relative path instead.',
                                                 location=self.current_node)
                    p = os.path.relpath(p, os.path.join(self.environment.get_source_dir(), self.subdir))
                result.append(self.build_incdir_object([p]))
        return result

    @typed_pos_args('include_directories', varargs=str)
    @typed_kwargs('include_directories', KwargInfo('is_system', bool, default=False))
    def func_include_directories(self, node: mparser.BaseNode, args: T.Tuple[T.List[str]],
                                 kwargs: 'kwtypes.FuncIncludeDirectories') -> build.IncludeDirs:
        return self.build_incdir_object(args[0], kwargs['is_system'])

    def build_incdir_object(self, incdir_strings: T.List[str], is_system: bool = False) -> build.IncludeDirs:
        if not isinstance(is_system, bool):
            raise InvalidArguments('Is_system must be boolean.')
        src_root = self.environment.get_source_dir()
        build_root = self.environment.get_build_dir()
        absbase_src = os.path.join(src_root, self.subdir)
        absbase_build = os.path.join(build_root, self.subdir)

        for a in incdir_strings:
            if path_is_in_root(Path(a), Path(src_root)):
                raise InvalidArguments(textwrap.dedent('''\
                    Tried to form an absolute path to a dir in the source tree.
                    You should not do that but use relative paths instead, for
                    directories that are part of your project.

                    To get include path to any directory relative to the current dir do

                    incdir = include_directories(dirname)

                    After this incdir will contain both the current source dir as well as the
                    corresponding build dir. It can then be used in any subdirectory and
                    Meson will take care of all the busywork to make paths work.

                    Dirname can even be '.' to mark the current directory. Though you should
                    remember that the current source and build directories are always
                    put in the include directories by default so you only need to do
                    include_directories('.') if you intend to use the result in a
                    different subdirectory.

                    Note that this error message can also be triggered by
                    external dependencies being installed within your source
                    tree - it's not recommended to do this.
                    '''))
            else:
                try:
                    self.validate_within_subproject(self.subdir, a)
                except InterpreterException:
                    mlog.warning('include_directories sandbox violation!', location=self.current_node)
                    print(textwrap.dedent(f'''\
                        The project is trying to access the directory {a!r} which belongs to a different
                        subproject. This is a problem as it hardcodes the relative paths of these two projects.
                        This makes it impossible to compile the project in any other directory layout and also
                        prevents the subproject from changing its own directory layout.

                        Instead of poking directly at the internals the subproject should be executed and
                        it should set a variable that the caller can then use. Something like:

                        # In subproject
                        some_dep = declare_dependency(include_directories: include_directories('include'))

                        # In subproject wrap file
                        [provide]
                        some = some_dep

                        # In parent project
                        some_dep = dependency('some')
                        executable(..., dependencies: [some_dep])

                        This warning will become a hard error in a future Meson release.
                        '''))
            absdir_src = os.path.join(absbase_src, a)
            absdir_build = os.path.join(absbase_build, a)
            if not os.path.isdir(absdir_src) and not os.path.isdir(absdir_build):
                raise InvalidArguments(f'Include dir {a} does not exist.')
        i = build.IncludeDirs(self.subdir, incdir_strings, is_system, self.current_build_project())
        return i

    @typed_pos_args('add_test_setup', str)
    @typed_kwargs(
        'add_test_setup',
        KwargInfo('exe_wrapper', ContainerTypeInfo(list, (str, ExternalProgram)), listify=True, default=[]),
        KwargInfo('gdb', bool, default=False),
        KwargInfo('timeout_multiplier', int, default=1),
        KwargInfo('exclude_suites', ContainerTypeInfo(list, str), listify=True, default=[], since='0.57.0'),
        KwargInfo('is_default', bool, default=False, since='0.49.0'),
        ENV_KW,
    )
    def func_add_test_setup(self, node: mparser.BaseNode, args: T.Tuple[str], kwargs: 'kwtypes.AddTestSetup') -> None:
        setup_name = args[0]
        if re.fullmatch('([_a-zA-Z][_0-9a-zA-Z]*:)?[_a-zA-Z][_0-9a-zA-Z]*', setup_name) is None:
            raise InterpreterException('Setup name may only contain alphanumeric characters.')
        if ":" not in setup_name:
            setup_name = f'{(self.subproject if self.subproject else self.build.project_name)}:{setup_name}'

        exe_wrapper: T.List[str] = []
        for i in kwargs['exe_wrapper']:
            if isinstance(i, str):
                exe_wrapper.append(i)
            else:
                if not i.found():
                    raise InterpreterException('Tried to use non-found executable.')
                exe_wrapper += i.get_command()

        timeout_multiplier = kwargs['timeout_multiplier']
        if timeout_multiplier <= 0:
            FeatureNew('add_test_setup() timeout_multiplier <= 0', '0.57.0').use(self.subproject)

        if kwargs['is_default']:
            if self.build.test_setup_default_name is not None:
                raise InterpreterException(f'{self.build.test_setup_default_name!r} is already set as default. '
                                           'is_default can be set to true only once')
            self.build.test_setup_default_name = setup_name
        self.build.test_setups[setup_name] = build.TestSetup(exe_wrapper, kwargs['gdb'], timeout_multiplier, kwargs['env'],
                                                             kwargs['exclude_suites'])

    @typed_pos_args('add_global_arguments', varargs=str)
    @typed_kwargs('add_global_arguments', NATIVE_KW, LANGUAGE_KW)
    @apply_machine_map
    def func_add_global_arguments(self, node: mparser.FunctionNode, args: T.Tuple[T.List[str]], kwargs: 'kwtypes.FuncAddProjectArgs') -> None:
        self._add_global_arguments(node, self.build.global_args[kwargs['native']], args[0], kwargs)

    @typed_pos_args('add_global_link_arguments', varargs=str)
    @typed_kwargs('add_global_link_arguments', NATIVE_KW, LANGUAGE_KW)
    @apply_machine_map
    def func_add_global_link_arguments(self, node: mparser.FunctionNode, args: T.Tuple[T.List[str]], kwargs: 'kwtypes.FuncAddProjectArgs') -> None:
        self._add_global_arguments(node, self.build.global_link_args[kwargs['native']], args[0], kwargs)

    @typed_pos_args('add_project_arguments', varargs=str)
    @typed_kwargs('add_project_arguments', NATIVE_KW, LANGUAGE_KW)
    @apply_machine_map
    def func_add_project_arguments(self, node: mparser.FunctionNode, args: T.Tuple[T.List[str]], kwargs: 'kwtypes.FuncAddProjectArgs') -> None:
        self._add_project_arguments(node, self.current_build_project().project_args[kwargs['native']],
                                    args[0], kwargs)

    @typed_pos_args('add_project_link_arguments', varargs=str)
    @typed_kwargs('add_project_link_arguments', NATIVE_KW, LANGUAGE_KW)
    @apply_machine_map
    def func_add_project_link_arguments(self, node: mparser.FunctionNode, args: T.Tuple[T.List[str]], kwargs: 'kwtypes.FuncAddProjectArgs') -> None:
        self._add_project_arguments(node, self.current_build_project().project_link_args[kwargs['native']],
                                    args[0], kwargs)

    def current_build_project(self) -> build.BuildProject:
        for_machine = self.build.machine_map.host
        return self.build.projects[for_machine][self.subproject]

    @FeatureNew('add_project_dependencies', '0.63.0')
    @typed_pos_args('add_project_dependencies', varargs=dependencies.Dependency)
    @typed_kwargs('add_project_dependencies', NATIVE_KW, LANGUAGE_KW)
    @apply_machine_map
    def func_add_project_dependencies(self, node: mparser.FunctionNode, args: T.Tuple[T.List[dependencies.Dependency]], kwargs: 'kwtypes.FuncAddProjectArgs') -> None:
        for_machine = kwargs['native']
        for lang in kwargs['language']:
            if lang not in self.compilers[for_machine]:
                raise InvalidCode(f'add_project_dependencies() called before add_language() for language "{lang}"')

        for d in dependencies.get_leaf_external_dependencies(args[0]):
            compile_args = list(d.get_compile_args())
            system_incdir = d.get_include_type() == 'system'
            for i in d.get_include_dirs():
                for lang in kwargs['language']:
                    comp = self.coredata.compilers[for_machine][lang]
                    for idir in i.abs_string_list(self.environment.get_source_dir(), self.environment.get_build_dir()):
                        compile_args.extend(comp.get_include_args(idir, system_incdir))

            self._add_project_arguments(node, self.current_build_project().project_args[for_machine],
                                        compile_args, kwargs)
            self._add_project_arguments(node, self.current_build_project().project_link_args[for_machine],
                                        d.get_link_args(), kwargs)

    def _warn_about_builtin_args(self, args: T.List[str]) -> None:
        # -Wpedantic is deliberately not included, since some people want to use it but not use -Wextra
        # see e.g.
        # https://github.com/mesonbuild/meson/issues/3275#issuecomment-641354956
        # https://github.com/mesonbuild/meson/issues/3742
        warnargs = ('/W1', '/W2', '/W3', '/W4', '/Wall', '-Wall', '-Wextra')
        optargs = ('-O0', '-O2', '-O3', '-Os', '-Oz', '/O1', '/O2', '/Os')
        for arg in args:
            if arg in warnargs:
                mlog.warning(f'Consider using the built-in warning_level option instead of using "{arg}".',
                             location=self.current_node)
            elif arg in optargs:
                mlog.warning(f'Consider using the built-in optimization level instead of using "{arg}".',
                             location=self.current_node)
            elif arg == '-Werror':
                mlog.warning(f'Consider using the built-in werror option instead of using "{arg}".',
                             location=self.current_node)
            elif arg == '-g':
                mlog.warning(f'Consider using the built-in debug option instead of using "{arg}".',
                             location=self.current_node)
            # Don't catch things like `-fsanitize-recover`
            elif arg in {'-fsanitize', '/fsanitize'} or arg.startswith(('-fsanitize=', '/fsanitize=')):
                mlog.warning(f'Consider using the built-in option for sanitizers instead of using "{arg}".',
                             location=self.current_node)
            elif arg.startswith('-std=') or arg.startswith('/std:'):
                mlog.warning(f'Consider using the built-in option for language standard version instead of using "{arg}".',
                             location=self.current_node)

    def _add_global_arguments(self, node: mparser.FunctionNode, argsdict: T.Dict[Language, T.List[str]],
                              args: T.List[str], kwargs: 'kwtypes.FuncAddProjectArgs') -> None:
        if self.is_subproject():
            msg = f'Function \'{node.func_name.value}\' cannot be used in subprojects because ' \
                  'there is no way to make that reliable.\nPlease only call ' \
                  'this if is_subproject() returns false. Alternatively, ' \
                  'define a variable that\ncontains your language-specific ' \
                  'arguments and add it to the appropriate *_args kwarg ' \
                  'in each target.'
            raise InvalidCode(msg)
        frozen = self.project_args_frozen or self.global_args_frozen
        self._add_arguments(node, argsdict, frozen, args, kwargs)

    def _add_project_arguments(self, node: mparser.FunctionNode, argsdict: T.Dict[Language, T.List[str]],
                               args: T.List[str], kwargs: 'kwtypes.FuncAddProjectArgs') -> None:
        self._add_arguments(node, argsdict, self.project_args_frozen, args, kwargs)

    def is_dup_machine(self, for_machine: MachineChoice) -> bool:
        # Return whether applying the caller's effect to the build and
        # host machine would duplicate the effect
        return \
            for_machine is not MachineChoice.HOST and \
            self.build.machine_map[for_machine] is self.build.machine_map.host

    def _add_arguments(self, node: mparser.FunctionNode, argsdict: T.Dict[Language, T.List[str]],
                       args_frozen: bool, args: T.List[str], kwargs: 'kwtypes.FuncAddProjectArgs') -> None:
        if self.is_dup_machine(kwargs['native']):
            return

        if args_frozen:
            msg = f'Tried to use \'{node.func_name.value}\' after a build target has been declared.\n' \
                  'This is not permitted. Please declare all arguments before your targets.'
            raise InvalidCode(msg)

        self._warn_about_builtin_args(args)

        for lang in kwargs['language']:
            argsdict[lang] = argsdict.get(lang, []) + args

    @noArgsFlattening
    @typed_pos_args('environment', optargs=[(str, list, dict)])
    @typed_kwargs('environment', ENV_METHOD_KW, ENV_SEPARATOR_KW.evolve(since='0.62.0'))
    def func_environment(self, node: mparser.FunctionNode, args: T.Tuple[T.Union[None, str, T.List['TYPE_var'], T.Dict[str, 'TYPE_var']]],
                         kwargs: kwtypes.FuncEnvironment) -> EnvironmentVariables:
        init = args[0]
        if init is not None:
            FeatureNew.single_use('environment positional arguments', '0.52.0', self.subproject, location=node)
            msg = ENV_KW.validator(init)
            if msg:
                raise InvalidArguments(f'"environment": {msg}')
            if isinstance(init, dict) and any(i for i in init.values() if isinstance(i, list)):
                FeatureNew.single_use('List of string in dictionary value', '0.62.0', self.subproject, location=node)
            # the validator call above ensured that we have the correct type
            return env_convertor_with_method(T.cast('FullEnvInitValueType', init), kwargs['method'], kwargs['separator'])
        return EnvironmentVariables()

    @typed_pos_args('join_paths', varargs=str, min_varargs=1)
    @noKwargs
    def func_join_paths(self, node: mparser.BaseNode, args: T.Tuple[T.List[str]], kwargs: 'TYPE_kwargs') -> str:
        parts = args[0]
        other = os.path.join('', *parts[1:]).replace('\\', '/')
        ret = os.path.join(*parts).replace('\\', '/')
        if isinstance(parts[0], P_OBJ.DependencyVariableString) and '..' not in other:
            return P_OBJ.DependencyVariableString(ret)
        elif isinstance(parts[0], P_OBJ.OptionString):
            name = os.path.join(parts[0].optname, other)
            return P_OBJ.OptionString(ret, name)
        else:
            return ret

    def run(self) -> None:
        super().run()
        mlog.log('Build targets in project:', mlog.bold(str(len(self.build.targets))))
        FeatureNew.report(self.subproject)
        FeatureDeprecated.report(self.subproject)
        FeatureBroken.report(self.subproject)
        if not self.is_subproject():
            self.print_extra_warnings()
            self._print_summary()

    def print_extra_warnings(self) -> None:
        # TODO cross compilation
        for c in self.coredata.compilers.host.values():
            if c.get_id() == 'clang':
                self.check_clang_asan_lundef()
                break

    def check_clang_asan_lundef(self) -> None:
        if OptionKey('b_lundef') not in self.coredata.optstore:
            return
        if OptionKey('b_sanitize') not in self.coredata.optstore:
            return
        if (self.coredata.optstore.get_value_for('b_lundef') and
                self.coredata.optstore.get_value_for('b_sanitize')):
            value = self.coredata.optstore.get_value_for('b_sanitize')
            assert isinstance(value, list), 'for mypy'
            mlog.warning(textwrap.dedent(f'''\
                    Trying to use {value} sanitizer on Clang with b_lundef.
                    This will probably not work.
                    Try setting b_lundef to false instead.'''),
                location=self.current_node)  # noqa: E128

    # Check that the indicated file is within the same subproject
    # as we currently are. This is to stop people doing
    # nasty things like:
    #
    # f = files('../../master_src/file.c')
    #
    # Note that this is validated only when the file
    # object is generated. The result can be used in a different
    # subproject than it is defined in (due to e.g. a
    # declare_dependency).
    def validate_within_subproject(self, subdir: str, fname: str) -> None:
        srcdir = self.environment.source_dir
        builddir = self.environment.build_dir
        if isinstance(fname, P_OBJ.DependencyVariableString):
            def validate_installable_file(fpath: Path) -> bool:
                installablefiles: T.Set[Path] = set()
                for d in self.build.data:
                    for s in d.sources:
                        installablefiles.add(Path(s.absolute_path(srcdir, builddir)))
                installabledirs = [str(Path(srcdir, s.source_subdir)) for s in self.build.install_dirs]
                if fpath in installablefiles:
                    return True
                for d in installabledirs:
                    if str(fpath).startswith(d):
                        return True
                return False

            norm = Path(fname)
            # variables built from a dep.get_variable are allowed to refer to
            # subproject files, as long as they are scheduled to be installed.
            if validate_installable_file(norm):
                return

        def do_validate_within_subproject(norm: str) -> None:
            if os.path.isdir(norm):
                inputtype = 'directory'
            else:
                inputtype = 'file'
            if is_parent_path(builddir, norm):
                raise BuiltFileByNameError(fname)

            if not is_parent_path(srcdir, norm):
                # Grabbing files outside the source tree is ok.
                # This is for vendor stuff like:
                #
                # /opt/vendorsdk/src/file_with_license_restrictions.c
                return

            project_root = os.path.join(srcdir, self.root_subdir)
            if not is_parent_path(project_root, norm):
                name = os.path.basename(norm)
                raise SandboxViolationError(inputtype, name, subproject=False)

            subproject_dir = os.path.join(project_root, self.subproject_dir)
            if is_parent_path(subproject_dir, norm):
                name = os.path.basename(norm)
                raise SandboxViolationError(inputtype, name)

        fname = os.path.join(subdir, fname)
        if fname in self.validated_cache:
            return

        norm = os.path.abspath(os.path.join(srcdir, fname))
        do_validate_within_subproject(norm)
        self.validated_cache.add(fname)

    @T.overload
    def source_strings_to_files(self, sources: list[str]) -> list[mesonlib.File]: ...

    @T.overload
    def source_strings_to_files(self, sources: list['mesonlib.FileOrString']) -> list['mesonlib.File']: ...

    @T.overload
    def source_strings_to_files(self, sources: list[T.Union[mesonlib.FileOrString, build.CustomTarget, build.CustomTargetIndex]]) -> list[T.Union[mesonlib.File, build.CustomTarget, build.CustomTargetIndex]]: ...

    @T.overload
    def source_strings_to_files(self, sources: list[T.Union[mesonlib.FileOrString, build.BuildTargetTypes]]) -> list[T.Union[mesonlib.File, build.BuildTargetTypes]]: ...  # type: ignore[overload-overlap]

    @T.overload
    def source_strings_to_files(self, sources: list[T.Union[str, build.TargetSources]]) -> list[build.TargetSources]: ...

    @T.overload
    def source_strings_to_files(self, sources: list[kwtypes.CustomTargetInputs]) -> list['CustomTargetSources']: ...  # type: ignore[overload-overlap]

    @T.overload
    def source_strings_to_files(self, sources: list[kwtypes.BuildTargetObjects],  # type: ignore[overload-overlap]
                                ) -> list[T.Union[build.ObjectTypes, build.GeneratedTypes]]: ...

    @T.overload
    def source_strings_to_files(self, sources: list[T.Union[str, build.TargetSources, build.BuildTargetTypes, build.BothLibraries, build.ExtractedObjects]],  # type: ignore[overload-overlap]
                                ) -> list[T.Union[build.TargetSources, build.BuildTargetTypes, build.BothLibraries, build.ExtractedObjects]]: ...

    @T.overload
    def source_strings_to_files(self, sources: list[T.Union[str, build.TargetSources, build.StructuredSources]],
                                ) -> list[T.Union[build.TargetSources, build.StructuredSources]]: ... # noqa: F811

    @T.overload
    def source_strings_to_files(self, sources: list[SourcesVarargsType]) -> list['SourceOutputs']: ...

    @T.overload
    def source_strings_to_files(self, sources: list['SourceInputs']) -> list['SourceOutputs']: ...  # type: ignore[overload-cannot-match]

    def source_strings_to_files(self,
                                sources: T.Union[
                                    list[str],
                                    list[mesonlib.File | str],
                                    list[mesonlib.File | str | build.CustomTarget | build.CustomTargetIndex],
                                    list[mesonlib.File | str | build.BuildTargetTypes],
                                    list[str | build.TargetSources],
                                    list[str | build.TargetSources | build.StructuredSources],
                                    list[kwtypes.CustomTargetInputs],
                                    list[mesonlib.File | str | build.BuildTargetTypes | build.BothLibraries | build.ExtractedObjects | build.GeneratedTypes],
                                    list[kwtypes.BuildTargetObjects],
                                    list[SourceInputs],
                                    list[SourcesVarargsType],
                                ]
                                ) -> T.Union[list[mesonlib.File],
                                             list[mesonlib.File | build.BuildTargetTypes],
                                             list[mesonlib.File | build.CustomTarget | build.CustomTargetIndex],
                                             list[build.TargetSources],
                                             list[build.TargetSources | build.StructuredSources],
                                             list[mesonlib.File | build.BuildTargetTypes | build.BothLibraries | build.ExtractedObjects | build.GeneratedTypes],
                                             list[build.ObjectTypes | build.GeneratedTypes],
                                             list[CustomTargetSources],
                                             list[SourceOutputs]]:
        """Lower inputs to a list of Targets and Files, replacing any strings.

        :param sources: A raw (Meson DSL) list of inputs (targets, files, and
            strings)
        :raises InterpreterException: if any of the inputs are of an invalid type
        :return: A list of Targets and Files
        """
        mesonlib.check_direntry_issues(sources)
        results: list[build.TargetSources | build.BuildTarget | build.ExtractedObjects | build.StructuredSources | Program] = []

        for s in sources:
            if isinstance(s, str):
                if s.endswith(' '):
                    raise MesonException(f'{s!r} ends with a space. This is probably an error.')
                try:
                    self.validate_within_subproject(self.subdir, s)
                except BuiltFileByNameError as e:
                    # In Meson 2.0 this should just raise
                    if InterpreterRuleRelaxation.ALLOW_BUILD_DIR_FILE_REFERENCES not in self.relaxations:
                        #raise
                        mlog.warning(str(e), location=self.current_node)
                    if path_has_root(s):
                        # A built File's name must be relative to the build
                        # root, otherwise the absolute fname leaks through
                        # File.relative_name() and breaks the backend.
                        # Use join and relpath together to handle paths without
                        # the drive part.
                        rel = os.path.relpath(os.path.join(self.environment.build_dir, s),
                                              self.environment.build_dir)
                        results.append(mesonlib.File.from_built_relative(rel))
                    else:
                        results.append(mesonlib.File.from_built_file(self.subdir, s))
                else:
                    results.append(mesonlib.File.from_source_file(self.environment.source_dir, self.subdir, s))
            elif isinstance(s, (mesonlib.File, build.GeneratedList, Program,
                                build.BuildTarget, build.CustomTargetIndex, build.CustomTarget,
                                build.ExtractedObjects, build.StructuredSources)):
                results.append(s)
            else:
                raise InterpreterException(f'Source item is {s!r} instead of '
                                           'string or File-type object')
        return results  # type: ignore[return-value]

    def source_string_to_file(self, source: str | mesonlib.File | build.CustomTarget | build.CustomTargetIndex | None) -> mesonlib.File | build.CustomTarget | build.CustomTargetIndex:
        if source is None:
            return None
        return self.source_strings_to_files([source])[0]

    def validate_forbidden_targets(self, name: str, in_root: bool) -> None:
        if name.startswith('meson-internal__'):
            raise InvalidArguments("Target names starting with 'meson-internal__' are reserved "
                                   "for Meson's internal use. Please rename.")
        if name.startswith('meson-') and '.' not in name:
            raise InvalidArguments("Target names starting with 'meson-' and without a file extension "
                                   "are reserved for Meson's internal use. Please rename.")
        if name in coredata.FORBIDDEN_TARGET_NAMES:
            if in_root:
                raise InvalidArguments(f"Target name '{name}' is reserved for Meson's "
                                       "internal use. Please rename.")
            else:
                FeatureNew.single_use(f"Target name '{name}' reserved in the root build directory, but allowed in subdirectories",
                                      '1.12.0', self.subproject, location=self.current_node)

    def add_target(self, name: str, tobj: build.Target) -> None:
        if self.backend.name == 'none':
            raise InterpreterException('Install-only backend cannot generate target rules, try using `--backend=ninja`.')
        if name == '':
            raise InterpreterException('Target name must not be empty.')
        if name.strip() == '':
            raise InterpreterException('Target name must not consist only of whitespace.')
        if has_path_sep(name):
            pathseg = os.path.join(self.subdir, os.path.split(name)[0])
            if os.path.exists(os.path.join(self.source_root, pathseg)):
                raise InvalidArguments(textwrap.dedent(f'''\
                    Target "{name}" has a path segment pointing to directory "{pathseg}". This is an error.
                    To define a target that builds in that directory you must define it
                    in the meson.build file in that directory.
            '''))

        # Make sure build_subdir doesn't exist in the source tree and
        # doesn't contain ..
        build_subdir = tobj.get_build_subdir()
        self.validate_build_subdir(build_subdir, name)

        subdir = tobj.get_builddir()
        self.validate_forbidden_targets(name, not subdir)

        # To permit an executable and a shared library to have the
        # same name, such as "foo.exe" and "libfoo.a".
        idname = tobj.get_id()
        namedir = (name, subdir)

        if idname in self.build.targets:
            raise InvalidCode(f'Tried to create target "{name}", but a target of that name already exists.')

        if isinstance(tobj, build.Executable) and namedir in self.build.targetnames:
            FeatureNew.single_use(f'multiple executables with the same name, "{tobj.name}", but different suffixes in the same directory',
                                  '1.3.0', self.subproject, location=self.current_node)

        if isinstance(tobj, build.BuildTarget):
            # add_languages mutates the `args` parameter, so we need to copy here
            self.add_languages(tobj.missing_languages.copy(), True, tobj.for_machine)
            tobj.process_compilers_late()
            self.add_stdlib_info(tobj)

        self.build.targets[idname] = tobj
        # Only need to add executables to this set
        if isinstance(tobj, build.Executable):
            self.build.targetnames.update([namedir])
        if idname not in self.coredata.target_guids:
            self.coredata.target_guids[idname] = str(uuid.uuid4()).upper()

    @FeatureNew('both_libraries', '0.46.0')
    def build_both_libraries(self, node: mparser.BaseNode, args: T.Tuple[str, SourcesVarargsType], kwargs: kwtypes.Library) -> build.BothLibraries:
        shared_lib = self.build_target(node, args, kwargs, build.SharedLibrary, shared_library_only=False)
        static_lib = self.build_target(node, args, kwargs, build.StaticLibrary)
        preferred_library = self.coredata.optstore.get_value_for(OptionKey('default_both_libraries', subproject=self.subproject))
        assert isinstance(preferred_library, str), 'for mypy'
        if preferred_library == 'auto':
            preferred_library = self.coredata.optstore.get_value_for(OptionKey('default_library', subproject=self.subproject))
            assert isinstance(preferred_library, str), 'for mypy'
            if preferred_library == 'both':
                preferred_library = 'shared'
        assert preferred_library in {'shared', 'static'}
        preferred_library = T.cast('Literal["static", "shared"]', preferred_library)

        if self.backend.name == 'xcode':
            # Xcode is a bit special in that you can't (at least for the moment)
            # form a library only from object file inputs. The simple but inefficient
            # solution is to use the sources directly. This will lead to them being
            # built twice. This is unfortunate and slow, but at least it works.
            # Feel free to submit patches to get this fixed if it is an
            # issue for you.
            reuse_object_files = False
        elif shared_lib.uses_rust():
            # FIXME: rustc supports generating both libraries in a single invocation,
            # but for now compile twice.
            reuse_object_files = False
        elif any(k.endswith(('static_args', 'shared_args')) and v for k, v in kwargs.items()):
            # Ensure not just the keyword arguments exist, but that they are non-empty.
            reuse_object_files = False
        else:
            reuse_object_files = static_lib.pic

        if reuse_object_files:
            # Replace sources with objects from the shared library to avoid
            # building them twice. We post-process the static library instead of
            # removing sources from args because sources could also come from
            # any InternalDependency, see BuildTarget.add_deps().
            static_lib.objects.append(build.ExtractedObjects(shared_lib, shared_lib.sources, shared_lib.generated, []))
            static_lib.sources = []
            static_lib.generated = []
            # Compilers with no corresponding sources confuses the backend.
            # Keep only compilers used for linking
            static_lib.compilers = {k: v for k, v in static_lib.compilers.items() if k in compilers.clink_langs}

        # Cross reference them to implement as_shared() and as_static() methods.
        shared_lib.set_static(static_lib)
        static_lib.set_shared(shared_lib)

        return build.BothLibraries(shared_lib, static_lib, preferred_library)

    def build_library(self, node: mparser.BaseNode, args: T.Tuple[str, SourcesVarargsType], kwargs: kwtypes.Library) -> build.SharedLibrary | build.BothLibraries | build.StaticLibrary:
        default_library = self.coredata.optstore.get_value_for(OptionKey('default_library', subproject=self.subproject))
        assert isinstance(default_library, str), 'for mypy'
        if default_library == 'shared':
            # Intentionally pass shared_library_only=False so that dependencies
            # end up in Requires.private.  Many libraries that refer to their
            # dependencies' in their headers expect this so that those dependencies
            # are added to the output of 'pkgconfig --cflags'.
            return self.build_target(node, args, T.cast('kwtypes.SharedLibrary', kwargs), build.SharedLibrary, shared_library_only=False)
        elif default_library == 'static':
            return self.build_target(node, args, T.cast('kwtypes.StaticLibrary', kwargs), build.StaticLibrary)
        elif default_library == 'both':
            return self.build_both_libraries(node, args, kwargs)
        else:
            raise InterpreterException(f'Unknown default_library value: {default_library}.')

    def __convert_file_args(self, raw: T.List[mesonlib.FileOrString]) -> T.Tuple[T.List[mesonlib.File], T.List[str]]:
        """Convert raw target arguments from File | str to File.

        This removes files from the command line and replaces them with string
        values, but adds the files to depends list

        :param raw: the raw arguments
        :return: A tuple of file dependencies and raw arguments
        """
        depend_files: T.List[mesonlib.File] = []
        args: T.List[str] = []
        build_to_source = mesonlib.relpath(self.environment.get_source_dir(),
                                           self.environment.get_build_dir())

        for a in raw:
            if isinstance(a, mesonlib.File):
                depend_files.append(a)
                args.append(a.rel_to_builddir(build_to_source))
            else:
                args.append(a)

        return depend_files, args

    def __process_language_args(self, kwargs: kwtypes.BaseBuildTarget,
                                ) -> T.Tuple[T.DefaultDict[Language, T.List[str]], T.List[mesonlib.File]]:
        """Convert split language args into a combined dictionary.

        The Meson DSL takes arguments in the form `<lang>_args : args`, but in the
        build layer we store these in a single dictionary as `{<lang>: args}`.
        This function extracts the arguments from the DSL format and prepares
        them for the IR.
        """
        deps: T.List[mesonlib.File] = []
        new_args: T.DefaultDict[Language, T.List[str]] = collections.defaultdict(list)

        for l in compilers.all_languages:
            deps, args = self.__convert_file_args(kwargs[f'{l}_args'])  # type: ignore[literal-required]
            new_args[l] = args
            deps.extend(deps)
        return new_args, deps

    @staticmethod
    def _handle_rust_abi(abi: T.Optional[Literal['c', 'rust']],
                         crate_type: T.Optional[build.RustCrateType],
                         default_rust_type: build.RustCrateType,
                         default_c_type: build.RustCrateType, typename: str,
                         extra_valid_types: T.Optional[T.Set[build.RustCrateType]] = None,
                         ) -> build.RustCrateType:
        """Handle the interactions between the rust_abi and rust_crate_type keyword arguments.

        :param abi: Is this using Rust ABI or C ABI
        :param crate_type: Is there an explicit crate type set
        :param default_rust_type: The default crate type to use for Rust ABI
        :param default_c_type: the default crate type to use for C ABI
        :param typename: The name of the type this argument is for
        :param extra_valid_types: additional valid crate types, defaults to None
        :raises InvalidArguments: If the crate_type argument is set, but not valid
        :raises InvalidArguments: If both crate_type and abi are set
        :return: The finalized crate type
        """
        if abi is not None:
            if crate_type is not None:
                raise InvalidArguments('rust_abi and rust_crate_type are mutually exclusive')
            crate_type = default_rust_type if abi == 'rust' else default_c_type
        elif crate_type is not None:
            if crate_type == 'lib':
                crate_type = default_rust_type
            valid_types = {default_rust_type, default_c_type} | (extra_valid_types or set())
            if crate_type not in valid_types:
                choices = ", " .join(f'"{c}"' for c in sorted(valid_types))
                raise InvalidArguments(f'Crate type for {typename} must be one of {choices}, but got "{crate_type}"')
        else:
            crate_type = default_rust_type
        return crate_type

    def _exe_to_shlib_kwargs(self, kwargs: kwtypes.Executable) -> kwtypes.SharedLibrary:
        nkwargs = T.cast('kwtypes.SharedLibrary', kwargs.copy())
        for exe_kwarg in EXCLUSIVE_EXECUTABLE_KWS:
            del nkwargs[exe_kwarg.name]  # type: ignore[misc]
        for sh_kwarg in SHARED_LIB_KWS:
            nkwargs.setdefault(sh_kwarg.name, sh_kwarg.default)  # type: ignore[misc]
        nkwargs['rust_abi'] = None
        nkwargs['rust_crate_type'] = 'cdylib'
        return nkwargs

    def __convert_build_target_base_kwargs(self, kwargs: kwtypes.BuildTarget, final: build.BuildTargetKeywordArguments) -> None:
        """Convert shared arguments for BuildTargets to the Build layer form.

        This takes the raw DSL form, and builds a new dict in the form that the BuildTarget expects

        :param kwargs: The arguments in raw DSL form
        :param final: A new dictionary to fill in with the Build layer
        :raises InvalidArguments: If one the PCH files doesn't exist
        """
        # copy common arguments directly
        for arg in ('build_by_default', 'build_rpath', 'build_subdir', 'c_pch',
                    'cpp_pch', 'd_debug', 'd_module_versions', 'd_unittest',
                    'dependencies', 'gnu_symbol_visibility', 'install',
                    'install_mode', 'install_rpath',
                    'implicit_include_directories', 'link_args', 'link_early_args',
                    'link_language', 'link_with', 'link_whole', 'name_prefix',
                    'name_suffix', 'native', 'resources', 'vala_header',
                    'vala_gir', 'vala_vapi', 'swift_interoperability_mode',
                    'swift_module_name', 'rust_crate_type',
                    'rust_dependency_map', 'override_options'):
            final[arg] = kwargs[arg]

        # this is not accessable from the DSL, so we need to initialize it
        # ourselves
        final['depend_files'] = []

        # Check for non-existant PCH files
        missing: T.List[str] = []
        for each in itertools.chain(kwargs['c_pch'] or [], kwargs['cpp_pch'] or []):
            if each is not None:
                if not os.path.isfile(os.path.join(self.environment.source_dir, self.subdir, each)):
                    missing.append(os.path.join(self.subdir, each))
        if missing:
            raise InvalidArguments('The following PCH files do not exist: {}'.format(', '.join(missing)))

        final['link_depends'] = self.source_strings_to_files(kwargs['link_depends'])
        final['install_tag'] = [kwargs['install_tag']]
        final['extra_files'] = mesonlib.unique_list(self.source_strings_to_files(kwargs['extra_files']))

        # Convert into IncludeDirs objects
        final['include_directories'] = self.extract_incdirs(kwargs['include_directories'])
        final['d_import_dirs'] = self.extract_incdirs(kwargs['d_import_dirs'], True)

        # Convert language arguments
        lang_args, deps = self.__process_language_args(kwargs)
        final['language_args'] = lang_args
        final['depend_files'].extend(deps)

        # Rewrite `install_dir : [main, vala_header, vala_vapi, vala_gir]`
        # Into split arguments
        vala_keys = ('install_vala_header', 'install_vala_vapi', 'install_vala_gir')
        if len(kwargs['install_dir']) > 1:
            if any(kwargs[k] is not None for k in vala_keys):  # type: ignore[literal-required]
                raise InvalidArguments('Passing install_vala_* and more than one argument to install_dir are mutually exclusive')

            install_dirs = kwargs['install_dir'].copy()
            install_dir = install_dirs.pop(0)

            for key in vala_keys:
                action = install_dirs.pop(0) if install_dirs else False
                if isinstance(action, bool):
                    final[key] = action  # type: ignore[literal-required]
                else:
                    final[key] = True  # type: ignore[literal-required]
                    final[f'{key}_dir'] = action  # type: ignore[literal-required]
            final['install_dir'] = [install_dir]

            # This was previously allowed, and tested, so we need to allow it to keep working.
            if final['vala_gir'] is None and final['install_vala_gir']:
                final['install_vala_gir'] = False
        else:
            for key in vala_keys:
                action = kwargs[key]  # type: ignore[literal-required]
                if action is None:
                    action = False
                if isinstance(action, bool):
                    final[key] = action  # type: ignore[literal-required]
                else:
                    final[key] = True  # type: ignore[literal-required]
                    final[f'{key}_dir'] = action  # type: ignore[literal-required]
            final['install_dir'] = [kwargs['install_dir'][0] if kwargs['install_dir'] else True]

    def __convert_executable_kwargs(self, node: mparser.BaseNode, kwargs: kwtypes.Executable) -> build.ExecutableKeywordArguments:
        """Convert Executable arguments from DSL form to the build layer form.

        :param node: The Node being evaluated
        :param kwargs: The DSL keyword arguments
        :raises InvalidArguments: If both gui_app and win_subsystem are set
        :raises InvalidArguments: If implib is false and export_dynamic is true
        :raises InvalidArguments: If the rust_crate_type is set to anything except bin
        :return: The keyword arguments as the Build layer expects
        """
        final: build.ExecutableKeywordArguments = {}
        self.__convert_build_target_base_kwargs(kwargs, final)

        # Exe exclusive arguments
        for exe_arg in ('android_exe_type', 'pie'):
            final[exe_arg] = kwargs[exe_arg]
        final['vs_module_defs'] = self.source_string_to_file(kwargs['vs_module_defs'])

        # rewrite `gui_app` to `win_subsystem`
        if kwargs['gui_app'] is not None:
            if kwargs['win_subsystem'] is not None:
                raise InvalidArguments.from_node(
                    'Executable got both "gui_app", and "win_subsystem" arguments, which are mutually exclusive',
                    node=node)
            final['win_subsystem'] = 'windows' if kwargs['gui_app'] else 'console'
        elif kwargs['win_subsystem'] is not None:
            final['win_subsystem'] = kwargs['win_subsystem']
        else:
            final['win_subsystem'] = 'console'

        # handle interactions between implib and export_dynamic
        if kwargs['implib']:
            if kwargs['export_dynamic'] is False:
                FeatureDeprecated.single_use(
                    'implib overrides explicit export_dynamic off', '1.3.0', self.subproject,
                    'Do not set ths if want export_dynamic disabled if implib is enabled',
                    location=node)
            kwargs['export_dynamic'] = True
        elif kwargs['export_dynamic']:
            if kwargs['implib'] is False:
                raise InvalidArguments.from_node(
                    '"implib" keyword" must not be false if "export_dynamic" is set and not false.',
                    node=node)
        if kwargs['export_dynamic'] is None:
            kwargs['export_dynamic'] = False
        final['export_dynamic'] = kwargs['export_dynamic']

        if isinstance(kwargs['implib'], bool):
            final['implib'] = None
        else:
            final['implib'] = kwargs['implib']

        # Handle executable speicific rust_crate_type
        if kwargs['rust_crate_type'] not in {None, 'bin'}:
            raise InvalidArguments.from_node(
                'Crate type for executable must be "bin"', node=node)
        final['rust_crate_type'] = 'bin'

        return final

    def __convert_static_library_kwargs(self, node: mparser.BaseNode, kwargs: kwtypes.StaticLibrary) -> build.StaticLibraryKeywordArguments:
        """Convert StaticLibrary arguments to the Build format.

        :param node: The Node currently be evaluated.
        :param kwargs: The DSL form of the keyword arguments.
        :return: The arguments in Build layer format.
        """
        final: build.StaticLibraryKeywordArguments = {}
        self.__convert_build_target_base_kwargs(kwargs, final)

        for arg in ('pic', 'prelink'):
            final[arg] = kwargs[arg]

        for lang in compilers.all_languages - {'java'}:
            deps, args = self.__convert_file_args(kwargs.get(f'{lang}_static_args', []))  # type: ignore[arg-type]
            final['language_args'][lang].extend(args)
            final['depend_files'].extend(deps)
        final['rust_crate_type'] = self._handle_rust_abi(
            kwargs['rust_abi'], kwargs['rust_crate_type'], 'rlib', 'staticlib',
            build.StaticLibrary.typename)

        return final

    def __convert_shared_library_kwargs(self, node: mparser.BaseNode, kwargs: kwtypes.SharedLibrary) -> build.SharedLibraryKeywordArguments:
        """Convert SharedLibrary arguments to the Build format.

        :param node: The Node currently be evaluated.
        :param kwargs: The DSL form of the keyword arguments.
        :return: The arguments in Build layer format.
        """
        final: build.SharedLibraryKeywordArguments = {}
        self.__convert_build_target_base_kwargs(kwargs, final)

        for arg in ('version', 'soversion', 'darwin_versions', 'shortname'):
            final[arg] = kwargs[arg]
        final['vs_module_defs'] = self.source_string_to_file(kwargs['vs_module_defs'])

        for lang in compilers.all_languages - {'java'}:
            deps, args = self.__convert_file_args(kwargs.get(f'{lang}_shared_args', []))  # type: ignore[arg-type]
            final['language_args'][lang].extend(args)
            final['depend_files'].extend(deps)
        final['rust_crate_type'] = self._handle_rust_abi(
            kwargs['rust_abi'], kwargs['rust_crate_type'], 'dylib', 'cdylib',
            build.SharedLibrary.typename, extra_valid_types={'proc-macro'})

        final['win_subsystem'] = kwargs['win_subsystem'] or 'console'

        return final

    def __convert_shared_module_kwargs(self, node: mparser.BaseNode, kwargs: kwtypes.SharedModule) -> build.SharedModuleKeywordArguments:
        """Convert SharedModule arguments to the Build format.

        :param node: The Node currently be evaluated.
        :param kwargs: The DSL form of the keyword arguments.
        :return: The arguments in Build layer format.
        """
        final: build.SharedModuleKeywordArguments = {}
        self.__convert_build_target_base_kwargs(kwargs, final)

        final['vs_module_defs'] = self.source_string_to_file(kwargs['vs_module_defs'])

        for lang in compilers.all_languages - {'java'}:
            deps, args = self.__convert_file_args(kwargs.get(f'{lang}_shared_args', []))  # type: ignore[arg-type]
            final['language_args'][lang].extend(args)
            final['depend_files'].extend(deps)
        final['rust_crate_type'] = self._handle_rust_abi(
            kwargs['rust_abi'], kwargs['rust_crate_type'], 'dylib', 'cdylib',
            build.SharedModule.typename, extra_valid_types={'proc-macro'})

        final['win_subsystem'] = kwargs['win_subsystem'] or 'console'

        return final

    def __convert_jar_kwargs(self, node: mparser.BaseNode, kwargs: kwtypes.Jar) -> build.JarKeywordArguments:
        """Convert Jar arguments to the Build format.

        :param node: The Node currently be evaluated.
        :param kwargs: The DSL form of the keyword arguments.
        :return: The arguments in Build layer format.
        """
        final: build.JarKeywordArguments = {}

        # copy common arguments directly
        for arg in ('build_by_default', 'build_subdir', 'dependencies',
                    'install', 'install_mode', 'implicit_include_directories',
                    'link_with', 'java_args', 'java_resources', 'main_class'):
            final[arg] = kwargs[arg]

        # this is not accessable from the DSL, so we need to initialize it
        # ourselves
        final['depend_files'] = []

        # The build layer and interpreter don't agree here, and it's not clear
        # that we're hanlding this correctly
        final['install_dir'] = kwargs['install_dir']  # type: ignore[typeddict-item]
        final['install_tag'] = [kwargs['install_tag']]
        final['extra_files'] = mesonlib.unique_list(self.source_strings_to_files(kwargs['extra_files']))

        # Convert into IncludeDirs objects
        final['include_directories'] = self.extract_incdirs(kwargs['include_directories'])

        # Convert language arguments
        lang_args, deps = self.__process_language_args(kwargs)
        final['language_args'] = lang_args
        final['depend_files'].extend(deps)

        return final

    @T.overload
    def build_target(self, node: mparser.BaseNode, args: T.Tuple[str, SourcesVarargsType],
                     kwargs: kwtypes.Executable, targetclass: T.Type[build.Executable]) -> build.Executable: ...

    @T.overload
    def build_target(self, node: mparser.BaseNode, args: T.Tuple[str, SourcesVarargsType],
                     kwargs: kwtypes.StaticLibrary, targetclass: T.Type[build.StaticLibrary]) -> build.StaticLibrary: ...

    @T.overload
    def build_target(self, node: mparser.BaseNode, args: T.Tuple[str, SourcesVarargsType],
                     kwargs: kwtypes.SharedModule, targetclass: T.Type[build.SharedModule]) -> build.SharedModule: ...

    @T.overload
    def build_target(self, node: mparser.BaseNode, args: T.Tuple[str, SourcesVarargsType],
                     kwargs: kwtypes.SharedLibrary, targetclass: T.Type[build.SharedLibrary],
                     shared_library_only: bool = True) -> build.SharedLibrary: ...

    @T.overload
    def build_target(self, node: mparser.BaseNode, args: T.Tuple[str, SourcesVarargsType],
                     kwargs: kwtypes.Jar, targetclass: T.Type[build.Jar]) -> build.Jar: ...

    def build_target(self, node: mparser.BaseNode, args: T.Tuple[str, SourcesVarargsType],
                     kwargs: T.Union[kwtypes.Executable, kwtypes.StaticLibrary, kwtypes.SharedLibrary, kwtypes.SharedModule, kwtypes.Jar],
                     targetclass: T.Type[T.Union[build.Executable, build.StaticLibrary, build.SharedModule, build.SharedLibrary, build.Jar]],
                     shared_library_only: bool = True
                     ) -> T.Union[build.Executable, build.StaticLibrary, build.SharedModule, build.SharedLibrary, build.Jar]:
        if targetclass not in {build.Executable, build.SharedLibrary, build.SharedModule, build.StaticLibrary, build.Jar}:
            mlog.debug('Unknown target type:', str(targetclass))
            raise RuntimeError('Unreachable code')

        self.apply_machine_map_to_kwargs(kwargs)
        for_machine = kwargs['native']

        if self.environment.is_cross_build() and kwargs.get('rust_crate_type') == 'proc-macro':
            # Silently force to native because that's the only sensible value
            # and rust_crate_type is deprecated any way.
            for_machine = MachineChoice.BUILD

        if targetclass is build.Executable and kwargs.get('android_exe_type') == 'application':
            m = self.environment.machines[for_machine]
            if m.is_android():
                # Mypy can't figure this out for some reason
                kwargs = T.cast('kwtypes.Executable', kwargs)
                return self.build_target(node, args, self._exe_to_shlib_kwargs(kwargs), build.SharedLibrary)

        # Because who owns this isn't clear
        kwargs = kwargs.copy()
        name, raw_sources = args
        # Avoid mutating, since there could be other references to sources
        raw_sources = raw_sources + T.cast('SourcesVarargsType', kwargs['sources'])
        if any(isinstance(s, build.BuildTarget) for s in raw_sources):
            FeatureBroken.single_use('passing references to built targets as a source file', '1.1.0', self.subproject,
                                     'Consider using `link_with` or `link_whole` if you meant to link, or dropping them as otherwise they are ignored.',
                                     node)
        if any(isinstance(s, build.ExtractedObjects) for s in raw_sources):
            FeatureBroken.single_use('passing object files as sources', '1.1.0', self.subproject,
                                     'Pass these to the `objects` keyword instead, they are ignored when passed as sources.',
                                     node)
        # Go ahead and drop these here, since they're only allowed through for
        # backwards compatibility anyway
        sources = self.source_strings_to_files([
            s for s in raw_sources if not isinstance(s, (build.BuildTarget, build.ExtractedObjects))])

        objs = self.source_strings_to_files(kwargs['objects'])

        srcs: T.List[SourceOutputs] = []
        struct: T.Optional[build.StructuredSources] = build.StructuredSources()
        for s in sources:
            if isinstance(s, build.StructuredSources):
                struct = struct + s
            else:
                srcs.append(s)

        if not struct:
            struct = None
        else:
            # Validate that we won't end up with two outputs with the same name.
            # i.e, don't allow:
            # [structured_sources('foo/bar.rs'), structured_sources('bar/bar.rs')]
            for v in struct.sources.values():
                outputs: T.Set[str] = set()
                for f in v:
                    o: T.List[str]
                    if isinstance(f, str):
                        o = [os.path.basename(f)]
                    elif isinstance(f, mesonlib.File):
                        o = [f.fname]
                    else:
                        o = f.get_outputs()
                    conflicts = outputs.intersection(o)
                    if conflicts:
                        raise InvalidArguments.from_node(
                            f"Conflicting sources in structured sources: {', '.join(sorted(conflicts))}",
                            node=node)
                    outputs.update(o)

        if targetclass is not build.Jar:
            self.check_for_jar_sources(sources, targetclass)

        target: build.BuildTarget
        if targetclass is build.Executable:
            nkwargs = self.__convert_executable_kwargs(
                node, T.cast('kwtypes.Executable', kwargs))
            target = build.Executable(name, self.subdir, for_machine, srcs, struct, objs,
                                      self.environment, self.compilers[for_machine], self.current_build_project(), nkwargs)
        elif targetclass is build.StaticLibrary:
            nkwargs = self.__convert_static_library_kwargs(
                node, T.cast('kwtypes.StaticLibrary', kwargs))
            target = build.StaticLibrary(name, self.subdir, for_machine, srcs, struct, objs,
                                         self.environment, self.compilers[for_machine], self.current_build_project(), nkwargs)
        elif targetclass is build.SharedLibrary:
            nkwargs = self.__convert_shared_library_kwargs(
                node, T.cast('kwtypes.SharedLibrary', kwargs))
            target = build.SharedLibrary(name, self.subdir, for_machine, srcs, struct, objs,
                                         self.environment, self.compilers[for_machine], self.current_build_project(), nkwargs)
            target.shared_library_only = shared_library_only
        elif targetclass is build.SharedModule:
            nkwargs = self.__convert_shared_module_kwargs(
                node, T.cast('kwtypes.SharedModule', kwargs))
            target = build.SharedModule(name, self.subdir, for_machine, srcs, struct, objs,
                                        self.environment, self.compilers[for_machine], self.current_build_project(), nkwargs)
            target.shared_library_only = shared_library_only
        else:
            nkwargs = self.__convert_jar_kwargs(
                node, T.cast('kwtypes.Jar', kwargs))
            target = build.Jar(name, self.subdir, for_machine, srcs, struct, objs,
                               self.environment, self.compilers[for_machine], self.current_build_project(), nkwargs)

        if objs and target.uses_rust():
            FeatureNew.single_use('objects in Rust targets', '1.8.0', self.subproject)

        self.add_target(name, target)
        self.project_args_frozen = True
        return target

    def add_stdlib_info(self, target: build.BuildTarget) -> None:
        for l in target.compilers.keys():
            dep = self.build.stdlibs[target.for_machine].get(l, None)
            if dep:
                target.add_deps([dep])

    def check_for_jar_sources(self, sources: T.Union[T.List[str], T.Sequence[T.Union[build.TargetSources, build.StructuredSources]]],
                              targetclass: T.Type[build.BuildTarget]) -> None:
        for s in sources:
            if isinstance(s, (str, mesonlib.File)) and compilers.is_java(s):
                raise InvalidArguments(f'Build target of type "{targetclass.typename}" cannot build java source: "{s}". Use "{build.Jar.typename}" instead.')
            elif isinstance(s, build.StructuredSources):
                self.check_for_jar_sources(s.as_list(), targetclass)
            elif isinstance(s, (build.GeneratedList, build.CustomTarget, build.CustomTargetIndex)):
                self.check_for_jar_sources(s.get_outputs(), targetclass)

    def is_subproject(self) -> bool:
        return self.subproject != ''

    @typed_pos_args('set_variable', str, (object, DefaultObject))
    @noKwargs
    @noArgsFlattening
    @noSecondLevelHolderResolving
    def func_set_variable(self, node: mparser.BaseNode, args: T.Tuple[str, TYPE_var | InterpreterObject], kwargs: 'TYPE_kwargs') -> None:
        varname, value = args
        if mparser.IDENT_RE.fullmatch(varname) is None:
            raise InvalidCode('Invalid variable name: ' + varname)
        self.set_variable(varname, value, holderify=True)

    @typed_pos_args('get_variable', (str, Disabler, DefaultObject), optargs=[object])
    @noKwargs
    @noArgsFlattening
    @unholder_return
    def func_get_variable(self, node: mparser.BaseNode, args: T.Tuple[T.Union[str, Disabler], T.Optional[TYPE_var | InterpreterObject]],
                          kwargs: 'TYPE_kwargs') -> TYPE_var | InterpreterObject:
        varname, fallback = args
        if isinstance(varname, Disabler):
            return varname

        try:
            return self.variables[varname]
        except KeyError:
            if fallback is not None:
                return self._holderify(fallback)
        ustr = f'Tried to get unknown variable "{varname}".'
        from difflib import get_close_matches
        close_matches = get_close_matches(varname, self.variables.keys())
        if close_matches:
            ustr += f' Did you mean "{close_matches[0]}"?'
        raise InterpreterException(ustr)

    @typed_pos_args('is_variable', str)
    @noKwargs
    def func_is_variable(self, node: mparser.BaseNode, args: T.Tuple[str], kwargs: 'TYPE_kwargs') -> bool:
        return args[0] in self.variables

    @FeatureNew('unset_variable', '0.60.0')
    @typed_pos_args('unset_variable', str)
    @noKwargs
    def func_unset_variable(self, node: mparser.BaseNode, args: T.Tuple[str], kwargs: 'TYPE_kwargs') -> None:
        varname = args[0]
        try:
            del self.variables[varname]
        except KeyError:
            ustr = f'Tried to unset unknown variable "{varname}".'
            from difflib import get_close_matches
            close_matches = get_close_matches(varname, self.variables.keys())
            if close_matches:
                ustr += f' Did you mean "{close_matches[0]}"?'
            raise InterpreterException(ustr)

    @FeatureNew('is_disabler', '0.52.0')
    @typed_pos_args('is_disabler', object)
    @noKwargs
    def func_is_disabler(self, node: mparser.BaseNode, args: T.Tuple[object], kwargs: 'TYPE_kwargs') -> bool:
        return isinstance(args[0], Disabler)

    @noKwargs
    @FeatureNew('range', '0.58.0')
    @typed_pos_args('range', int, optargs=[int, int])
    def func_range(self, node: mparser.BaseNode, args: T.Tuple[int, T.Optional[int], T.Optional[int]],
                   kwargs: TYPE_kwargs) -> P_OBJ.RangeHolder:
        start, stop, step = args
        # Just like Python's range, we allow range(stop), range(start, stop), or
        # range(start, stop, step)
        if stop is None:
            stop = start
            start = 0
        if step is None:
            step = 1
        # This is more strict than Python's range()
        if start < 0:
            raise InterpreterException('start cannot be negative')
        if stop < start:
            raise InterpreterException('stop cannot be less than start')
        if step < 1:
            raise InterpreterException('step must be >=1')
        return P_OBJ.RangeHolder(start, stop, step, subproject=self.subproject)
