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

from __future__ import annotations
import copy
import itertools
import os
import xml.dom.minidom
import xml.etree.ElementTree as ET
import uuid
import typing as T
from pathlib import Path, PurePath, PureWindowsPath
import re
from collections import Counter

from . import backends
from .. import build
from .. import mlog
from .. import compilers
from .. import mesonlib
from ..mesonlib import (
    File, MesonBugException, MesonException, replace_if_different, OptionKey, version_compare, MachineChoice
)
from ..environment import Environment, build_filename
from .. import coredata

if T.TYPE_CHECKING:
    from ..arglist import CompilerArgs
    from ..interpreter import Interpreter

    Project = T.Tuple[str, Path, str, MachineChoice]

def autodetect_vs_version(build: T.Optional[build.Build], interpreter: T.Optional[Interpreter]) -> backends.Backend:
    vs_version = os.getenv('VisualStudioVersion', None)
    vs_install_dir = os.getenv('VSINSTALLDIR', None)
    if not vs_install_dir:
        raise MesonException('Could not detect Visual Studio: Environment variable VSINSTALLDIR is not set!\n'
                             'Are you running meson from the Visual Studio Developer Command Prompt?')
    # VisualStudioVersion is set since Visual Studio 11.0, but sometimes
    # vcvarsall.bat doesn't set it, so also use VSINSTALLDIR
    if vs_version == '11.0' or 'Visual Studio 11' in vs_install_dir:
        from mesonbuild.backend.vs2012backend import Vs2012Backend
        return Vs2012Backend(build, interpreter)
    if vs_version == '12.0' or 'Visual Studio 12' in vs_install_dir:
        from mesonbuild.backend.vs2013backend import Vs2013Backend
        return Vs2013Backend(build, interpreter)
    if vs_version == '14.0' or 'Visual Studio 14' in vs_install_dir:
        from mesonbuild.backend.vs2015backend import Vs2015Backend
        return Vs2015Backend(build, interpreter)
    if vs_version == '15.0' or 'Visual Studio 17' in vs_install_dir or \
       'Visual Studio\\2017' in vs_install_dir:
        from mesonbuild.backend.vs2017backend import Vs2017Backend
        return Vs2017Backend(build, interpreter)
    if vs_version == '16.0' or 'Visual Studio 19' in vs_install_dir or \
       'Visual Studio\\2019' in vs_install_dir:
        from mesonbuild.backend.vs2019backend import Vs2019Backend
        return Vs2019Backend(build, interpreter)
    if vs_version == '17.0' or 'Visual Studio 22' in vs_install_dir or \
       'Visual Studio\\2022' in vs_install_dir:
        from mesonbuild.backend.vs2022backend import Vs2022Backend
        return Vs2022Backend(build, interpreter)
    if 'Visual Studio 10.0' in vs_install_dir:
        return Vs2010Backend(build, interpreter)
    raise MesonException('Could not detect Visual Studio using VisualStudioVersion: {!r} or VSINSTALLDIR: {!r}!\n'
                         'Please specify the exact backend to use.'.format(vs_version, vs_install_dir))


def split_o_flags_args(args: T.List[str]) -> T.List[str]:
    """
    Splits any /O args and returns them. Does not take care of flags overriding
    previous ones. Skips non-O flag arguments.

    ['/Ox', '/Ob1'] returns ['/Ox', '/Ob1']
    ['/Oxj', '/MP'] returns ['/Ox', '/Oj']
    """
    o_flags = []
    for arg in args:
        if not arg.startswith('/O'):
            continue
        flags = list(arg[2:])
        # Assume that this one can't be clumped with the others since it takes
        # an argument itself
        if 'b' in flags:
            o_flags.append(arg)
        else:
            o_flags += ['/O' + f for f in flags]
    return o_flags

def generate_guid_from_path(path, path_type) -> str:
    return str(uuid.uuid5(uuid.NAMESPACE_URL, 'meson-vs-' + path_type + ':' + str(path))).upper()

def detect_microsoft_gdk(platform: str) -> bool:
    return re.match(r'Gaming\.(Desktop|Xbox.XboxOne|Xbox.Scarlett)\.x64', platform, re.IGNORECASE)

def filtered_src_langs_generator(sources: T.List[str]):
    for src in sources:
        ext = src.split('.')[-1]
        if compilers.compilers.is_source_suffix(ext):
            yield compilers.compilers.SUFFIX_TO_LANG[ext]

# Returns the source language (i.e. a key from 'lang_suffixes') of the most frequent source language in the given
# list of sources.
# We choose the most frequent language as 'primary' because it means the most sources in a target/project can
# simply refer to the project's shared intellisense define and include fields, rather than have to fill out their
# own duplicate full set of defines/includes/opts intellisense fields.  All of which helps keep the vcxproj file
# size down.
def get_primary_source_lang(target_sources: T.List[File], custom_sources: T.List[str]) -> T.Optional[str]:
    lang_counts = Counter([compilers.compilers.SUFFIX_TO_LANG[src.suffix] for src in target_sources if compilers.compilers.is_source_suffix(src.suffix)])
    lang_counts += Counter(filtered_src_langs_generator(custom_sources))
    most_common_lang_list = lang_counts.most_common(1)
    # It may be possible that we have a target with no actual src files of interest (e.g. a generator target),
    # leaving us with an empty list, which we should handle -
    return most_common_lang_list[0][0] if most_common_lang_list else None

# Returns a dictionary (by [src type][build type]) that contains a tuple of -
# (pre-processor defines, include paths, additional compiler options)
# fields to use to fill in the respective intellisense fields of sources that can't simply
# reference and re-use the shared 'primary' language intellisense fields of the vcxproj.
def get_non_primary_lang_intellisense_fields(vslite_ctx: dict,
                                             target_id: str,
                                             primary_src_lang: str) -> T.Dict[str, T.Dict[str, T.Tuple[str, str, str]]]:
    defs_paths_opts_per_lang_and_buildtype = {}
    for buildtype in coredata.get_genvs_default_buildtype_list():
        captured_build_args = vslite_ctx[buildtype][target_id] # Results in a 'Src types to compile args' dict
        non_primary_build_args_per_src_lang = [(lang, build_args) for lang, build_args in captured_build_args.items() if lang != primary_src_lang] # Only need to individually populate intellisense fields for sources of non-primary types.
        for src_lang, args_list in non_primary_build_args_per_src_lang:
            if src_lang not in defs_paths_opts_per_lang_and_buildtype:
                defs_paths_opts_per_lang_and_buildtype[src_lang] = {}
            defs_paths_opts_per_lang_and_buildtype[src_lang][buildtype] = Vs2010Backend._extract_nmake_fields(args_list)
    return defs_paths_opts_per_lang_and_buildtype

class Vs2010Backend(backends.Backend):

    name = 'vs2010'

    def __init__(self, build: T.Optional[build.Build], interpreter: T.Optional[Interpreter], gen_lite: bool = False):
        super().__init__(build, interpreter)
        self.project_file_version = '10.0.30319.1'
        self.sln_file_version = '11.00'
        self.sln_version_comment = '2010'
        self.platform_toolset = None
        self.vs_version = '2010'
        self.windows_target_platform_version = None
        self.subdirs = {}
        self.handled_target_deps = {}
        self.gen_lite = gen_lite  # Synonymous with generating the simpler makefile-style multi-config projects that invoke 'meson compile' builds, avoiding native MSBuild complications

    def get_target_private_dir(self, target):
        return os.path.join(self.get_target_dir(target), target.get_id())

    def generate_genlist_for_target(self, genlist: T.Union[build.GeneratedList, build.CustomTarget, build.CustomTargetIndex], target: build.BuildTarget, parent_node: ET.Element, generator_output_files: T.List[str], custom_target_include_dirs: T.List[str], custom_target_output_files: T.List[str]) -> None:
        if isinstance(genlist, build.GeneratedList):
            for x in genlist.depends:
                self.generate_genlist_for_target(x, target, parent_node, [], [], [])
        target_private_dir = self.relpath(self.get_target_private_dir(target), self.get_target_dir(target))
        down = self.target_to_build_root(target)
        if isinstance(genlist, (build.CustomTarget, build.CustomTargetIndex)):
            for i in genlist.get_outputs():
                # Path to the generated source from the current vcxproj dir via the build root
                ipath = os.path.join(down, self.get_target_dir(genlist), i)
                custom_target_output_files.append(ipath)
            idir = self.relpath(self.get_target_dir(genlist), self.get_target_dir(target))
            if idir not in custom_target_include_dirs:
                custom_target_include_dirs.append(idir)
        else:
            generator = genlist.get_generator()
            exe = generator.get_exe()
            infilelist = genlist.get_inputs()
            outfilelist = genlist.get_outputs()
            source_dir = os.path.join(down, self.build_to_src, genlist.subdir)
            idgroup = ET.SubElement(parent_node, 'ItemGroup')
            samelen = len(infilelist) == len(outfilelist)
            for i, curfile in enumerate(infilelist):
                if samelen:
                    sole_output = os.path.join(target_private_dir, outfilelist[i])
                else:
                    sole_output = ''
                infilename = os.path.join(down, curfile.rel_to_builddir(self.build_to_src, target_private_dir))
                deps = self.get_target_depend_files(genlist, True)
                base_args = generator.get_arglist(infilename)
                outfiles_rel = genlist.get_outputs_for(curfile)
                outfiles = [os.path.join(target_private_dir, of) for of in outfiles_rel]
                generator_output_files += outfiles
                args = [x.replace("@INPUT@", infilename).replace('@OUTPUT@', sole_output)
                        for x in base_args]
                args = self.replace_outputs(args, target_private_dir, outfiles_rel)
                args = [x.replace("@SOURCE_DIR@", self.environment.get_source_dir())
                        .replace("@BUILD_DIR@", target_private_dir)
                        for x in args]
                args = [x.replace("@CURRENT_SOURCE_DIR@", source_dir) for x in args]
                args = [x.replace("@SOURCE_ROOT@", self.environment.get_source_dir())
                        .replace("@BUILD_ROOT@", self.environment.get_build_dir())
                        for x in args]
                args = [x.replace('\\', '/') for x in args]
                # Always use a wrapper because MSBuild eats random characters when
                # there are many arguments.
                tdir_abs = os.path.join(self.environment.get_build_dir(), self.get_target_dir(target))
                cmd, _ = self.as_meson_exe_cmdline(
                    exe,
                    self.replace_extra_args(args, genlist),
                    workdir=tdir_abs,
                    capture=outfiles[0] if generator.capture else None,
                    force_serialize=True,
                    env=genlist.env
                )
                deps = cmd[-1:] + deps
                abs_pdir = os.path.join(self.environment.get_build_dir(), self.get_target_dir(target))
                os.makedirs(abs_pdir, exist_ok=True)
                cbs = ET.SubElement(idgroup, 'CustomBuild', Include=infilename)
                ET.SubElement(cbs, 'Command').text = ' '.join(self.quote_arguments(cmd))
                ET.SubElement(cbs, 'Outputs').text = ';'.join(outfiles)
                ET.SubElement(cbs, 'AdditionalInputs').text = ';'.join(deps)

    def generate_custom_generator_commands(self, target, parent_node):
        generator_output_files = []
        custom_target_include_dirs = []
        custom_target_output_files = []
        for genlist in target.get_generated_sources():
            self.generate_genlist_for_target(genlist, target, parent_node, generator_output_files, custom_target_include_dirs, custom_target_output_files)
        return generator_output_files, custom_target_output_files, custom_target_include_dirs

    def generate(self,
                 capture: bool = False,
                 vslite_ctx: dict = None) -> T.Optional[dict]:
        # Check for (currently) unexpected capture arg use cases -
        if capture:
            raise MesonBugException('We do not expect any vs backend to generate with \'capture = True\'')
        host_machine = self.environment.machines.host.cpu_family
        if host_machine in {'64', 'x86_64'}:
            # amd64 or x86_64
            target_system = self.environment.machines.host.system
            if detect_microsoft_gdk(target_system):
                self.platform = target_system
            else:
                self.platform = 'x64'
        elif host_machine == 'x86':
            # x86
            self.platform = 'Win32'
        elif host_machine in {'aarch64', 'arm64'}:
            target_cpu = self.environment.machines.host.cpu
            if target_cpu == 'arm64ec':
                self.platform = 'arm64ec'
            else:
                self.platform = 'arm64'
        elif 'arm' in host_machine.lower():
            self.platform = 'ARM'
        else:
            raise MesonException('Unsupported Visual Studio platform: ' + host_machine)

        build_machine = self.environment.machines.build.cpu_family
        if build_machine in {'64', 'x86_64'}:
            # amd64 or x86_64
            self.build_platform = 'x64'
        elif build_machine == 'x86':
            # x86
            self.build_platform = 'Win32'
        elif build_machine in {'aarch64', 'arm64'}:
            target_cpu = self.environment.machines.build.cpu
            if target_cpu == 'arm64ec':
                self.build_platform = 'arm64ec'
            else:
                self.build_platform = 'arm64'
        elif 'arm' in build_machine.lower():
            self.build_platform = 'ARM'
        else:
            raise MesonException('Unsupported Visual Studio platform: ' + build_machine)

        self.buildtype = self.environment.coredata.get_option(OptionKey('buildtype'))
        self.optimization = self.environment.coredata.get_option(OptionKey('optimization'))
        self.debug = self.environment.coredata.get_option(OptionKey('debug'))
        try:
            self.sanitize = self.environment.coredata.get_option(OptionKey('b_sanitize'))
        except MesonException:
            self.sanitize = 'none'
        sln_filename = os.path.join(self.environment.get_build_dir(), self.build.project_name + '.sln')
        projlist = self.generate_projects(vslite_ctx)
        self.gen_testproj()
        self.gen_installproj()
        self.gen_regenproj()
        self.generate_solution(sln_filename, projlist)
        self.generate_regen_info()
        Vs2010Backend.touch_regen_timestamp(self.environment.get_build_dir())

    @staticmethod
    def get_regen_stampfile(build_dir: str) -> None:
        return os.path.join(os.path.join(build_dir, Environment.private_dir), 'regen.stamp')

    @staticmethod
    def touch_regen_timestamp(build_dir: str) -> None:
        with open(Vs2010Backend.get_regen_stampfile(build_dir), 'w', encoding='utf-8'):
            pass

    def get_vcvars_command(self):
        has_arch_values = 'VSCMD_ARG_TGT_ARCH' in os.environ and 'VSCMD_ARG_HOST_ARCH' in os.environ

        # Use vcvarsall.bat if we found it.
        if 'VCINSTALLDIR' in os.environ:
            vs_version = os.environ['VisualStudioVersion'] \
                if 'VisualStudioVersion' in os.environ else None
            relative_path = 'Auxiliary\\Build\\' if vs_version is not None and vs_version >= '15.0' else ''
            script_path = os.environ['VCINSTALLDIR'] + relative_path + 'vcvarsall.bat'
            if os.path.exists(script_path):
                if has_arch_values:
                    target_arch = os.environ['VSCMD_ARG_TGT_ARCH']
                    host_arch = os.environ['VSCMD_ARG_HOST_ARCH']
                else:
                    target_arch = os.environ.get('Platform', 'x86')
                    host_arch = target_arch
                arch = host_arch + '_' + target_arch if host_arch != target_arch else target_arch
                return f'"{script_path}" {arch}'

        # Otherwise try the VS2017 Developer Command Prompt.
        if 'VS150COMNTOOLS' in os.environ and has_arch_values:
            script_path = os.environ['VS150COMNTOOLS'] + 'VsDevCmd.bat'
            if os.path.exists(script_path):
                return '"%s" -arch=%s -host_arch=%s' % \
                    (script_path, os.environ['VSCMD_ARG_TGT_ARCH'], os.environ['VSCMD_ARG_HOST_ARCH'])
        return ''

    def get_obj_target_deps(self, obj_list):
        result = {}
        for o in obj_list:
            if isinstance(o, build.ExtractedObjects):
                result[o.target.get_id()] = o.target
        return result.items()

    def get_target_deps(self, t: T.Dict[T.Any, build.Target], recursive=False):
        all_deps: T.Dict[str, build.Target] = {}
        for target in t.values():
            if isinstance(target, build.CustomTarget):
                for d in target.get_target_dependencies():
                    # FIXME: this isn't strictly correct, as the target doesn't
                    # Get dependencies on non-targets, such as Files
                    if isinstance(d, build.Target):
                        all_deps[d.get_id()] = d
            elif isinstance(target, build.RunTarget):
                for d in target.get_dependencies():
                    all_deps[d.get_id()] = d
            elif isinstance(target, build.BuildTarget):
                for ldep in target.link_targets:
                    if isinstance(ldep, build.CustomTargetIndex):
                        all_deps[ldep.get_id()] = ldep.target
                    else:
                        all_deps[ldep.get_id()] = ldep
                for ldep in target.link_whole_targets:
                    if isinstance(ldep, build.CustomTargetIndex):
                        all_deps[ldep.get_id()] = ldep.target
                    else:
                        all_deps[ldep.get_id()] = ldep

                for ldep in target.link_depends:
                    if isinstance(ldep, build.CustomTargetIndex):
                        all_deps[ldep.get_id()] = ldep.target
                    elif isinstance(ldep, File):
                        # Already built, no target references needed
                        pass
                    else:
                        all_deps[ldep.get_id()] = ldep

                for obj_id, objdep in self.get_obj_target_deps(target.objects):
                    all_deps[obj_id] = objdep
            else:
                raise MesonException(f'Unknown target type for target {target}')

            for gendep in target.get_generated_sources():
                if isinstance(gendep, build.CustomTarget):
                    all_deps[gendep.get_id()] = gendep
                elif isinstance(gendep, build.CustomTargetIndex):
                    all_deps[gendep.target.get_id()] = gendep.target
                else:
                    generator = gendep.get_generator()
                    gen_exe = generator.get_exe()
                    if isinstance(gen_exe, build.Executable):
                        all_deps[gen_exe.get_id()] = gen_exe
                    for d in itertools.chain(generator.depends, gendep.depends):
                        if isinstance(d, build.CustomTargetIndex):
                            all_deps[d.get_id()] = d.target
                        elif isinstance(d, build.Target):
                            all_deps[d.get_id()] = d
                        # FIXME: we don't handle other kinds of deps correctly here, such
                        # as GeneratedLists, StructuredSources, and generated File.

        if not t or not recursive:
            return all_deps
        ret = self.get_target_deps(all_deps, recursive)
        ret.update(all_deps)
        return ret

    def generate_solution_dirs(self, ofile: str, parents: T.Sequence[Path]) -> None:
        prj_templ = 'Project("{%s}") = "%s", "%s", "{%s}"\n'
        iterpaths = reversed(parents)
        # Skip first path
        next(iterpaths)
        for path in iterpaths:
            if path not in self.subdirs:
                basename = path.name
                identifier = generate_guid_from_path(path, 'subdir')
                # top-level directories have None as their parent_dir
                parent_dir = path.parent
                parent_identifier = self.subdirs[parent_dir][0] \
                    if parent_dir != PurePath('.') else None
                self.subdirs[path] = (identifier, parent_identifier)
                prj_line = prj_templ % (
                    self.environment.coredata.lang_guids['directory'],
                    basename, basename, self.subdirs[path][0])
                ofile.write(prj_line)
                ofile.write('EndProject\n')

    def generate_solution(self, sln_filename: str, projlist: T.List[Project]) -> None:
        default_projlist = self.get_build_by_default_targets()
        default_projlist.update(self.get_testlike_targets())
        sln_filename_tmp = sln_filename + '~'
        # Note using the utf-8 BOM requires the blank line, otherwise Visual Studio Version Selector fails.
        # Without the BOM, VSVS fails if there is a blank line.
        with open(sln_filename_tmp, 'w', encoding='utf-8-sig') as ofile:
            ofile.write('\nMicrosoft Visual Studio Solution File, Format Version %s\n' % self.sln_file_version)
            ofile.write('# Visual Studio %s\n' % self.sln_version_comment)
            prj_templ = 'Project("{%s}") = "%s", "%s", "{%s}"\n'
            for prj in projlist:
                if self.environment.coredata.get_option(OptionKey('layout')) == 'mirror':
                    self.generate_solution_dirs(ofile, prj[1].parents)
                target = self.build.targets[prj[0]]
                lang = 'default'
                if hasattr(target, 'compilers') and target.compilers:
                    for lang_out in target.compilers.keys():
                        lang = lang_out
                        break
                prj_line = prj_templ % (
                    self.environment.coredata.lang_guids[lang],
                    prj[0], prj[1], prj[2])
                ofile.write(prj_line)
                target_dict = {target.get_id(): target}
                # Get recursive deps
                recursive_deps = self.get_target_deps(
                    target_dict, recursive=True)
                ofile.write('EndProject\n')
                for dep, target in recursive_deps.items():
                    if prj[0] in default_projlist:
                        default_projlist[dep] = target

            test_line = prj_templ % (self.environment.coredata.lang_guids['default'],
                                     'RUN_TESTS', 'RUN_TESTS.vcxproj',
                                     self.environment.coredata.test_guid)
            ofile.write(test_line)
            ofile.write('EndProject\n')
            if self.gen_lite: # REGEN is replaced by the lighter-weight RECONFIGURE utility, for now.  See comment in 'gen_regenproj'
                regen_proj_name = 'RECONFIGURE'
                regen_proj_fname = 'RECONFIGURE.vcxproj'
            else:
                regen_proj_name = 'REGEN'
                regen_proj_fname = 'REGEN.vcxproj'
            regen_line = prj_templ % (self.environment.coredata.lang_guids['default'],
                                      regen_proj_name, regen_proj_fname,
                                      self.environment.coredata.regen_guid)
            ofile.write(regen_line)
            ofile.write('EndProject\n')
            install_line = prj_templ % (self.environment.coredata.lang_guids['default'],
                                        'RUN_INSTALL', 'RUN_INSTALL.vcxproj',
                                        self.environment.coredata.install_guid)
            ofile.write(install_line)
            ofile.write('EndProject\n')
            ofile.write('Global\n')
            ofile.write('\tGlobalSection(SolutionConfigurationPlatforms) = '
                        'preSolution\n')
            multi_config_buildtype_list = coredata.get_genvs_default_buildtype_list() if self.gen_lite else [self.buildtype]
            for buildtype in multi_config_buildtype_list:
                ofile.write('\t\t%s|%s = %s|%s\n' %
                            (buildtype, self.platform, buildtype,
                             self.platform))
            ofile.write('\tEndGlobalSection\n')
            ofile.write('\tGlobalSection(ProjectConfigurationPlatforms) = '
                        'postSolution\n')
            # REGEN project (multi-)configurations
            for buildtype in multi_config_buildtype_list:
                ofile.write('\t\t{%s}.%s|%s.ActiveCfg = %s|%s\n' %
                            (self.environment.coredata.regen_guid, buildtype,
                                self.platform, buildtype, self.platform))
                if not self.gen_lite: # With a 'genvslite'-generated solution, the regen (i.e. reconfigure) utility is only intended to run when the user explicitly builds this proj.
                    ofile.write('\t\t{%s}.%s|%s.Build.0 = %s|%s\n' %
                                (self.environment.coredata.regen_guid, buildtype,
                                    self.platform, buildtype, self.platform))
            # Create the solution configuration
            for project_index, p in enumerate(projlist):
                if p[3] is MachineChoice.BUILD:
                    config_platform = self.build_platform
                else:
                    config_platform = self.platform
                # Add to the list of projects in this solution
                for buildtype in multi_config_buildtype_list:
                    ofile.write('\t\t{%s}.%s|%s.ActiveCfg = %s|%s\n' %
                                (p[2], buildtype, self.platform,
                                 buildtype, config_platform))
                    # If we're building the solution with Visual Studio's build system, enable building of buildable
                    # projects.  However, if we're building with meson (via --genvslite), then, since each project's
                    # 'build' action just ends up doing the same 'meson compile ...' we don't want the 'solution build'
                    # repeatedly going off and doing the same 'meson compile ...' multiple times over, so we default
                    # to building the startup project, which is the first listed project in the solution file by
                    # default for Visual Studio. The user is free to change this afterwards, but this provides a
                    # sensible default.
                    if (not self.gen_lite or project_index == 0) and \
                       p[0] in default_projlist and \
                       not isinstance(self.build.targets[p[0]], build.RunTarget):
                        ofile.write('\t\t{%s}.%s|%s.Build.0 = %s|%s\n' %
                                    (p[2], buildtype, self.platform,
                                     buildtype, config_platform))
            # RUN_TESTS and RUN_INSTALL project (multi-)configurations
            for buildtype in multi_config_buildtype_list:
                ofile.write('\t\t{%s}.%s|%s.ActiveCfg = %s|%s\n' %
                            (self.environment.coredata.test_guid, buildtype,
                             self.platform, buildtype, self.platform))
                ofile.write('\t\t{%s}.%s|%s.ActiveCfg = %s|%s\n' %
                            (self.environment.coredata.install_guid, buildtype,
                             self.platform, buildtype, self.platform))
            ofile.write('\tEndGlobalSection\n')
            ofile.write('\tGlobalSection(SolutionProperties) = preSolution\n')
            ofile.write('\t\tHideSolutionNode = FALSE\n')
            ofile.write('\tEndGlobalSection\n')
            if self.subdirs:
                ofile.write('\tGlobalSection(NestedProjects) = '
                            'preSolution\n')
                for p in projlist:
                    if p[1].parent != PurePath('.'):
                        ofile.write("\t\t{{{}}} = {{{}}}\n".format(p[2], self.subdirs[p[1].parent][0]))
                for subdir in self.subdirs.values():
                    if subdir[1]:
                        ofile.write("\t\t{{{}}} = {{{}}}\n".format(subdir[0], subdir[1]))
                ofile.write('\tEndGlobalSection\n')
            ofile.write('EndGlobal\n')
        replace_if_different(sln_filename, sln_filename_tmp)

    def generate_projects(self, vslite_ctx: dict = None) -> T.List[Project]:
        startup_project = self.environment.coredata.options[OptionKey('backend_startup_project')].value
        projlist: T.List[Project] = []
        startup_idx = 0
        for (i, (name, target)) in enumerate(self.build.targets.items()):
            if startup_project and startup_project == target.get_basename():
                startup_idx = i
            outdir = Path(
                self.environment.get_build_dir(),
                self.get_target_dir(target)
            )
            outdir.mkdir(exist_ok=True, parents=True)
            fname = name + '.vcxproj'
            target_dir = PurePath(self.get_target_dir(target))
            relname = target_dir / fname
            projfile_path = outdir / fname
            proj_uuid = self.environment.coredata.target_guids[name]
            generated = self.gen_vcxproj(target, str(projfile_path), proj_uuid, vslite_ctx)
            if generated:
                projlist.append((name, relname, proj_uuid, target.for_machine))

        # Put the startup project first in the project list
        if startup_idx:
            projlist.insert(0, projlist.pop(startup_idx))

        return projlist

    def split_sources(self, srclist):
        sources = []
        headers = []
        objects = []
        languages = []
        for i in srclist:
            if self.environment.is_header(i):
                headers.append(i)
            elif self.environment.is_object(i):
                objects.append(i)
            elif self.environment.is_source(i):
                sources.append(i)
                lang = self.lang_from_source_file(i)
                if lang not in languages:
                    languages.append(lang)
            elif self.environment.is_library(i):
                pass
            else:
                # Everything that is not an object or source file is considered a header.
                headers.append(i)
        return sources, headers, objects, languages

    def target_to_build_root(self, target):
        if self.get_target_dir(target) == '':
            return ''

        directories = os.path.normpath(self.get_target_dir(target)).split(os.sep)
        return os.sep.join(['..'] * len(directories))

    def quote_arguments(self, arr):
        return ['"%s"' % i for i in arr]

    def add_project_reference(self, root: ET.Element, include: str, projid: str, link_outputs: bool = False) -> None:
        ig = ET.SubElement(root, 'ItemGroup')
        pref = ET.SubElement(ig, 'ProjectReference', Include=include)
        ET.SubElement(pref, 'Project').text = '{%s}' % projid
        if not link_outputs:
            # Do not link in generated .lib files from dependencies automatically.
            # We only use the dependencies for ordering and link in the generated
            # objects and .lib files manually.
            ET.SubElement(pref, 'LinkLibraryDependencies').text = 'false'

    def add_target_deps(self, root: ET.Element, target):
        target_dict = {target.get_id(): target}
        for dep in self.get_target_deps(target_dict).values():
            if dep.get_id() in self.handled_target_deps[target.get_id()]:
                # This dependency was already handled manually.
                continue
            relpath = self.get_target_dir_relative_to(dep, target)
            vcxproj = os.path.join(relpath, dep.get_id() + '.vcxproj')
            tid = self.environment.coredata.target_guids[dep.get_id()]
            self.add_project_reference(root, vcxproj, tid)

    def create_basic_project(self, target_name, *,
                             temp_dir,
                             guid,
                             conftype='Utility',
                             target_ext=None,
                             target_platform=None) -> T.Tuple[ET.Element, ET.Element]:
        root = ET.Element('Project', {'DefaultTargets': "Build",
                                      'ToolsVersion': '4.0',
                                      'xmlns': 'http://schemas.microsoft.com/developer/msbuild/2003'})

        confitems = ET.SubElement(root, 'ItemGroup', {'Label': 'ProjectConfigurations'})
        if not target_platform:
            target_platform = self.platform

        multi_config_buildtype_list = coredata.get_genvs_default_buildtype_list() if self.gen_lite else [self.buildtype]
        for buildtype in multi_config_buildtype_list:
            prjconf = ET.SubElement(confitems, 'ProjectConfiguration',
                                    {'Include': buildtype + '|' + target_platform})
            ET.SubElement(prjconf, 'Configuration').text = buildtype
            ET.SubElement(prjconf, 'Platform').text = target_platform

        # Globals
        globalgroup = ET.SubElement(root, 'PropertyGroup', Label='Globals')
        guidelem = ET.SubElement(globalgroup, 'ProjectGuid')
        guidelem.text = '{%s}' % guid
        kw = ET.SubElement(globalgroup, 'Keyword')
        kw.text = self.platform + 'Proj'

        ET.SubElement(root, 'Import', Project=r'$(VCTargetsPath)\Microsoft.Cpp.Default.props')

        # Configuration
        type_config = ET.SubElement(root, 'PropertyGroup', Label='Configuration')
        ET.SubElement(type_config, 'ConfigurationType').text = conftype
        if self.platform_toolset:
            ET.SubElement(type_config, 'PlatformToolset').text = self.platform_toolset

        # This must come AFTER the '<PropertyGroup Label="Configuration">' element;  importing before the 'PlatformToolset' elt
        # gets set leads to msbuild failures reporting -
        #   "The build tools for v142 (Platform Toolset = 'v142') cannot be found. ... please install v142 build tools."
        # This is extremely unhelpful and misleading since the v14x build tools ARE installed.
        ET.SubElement(root, 'Import', Project=r'$(VCTargetsPath)\Microsoft.Cpp.props')

        # This attribute makes sure project names are displayed as expected in solution files even when their project file names differ
        pname = ET.SubElement(globalgroup, 'ProjectName')
        pname.text = target_name

        if not self.gen_lite: # Plenty of elements aren't necessary for 'makefile'-style project that just redirects to meson builds
            # XXX Wasn't here before for anything but gen_vcxproj , but seems fine?
            ns = ET.SubElement(globalgroup, 'RootNamespace')
            ns.text = target_name

            p = ET.SubElement(globalgroup, 'Platform')
            p.text = target_platform
            if self.windows_target_platform_version:
                ET.SubElement(globalgroup, 'WindowsTargetPlatformVersion').text = self.windows_target_platform_version
            ET.SubElement(globalgroup, 'UseMultiToolTask').text = 'true'

            ET.SubElement(type_config, 'CharacterSet').text = 'MultiByte'
            # Fixme: wasn't here before for gen_vcxproj()
            ET.SubElement(type_config, 'UseOfMfc').text = 'false'

            # Project information
            direlem = ET.SubElement(root, 'PropertyGroup')
            fver = ET.SubElement(direlem, '_ProjectFileVersion')
            fver.text = self.project_file_version
            outdir = ET.SubElement(direlem, 'OutDir')
            outdir.text = '.\\'
            intdir = ET.SubElement(direlem, 'IntDir')
            intdir.text = temp_dir + '\\'

            tname = ET.SubElement(direlem, 'TargetName')
            tname.text = target_name

            if target_ext:
                ET.SubElement(direlem, 'TargetExt').text = target_ext

            ET.SubElement(direlem, 'EmbedManifest').text = 'false'

        return (root, type_config)

    def gen_run_target_vcxproj(self, target: build.RunTarget, ofname: str, guid: str) -> None:
        (root, type_config) = self.create_basic_project(target.name,
                                                        temp_dir=target.get_id(),
                                                        guid=guid)
        depend_files = self.get_target_depend_files(target)

        if not target.command:
            # This is an alias target and thus doesn't run any command. It's
            # enough to emit the references to the other projects for them to
            # be built/run/..., if necessary.
            assert isinstance(target, build.AliasTarget)
            assert len(depend_files) == 0
        else:
            assert not isinstance(target, build.AliasTarget)

            target_env = self.get_run_target_env(target)
            _, _, cmd_raw = self.eval_custom_target_command(target)
            wrapper_cmd, _ = self.as_meson_exe_cmdline(target.command[0], cmd_raw[1:],
                                                       force_serialize=True, env=target_env,
                                                       verbose=True)
            self.add_custom_build(root, 'run_target', ' '.join(self.quote_arguments(wrapper_cmd)),
                                  deps=depend_files)

        # The import is needed even for alias targets, otherwise the build
        # target isn't defined
        ET.SubElement(root, 'Import', Project=r'$(VCTargetsPath)\Microsoft.Cpp.targets')
        self.add_regen_dependency(root)
        self.add_target_deps(root, target)
        self._prettyprint_vcxproj_xml(ET.ElementTree(root), ofname)

    def gen_custom_target_vcxproj(self, target: build.CustomTarget, ofname: str, guid: str) -> None:
        if target.for_machine is MachineChoice.BUILD:
            platform = self.build_platform
        else:
            platform = self.platform
        (root, type_config) = self.create_basic_project(target.name,
                                                        temp_dir=target.get_id(),
                                                        guid=guid,
                                                        target_platform=platform)
        # We need to always use absolute paths because our invocation is always
        # from the target dir, not the build root.
        target.absolute_paths = True
        (srcs, ofilenames, cmd) = self.eval_custom_target_command(target, True)
        depend_files = self.get_target_depend_files(target, True)
        # Always use a wrapper because MSBuild eats random characters when
        # there are many arguments.
        tdir_abs = os.path.join(self.environment.get_build_dir(), self.get_target_dir(target))
        extra_bdeps = target.get_transitive_build_target_deps()
        wrapper_cmd, _ = self.as_meson_exe_cmdline(target.command[0], cmd[1:],
                                                   # All targets run from the target dir
                                                   workdir=tdir_abs,
                                                   extra_bdeps=extra_bdeps,
                                                   capture=ofilenames[0] if target.capture else None,
                                                   feed=srcs[0] if target.feed else None,
                                                   force_serialize=True,
                                                   env=target.env,
                                                   verbose=target.console)
        if target.build_always_stale:
            # Use a nonexistent file to always consider the target out-of-date.
            ofilenames += [self.nonexistent_file(os.path.join(self.environment.get_scratch_dir(),
                                                 'outofdate.file'))]
        self.add_custom_build(root, 'custom_target', ' '.join(self.quote_arguments(wrapper_cmd)),
                              deps=wrapper_cmd[-1:] + srcs + depend_files, outputs=ofilenames,
                              verify_files=not target.build_always_stale)
        ET.SubElement(root, 'Import', Project=r'$(VCTargetsPath)\Microsoft.Cpp.targets')
        self.generate_custom_generator_commands(target, root)
        self.add_regen_dependency(root)
        self.add_target_deps(root, target)
        self._prettyprint_vcxproj_xml(ET.ElementTree(root), ofname)

    def gen_compile_target_vcxproj(self, target: build.CompileTarget, ofname: str, guid: str) -> None:
        if target.for_machine is MachineChoice.BUILD:
            platform = self.build_platform
        else:
            platform = self.platform
        (root, type_config) = self.create_basic_project(target.name,
                                                        temp_dir=target.get_id(),
                                                        guid=guid,
                                                        target_platform=platform)
        ET.SubElement(root, 'Import', Project=r'$(VCTargetsPath)\Microsoft.Cpp.targets')
        target.generated = [self.compile_target_to_generator(target)]
        target.sources = []
        self.generate_custom_generator_commands(target, root)
        self.add_regen_dependency(root)
        self.add_target_deps(root, target)
        self._prettyprint_vcxproj_xml(ET.ElementTree(root), ofname)

    @classmethod
    def lang_from_source_file(cls, src):
        ext = src.split('.')[-1]
        if ext in compilers.c_suffixes:
            return 'c'
        if ext in compilers.cpp_suffixes:
            return 'cpp'
        raise MesonException(f'Could not guess language from source file {src}.')

    def add_pch(self, pch_sources, lang, inc_cl):
        if lang in pch_sources:
            self.use_pch(pch_sources, lang, inc_cl)

    def create_pch(self, pch_sources, lang, inc_cl):
        pch = ET.SubElement(inc_cl, 'PrecompiledHeader')
        pch.text = 'Create'
        self.add_pch_files(pch_sources, lang, inc_cl)

    def use_pch(self, pch_sources, lang, inc_cl):
        pch = ET.SubElement(inc_cl, 'PrecompiledHeader')
        pch.text = 'Use'
        header = self.add_pch_files(pch_sources, lang, inc_cl)
        pch_include = ET.SubElement(inc_cl, 'ForcedIncludeFiles')
        pch_include.text = header + ';%(ForcedIncludeFiles)'

    def add_pch_files(self, pch_sources, lang, inc_cl):
        header = os.path.basename(pch_sources[lang][0])
        pch_file = ET.SubElement(inc_cl, 'PrecompiledHeaderFile')
        # When USING PCHs, MSVC will not do the regular include
        # directory lookup, but simply use a string match to find the
        # PCH to use. That means the #include directive must match the
        # pch_file.text used during PCH CREATION verbatim.
        # When CREATING a PCH, MSVC will do the include directory
        # lookup to find the actual PCH header to use. Thus, the PCH
        # header must either be in the include_directories of the target
        # or be in the same directory as the PCH implementation.
        pch_file.text = header
        pch_out = ET.SubElement(inc_cl, 'PrecompiledHeaderOutputFile')
        pch_out.text = f'$(IntDir)$(TargetName)-{lang}.pch'

        # Need to set the name for the pdb, as cl otherwise gives it a static
        # name. Which leads to problems when there is more than one pch
        # (e.g. for different languages).
        pch_pdb = ET.SubElement(inc_cl, 'ProgramDataBaseFileName')
        pch_pdb.text = f'$(IntDir)$(TargetName)-{lang}.pdb'

        return header

    def is_argument_with_msbuild_xml_entry(self, entry):
        # Remove arguments that have a top level XML entry so
        # they are not used twice.
        # FIXME add args as needed.
        if entry[1:].startswith('fsanitize'):
            return True
        return entry[1:].startswith('M')

    def add_additional_options(self, lang, parent_node, file_args):
        args = []
        for arg in file_args[lang].to_native():
            if self.is_argument_with_msbuild_xml_entry(arg):
                continue
            if arg == '%(AdditionalOptions)':
                args.append(arg)
            else:
                args.append(self.escape_additional_option(arg))
        ET.SubElement(parent_node, "AdditionalOptions").text = ' '.join(args)

    # Set up each project's source file ('CLCompile') element with appropriate preprocessor, include dir, and compile option values for correct intellisense.
    def add_project_nmake_defs_incs_and_opts(self, parent_node, src: str, defs_paths_opts_per_lang_and_buildtype: dict, platform: str):
        # For compactness, sources whose type matches the primary src type (i.e. most frequent in the set of source types used in the target/project,
        # according to the 'captured_build_args' map), can simply reference the preprocessor definitions, include dirs, and compile option NMake fields of
        # the project itself.
        # However, if a src is of a non-primary type, it could have totally different defs/dirs/options so we're going to have to fill in the full, verbose
        # set of values for these fields, which needs to be fully expanded per build type / configuration.
        #
        # FIXME:  Suppose a project contains .cpp and .c src files with different compile defs/dirs/options, while also having .h files, some of which
        # are included by .cpp sources and others included by .c sources:  How do we know whether the .h source should be using the .cpp or .c src
        # defs/dirs/options?  Might it also be possible for a .h header to be shared between .cpp and .c sources?  If so, I don't see how we can
        # correctly configure these intellisense fields.
        # For now, all sources/headers that fail to find their extension's language in the '...nmake_defs_paths_opts...' map will just adopt the project
        # defs/dirs/opts that are set for the nominal 'primary' src type.
        ext = src.split('.')[-1]
        lang = compilers.compilers.SUFFIX_TO_LANG.get(ext, None)
        if lang in defs_paths_opts_per_lang_and_buildtype.keys():
            # This is a non-primary src type for which can't simply reference the project's nmake fields;
            # we must laboriously fill in the fields for all buildtypes.
            for buildtype in coredata.get_genvs_default_buildtype_list():
                (defs, paths, opts) = defs_paths_opts_per_lang_and_buildtype[lang][buildtype]
                condition = f'\'$(Configuration)|$(Platform)\'==\'{buildtype}|{platform}\''
                ET.SubElement(parent_node, 'PreprocessorDefinitions', Condition=condition).text = defs
                ET.SubElement(parent_node, 'AdditionalIncludeDirectories', Condition=condition).text = paths
                ET.SubElement(parent_node, 'AdditionalOptions', Condition=condition).text = opts
        else: # Can't find bespoke nmake defs/dirs/opts fields for this extention, so just reference the project's fields
            ET.SubElement(parent_node, 'PreprocessorDefinitions').text = '$(NMakePreprocessorDefinitions)'
            ET.SubElement(parent_node, 'AdditionalIncludeDirectories').text = '$(NMakeIncludeSearchPath)'
            ET.SubElement(parent_node, 'AdditionalOptions').text = '$(AdditionalOptions)'

    def add_preprocessor_defines(self, lang, parent_node, file_defines):
        defines = []
        for define in file_defines[lang]:
            if define == '%(PreprocessorDefinitions)':
                defines.append(define)
            else:
                defines.append(self.escape_preprocessor_define(define))
        ET.SubElement(parent_node, "PreprocessorDefinitions").text = ';'.join(defines)

    def add_include_dirs(self, lang, parent_node, file_inc_dirs):
        dirs = file_inc_dirs[lang]
        ET.SubElement(parent_node, "AdditionalIncludeDirectories").text = ';'.join(dirs)

    @staticmethod
    def escape_preprocessor_define(define: str) -> str:
        # See: https://msdn.microsoft.com/en-us/library/bb383819.aspx
        table = str.maketrans({'%': '%25', '$': '%24', '@': '%40',
                               "'": '%27', ';': '%3B', '?': '%3F', '*': '%2A',
                               # We need to escape backslash because it'll be un-escaped by
                               # Windows during process creation when it parses the arguments
                               # Basically, this converts `\` to `\\`.
                               '\\': '\\\\'})
        return define.translate(table)

    @staticmethod
    def escape_additional_option(option: str) -> str:
        # See: https://msdn.microsoft.com/en-us/library/bb383819.aspx
        table = str.maketrans({'%': '%25', '$': '%24', '@': '%40',
                               "'": '%27', ';': '%3B', '?': '%3F', '*': '%2A', ' ': '%20'})
        option = option.translate(table)
        # Since we're surrounding the option with ", if it ends in \ that will
        # escape the " when the process arguments are parsed and the starting
        # " will not terminate. So we escape it if that's the case.  I'm not
        # kidding, this is how escaping works for process args on Windows.
        if option.endswith('\\'):
            option += '\\'
        return f'"{option}"'

    @staticmethod
    def split_link_args(args):
        """
        Split a list of link arguments into three lists:
        * library search paths
        * library filenames (or paths)
        * other link arguments
        """
        lpaths = []
        libs = []
        other = []
        for arg in args:
            if arg.startswith('/LIBPATH:'):
                lpath = arg[9:]
                # De-dup library search paths by removing older entries when
                # a new one is found. This is necessary because unlike other
                # search paths such as the include path, the library is
                # searched for in the newest (right-most) search path first.
                if lpath in lpaths:
                    lpaths.remove(lpath)
                lpaths.append(lpath)
            elif arg.startswith(('/', '-')):
                other.append(arg)
            # It's ok if we miss libraries with non-standard extensions here.
            # They will go into the general link arguments.
            elif arg.endswith('.lib') or arg.endswith('.a'):
                # De-dup
                if arg not in libs:
                    libs.append(arg)
            else:
                other.append(arg)
        return lpaths, libs, other

    def _get_cl_compiler(self, target):
        for lang, c in target.compilers.items():
            if lang in {'c', 'cpp'}:
                return c
        # No source files, only objects, but we still need a compiler, so
        # return a found compiler
        if len(target.objects) > 0:
            for lang, c in self.environment.coredata.compilers[target.for_machine].items():
                if lang in {'c', 'cpp'}:
                    return c
        raise MesonException('Could not find a C or C++ compiler. MSVC can only build C/C++ projects.')

    def _prettyprint_vcxproj_xml(self, tree: ET.ElementTree, ofname: str) -> None:
        ofname_tmp = ofname + '~'
        tree.write(ofname_tmp, encoding='utf-8', xml_declaration=True)

        # ElementTree cannot do pretty-printing, so do it manually
        doc = xml.dom.minidom.parse(ofname_tmp)
        with open(ofname_tmp, 'w', encoding='utf-8') as of:
            of.write(doc.toprettyxml())
        replace_if_different(ofname, ofname_tmp)

    # Returns:  (target_args,file_args), (target_defines,file_defines), (target_inc_dirs,file_inc_dirs)
    def get_args_defines_and_inc_dirs(self, target, compiler, generated_files_include_dirs, proj_to_src_root, proj_to_src_dir, build_args):
        # Arguments, include dirs, defines for all files in the current target
        target_args = []
        target_defines = []
        target_inc_dirs = []
        # Arguments, include dirs, defines passed to individual files in
        # a target; perhaps because the args are language-specific
        #
        # file_args is also later split out into defines and include_dirs in
        # case someone passed those in there
        file_args: T.Dict[str, CompilerArgs] = {l: c.compiler_args() for l, c in target.compilers.items()}
        file_defines = {l: [] for l in target.compilers}
        file_inc_dirs = {l: [] for l in target.compilers}
        # The order in which these compile args are added must match
        # generate_single_compile() and generate_basic_compiler_args()
        for l, comp in target.compilers.items():
            if l in file_args:
                file_args[l] += compilers.get_base_compile_args(
                    target.get_options(), comp)
                file_args[l] += comp.get_option_compile_args(
                    target.get_options())

        # Add compile args added using add_project_arguments()
        for l, args in self.build.projects_args[target.for_machine].get(target.subproject, {}).items():
            if l in file_args:
                file_args[l] += args
        # Add compile args added using add_global_arguments()
        # These override per-project arguments
        for l, args in self.build.global_args[target.for_machine].items():
            if l in file_args:
                file_args[l] += args
        # Compile args added from the env or cross file: CFLAGS/CXXFLAGS, etc. We want these
        # to override all the defaults, but not the per-target compile args.
        for l in file_args.keys():
            file_args[l] += target.get_option(OptionKey('args', machine=target.for_machine, lang=l))
        for args in file_args.values():
            # This is where Visual Studio will insert target_args, target_defines,
            # etc, which are added later from external deps (see below).
            args += ['%(AdditionalOptions)', '%(PreprocessorDefinitions)', '%(AdditionalIncludeDirectories)']
            # Add custom target dirs as includes automatically, but before
            # target-specific include dirs. See _generate_single_compile() in
            # the ninja backend for caveats.
            args += ['-I' + arg for arg in generated_files_include_dirs]
            # Add include dirs from the `include_directories:` kwarg on the target
            # and from `include_directories:` of internal deps of the target.
            #
            # Target include dirs should override internal deps include dirs.
            # This is handled in BuildTarget.process_kwargs()
            #
            # Include dirs from internal deps should override include dirs from
            # external deps and must maintain the order in which they are
            # specified. Hence, we must reverse so that the order is preserved.
            #
            # These are per-target, but we still add them as per-file because we
            # need them to be looked in first.
            for d in reversed(target.get_include_dirs()):
                # reversed is used to keep order of includes
                for i in reversed(d.get_incdirs()):
                    curdir = os.path.join(d.get_curdir(), i)
                    try:
                        # Add source subdir first so that the build subdir overrides it
                        args.append('-I' + os.path.join(proj_to_src_root, curdir))  # src dir
                        args.append('-I' + self.relpath(curdir, target.subdir)) # build dir
                    except ValueError:
                        # Include is on different drive
                        args.append('-I' + os.path.normpath(curdir))
                for i in d.get_extra_build_dirs():
                    curdir = os.path.join(d.get_curdir(), i)
                    args.append('-I' + self.relpath(curdir, target.subdir))  # build dir
        # Add per-target compile args, f.ex, `c_args : ['/DFOO']`. We set these
        # near the end since these are supposed to override everything else.
        for l, args in target.extra_args.items():
            if l in file_args:
                file_args[l] += args
        # The highest priority includes. In order of directory search:
        # target private dir, target build dir, target source dir
        for args in file_args.values():
            t_inc_dirs = [self.relpath(self.get_target_private_dir(target),
                                       self.get_target_dir(target))]
            if target.implicit_include_directories:
                t_inc_dirs += ['.', proj_to_src_dir]
            args += ['-I' + arg for arg in t_inc_dirs]

        # Split preprocessor defines and include directories out of the list of
        # all extra arguments. The rest go into %(AdditionalOptions).
        for l, args in file_args.items():
            for arg in args[:]:
                if arg.startswith(('-D', '/D')) or arg == '%(PreprocessorDefinitions)':
                    file_args[l].remove(arg)
                    # Don't escape the marker
                    if arg == '%(PreprocessorDefinitions)':
                        define = arg
                    else:
                        define = arg[2:]
                    # De-dup
                    if define not in file_defines[l]:
                        file_defines[l].append(define)
                elif arg.startswith(('-I', '/I')) or arg == '%(AdditionalIncludeDirectories)':
                    file_args[l].remove(arg)
                    # Don't escape the marker
                    if arg == '%(AdditionalIncludeDirectories)':
                        inc_dir = arg
                    else:
                        inc_dir = arg[2:]
                    # De-dup
                    if inc_dir not in file_inc_dirs[l]:
                        file_inc_dirs[l].append(inc_dir)
                    # Add include dirs to target as well so that "Go to Document" works in headers
                    if inc_dir not in target_inc_dirs:
                        target_inc_dirs.append(inc_dir)

        # Split compile args needed to find external dependencies
        # Link args are added while generating the link command
        for d in reversed(target.get_external_deps()):
            # Cflags required by external deps might have UNIX-specific flags,
            # so filter them out if needed
            if d.name != 'openmp':
                d_compile_args = compiler.unix_args_to_native(d.get_compile_args())
                for arg in d_compile_args:
                    if arg.startswith(('-D', '/D')):
                        define = arg[2:]
                        # De-dup
                        if define in target_defines:
                            target_defines.remove(define)
                        target_defines.append(define)
                    elif arg.startswith(('-I', '/I')):
                        inc_dir = arg[2:]
                        # De-dup
                        if inc_dir not in target_inc_dirs:
                            target_inc_dirs.append(inc_dir)
                    else:
                        target_args.append(arg)

        if '/Gw' in build_args:
            target_args.append('/Gw')

        return (target_args, file_args), (target_defines, file_defines), (target_inc_dirs, file_inc_dirs)

    @staticmethod
    def get_build_args(compiler, optimization_level: str, debug: bool, sanitize: str) -> T.List[str]:
        build_args = compiler.get_optimization_args(optimization_level)
        build_args += compiler.get_debug_args(debug)
        build_args += compiler.sanitizer_compile_args(sanitize)

        return build_args

    # Used in populating a simple nmake-style project's intellisense fields.
    # Given a list of compile args, for example -
    #    [ '-I..\\some\\dir\\include', '-I../../some/other/dir', '/MDd', '/W2', '/std:c++17', '/Od', '/Zi', '-DSOME_DEF=1', '-DANOTHER_DEF=someval', ...]
    # returns a tuple of pre-processor defs (for this example) -
    #    'SOME_DEF=1;ANOTHER_DEF=someval;'
    # and include paths, e.g. -
    #    '..\\some\\dir\\include;../../some/other/dir;'
    # and finally any remaining compiler options, e.g. -
    #    '/MDd /W2 /std:c++17 /Od/Zi'
    @staticmethod
    def _extract_nmake_fields(captured_build_args: list[str]) -> T.Tuple[str, str, str]:
        include_dir_options = [
            '-I',
            '/I',
            '-isystem', # regular gcc / clang option to denote system header include search paths
            '/clang:-isystem', # clang-cl (msvc 'cl'-style clang wrapper) option to pass '-isystem' option to clang driver
            '/imsvc', # clang-cl option to 'Add directory to system include search path'
            '/external:I', # msvc cl option to add 'external' include search paths
        ]

        defs = ''
        paths = '$(VC_IncludePath);$(WindowsSDK_IncludePath);'
        additional_opts = ''
        for arg in captured_build_args:
            if arg.startswith(('-D', '/D')):
                defs += arg[2:] + ';'
            else:
                opt_match = next((opt for opt in include_dir_options if arg.startswith(opt)), None)
                if opt_match:
                    paths += arg[len(opt_match):] + ';'
                elif arg.startswith(('-', '/')):
                    additional_opts += arg + ' '
        return (defs, paths, additional_opts)

    @staticmethod
    def get_nmake_base_meson_command_and_exe_search_paths() -> T.Tuple[str, str]:
        meson_cmd_list = mesonlib.get_meson_command()
        assert (len(meson_cmd_list) == 1) or (len(meson_cmd_list) == 2)
        # We expect get_meson_command() to either be of the form -
        #   1:  ['path/to/meson.exe']
        # or -
        #   2:  ['path/to/python.exe', 'and/path/to/meson.py']
        # so we'd like to ensure our makefile-style project invokes the same meson executable or python src as this instance.
        exe_search_paths = os.path.dirname(meson_cmd_list[0])
        nmake_base_meson_command = os.path.basename(meson_cmd_list[0])
        if len(meson_cmd_list) != 1:
            # We expect to be dealing with case '2', shown above.
            # With Windows, it's also possible that we get a path to the second element of meson_cmd_list that contains spaces
            # (e.g. 'and/path to/meson.py').  So, because this will end up directly in the makefile/NMake command lines, we'd
            # better always enclose it in quotes.  Only strictly necessary for paths with spaces but no harm for paths without -
            nmake_base_meson_command += ' \"' + meson_cmd_list[1] + '\"'
            exe_search_paths += ';' + os.path.dirname(meson_cmd_list[1])

        # Additionally, in some cases, we appear to have to add 'C:\Windows\system32;C:\Windows' to the 'Path' environment (via the
        # ExecutablePath element), without which, the 'meson compile ...' (NMakeBuildCommandLine) command can fail (failure to find
        # stdio.h and similar), so something is quietly switching some critical build behaviour based on the presence of these in
        # the 'Path'.
        # Not sure if this ultimately comes down to some 'find and guess' hidden behaviours within meson or within MSVC tools, but
        # I guess some projects may implicitly rely on this behaviour.
        # Things would be cleaner, more robust, repeatable, and portable if meson (and msvc tools) replaced all this kind of
        # find/guess behaviour with the requirement that things just be explicitly specified by the user.
        # An example of this can be seen with -
        #   1:  Download https://github.com/facebook/zstd source
        #   2:  cd to the 'zstd-dev\build\meson' dir
        #   3:  meson setup -Dbin_programs=true -Dbin_contrib=true --genvslite vs2022 builddir_vslite
        #   4:  Open the generated 'builddir_vslite_vs\zstd.sln' and build through a project, which should explicitly add the above to
        #       the project's 'Executable Directories' paths and build successfully.
        #   5:  Remove 'C:\Windows\system32;C:\Windows;' from the same project's 'Executable Directories' paths and rebuild.
        #       This should now fail.
        # It feels uncomfortable to do this but what better alternative is there (and might this introduce new problems)? -
        exe_search_paths += ';C:\\Windows\\system32;C:\\Windows'
        # A meson project that explicitly specifies compiler/linker tools and sdk/include paths is not going to have any problems
        # with this addition.

        return (nmake_base_meson_command, exe_search_paths)

    def add_gen_lite_makefile_vcxproj_elements(self,
                                               root: ET.Element,
                                               platform: str,
                                               target_ext: str,
                                               vslite_ctx: dict,
                                               target,
                                               proj_to_build_root: str,
                                               primary_src_lang: T.Optional[str]) -> None:
        ET.SubElement(root, 'ImportGroup', Label='ExtensionSettings')
        ET.SubElement(root, 'ImportGroup', Label='Shared')
        prop_sheets_grp = ET.SubElement(root, 'ImportGroup', Label='PropertySheets')
        ET.SubElement(prop_sheets_grp, 'Import', {'Project': r'$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props',
                                                  'Condition': r"exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')",
                                                  'Label': 'LocalAppDataPlatform'
                                                  })
        ET.SubElement(root, 'PropertyGroup', Label='UserMacros')

        (nmake_base_meson_command, exe_search_paths) = Vs2010Backend.get_nmake_base_meson_command_and_exe_search_paths()

        # Relative path from this .vcxproj to the directory containing the set of '..._[debug/debugoptimized/release]' setup meson build dirs.
        proj_to_multiconfigured_builds_parent_dir = os.path.join(proj_to_build_root, '..')

        # Conditional property groups per configuration (buildtype). E.g. -
        #   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release|x64'">
        multi_config_buildtype_list = coredata.get_genvs_default_buildtype_list()
        for buildtype in multi_config_buildtype_list:
            per_config_prop_group = ET.SubElement(root, 'PropertyGroup', Condition=f'\'$(Configuration)|$(Platform)\'==\'{buildtype}|{platform}\'')
            (_, build_dir_tail) = os.path.split(self.src_to_build)
            meson_build_dir_for_buildtype = build_dir_tail[:-2] + buildtype # Get the buildtype suffixed 'builddir_[debug/release/etc]' from 'builddir_vs', for example.
            proj_to_build_dir_for_buildtype = str(os.path.join(proj_to_multiconfigured_builds_parent_dir, meson_build_dir_for_buildtype))
            ET.SubElement(per_config_prop_group, 'OutDir').text = f'{proj_to_build_dir_for_buildtype}\\'
            ET.SubElement(per_config_prop_group, 'IntDir').text = f'{proj_to_build_dir_for_buildtype}\\'
            ET.SubElement(per_config_prop_group, 'NMakeBuildCommandLine').text = f'{nmake_base_meson_command} compile -C "{proj_to_build_dir_for_buildtype}"'
            ET.SubElement(per_config_prop_group, 'NMakeOutput').text = f'$(OutDir){target.name}{target_ext}'
            captured_build_args = vslite_ctx[buildtype][target.get_id()]
            # 'captured_build_args' is a dictionary, mapping from each src file type to a list of compile args to use for that type.
            # Usually, there's just one but we could have multiple src types.  However, since there's only one field for the makefile
            # project's NMake... preprocessor/include intellisense fields, we'll just use the first src type we have to fill in
            # these fields.  Then, any src files in this VS project that aren't of this first src type will then need to override
            # its intellisense fields instead of simply referencing the values in the project.
            ET.SubElement(per_config_prop_group, 'NMakeReBuildCommandLine').text = f'{nmake_base_meson_command} compile -C "{proj_to_build_dir_for_buildtype}" --clean && {nmake_base_meson_command} compile -C "{proj_to_build_dir_for_buildtype}"'
            ET.SubElement(per_config_prop_group, 'NMakeCleanCommandLine').text = f'{nmake_base_meson_command} compile -C "{proj_to_build_dir_for_buildtype}" --clean'
            # Need to set the 'ExecutablePath' element for the above NMake... commands to be able to invoke the meson command.
            ET.SubElement(per_config_prop_group, 'ExecutablePath').text = exe_search_paths
            # We may not have any src files and so won't have a primary src language.  In which case, we've nothing to fill in for this target's intellisense fields -
            if primary_src_lang:
                primary_src_type_build_args = captured_build_args[primary_src_lang]
                preproc_defs, inc_paths, other_compile_opts = Vs2010Backend._extract_nmake_fields(primary_src_type_build_args)
                ET.SubElement(per_config_prop_group, 'NMakePreprocessorDefinitions').text = preproc_defs
                ET.SubElement(per_config_prop_group, 'NMakeIncludeSearchPath').text = inc_paths
                ET.SubElement(per_config_prop_group, 'AdditionalOptions').text = other_compile_opts

            # Unless we explicitly specify the following empty path elements, the project is assigned a load of nasty defaults that fill these
            # with values like -
            #    $(VC_IncludePath);$(WindowsSDK_IncludePath);
            # which are all based on the current install environment (a recipe for non-reproducibility problems), not the paths that will be used by
            # the actual meson compile jobs.  Although these elements look like they're only for MSBuild operations, they're not needed with our simple,
            # lite/makefile-style projects so let's just remove them in case they do get used/confused by intellisense.
            ET.SubElement(per_config_prop_group, 'IncludePath')
            ET.SubElement(per_config_prop_group, 'ExternalIncludePath')
            ET.SubElement(per_config_prop_group, 'ReferencePath')
            ET.SubElement(per_config_prop_group, 'LibraryPath')
            ET.SubElement(per_config_prop_group, 'LibraryWPath')
            ET.SubElement(per_config_prop_group, 'SourcePath')
            ET.SubElement(per_config_prop_group, 'ExcludePath')

    def add_non_makefile_vcxproj_elements(
            self,
            root: ET.Element,
            type_config: ET.Element,
            target,
            platform: str,
            subsystem,
            build_args,
            target_args,
            target_defines,
            target_inc_dirs,
            file_args
            ) -> None:
        compiler = self._get_cl_compiler(target)
        buildtype_link_args = compiler.get_optimization_link_args(self.optimization)

        # Prefix to use to access the build root from the vcxproj dir
        down = self.target_to_build_root(target)

        # FIXME: Should the following just be set in create_basic_project(), even if
        # irrelevant for current target?

        # FIXME: Meson's LTO support needs to be integrated here
        ET.SubElement(type_config, 'WholeProgramOptimization').text = 'false'
        # Let VS auto-set the RTC level
        ET.SubElement(type_config, 'BasicRuntimeChecks').text = 'Default'
        # Incremental linking increases code size
        if '/INCREMENTAL:NO' in buildtype_link_args:
            ET.SubElement(type_config, 'LinkIncremental').text = 'false'

        # Build information
        compiles = ET.SubElement(root, 'ItemDefinitionGroup')
        clconf = ET.SubElement(compiles, 'ClCompile')
        if True in ((dep.name == 'openmp') for dep in target.get_external_deps()):
            ET.SubElement(clconf, 'OpenMPSupport').text = 'true'
        # CRT type; debug or release
        vscrt_type = target.get_option(OptionKey('b_vscrt'))
        vscrt_val = compiler.get_crt_val(vscrt_type, self.buildtype)
        if vscrt_val == 'mdd':
            ET.SubElement(type_config, 'UseDebugLibraries').text = 'true'
            ET.SubElement(clconf, 'RuntimeLibrary').text = 'MultiThreadedDebugDLL'
        elif vscrt_val == 'mt':
            # FIXME, wrong
            ET.SubElement(type_config, 'UseDebugLibraries').text = 'false'
            ET.SubElement(clconf, 'RuntimeLibrary').text = 'MultiThreaded'
        elif vscrt_val == 'mtd':
            # FIXME, wrong
            ET.SubElement(type_config, 'UseDebugLibraries').text = 'true'
            ET.SubElement(clconf, 'RuntimeLibrary').text = 'MultiThreadedDebug'
        else:
            ET.SubElement(type_config, 'UseDebugLibraries').text = 'false'
            ET.SubElement(clconf, 'RuntimeLibrary').text = 'MultiThreadedDLL'
        # Sanitizers
        if '/fsanitize=address' in build_args:
            ET.SubElement(type_config, 'EnableASAN').text = 'true'
        # Debug format
        if '/ZI' in build_args:
            ET.SubElement(clconf, 'DebugInformationFormat').text = 'EditAndContinue'
        elif '/Zi' in build_args:
            ET.SubElement(clconf, 'DebugInformationFormat').text = 'ProgramDatabase'
        elif '/Z7' in build_args:
            ET.SubElement(clconf, 'DebugInformationFormat').text = 'OldStyle'
        else:
            ET.SubElement(clconf, 'DebugInformationFormat').text = 'None'
        # Runtime checks
        if '/RTC1' in build_args:
            ET.SubElement(clconf, 'BasicRuntimeChecks').text = 'EnableFastChecks'
        elif '/RTCu' in build_args:
            ET.SubElement(clconf, 'BasicRuntimeChecks').text = 'UninitializedLocalUsageCheck'
        elif '/RTCs' in build_args:
            ET.SubElement(clconf, 'BasicRuntimeChecks').text = 'StackFrameRuntimeCheck'
        # Exception handling has to be set in the xml in addition to the "AdditionalOptions" because otherwise
        # cl will give warning D9025: overriding '/Ehs' with cpp_eh value
        if 'cpp' in target.compilers:
            eh = target.get_option(OptionKey('eh', machine=target.for_machine, lang='cpp'))
            if eh == 'a':
                ET.SubElement(clconf, 'ExceptionHandling').text = 'Async'
            elif eh == 's':
                ET.SubElement(clconf, 'ExceptionHandling').text = 'SyncCThrow'
            elif eh == 'none':
                ET.SubElement(clconf, 'ExceptionHandling').text = 'false'
            else:  # 'sc' or 'default'
                ET.SubElement(clconf, 'ExceptionHandling').text = 'Sync'

        if len(target_args) > 0:
            target_args.append('%(AdditionalOptions)')
            ET.SubElement(clconf, "AdditionalOptions").text = ' '.join(target_args)
        ET.SubElement(clconf, 'AdditionalIncludeDirectories').text = ';'.join(target_inc_dirs)
        target_defines.append('%(PreprocessorDefinitions)')
        ET.SubElement(clconf, 'PreprocessorDefinitions').text = ';'.join(target_defines)
        ET.SubElement(clconf, 'FunctionLevelLinking').text = 'true'
        # Warning level
        warning_level = T.cast('str', target.get_option(OptionKey('warning_level')))
        warning_level = 'EnableAllWarnings' if warning_level == 'everything' else 'Level' + str(1 + int(warning_level))
        ET.SubElement(clconf, 'WarningLevel').text = warning_level
        if target.get_option(OptionKey('werror')):
            ET.SubElement(clconf, 'TreatWarningAsError').text = 'true'
        # Optimization flags
        o_flags = split_o_flags_args(build_args)
        if '/Ox' in o_flags:
            ET.SubElement(clconf, 'Optimization').text = 'Full'
        elif '/O2' in o_flags:
            ET.SubElement(clconf, 'Optimization').text = 'MaxSpeed'
        elif '/O1' in o_flags:
            ET.SubElement(clconf, 'Optimization').text = 'MinSpace'
        elif '/Od' in o_flags:
            ET.SubElement(clconf, 'Optimization').text = 'Disabled'
        if '/Oi' in o_flags:
            ET.SubElement(clconf, 'IntrinsicFunctions').text = 'true'
        if '/Ob1' in o_flags:
            ET.SubElement(clconf, 'InlineFunctionExpansion').text = 'OnlyExplicitInline'
        elif '/Ob2' in o_flags:
            ET.SubElement(clconf, 'InlineFunctionExpansion').text = 'AnySuitable'
        # Size-preserving flags
        if '/Os' in o_flags or '/O1' in o_flags:
            ET.SubElement(clconf, 'FavorSizeOrSpeed').text = 'Size'
        # Note: setting FavorSizeOrSpeed with clang-cl conflicts with /Od and can make debugging difficult, so don't.
        elif '/Od' not in o_flags:
            ET.SubElement(clconf, 'FavorSizeOrSpeed').text = 'Speed'
        # Note: SuppressStartupBanner is /NOLOGO and is 'true' by default
        self.generate_lang_standard_info(file_args, clconf)

        resourcecompile = ET.SubElement(compiles, 'ResourceCompile')
        ET.SubElement(resourcecompile, 'PreprocessorDefinitions')

        # Linker options
        link = ET.SubElement(compiles, 'Link')
        extra_link_args = compiler.compiler_args()
        extra_link_args += compiler.get_optimization_link_args(self.optimization)
        # Generate Debug info
        if self.debug:
            self.generate_debug_information(link)
        else:
            ET.SubElement(link, 'GenerateDebugInformation').text = 'false'
        if not isinstance(target, build.StaticLibrary):
            if isinstance(target, build.SharedModule):
                extra_link_args += compiler.get_std_shared_module_link_args(target.get_options())
            # Add link args added using add_project_link_arguments()
            extra_link_args += self.build.get_project_link_args(compiler, target.subproject, target.for_machine)
            # Add link args added using add_global_link_arguments()
            # These override per-project link arguments
            extra_link_args += self.build.get_global_link_args(compiler, target.for_machine)
            # Link args added from the env: LDFLAGS, or the cross file. We want
            # these to override all the defaults but not the per-target link
            # args.
            extra_link_args += self.environment.coredata.get_external_link_args(
                target.for_machine, compiler.get_language())
            # Only non-static built targets need link args and link dependencies
            extra_link_args += target.link_args
            # External deps must be last because target link libraries may depend on them.
            for dep in target.get_external_deps():
                # Extend without reordering or de-dup to preserve `-L -l` sets
                # https://github.com/mesonbuild/meson/issues/1718
                if dep.name == 'openmp':
                    ET.SubElement(clconf, 'OpenMPSupport').text = 'true'
                else:
                    extra_link_args.extend_direct(dep.get_link_args())
            for d in target.get_dependencies():
                if isinstance(d, build.StaticLibrary):
                    for dep in d.get_external_deps():
                        if dep.name == 'openmp':
                            ET.SubElement(clconf, 'OpenMPSupport').text = 'true'
                        else:
                            extra_link_args.extend_direct(dep.get_link_args())
        # Add link args for c_* or cpp_* build options. Currently this only
        # adds c_winlibs and cpp_winlibs when building for Windows. This needs
        # to be after all internal and external libraries so that unresolved
        # symbols from those can be found here. This is needed when the
        # *_winlibs that we want to link to are static mingw64 libraries.
        extra_link_args += compiler.get_option_link_args(target.get_options())
        (additional_libpaths, additional_links, extra_link_args) = self.split_link_args(extra_link_args.to_native())

        # Add more libraries to be linked if needed
        for t in target.get_dependencies():
            if isinstance(t, build.CustomTargetIndex):
                # We don't need the actual project here, just the library name
                lobj = t
            else:
                lobj = self.build.targets[t.get_id()]
            linkname = os.path.join(down, self.get_target_filename_for_linking(lobj))
            if t in target.link_whole_targets:
                if compiler.id == 'msvc' and version_compare(compiler.version, '<19.00.23918'):
                    # Expand our object lists manually if we are on pre-Visual Studio 2015 Update 2
                    l = t.extract_all_objects(False)

                    # Unfortunately, we can't use self.object_filename_from_source()
                    for gen in l.genlist:
                        for src in gen.get_outputs():
                            if self.environment.is_source(src):
                                path = self.get_target_generated_dir(t, gen, src)
                                gen_src_ext = '.' + os.path.splitext(path)[1][1:]
                                extra_link_args.append(path[:-len(gen_src_ext)] + '.obj')

                    for src in l.srclist:
                        if self.environment.is_source(src):
                            target_private_dir = self.relpath(self.get_target_private_dir(t),
                                                              self.get_target_dir(t))
                            rel_obj = self.object_filename_from_source(t, src, target_private_dir)
                            extra_link_args.append(rel_obj)

                    extra_link_args.extend(self.flatten_object_list(t))
                else:
                    # /WHOLEARCHIVE:foo must go into AdditionalOptions
                    extra_link_args += compiler.get_link_whole_for(linkname)
                # To force Visual Studio to build this project even though it
                # has no sources, we include a reference to the vcxproj file
                # that builds this target. Technically we should add this only
                # if the current target has no sources, but it doesn't hurt to
                # have 'extra' references.
                trelpath = self.get_target_dir_relative_to(t, target)
                tvcxproj = os.path.join(trelpath, t.get_id() + '.vcxproj')
                tid = self.environment.coredata.target_guids[t.get_id()]
                self.add_project_reference(root, tvcxproj, tid, link_outputs=True)
                # Mark the dependency as already handled to not have
                # multiple references to the same target.
                self.handled_target_deps[target.get_id()].append(t.get_id())
            else:
                # Other libraries go into AdditionalDependencies
                if linkname not in additional_links:
                    additional_links.append(linkname)
        for lib in self.get_custom_target_provided_libraries(target):
            additional_links.append(self.relpath(lib, self.get_target_dir(target)))

        if len(extra_link_args) > 0:
            extra_link_args.append('%(AdditionalOptions)')
            ET.SubElement(link, "AdditionalOptions").text = ' '.join(extra_link_args)
        if len(additional_libpaths) > 0:
            additional_libpaths.insert(0, '%(AdditionalLibraryDirectories)')
            ET.SubElement(link, 'AdditionalLibraryDirectories').text = ';'.join(additional_libpaths)
        if len(additional_links) > 0:
            additional_links.append('%(AdditionalDependencies)')
            ET.SubElement(link, 'AdditionalDependencies').text = ';'.join(additional_links)
        ofile = ET.SubElement(link, 'OutputFile')
        ofile.text = f'$(OutDir){target.get_filename()}'
        subsys = ET.SubElement(link, 'SubSystem')
        subsys.text = subsystem
        if isinstance(target, (build.SharedLibrary, build.Executable)) and target.get_import_filename():
            # DLLs built with MSVC always have an import library except when
            # they're data-only DLLs, but we don't support those yet.
            ET.SubElement(link, 'ImportLibrary').text = target.get_import_filename()
        if isinstance(target, (build.SharedLibrary, build.Executable)):
            # Add module definitions file, if provided
            if target.vs_module_defs:
                relpath = os.path.join(down, target.vs_module_defs.rel_to_builddir(self.build_to_src))
                ET.SubElement(link, 'ModuleDefinitionFile').text = relpath
        if self.debug:
            pdb = ET.SubElement(link, 'ProgramDataBaseFileName')
            pdb.text = f'$(OutDir){target.name}.pdb'
        targetmachine = ET.SubElement(link, 'TargetMachine')
        if target.for_machine is MachineChoice.BUILD:
            targetplatform = platform.lower()
        else:
            targetplatform = self.platform.lower()
        if targetplatform == 'win32':
            targetmachine.text = 'MachineX86'
        elif targetplatform == 'x64' or detect_microsoft_gdk(targetplatform):
            targetmachine.text = 'MachineX64'
        elif targetplatform == 'arm':
            targetmachine.text = 'MachineARM'
        elif targetplatform == 'arm64':
            targetmachine.text = 'MachineARM64'
        elif targetplatform == 'arm64ec':
            targetmachine.text = 'MachineARM64EC'
        else:
            raise MesonException('Unsupported Visual Studio target machine: ' + targetplatform)
        # /nologo
        ET.SubElement(link, 'SuppressStartupBanner').text = 'true'
        # /release
        if not target.get_option(OptionKey('debug')):
            ET.SubElement(link, 'SetChecksum').text = 'true'

    # Visual studio doesn't simply allow the src files of a project to be added with the 'Condition=...' attribute,
    # to allow us to point to the different debug/debugoptimized/release sets of generated src files for each of
    # the solution's configurations.  Similarly, 'ItemGroup' also doesn't support 'Condition'.  So, without knowing
    # a better (simple) alternative, for now, we'll repoint these generated sources (which will be incorrectly
    # pointing to non-existent files under our '[builddir]_vs' directory) to the appropriate location under one of
    # our buildtype build directores (e.g. '[builddir]_debug').
    # This will at least allow the user to open the files of generated sources listed in the solution explorer,
    # once a build/compile has generated these sources.
    #
    # This modifies the paths in 'gen_files' in place, as opposed to returning a new list of modified paths.
    def relocate_generated_file_paths_to_concrete_build_dir(self, gen_files: T.List[str], target: T.Union[build.Target, build.CustomTargetIndex]) -> None:
        (_, build_dir_tail) = os.path.split(self.src_to_build)
        meson_build_dir_for_buildtype = build_dir_tail[:-2] + coredata.get_genvs_default_buildtype_list()[0] # Get the first buildtype suffixed dir (i.e. '[builddir]_debug') from '[builddir]_vs'
        # Relative path from this .vcxproj to the directory containing the set of '..._[debug/debugoptimized/release]' setup meson build dirs.
        proj_to_build_root = self.target_to_build_root(target)
        proj_to_multiconfigured_builds_parent_dir = os.path.join(proj_to_build_root, '..')
        proj_to_build_dir_for_buildtype = str(os.path.join(proj_to_multiconfigured_builds_parent_dir, meson_build_dir_for_buildtype))
        relocate_to_concrete_builddir_target = os.path.normpath(os.path.join(proj_to_build_dir_for_buildtype, self.get_target_dir(target)))
        for idx, file_path in enumerate(gen_files):
            gen_files[idx] = os.path.normpath(os.path.join(relocate_to_concrete_builddir_target, file_path))

    # Returns bool indicating whether the .vcxproj has been generated.
    # Under some circumstances, it's unnecessary to create some .vcxprojs, so, when generating the .sln,
    # we need to respect that not all targets will have generated a project.
    def gen_vcxproj(self, target: build.BuildTarget, ofname: str, guid: str, vslite_ctx: dict = None) -> bool:
        mlog.debug(f'Generating vcxproj {target.name}.')
        subsystem = 'Windows'
        self.handled_target_deps[target.get_id()] = []

        if self.gen_lite:
            if not isinstance(target, build.BuildTarget):
                # Since we're going to delegate all building to the one true meson build command, we don't need
                # to generate .vcxprojs for targets that don't add any source files or just perform custom build
                # commands.  These are targets of types CustomTarget or RunTarget.  So let's just skip generating
                # these otherwise insubstantial non-BuildTarget targets.
                return False
            conftype = 'Makefile'
        elif isinstance(target, build.Executable):
            conftype = 'Application'
            # If someone knows how to set the version properly,
            # please send a patch.
            subsystem = target.win_subsystem.split(',')[0]
        elif isinstance(target, build.StaticLibrary):
            conftype = 'StaticLibrary'
        elif isinstance(target, build.SharedLibrary):
            conftype = 'DynamicLibrary'
        elif isinstance(target, build.CustomTarget):
            self.gen_custom_target_vcxproj(target, ofname, guid)
            return True
        elif isinstance(target, build.RunTarget):
            self.gen_run_target_vcxproj(target, ofname, guid)
            return True
        elif isinstance(target, build.CompileTarget):
            self.gen_compile_target_vcxproj(target, ofname, guid)
            return True
        else:
            raise MesonException(f'Unknown target type for {target.get_basename()}')

        (sources, headers, objects, _languages) = self.split_sources(target.sources)
        if target.is_unity:
            sources = self.generate_unity_files(target, sources)
        if target.for_machine is MachineChoice.BUILD:
            platform = self.build_platform
        else:
            platform = self.platform

        tfilename = os.path.splitext(target.get_filename())

        (root, type_config) = self.create_basic_project(tfilename[0],
                                                        temp_dir=target.get_id(),
                                                        guid=guid,
                                                        conftype=conftype,
                                                        target_ext=tfilename[1],
                                                        target_platform=platform)

        generated_files, custom_target_output_files, generated_files_include_dirs = self.generate_custom_generator_commands(
            target, root)
        (gen_src, gen_hdrs, gen_objs, _gen_langs) = self.split_sources(generated_files)
        (custom_src, custom_hdrs, custom_objs, _custom_langs) = self.split_sources(custom_target_output_files)
        gen_src += custom_src
        gen_hdrs += custom_hdrs

        compiler = self._get_cl_compiler(target)
        build_args = Vs2010Backend.get_build_args(compiler, self.optimization, self.debug, self.sanitize)

        assert isinstance(target, (build.Executable, build.SharedLibrary, build.StaticLibrary, build.SharedModule)), 'for mypy'
        # Prefix to use to access the build root from the vcxproj dir
        proj_to_build_root = self.target_to_build_root(target)
        # Prefix to use to access the source tree's root from the vcxproj dir
        proj_to_src_root = os.path.join(proj_to_build_root, self.build_to_src)
        # Prefix to use to access the source tree's subdir from the vcxproj dir
        proj_to_src_dir = os.path.join(proj_to_src_root, self.get_target_dir(target))

        (target_args, file_args), (target_defines, file_defines), (target_inc_dirs, file_inc_dirs) = self.get_args_defines_and_inc_dirs(
            target, compiler, generated_files_include_dirs, proj_to_src_root, proj_to_src_dir, build_args)

        if self.gen_lite:
            assert vslite_ctx is not None
            primary_src_lang = get_primary_source_lang(target.sources, custom_src)
            self.add_gen_lite_makefile_vcxproj_elements(root, platform, tfilename[1], vslite_ctx, target, proj_to_build_root, primary_src_lang)
        else:
            self.add_non_makefile_vcxproj_elements(root, type_config, target, platform, subsystem, build_args, target_args, target_defines, target_inc_dirs, file_args)

        meson_file_group = ET.SubElement(root, 'ItemGroup')
        ET.SubElement(meson_file_group, 'None', Include=os.path.join(proj_to_src_dir, build_filename))

        # Visual Studio can't load projects that present duplicated items. Filter them out
        # by keeping track of already added paths.
        def path_normalize_add(path, lis):
            normalized = os.path.normcase(os.path.normpath(path))
            if normalized not in lis:
                lis.append(normalized)
                return True
            else:
                return False

        pch_sources = {}
        if self.target_uses_pch(target):
            for lang in ['c', 'cpp']:
                pch = target.get_pch(lang)
                if not pch:
                    continue
                if compiler.id == 'msvc':
                    if len(pch) == 1:
                        # Auto generate PCH.
                        src = os.path.join(proj_to_build_root, self.create_msvc_pch_implementation(target, lang, pch[0]))
                        pch_header_dir = os.path.dirname(os.path.join(proj_to_src_dir, pch[0]))
                    else:
                        src = os.path.join(proj_to_src_dir, pch[1])
                        pch_header_dir = None
                    pch_sources[lang] = [pch[0], src, lang, pch_header_dir]
                else:
                    # I don't know whether its relevant but let's handle other compilers
                    # used with a vs backend
                    pch_sources[lang] = [pch[0], None, lang, None]

        previous_includes = []
        if len(headers) + len(gen_hdrs) + len(target.extra_files) + len(pch_sources) > 0:
            if self.gen_lite and gen_hdrs:
                # Although we're constructing our .vcxproj under our '..._vs' directory, we want to reference generated files
                # in our concrete build directories (e.g. '..._debug'), where generated files will exist after building.
                self.relocate_generated_file_paths_to_concrete_build_dir(gen_hdrs, target)

            inc_hdrs = ET.SubElement(root, 'ItemGroup')
            for h in headers:
                relpath = os.path.join(proj_to_build_root, h.rel_to_builddir(self.build_to_src))
                if path_normalize_add(relpath, previous_includes):
                    ET.SubElement(inc_hdrs, 'CLInclude', Include=relpath)
            for h in gen_hdrs:
                if path_normalize_add(h, previous_includes):
                    ET.SubElement(inc_hdrs, 'CLInclude', Include=h)
            for h in target.extra_files:
                relpath = os.path.join(proj_to_build_root, h.rel_to_builddir(self.build_to_src))
                if path_normalize_add(relpath, previous_includes):
                    ET.SubElement(inc_hdrs, 'CLInclude', Include=relpath)
            for headers in pch_sources.values():
                path = os.path.join(proj_to_src_dir, headers[0])
                if path_normalize_add(path, previous_includes):
                    ET.SubElement(inc_hdrs, 'CLInclude', Include=path)

        previous_sources = []
        if len(sources) + len(gen_src) + len(pch_sources) > 0:
            if self.gen_lite:
                # Get data to fill in intellisense fields for sources that can't reference the project-wide values
                defs_paths_opts_per_lang_and_buildtype = get_non_primary_lang_intellisense_fields(
                    vslite_ctx,
                    target.get_id(),
                    primary_src_lang)
                if gen_src:
                    # Although we're constructing our .vcxproj under our '..._vs' directory, we want to reference generated files
                    # in our concrete build directories (e.g. '..._debug'), where generated files will exist after building.
                    self.relocate_generated_file_paths_to_concrete_build_dir(gen_src, target)

            inc_src = ET.SubElement(root, 'ItemGroup')
            for s in sources:
                relpath = os.path.join(proj_to_build_root, s.rel_to_builddir(self.build_to_src))
                if path_normalize_add(relpath, previous_sources):
                    inc_cl = ET.SubElement(inc_src, 'CLCompile', Include=relpath)
                    if self.gen_lite:
                        self.add_project_nmake_defs_incs_and_opts(inc_cl, relpath, defs_paths_opts_per_lang_and_buildtype, platform)
                    else:
                        lang = Vs2010Backend.lang_from_source_file(s)
                        self.add_pch(pch_sources, lang, inc_cl)
                        self.add_additional_options(lang, inc_cl, file_args)
                        self.add_preprocessor_defines(lang, inc_cl, file_defines)
                        self.add_include_dirs(lang, inc_cl, file_inc_dirs)
                        ET.SubElement(inc_cl, 'ObjectFileName').text = "$(IntDir)" + \
                            self.object_filename_from_source(target, s)
            for s in gen_src:
                if path_normalize_add(s, previous_sources):
                    inc_cl = ET.SubElement(inc_src, 'CLCompile', Include=s)
                    if self.gen_lite:
                        self.add_project_nmake_defs_incs_and_opts(inc_cl, s, defs_paths_opts_per_lang_and_buildtype, platform)
                    else:
                        lang = Vs2010Backend.lang_from_source_file(s)
                        self.add_pch(pch_sources, lang, inc_cl)
                        self.add_additional_options(lang, inc_cl, file_args)
                        self.add_preprocessor_defines(lang, inc_cl, file_defines)
                        self.add_include_dirs(lang, inc_cl, file_inc_dirs)
                        s = File.from_built_file(target.get_subdir(), s)
                        ET.SubElement(inc_cl, 'ObjectFileName').text = "$(IntDir)" + \
                            self.object_filename_from_source(target, s)
            for lang, headers in pch_sources.items():
                impl = headers[1]
                if impl and path_normalize_add(impl, previous_sources):
                    inc_cl = ET.SubElement(inc_src, 'CLCompile', Include=impl)
                    self.create_pch(pch_sources, lang, inc_cl)
                    if self.gen_lite:
                        self.add_project_nmake_defs_incs_and_opts(inc_cl, impl, defs_paths_opts_per_lang_and_buildtype, platform)
                    else:
                        self.add_additional_options(lang, inc_cl, file_args)
                        self.add_preprocessor_defines(lang, inc_cl, file_defines)
                        pch_header_dir = pch_sources[lang][3]
                        if pch_header_dir:
                            inc_dirs = copy.deepcopy(file_inc_dirs)
                            inc_dirs[lang] = [pch_header_dir] + inc_dirs[lang]
                        else:
                            inc_dirs = file_inc_dirs
                        self.add_include_dirs(lang, inc_cl, inc_dirs)
                        # XXX: Do we need to set the object file name here too?

        additional_objects = []
        for o in self.flatten_object_list(target, proj_to_build_root)[0]:
            assert isinstance(o, str)
            additional_objects.append(o)
        for o in custom_objs:
            additional_objects.append(o)

        # VS automatically links CustomBuild outputs whose name ends in .obj or .res,
        # but the others need to be included explicitly
        explicit_link_gen_objs = [obj for obj in gen_objs if not obj.endswith(('.obj', '.res'))]

        previous_objects = []
        if len(objects) + len(additional_objects) + len(explicit_link_gen_objs) > 0:
            inc_objs = ET.SubElement(root, 'ItemGroup')
            for s in objects:
                relpath = os.path.join(proj_to_build_root, s.rel_to_builddir(self.build_to_src))
                if path_normalize_add(relpath, previous_objects):
                    ET.SubElement(inc_objs, 'Object', Include=relpath)
            for s in additional_objects + explicit_link_gen_objs:
                if path_normalize_add(s, previous_objects):
                    ET.SubElement(inc_objs, 'Object', Include=s)

        ET.SubElement(root, 'Import', Project=r'$(VCTargetsPath)\Microsoft.Cpp.targets')
        self.add_regen_dependency(root)
        if not self.gen_lite:
            # Injecting further target dependencies into this vcxproj implies and forces a Visual Studio BUILD dependency,
            # which we don't want when using 'genvslite'.  A gen_lite build as little involvement with the visual studio's
            # build system as possible.
            self.add_target_deps(root, target)
        self._prettyprint_vcxproj_xml(ET.ElementTree(root), ofname)
        if self.environment.coredata.get_option(OptionKey('layout')) == 'mirror':
            self.gen_vcxproj_filters(target, ofname)
        return True

    def gen_vcxproj_filters(self, target, ofname):
        # Generate pitchfork of filters based on directory structure.
        root = ET.Element('Project', {'ToolsVersion': '4.0',
                                      'xmlns': 'http://schemas.microsoft.com/developer/msbuild/2003'})
        filter_folders = ET.SubElement(root, 'ItemGroup')
        filter_items = ET.SubElement(root, 'ItemGroup')
        mlog.debug(f'Generating vcxproj filters {target.name}.')

        def relative_to_defined_in(file):
            # Get the relative path to file's directory from the location of the meson.build that defines this target.
            return os.path.dirname(self.relpath(PureWindowsPath(file.subdir, file.fname), self.get_target_dir(target)))

        found_folders_to_filter = {}
        all_files = target.sources + target.extra_files

        # Build a dictionary of all used relative paths (i.e. from the meson.build defining this target)
        # for all sources.
        for i in all_files:
            if not os.path.isabs(i.fname):
                dirname = relative_to_defined_in(i)
                if dirname:
                    found_folders_to_filter[dirname] = ''

        # Now walk up each of those relative paths checking for empty intermediate dirs to generate the filter.
        for folder in found_folders_to_filter:
            dirname = folder
            filter = ''

            while dirname:
                basename = os.path.basename(dirname)

                if filter == '':
                    filter = basename
                else:
                    # Use '/' to squash empty dirs. To actually get a '\', use '%255c'.
                    filter = basename + ('\\' if dirname in found_folders_to_filter else '/') + filter

                dirname = os.path.dirname(dirname)

            # Don't add an empty filter, breaks all other (?) filters.
            if filter != '':
                found_folders_to_filter[folder] = filter
                filter_element = ET.SubElement(filter_folders, 'Filter', {'Include': filter})
                uuid_element = ET.SubElement(filter_element, 'UniqueIdentifier')
                uuid_element.text = '{' + str(uuid.uuid4()).upper() + '}'

        sources, headers, objects, _ = self.split_sources(all_files)
        down = self.target_to_build_root(target)

        def add_element(type_name, elements):
            for i in elements:
                if not os.path.isabs(i.fname):
                    dirname = relative_to_defined_in(i)

                    if dirname and dirname in found_folders_to_filter:
                        relpath = os.path.join(down, i.rel_to_builddir(self.build_to_src))
                        target_element = ET.SubElement(filter_items, type_name, {'Include': relpath})
                        filter_element = ET.SubElement(target_element, 'Filter')
                        filter_element.text = found_folders_to_filter[dirname]

        add_element('ClCompile', sources)
        add_element('ClInclude', headers)
        add_element('Object', objects)

        self._prettyprint_vcxproj_xml(ET.ElementTree(root), ofname + '.filters')

    def gen_regenproj(self):
        # To fully adapt the REGEN work for a 'genvslite' solution, to check timestamps, settings, and regenerate the
        # '[builddir]_vs' solution/vcxprojs, as well as regenerating the accompanying buildtype-suffixed ninja build
        # directories (from which we need to first collect correct, updated preprocessor defs and compiler options in
        # order to fill in the regenerated solution's intellisense settings) would require some non-trivial intrusion
        # into the 'meson --internal regencheck ./meson-private' execution path (and perhaps also the '--internal
        # regenerate' and even 'meson setup --reconfigure' code).  So, for now, we'll instead give the user a simpler
        # 'reconfigure' utility project that just runs 'meson setup --reconfigure [builddir]_[buildtype] [srcdir]' on
        # each of the ninja build dirs.
        #
        # FIXME:  That will keep the building and compiling correctly configured but obviously won't update the
        # solution and vcxprojs, which may allow solution src files and intellisense options to go out-of-date;  the
        # user would still have to manually 'meson setup --genvslite [vsxxxx] [builddir] [srcdir]' to fully regenerate
        # a complete and correct solution.
        if self.gen_lite:
            project_name = 'RECONFIGURE'
            ofname = os.path.join(self.environment.get_build_dir(), 'RECONFIGURE.vcxproj')
            conftype = 'Makefile'
            # I find the REGEN project doesn't work; it fails to invoke the appropriate -
            #    python meson.py --internal regencheck builddir\meson-private
            # command, despite the fact that manually running such a command in a shell runs just fine.
            # Running/building the regen project produces the error -
            #    ...Microsoft.CppBuild.targets(460,5): error MSB8020: The build tools for ClangCL (Platform Toolset = 'ClangCL') cannot be found. To build using the ClangCL build tools, please install ...
            # Not sure why but a simple makefile-style project that executes the full '...regencheck...' command actually works (and seems a little simpler).
            # Although I've limited this change to only happen under '--genvslite', perhaps ...
            # FIXME : Should all utility projects use the simpler and less problematic makefile-style project?
        else:
            project_name = 'REGEN'
            ofname = os.path.join(self.environment.get_build_dir(), 'REGEN.vcxproj')
            conftype = 'Utility'

        guid = self.environment.coredata.regen_guid
        (root, type_config) = self.create_basic_project(project_name,
                                                        temp_dir='regen-temp',
                                                        guid=guid,
                                                        conftype=conftype
                                                        )

        if self.gen_lite:
            (nmake_base_meson_command, exe_search_paths) = Vs2010Backend.get_nmake_base_meson_command_and_exe_search_paths()
            all_configs_prop_group = ET.SubElement(root, 'PropertyGroup')

            # Multi-line command to reconfigure all buildtype-suffixed build dirs
            multi_config_buildtype_list = coredata.get_genvs_default_buildtype_list()
            (_, build_dir_tail) = os.path.split(self.src_to_build)
            proj_to_multiconfigured_builds_parent_dir = '..' # We know this RECONFIGURE.vcxproj will always be in the '[buildir]_vs' dir.
            proj_to_src_dir = self.build_to_src
            reconfigure_all_cmd = ''
            for buildtype in multi_config_buildtype_list:
                meson_build_dir_for_buildtype = build_dir_tail[:-2] + buildtype # Get the buildtype suffixed 'builddir_[debug/release/etc]' from 'builddir_vs', for example.
                proj_to_build_dir_for_buildtype = str(os.path.join(proj_to_multiconfigured_builds_parent_dir, meson_build_dir_for_buildtype))
                reconfigure_all_cmd += f'{nmake_base_meson_command} setup --reconfigure "{proj_to_build_dir_for_buildtype}" "{proj_to_src_dir}"\n'
            ET.SubElement(all_configs_prop_group, 'NMakeBuildCommandLine').text = reconfigure_all_cmd
            ET.SubElement(all_configs_prop_group, 'NMakeReBuildCommandLine').text = reconfigure_all_cmd
            ET.SubElement(all_configs_prop_group, 'NMakeCleanCommandLine').text = ''

            #Need to set the 'ExecutablePath' element for the above NMake... commands to be able to execute
            ET.SubElement(all_configs_prop_group, 'ExecutablePath').text = exe_search_paths
        else:
            action = ET.SubElement(root, 'ItemDefinitionGroup')
            midl = ET.SubElement(action, 'Midl')
            ET.SubElement(midl, "AdditionalIncludeDirectories").text = '%(AdditionalIncludeDirectories)'
            ET.SubElement(midl, "OutputDirectory").text = '$(IntDir)'
            ET.SubElement(midl, 'HeaderFileName').text = '%(Filename).h'
            ET.SubElement(midl, 'TypeLibraryName').text = '%(Filename).tlb'
            ET.SubElement(midl, 'InterfaceIdentifierFilename').text = '%(Filename)_i.c'
            ET.SubElement(midl, 'ProxyFileName').text = '%(Filename)_p.c'
            regen_command = self.environment.get_build_command() + ['--internal', 'regencheck']
            cmd_templ = '''call %s > NUL
"%s" "%s"'''
            regen_command = cmd_templ % \
                (self.get_vcvars_command(), '" "'.join(regen_command), self.environment.get_scratch_dir())
            self.add_custom_build(root, 'regen', regen_command, deps=self.get_regen_filelist(),
                                  outputs=[Vs2010Backend.get_regen_stampfile(self.environment.get_build_dir())],
                                  msg='Checking whether solution needs to be regenerated.')

        ET.SubElement(root, 'Import', Project=r'$(VCTargetsPath)\Microsoft.Cpp.targets')
        ET.SubElement(root, 'ImportGroup', Label='ExtensionTargets')
        self._prettyprint_vcxproj_xml(ET.ElementTree(root), ofname)

    def gen_testproj(self):
        project_name = 'RUN_TESTS'
        ofname = os.path.join(self.environment.get_build_dir(), f'{project_name}.vcxproj')
        guid = self.environment.coredata.test_guid
        if self.gen_lite:
            (root, type_config) = self.create_basic_project(project_name,
                                                            temp_dir='install-temp',
                                                            guid=guid,
                                                            conftype='Makefile'
                                                            )
            (nmake_base_meson_command, exe_search_paths) = Vs2010Backend.get_nmake_base_meson_command_and_exe_search_paths()
            multi_config_buildtype_list = coredata.get_genvs_default_buildtype_list()
            (_, build_dir_tail) = os.path.split(self.src_to_build)
            proj_to_multiconfigured_builds_parent_dir = '..' # We know this .vcxproj will always be in the '[buildir]_vs' dir.
            # Add appropriate 'test' commands for the 'build' action of this project, for all buildtypes
            for buildtype in multi_config_buildtype_list:
                meson_build_dir_for_buildtype = build_dir_tail[:-2] + buildtype # Get the buildtype suffixed 'builddir_[debug/release/etc]' from 'builddir_vs', for example.
                proj_to_build_dir_for_buildtype = str(os.path.join(proj_to_multiconfigured_builds_parent_dir, meson_build_dir_for_buildtype))
                test_cmd = f'{nmake_base_meson_command} test -C "{proj_to_build_dir_for_buildtype}" --no-rebuild'
                if not self.environment.coredata.get_option(OptionKey('stdsplit')):
                    test_cmd += ' --no-stdsplit'
                if self.environment.coredata.get_option(OptionKey('errorlogs')):
                    test_cmd += ' --print-errorlogs'
                condition = f'\'$(Configuration)|$(Platform)\'==\'{buildtype}|{self.platform}\''
                prop_group = ET.SubElement(root, 'PropertyGroup', Condition=condition)
                ET.SubElement(prop_group, 'NMakeBuildCommandLine').text = test_cmd
                #Need to set the 'ExecutablePath' element for the NMake... commands to be able to execute
                ET.SubElement(prop_group, 'ExecutablePath').text = exe_search_paths
        else:
            (root, type_config) = self.create_basic_project(project_name,
                                                            temp_dir='test-temp',
                                                            guid=guid)

            action = ET.SubElement(root, 'ItemDefinitionGroup')
            midl = ET.SubElement(action, 'Midl')
            ET.SubElement(midl, "AdditionalIncludeDirectories").text = '%(AdditionalIncludeDirectories)'
            ET.SubElement(midl, "OutputDirectory").text = '$(IntDir)'
            ET.SubElement(midl, 'HeaderFileName').text = '%(Filename).h'
            ET.SubElement(midl, 'TypeLibraryName').text = '%(Filename).tlb'
            ET.SubElement(midl, 'InterfaceIdentifierFilename').text = '%(Filename)_i.c'
            ET.SubElement(midl, 'ProxyFileName').text = '%(Filename)_p.c'
            # FIXME: No benchmarks?
            test_command = self.environment.get_build_command() + ['test', '--no-rebuild']
            if not self.environment.coredata.get_option(OptionKey('stdsplit')):
                test_command += ['--no-stdsplit']
            if self.environment.coredata.get_option(OptionKey('errorlogs')):
                test_command += ['--print-errorlogs']
            self.serialize_tests()
            self.add_custom_build(root, 'run_tests', '"%s"' % ('" "'.join(test_command)))

        ET.SubElement(root, 'Import', Project=r'$(VCTargetsPath)\Microsoft.Cpp.targets')
        self.add_regen_dependency(root)
        self._prettyprint_vcxproj_xml(ET.ElementTree(root), ofname)

    def gen_installproj(self):
        project_name = 'RUN_INSTALL'
        ofname = os.path.join(self.environment.get_build_dir(), f'{project_name}.vcxproj')
        guid = self.environment.coredata.install_guid
        if self.gen_lite:
            (root, type_config) = self.create_basic_project(project_name,
                                                            temp_dir='install-temp',
                                                            guid=guid,
                                                            conftype='Makefile'
                                                            )
            (nmake_base_meson_command, exe_search_paths) = Vs2010Backend.get_nmake_base_meson_command_and_exe_search_paths()
            multi_config_buildtype_list = coredata.get_genvs_default_buildtype_list()
            (_, build_dir_tail) = os.path.split(self.src_to_build)
            proj_to_multiconfigured_builds_parent_dir = '..' # We know this .vcxproj will always be in the '[buildir]_vs' dir.
            # Add appropriate 'install' commands for the 'build' action of this project, for all buildtypes
            for buildtype in multi_config_buildtype_list:
                meson_build_dir_for_buildtype = build_dir_tail[:-2] + buildtype # Get the buildtype suffixed 'builddir_[debug/release/etc]' from 'builddir_vs', for example.
                proj_to_build_dir_for_buildtype = str(os.path.join(proj_to_multiconfigured_builds_parent_dir, meson_build_dir_for_buildtype))
                install_cmd = f'{nmake_base_meson_command} install -C "{proj_to_build_dir_for_buildtype}" --no-rebuild'
                condition = f'\'$(Configuration)|$(Platform)\'==\'{buildtype}|{self.platform}\''
                prop_group = ET.SubElement(root, 'PropertyGroup', Condition=condition)
                ET.SubElement(prop_group, 'NMakeBuildCommandLine').text = install_cmd
                #Need to set the 'ExecutablePath' element for the NMake... commands to be able to execute
                ET.SubElement(prop_group, 'ExecutablePath').text = exe_search_paths
        else:
            self.create_install_data_files()

            (root, type_config) = self.create_basic_project(project_name,
                                                            temp_dir='install-temp',
                                                            guid=guid)

            action = ET.SubElement(root, 'ItemDefinitionGroup')
            midl = ET.SubElement(action, 'Midl')
            ET.SubElement(midl, "AdditionalIncludeDirectories").text = '%(AdditionalIncludeDirectories)'
            ET.SubElement(midl, "OutputDirectory").text = '$(IntDir)'
            ET.SubElement(midl, 'HeaderFileName').text = '%(Filename).h'
            ET.SubElement(midl, 'TypeLibraryName').text = '%(Filename).tlb'
            ET.SubElement(midl, 'InterfaceIdentifierFilename').text = '%(Filename)_i.c'
            ET.SubElement(midl, 'ProxyFileName').text = '%(Filename)_p.c'
            install_command = self.environment.get_build_command() + ['install', '--no-rebuild']
            self.add_custom_build(root, 'run_install', '"%s"' % ('" "'.join(install_command)))

        ET.SubElement(root, 'Import', Project=r'$(VCTargetsPath)\Microsoft.Cpp.targets')
        self.add_regen_dependency(root)
        self._prettyprint_vcxproj_xml(ET.ElementTree(root), ofname)

    def add_custom_build(self, node: ET.Element, rulename: str, command: str, deps: T.Optional[T.List[str]] = None,
                         outputs: T.Optional[T.List[str]] = None, msg: T.Optional[str] = None, verify_files: bool = True) -> None:
        igroup = ET.SubElement(node, 'ItemGroup')
        rulefile = os.path.join(self.environment.get_scratch_dir(), rulename + '.rule')
        if not os.path.exists(rulefile):
            with open(rulefile, 'w', encoding='utf-8') as f:
                f.write("# Meson regen file.")
        custombuild = ET.SubElement(igroup, 'CustomBuild', Include=rulefile)
        if msg:
            message = ET.SubElement(custombuild, 'Message')
            message.text = msg
        if not verify_files:
            ET.SubElement(custombuild, 'VerifyInputsAndOutputsExist').text = 'false'

        # If a command ever were to change the current directory or set local
        # variables this would need to be more complicated, as msbuild by
        # default executes all CustomBuilds in a project using the same
        # shell. Right now such tasks are all done inside the meson_exe
        # wrapper. The trailing newline appears to be necessary to allow
        # parallel custom builds to work.
        ET.SubElement(custombuild, 'Command').text = f"{command}\n"

        if not outputs:
            # Use a nonexistent file to always consider the target out-of-date.
            outputs = [self.nonexistent_file(os.path.join(self.environment.get_scratch_dir(),
                                                          'outofdate.file'))]
        ET.SubElement(custombuild, 'Outputs').text = ';'.join(outputs)
        if deps:
            ET.SubElement(custombuild, 'AdditionalInputs').text = ';'.join(deps)

    @staticmethod
    def nonexistent_file(prefix: str) -> str:
        i = 0
        file = prefix
        while os.path.exists(file):
            file = '%s%d' % (prefix, i)
        return file

    def generate_debug_information(self, link: ET.Element) -> None:
        # valid values for vs2015 is 'false', 'true', 'DebugFastLink'
        ET.SubElement(link, 'GenerateDebugInformation').text = 'true'

    def add_regen_dependency(self, root: ET.Element) -> None:
        # For now, with 'genvslite' solutions, REGEN is replaced by the lighter-weight RECONFIGURE utility that is
        # no longer a forced build dependency.  See comment in 'gen_regenproj'
        if not self.gen_lite:
            regen_vcxproj = os.path.join(self.environment.get_build_dir(), 'REGEN.vcxproj')
            self.add_project_reference(root, regen_vcxproj, self.environment.coredata.regen_guid)

    def generate_lang_standard_info(self, file_args: T.Dict[str, CompilerArgs], clconf: ET.Element) -> None:
        pass
