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

from __future__ import annotations

import functools, uuid, os, operator, re
import typing as T

from . import backends
from .. import build
from .. import compilers
from .. import mesonlib
from .. import mlog
from ..arglist import CompilerArgs
from ..dependencies.platform import AppleFrameworks
from ..mesonlib import MesonBugException, MesonException
from ..linkers import StaticLinker
from ..options import OptionKey

if T.TYPE_CHECKING:
    from ..build import BuildTarget
    from ..compilers import Compiler

    PbxDictItemTypes = T.TypeVar('PbxDictItemTypes', 'PbxArray', 'PbxDict', str, int)

INDENT = '\t'

XCODETYPEMAP: T.Mapping[str, str] = {
    'c': 'sourcecode.c.c',
    'a': 'archive.ar',
    'cc': 'sourcecode.cpp.cpp',
    'cxx': 'sourcecode.cpp.cpp',
    'cpp': 'sourcecode.cpp.cpp',
    'c++': 'sourcecode.cpp.cpp',
    'm': 'sourcecode.c.objc',
    'mm': 'sourcecode.cpp.objcpp',
    'h': 'sourcecode.c.h',
    'hpp': 'sourcecode.cpp.h',
    'hxx': 'sourcecode.cpp.h',
    'hh': 'sourcecode.cpp.hh',
    'inc': 'sourcecode.c.h',
    'swift': 'sourcecode.swift',
    'dylib': 'compiled.mach-o.dylib',
    'o': 'compiled.mach-o.objfile',
    's': 'sourcecode.asm',
    'asm': 'sourcecode.nasm',
    'metal': 'sourcecode.metal',
    'glsl': 'sourcecode.glsl',
}

NEEDS_CUSTOM_RULES: T.Mapping[str, str] = {
    'nasm': 'sourcecode.nasm',
}

LANGNAMEMAP: T.Mapping[str, str] = {
    'c': 'C',
    'cpp': 'CPLUSPLUS',
    'objc': 'OBJC',
    'objcpp': 'OBJCPLUSPLUS',
    'swift': 'SWIFT_'
}

OPT2XCODEOPT: T.Mapping[str, str | None] = {
    'plain': None,
    '0': '0',
    'g': '0',
    '1': '1',
    '2': '2',
    '3': '3',
    's': 's',
}

BOOL2XCODEBOOL: T.Mapping[bool, str] = {True: 'YES', False: 'NO'}

LINKABLE_EXTENSIONS: T.AbstractSet[str] = {'.o', '.a', '.obj', '.so', '.dylib'}

XCODEVERSIONS: T.Mapping[str, tuple[str, int]] = {
    '1500': ('Xcode 15.0', 60),
    '1400': ('Xcode 14.0', 56),
    '1300': ('Xcode 13.0', 55),
    '1200': ('Xcode 12.0', 54),
    '1140': ('Xcode 11.4', 53),
    '1100': ('Xcode 11.0', 52),
    '1000': ('Xcode 10.0', 51),
    '930': ('Xcode 9.3', 50),
    '800': ('Xcode 8.0', 48),
    '630': ('Xcode 6.3', 47),
    '320': ('Xcode 3.2', 46),
    '310': ('Xcode 3.1', 45)
}

def autodetect_xcode_version() -> T.Tuple[str, int]:
    try:
        pc, stdout, stderr = mesonlib.Popen_safe(['xcodebuild', '-version'])
    except FileNotFoundError:
        raise MesonException('Could not detect Xcode. Please install it if you wish to use the Xcode backend.')
    if pc.returncode != 0:
        raise MesonException(f'An error occurred while detecting Xcode: {stderr}')
    version = int(''.join(re.search(r'\d*\.\d*\.*\d*', stdout).group(0).split('.')))
    # If the version number does not have two decimal points, pretend it does.
    if stdout.count('.') < 2:
        version *= 10
    for v, r in XCODEVERSIONS.items():
        if int(v) <= version:
            return r
    raise MesonException('Your Xcode installation is too old and is not supported.')

class FileTreeEntry:

    def __init__(self) -> None:
        self.subdirs: T.Dict[str, FileTreeEntry] = {}
        self.targets: T.List[build.BuildTarget] = []

class PbxArray:
    def __init__(self) -> None:
        self.items: T.List[PbxArrayItem] = []

    def add_item(self, item: T.Union[PbxArrayItem, str], comment: str = '') -> None:
        if isinstance(item, PbxArrayItem):
            self.items.append(item)
        else:
            self.items.append(PbxArrayItem(item, comment))

    def write(self, ofile: T.TextIO, indent_level: int) -> None:
        ofile.write('(\n')
        indent_level += 1
        for i in self.items:
            if i.comment:
                ofile.write(indent_level*INDENT + f'{i.value} {i.comment},\n')
            else:
                ofile.write(indent_level*INDENT + f'{i.value},\n')
        indent_level -= 1
        ofile.write(indent_level*INDENT + ');\n')

class PbxArrayItem:
    def __init__(self, value: str, comment: str = ''):
        self.value = value
        if comment:
            if '/*' in comment:
                self.comment = comment
            else:
                self.comment = f'/* {comment} */'
        else:
            self.comment = comment

class PbxComment:
    def __init__(self, text: str):
        assert '/*' not in text
        self.text = f'/* {text} */'

    def write(self, ofile: T.TextIO, indent_level: int) -> None:
        ofile.write(f'\n{self.text}\n')

class PbxDictItem:
    value: PbxArray | PbxDict | str | int

    def __init__(self, key: str, value: T.Union[PbxArray, PbxDict, str, int], comment: str = ''):
        self.key = key
        if isinstance(value, str):
            self.value = self.quote_value(value)
        else:
            self.value = value

        if comment:
            if '/*' in comment:
                self.comment = comment
            else:
                self.comment = f'/* {comment} */'
        else:
            self.comment = comment

    def quote_value(self, value: str) -> str:
        quoted = f'"{value}"'

        if not value:
            return quoted

        if set(' +@$<>/').isdisjoint(value) or value[0] == '"':
            return value

        return quoted


class PbxDict:
    def __init__(self) -> None:
        # This class is a bit weird, because we want to write PBX dicts in
        # defined order _and_ we want to write intermediate comments also in order.
        self.keys: T.Set[str] = set()
        self.items: T.List[T.Union[PbxDictItem, PbxComment]] = []

    def add_item(self, key: str, value: T.Union[PbxArray, PbxDict, str, int], comment: str = '') -> None:
        assert key not in self.keys
        item = PbxDictItem(key, value, comment)
        self.keys.add(key)
        self.items.append(item)

    def get_item(self, key: str) -> PbxDictItem:
        assert key in self.keys
        for item in self.items:
            if not isinstance(item, PbxDictItem):
                continue
            if item.key == key:
                return item
        return None

    def get_item_value(self, key: str, type_: type[PbxDictItemTypes]) -> PbxDictItemTypes:
        i = self.get_item(key).value
        if not isinstance(i, type_):
            raise MesonBugException(f'Attempted to get the wrong type for key {key}, expected {type_} but got {type(i)}')
        return i

    def has_item(self, key: str) -> bool:
        return key in self.keys

    def add_comment(self, comment: PbxComment) -> None:
        assert isinstance(comment, PbxComment)
        self.items.append(comment)

    def write(self, ofile: T.TextIO, indent_level: int) -> None:
        ofile.write('{\n')
        indent_level += 1
        for i in self.items:
            if isinstance(i, PbxComment):
                i.write(ofile, indent_level)
            elif isinstance(i, PbxDictItem):
                if isinstance(i.value, (str, int)):
                    if i.comment:
                        ofile.write(indent_level*INDENT + f'{i.key} = {i.value} {i.comment};\n')
                    else:
                        ofile.write(indent_level*INDENT + f'{i.key} = {i.value};\n')
                elif isinstance(i.value, PbxDict):
                    if i.comment:
                        ofile.write(indent_level*INDENT + f'{i.key} {i.comment} = ')
                    else:
                        ofile.write(indent_level*INDENT + f'{i.key} = ')
                    i.value.write(ofile, indent_level)
                elif isinstance(i.value, PbxArray):
                    if i.comment:
                        ofile.write(indent_level*INDENT + f'{i.key} {i.comment} = ')
                    else:
                        ofile.write(indent_level*INDENT + f'{i.key} = ')
                    i.value.write(ofile, indent_level)
                else:
                    print(i)
                    print(i.key)
                    print(i.value)
                    raise RuntimeError('missing code')
            else:
                print(i)
                raise RuntimeError('missing code2')

        indent_level -= 1
        ofile.write(indent_level*INDENT + '}')
        if indent_level == 0:
            ofile.write('\n')
        else:
            ofile.write(';\n')

class XCodeBackend(backends.Backend):

    name = 'xcode'

    def __init__(self, build: T.Optional[build.Build]):
        super().__init__(build)
        self.project_uid = self.environment.coredata.lang_guids['default'].replace('-', '')[:24]
        self.buildtype = T.cast('str', self.environment.coredata.optstore.get_value_for(OptionKey('buildtype')))
        self.project_conflist = self.gen_id()
        self.maingroup_id = self.gen_id()
        self.all_id = self.gen_id()
        self.all_buildconf_id = self.gen_id()
        self.buildtypes = [self.buildtype]
        self.test_id = self.gen_id()
        self.test_command_id = self.gen_id()
        self.test_buildconf_id = self.gen_id()
        self.regen_id = self.gen_id()
        self.regen_command_id = self.gen_id()
        self.regen_buildconf_id = self.gen_id()
        self.regen_dependency_id = self.gen_id()
        self.top_level_dict = PbxDict()
        self.generator_outputs: dict[tuple[str, int], list[str]] = {}
        self.set_arch()
        self.xcodeversion, self.objversion = autodetect_xcode_version()
        # In Xcode files are not accessed via their file names, but rather every one of them
        # gets an unique id. More precisely they get one unique id per target they are used
        # in. If you generate only one id per file and use them, compilation will work but the
        # UI will only show the file in one target but not the others. Thus they key is
        # a tuple containing the target and filename.
        self.buildfile_ids: dict[tuple[str, str] | str, str] = {}
        # That is not enough, though. Each target/file combination also gets a unique id
        # in the file reference section. Because why not. This means that a source file
        # that is used in two targets gets a total of four unique ID numbers.
        self.fileref_ids: dict[tuple[str, str] | str, str] = {}

        self.buildphase_map: dict[str, dict[str, str]] = {}

    def write_pbxfile(self, top_level_dict: PbxDict, ofilename: str) -> None:
        tmpname = ofilename + '.tmp'
        with open(tmpname, 'w', encoding='utf-8') as ofile:
            ofile.write('// !$*UTF8*$!\n')
            top_level_dict.write(ofile, 0)
        os.replace(tmpname, ofilename)

    def gen_id(self) -> str:
        return str(uuid.uuid4()).upper().replace('-', '')[:24]

    @functools.lru_cache(maxsize=None)
    def get_target_dir_cached(self, target: build.Target) -> str:
        dirname = os.path.join(target.get_subdir(), T.cast('str', self.environment.coredata.optstore.get_value_for(OptionKey('buildtype'))))
        return dirname

    def get_custom_target_output_dir(self, target: build.AnyTargetType) -> str:
        dirname = target.get_subdir()
        os.makedirs(os.path.join(self.environment.get_build_dir(), dirname), exist_ok=True)
        return dirname

    def object_filename_from_source(self, target: build.BuildTarget, compiler: Compiler,
                                    source: mesonlib.File, targetdir: T.Optional[str] = None) -> str:
        # Xcode has the following naming scheme:
        # projectname.build/debug/prog@exe.build/Objects-normal/x86_64/func.o
        project = self.build.project_name
        buildtype = self.buildtype
        tname = target.get_id()
        stem = os.path.splitext(os.path.basename(source.fname))[0]
        # Append "build" before the actual object path to match OBJROOT
        obj_path = f'build/{project}.build/{buildtype}/{tname}.build/Objects-normal/{self.arch}/{stem}.o'
        return obj_path

    def determine_swift_dep_dirs(self, target: build.BuildTarget) -> T.List[str]:
        result: T.List[str] = []
        for l in target.link_targets:
            # Xcode does not recognize our private directories, so we have to use its build directories instead.
            result.append(os.path.join(self.environment.get_build_dir(), self.get_target_dir(l)))
        return result

    def set_arch(self) -> None:
        self.arch = self.build.environment.machines.host.cpu
        if self.arch == 'aarch64':
            self.arch = 'arm64'

    def generate(self, capture: bool = False, vslite_ctx: T.Optional[T.Dict] = None) -> None:
        if self.arch is None: # The host machine arch may not be set when backend is created
            self.set_arch()
        # Check for (currently) unexpected capture arg use cases -
        if capture:
            raise MesonBugException('We do not expect the xcode backend to generate with \'capture = True\'')
        if vslite_ctx:
            raise MesonBugException('We do not expect the xcode backend to be given a valid \'vslite_ctx\'')
        self.serialize_tests()
        # Cache the result as the method rebuilds the array every time it is called.
        self.build_targets = self.build.get_build_targets()
        self.custom_targets = self.build.get_custom_targets()
        self.generate_filemap()
        if self.objversion < 50:
            self.generate_buildstylemap()
        self.generate_build_phase_map()
        self.generate_build_configuration_map()
        self.generate_build_configurationlist_map()
        self.generate_project_configurations_map()
        self.generate_buildall_configurations_map()
        self.generate_test_configurations_map()
        self.generate_native_target_map()
        self.generate_native_frameworks_map()
        self.generate_custom_target_map()
        self.generate_native_target_build_rules_map()
        self.generate_generator_target_map()
        self.generate_source_phase_map()
        self.generate_target_dependency_map()
        self.generate_pbxdep_map()
        self.generate_containerproxy_map()
        self.generate_target_file_maps()
        self.generate_build_file_maps()
        self.proj_dir = os.path.join(self.environment.get_build_dir(), self.build.project_name + '.xcodeproj')
        os.makedirs(self.proj_dir, exist_ok=True)
        self.proj_file = os.path.join(self.proj_dir, 'project.pbxproj')
        objects_dict = self.generate_prefix(self.top_level_dict)
        objects_dict.add_comment(PbxComment('Begin PBXAggregateTarget section'))
        self.generate_pbx_aggregate_target(objects_dict)
        objects_dict.add_comment(PbxComment('End PBXAggregateTarget section'))
        objects_dict.add_comment(PbxComment('Begin PBXBuildFile section'))
        self.generate_pbx_build_file(objects_dict)
        objects_dict.add_comment(PbxComment('End PBXBuildFile section'))
        objects_dict.add_comment(PbxComment('Begin PBXBuildRule section'))
        self.generate_pbx_build_rule(objects_dict)
        objects_dict.add_comment(PbxComment('End PBXBuildRule section'))
        objects_dict.add_comment(PbxComment('Begin PBXBuildStyle section'))
        if self.objversion < 50:
            self.generate_pbx_build_style(objects_dict)
            objects_dict.add_comment(PbxComment('End PBXBuildStyle section'))
            objects_dict.add_comment(PbxComment('Begin PBXContainerItemProxy section'))
        self.generate_pbx_container_item_proxy(objects_dict)
        objects_dict.add_comment(PbxComment('End PBXContainerItemProxy section'))
        objects_dict.add_comment(PbxComment('Begin PBXFileReference section'))
        self.generate_pbx_file_reference(objects_dict)
        objects_dict.add_comment(PbxComment('End PBXFileReference section'))
        objects_dict.add_comment(PbxComment('Begin PBXFrameworksBuildPhase section'))
        self.generate_pbx_frameworks_buildphase(objects_dict)
        objects_dict.add_comment(PbxComment('End PBXFrameworksBuildPhase section'))
        objects_dict.add_comment(PbxComment('Begin PBXGroup section'))
        self.generate_pbx_group(objects_dict)
        objects_dict.add_comment(PbxComment('End PBXGroup section'))
        objects_dict.add_comment(PbxComment('Begin PBXNativeTarget section'))
        self.generate_pbx_native_target(objects_dict)
        objects_dict.add_comment(PbxComment('End PBXNativeTarget section'))
        objects_dict.add_comment(PbxComment('Begin PBXProject section'))
        self.generate_pbx_project(objects_dict)
        objects_dict.add_comment(PbxComment('End PBXProject section'))
        objects_dict.add_comment(PbxComment('Begin PBXShellScriptBuildPhase section'))
        self.generate_pbx_shell_build_phase(objects_dict)
        objects_dict.add_comment(PbxComment('End PBXShellScriptBuildPhase section'))
        objects_dict.add_comment(PbxComment('Begin PBXSourcesBuildPhase section'))
        self.generate_pbx_sources_build_phase(objects_dict)
        objects_dict.add_comment(PbxComment('End PBXSourcesBuildPhase section'))
        objects_dict.add_comment(PbxComment('Begin PBXTargetDependency section'))
        self.generate_pbx_target_dependency(objects_dict)
        objects_dict.add_comment(PbxComment('End PBXTargetDependency section'))
        objects_dict.add_comment(PbxComment('Begin XCBuildConfiguration section'))
        self.generate_xc_build_configuration(objects_dict)
        objects_dict.add_comment(PbxComment('End XCBuildConfiguration section'))
        objects_dict.add_comment(PbxComment('Begin XCConfigurationList section'))
        self.generate_xc_configurationList(objects_dict)
        objects_dict.add_comment(PbxComment('End XCConfigurationList section'))
        self.generate_suffix(self.top_level_dict)
        self.write_pbxfile(self.top_level_dict, self.proj_file)
        self.generate_regen_info()

    def get_xcodetype(self, fname: str) -> str:
        extension = fname.split('.')[-1]
        if extension == 'C':
            extension = 'cpp'
        xcodetype = XCODETYPEMAP.get(extension.lower())
        if not xcodetype:
            xcodetype = 'sourcecode.unknown'
        return xcodetype

    def generate_filemap(self) -> None:
        self.filemap: dict[str, str] = {} # Key is source file relative to src root.
        self.foldermap: dict[tuple[str, build.BuildTarget], str] = {}
        self.target_filemap: dict[str, str] = {}
        for name, t in self.build_targets.items():
            for s in t.sources:
                if isinstance(s, mesonlib.File):
                    if '/' in s.fname:
                        # From the top level down, add the folders containing the source file.
                        folder = os.path.split(os.path.dirname(s.fname))
                        while folder:
                            fpath = os.path.join(*folder)
                            # Multiple targets might use the same folders, so store their targets with them.
                            # Otherwise, folders and their source files will appear in the wrong places in Xcode.
                            if (fpath, t) not in self.foldermap:
                                self.foldermap[(fpath, t)] = self.gen_id()
                            else:
                                break
                            folder = folder[:-1]
                    s = os.path.join(s.subdir, s.fname)
                    self.filemap[s] = self.gen_id()
            for o in t.objects:
                if isinstance(o, str):
                    o = os.path.join(t.subdir, o)
                    self.filemap[o] = self.gen_id()
            for e in t.extra_files:
                if isinstance(e, mesonlib.File):
                    e = os.path.join(e.subdir, e.fname)
                    self.filemap[e] = self.gen_id()
                else:
                    e = os.path.join(t.subdir, e)
                    self.filemap[e] = self.gen_id()
            self.target_filemap[name] = self.gen_id()

    def generate_buildstylemap(self) -> None:
        self.buildstylemap = {self.buildtype: self.gen_id()}

    def generate_build_phase_map(self) -> None:
        for tname, t in self.build_targets.items():
            # generate id for our own target-name
            self.buildphase_map[t.id] = {
                tname: self.gen_id(),
                # each target can have its own Frameworks/Sources/..., generate
                # id's for those
                'Frameworks': self.gen_id(),
                'Resources': self.gen_id(),
                'Sources': self.gen_id(),
            }

    def generate_build_configuration_map(self) -> None:
        self.buildconfmap = {}
        for t in self.build_targets:
            bconfs = {self.buildtype: self.gen_id()}
            self.buildconfmap[t] = bconfs
        for t in self.custom_targets:
            bconfs = {self.buildtype: self.gen_id()}
            self.buildconfmap[t] = bconfs

    def generate_project_configurations_map(self) -> None:
        self.project_configurations = {self.buildtype: self.gen_id()}

    def generate_buildall_configurations_map(self) -> None:
        self.buildall_configurations = {self.buildtype: self.gen_id()}

    def generate_test_configurations_map(self) -> None:
        self.test_configurations = {self.buildtype: self.gen_id()}

    def generate_build_configurationlist_map(self) -> None:
        self.buildconflistmap = {}
        for t in self.build_targets:
            self.buildconflistmap[t] = self.gen_id()
        for t in self.custom_targets:
            self.buildconflistmap[t] = self.gen_id()

    def generate_native_target_map(self) -> None:
        self.native_targets = {}
        for t in self.build_targets:
            self.native_targets[t] = self.gen_id()

    def generate_native_target_build_rules_map(self) -> None:
        self.build_rules = {}
        for name, target in self.build_targets.items():
            languages = {}
            for language in target.compilers:
                if language not in NEEDS_CUSTOM_RULES:
                    continue
                languages[language] = self.gen_id()
            self.build_rules[name] = languages

    def generate_custom_target_map(self) -> None:
        self.shell_targets: T.Dict[T.Union[str, T.Tuple[str, int]], str] = {}
        self.custom_target_output_buildfile = {}
        self.custom_target_output_fileref = {}
        for tname, t in self.custom_targets.items():
            self.shell_targets[tname] = self.gen_id()
            if not isinstance(t, build.CustomTarget):
                continue
            (srcs, ofilenames, cmd) = self.eval_custom_target_command(t)
            for o in ofilenames:
                self.custom_target_output_buildfile[o] = self.gen_id()
                self.custom_target_output_fileref[o] = self.gen_id()

    def generate_generator_target_map(self) -> None:
        # Generator objects do not have natural unique ids
        # so use a counter.
        self.generator_fileref_ids: dict[tuple[str, int], list[str]] = {}
        self.generator_buildfile_ids: dict[tuple[str, int], list[str]] = {}
        for tname, t in self.build_targets.items():
            generator_id = 0
            for genlist in t.generated:
                if not isinstance(genlist, build.GeneratedList):
                    continue
                self.gen_single_target_map(genlist, tname, t, generator_id)
                generator_id += 1
        # FIXME add outputs.
        for tname, t in self.custom_targets.items():
            generator_id = 0
            for genlist in t.sources:
                if not isinstance(genlist, build.GeneratedList):
                    continue
                self.gen_single_target_map(genlist, tname, t, generator_id)
                generator_id += 1

    def gen_single_target_map(self, genlist: build.GeneratedList, tname: str,
                              t: build.AnyTargetType, generator_id: int) -> None:
        k = (tname, generator_id)
        assert k not in self.shell_targets
        if genlist.extra_depends:
            raise NotImplementedError('XCode backend does not support depends for generator.process')
        self.shell_targets[k] = self.gen_id()
        ofile_abs: list[str] = []
        for i in genlist.get_inputs():
            for o_base in genlist.get_outputs_for(i):
                o = os.path.join(self.get_target_private_dir(t), o_base)
                ofile_abs.append(os.path.join(self.environment.get_build_dir(), o))
        assert k not in self.generator_outputs
        self.generator_outputs[k] = ofile_abs
        buildfile_ids: list[str] = []
        fileref_ids: list[str] = []
        for i in range(len(ofile_abs)):
            buildfile_ids.append(self.gen_id())
            fileref_ids.append(self.gen_id())
        self.generator_buildfile_ids[k] = buildfile_ids
        self.generator_fileref_ids[k] = fileref_ids

    def generate_native_frameworks_map(self) -> None:
        self.native_frameworks = {}
        self.native_frameworks_fileref = {}
        for t in self.build_targets.values():
            for dep in t.get_external_deps():
                if dep.found() and isinstance(dep, AppleFrameworks):
                    for f in dep.frameworks:
                        self.native_frameworks[f] = self.gen_id()
                        self.native_frameworks_fileref[f] = self.gen_id()

    def generate_target_dependency_map(self) -> None:
        self.target_dependency_map: T.Dict[T.Union[str, T.Tuple[str, str]], str] = {}
        for tname, t in self.build_targets.items():
            for target in t.link_targets:
                k = (tname, target.get_basename())
                assert k not in self.target_dependency_map
                self.target_dependency_map[k] = self.gen_id()
        for tname, t in self.custom_targets.items():
            k = tname
            assert k not in self.target_dependency_map
            self.target_dependency_map[k] = self.gen_id()

    def generate_pbxdep_map(self) -> None:
        self.pbx_dep_map = {}
        self.pbx_custom_dep_map = {}
        for t in self.build_targets:
            self.pbx_dep_map[t] = self.gen_id()
        for t in self.custom_targets:
            self.pbx_custom_dep_map[t] = self.gen_id()

    def generate_containerproxy_map(self) -> None:
        self.containerproxy_map = {}
        for t in self.build_targets:
            self.containerproxy_map[t] = self.gen_id()

    def generate_target_file_maps(self) -> None:
        self.generate_target_file_maps_impl(self.build_targets)
        self.generate_target_file_maps_impl(self.custom_targets)

    def generate_target_file_maps_impl(
            self, targets: T.Mapping[str, build.BuildTarget | build.CustomTarget]
            ) -> None:
        for tname, t in targets.items():
            for s in t.sources:
                if not isinstance(s, mesonlib.File):
                    continue
                s = os.path.join(s.subdir, s.fname)
                k = (tname, s)
                assert k not in self.buildfile_ids
                self.buildfile_ids[k] = self.gen_id()
                assert k not in self.fileref_ids
                self.fileref_ids[k] = self.gen_id()
            if isinstance(t, build.CustomTarget):
                continue
            for o in t.objects:
                if isinstance(o, build.ExtractedObjects):
                    # Extracted objects do not live in "the Xcode world".
                    continue
                if isinstance(o, mesonlib.File):
                    o = os.path.join(o.subdir, o.fname)
                if isinstance(o, str):
                    o = os.path.join(t.subdir, o)
                    k = (tname, o)
                    assert k not in self.buildfile_ids
                    self.buildfile_ids[k] = self.gen_id()
                    assert k not in self.fileref_ids
                    self.fileref_ids[k] = self.gen_id()
                else:
                    raise RuntimeError('Unknown input type ' + str(o))
            for e in t.extra_files:
                if isinstance(e, mesonlib.File):
                    e = os.path.join(e.subdir, e.fname)
                if isinstance(e, str):
                    e = os.path.join(t.subdir, e)
                    k = (tname, e)
                    assert k not in self.buildfile_ids
                    self.buildfile_ids[k] = self.gen_id()
                    assert k not in self.fileref_ids
                    self.fileref_ids[k] = self.gen_id()

    def generate_build_file_maps(self) -> None:
        for buildfile in self.build.def_files:
            self.buildfile_ids[buildfile] = self.gen_id()
            self.fileref_ids[buildfile] = self.gen_id()

    def generate_source_phase_map(self) -> None:
        self.source_phase = {}
        for t in self.build_targets:
            self.source_phase[t] = self.gen_id()

    def generate_pbx_aggregate_target(self, objects_dict: PbxDict) -> None:
        self.custom_aggregate_targets = {}
        self.build_all_tdep_id = self.gen_id()
        target_dependencies = []
        custom_target_dependencies = []
        for tname, t in self.get_build_by_default_targets().items():
            if isinstance(t, build.CustomTarget):
                custom_target_dependencies.append(self.pbx_custom_dep_map[t.get_id()])
            elif isinstance(t, build.BuildTarget):
                target_dependencies.append(self.pbx_dep_map[t.get_id()])
        aggregated_targets: list[tuple[str, str, str, list[str], list[str]]] = []
        aggregated_targets.append((self.all_id,
                                   'ALL_BUILD',
                                   self.all_buildconf_id,
                                   [],
                                   [self.regen_dependency_id] + target_dependencies + custom_target_dependencies))
        aggregated_targets.append((self.test_id,
                                   'RUN_TESTS',
                                   self.test_buildconf_id,
                                   [self.test_command_id],
                                   [self.regen_dependency_id, self.build_all_tdep_id]))
        aggregated_targets.append((self.regen_id,
                                   'REGENERATE',
                                   self.regen_buildconf_id,
                                   [self.regen_command_id],
                                   []))
        for tname, t in self.build.get_custom_targets().items():
            ct_id = self.gen_id()
            self.custom_aggregate_targets[tname] = ct_id
            build_phases = []
            dependencies = [self.regen_dependency_id]
            generator_id = 0
            for d in t.dependencies:
                if isinstance(d, build.CustomTarget):
                    dependencies.append(self.pbx_custom_dep_map[d.get_id()])
                elif isinstance(d, build.BuildTarget):
                    dependencies.append(self.pbx_dep_map[d.get_id()])
            for s in t.sources:
                if isinstance(s, build.GeneratedList):
                    build_phases.append(self.shell_targets[(tname, generator_id)])
                    for d in s.depends:
                        if isinstance(d, build.GeneratedList):
                            # TODO: what to do about this
                            raise MesonBugException('Not implemented, patches highly welcome')
                        dependencies.append(self.pbx_custom_dep_map[d.get_id()])
                    generator_id += 1
                elif isinstance(s, build.ExtractedObjects):
                    source_target_id = self.pbx_dep_map[s.target.get_id()]
                    if source_target_id not in dependencies:
                        dependencies.append(source_target_id)
            build_phases.append(self.shell_targets[tname])
            aggregated_targets.append((ct_id, tname, self.buildconflistmap[tname], build_phases, dependencies))

        # Sort objects by ID before writing
        sorted_aggregated_targets = sorted(aggregated_targets, key=operator.itemgetter(0))
        for t in sorted_aggregated_targets:
            agt_dict = PbxDict()
            name = t[1]
            buildconf_id = t[2]
            build_phases = t[3]
            dependencies = t[4]
            agt_dict.add_item('isa', 'PBXAggregateTarget')
            agt_dict.add_item('buildConfigurationList', buildconf_id, f'Build configuration list for PBXAggregateTarget "{name}"')
            bp_arr = PbxArray()
            agt_dict.add_item('buildPhases', bp_arr)
            for bp in build_phases:
                bp_arr.add_item(bp, 'ShellScript')
            dep_arr = PbxArray()
            agt_dict.add_item('dependencies', dep_arr)
            for td in dependencies:
                dep_arr.add_item(td, 'PBXTargetDependency')
            agt_dict.add_item('name', name)
            agt_dict.add_item('productName', name)
            objects_dict.add_item(t[0], agt_dict, name)

    def generate_pbx_build_file(self, objects_dict: PbxDict) -> None:
        for tname, t in self.build_targets.items():
            for dep in t.get_external_deps():
                if dep.found() and isinstance(dep, AppleFrameworks):
                    for f in dep.frameworks:
                        fw_dict = PbxDict()
                        fwkey = self.native_frameworks[f]
                        if fwkey not in objects_dict.keys:
                            objects_dict.add_item(fwkey, fw_dict, f'{f}.framework in Frameworks')
                        fw_dict.add_item('isa', 'PBXBuildFile')
                        fw_dict.add_item('fileRef', self.native_frameworks_fileref[f], f)

            for s in t.sources:
                if not isinstance(s, mesonlib.File):
                    continue
                in_build_dir = s.is_built
                s = os.path.join(s.subdir, s.fname)
                sdict = PbxDict()
                k = (tname, s)
                idval = self.buildfile_ids[k]
                fileref = self.fileref_ids[k]
                if in_build_dir:
                    fullpath = os.path.join(self.environment.get_build_dir(), s)
                else:
                    fullpath = os.path.join(self.environment.get_source_dir(), s)
                sdict.add_item('isa', 'PBXBuildFile')
                sdict.add_item('fileRef', fileref, fullpath)
                objects_dict.add_item(idval, sdict)

            for o in t.objects:
                if isinstance(o, build.ExtractedObjects):
                    # Object files are not source files as such. We add them
                    # by hand in linker flags. It is also not particularly
                    # clear how to define build files in Xcode's file format.
                    continue
                if isinstance(o, mesonlib.File):
                    o = os.path.join(o.subdir, o.fname)
                elif isinstance(o, str):
                    o = os.path.join(t.subdir, o)
                else:
                    # TODO: handle CustomTarget | CustomTargetIndex | GeneratedList
                    raise MesonBugException('Not implemented, patches highly welcome')
                idval = self.buildfile_ids[(tname, o)]
                k = (tname, o)
                fileref = self.fileref_ids[k]
                assert o not in self.filemap
                self.filemap[o] = idval
                fullpath = os.path.join(self.environment.get_source_dir(), o)
                fullpath2 = fullpath
                o_dict = PbxDict()
                objects_dict.add_item(idval, o_dict, fullpath)
                o_dict.add_item('isa', 'PBXBuildFile')
                o_dict.add_item('fileRef', fileref, fullpath2)

            generator_id = 0
            for g in t.generated:
                if not isinstance(g, build.GeneratedList):
                    continue
                self.create_generator_shellphase(objects_dict, tname, generator_id)
                generator_id += 1

        # Custom targets are shell build phases in Xcode terminology.
        for tname, t in self.custom_targets.items():
            if not isinstance(t, build.CustomTarget):
                continue
            (srcs, ofilenames, cmd) = self.eval_custom_target_command(t)
            for o in ofilenames:
                custom_dict = PbxDict()
                objects_dict.add_item(self.custom_target_output_buildfile[o], custom_dict, f'/* {o} */')
                custom_dict.add_item('isa', 'PBXBuildFile')
                custom_dict.add_item('fileRef', self.custom_target_output_fileref[o])
            generator_id = 0
            for g in t.sources:
                if not isinstance(g, build.GeneratedList):
                    continue
                self.create_generator_shellphase(objects_dict, tname, generator_id)
                generator_id += 1

    def create_generator_shellphase(self, objects_dict: PbxDict, tname: str, generator_id: int) -> None:
        file_ids = self.generator_buildfile_ids[(tname, generator_id)]
        ref_ids = self.generator_fileref_ids[(tname, generator_id)]
        assert len(ref_ids) == len(file_ids)
        for file_o, ref_id in zip(file_ids, ref_ids):
            odict = PbxDict()
            objects_dict.add_item(file_o, odict)
            odict.add_item('isa', 'PBXBuildFile')
            odict.add_item('fileRef', ref_id)

    # This is skipped if Xcode 9 or above is installed, as PBXBuildStyle was removed on that version.
    def generate_pbx_build_style(self, objects_dict: PbxDict) -> None:
        for name, idval in self.buildstylemap.items():
            styledict = PbxDict()
            objects_dict.add_item(idval, styledict, name)
            styledict.add_item('isa', 'PBXBuildStyle')
            settings_dict = PbxDict()
            styledict.add_item('buildSettings', settings_dict)
            settings_dict.add_item('COPY_PHASE_STRIP', 'NO')
            styledict.add_item('name', name)

    def to_shell_script(self, args: CompilerArgs) -> str:
        quoted_cmd = []
        for c in args:
            quoted_cmd.append(c.replace('"', chr(92) + '"'))
        cmd = ' '.join(quoted_cmd)
        return f"\"#!/bin/sh\\n{cmd}\\n\""

    def generate_pbx_build_rule(self, objects_dict: PbxDict) -> None:
        for name, languages in self.build_rules.items():
            target: BuildTarget = self.build_targets[name]
            for language, idval in languages.items():
                compiler: Compiler = target.compilers[language]
                buildrule = PbxDict()
                buildrule.add_item('isa', 'PBXBuildRule')
                buildrule.add_item('compilerSpec', 'com.apple.compilers.proxy.script')
                if compiler.get_id() != 'yasm':
                    # Yasm doesn't generate escaped build rules
                    buildrule.add_item('dependencyFile', '$(DERIVED_FILE_DIR)/$(INPUT_FILE_BASE).d')
                buildrule.add_item('fileType', NEEDS_CUSTOM_RULES[language])
                inputfiles = PbxArray()
                buildrule.add_item('inputFiles', inputfiles)
                buildrule.add_item('isEditable', '0')
                outputfiles = PbxArray()
                outputfiles.add_item('$(DERIVED_FILE_DIR)/$(INPUT_FILE_BASE).o')
                buildrule.add_item('outputFiles', outputfiles)
                # Do NOT use this parameter. Xcode will accept it from the UI,
                # but the parser will break down inconsistently upon next
                # opening. rdar://FB12144055
                # outputargs = PbxArray()
                # args = self.generate_basic_compiler_args(target, compiler)
                # outputargs.add_item(self.to_shell_script(args))
                # buildrule.add_item('outputFilesCompilerFlags', outputargs)
                commands = CompilerArgs(compiler)
                commands += compiler.get_exelist()
                if compiler.get_id() == 'yasm':
                    # Yasm doesn't generate escaped build rules
                    commands += self.compiler_to_generator_args(target, compiler, output='"$SCRIPT_OUTPUT_FILE_0"', input='"$SCRIPT_INPUT_FILE"', depfile=None)
                else:
                    commands += self.compiler_to_generator_args(target,
                                                                compiler,
                                                                output='"$SCRIPT_OUTPUT_FILE_0"',
                                                                input='"$SCRIPT_INPUT_FILE"',
                                                                depfile='"$(dirname "$SCRIPT_OUTPUT_FILE_0")/$(basename "$SCRIPT_OUTPUT_FILE_0" .o).d"',
                                                                extras=['$OTHER_INPUT_FILE_FLAGS'])
                buildrule.add_item('script', self.to_shell_script(commands))
                objects_dict.add_item(idval, buildrule, 'PBXBuildRule')

    def generate_pbx_container_item_proxy(self, objects_dict: PbxDict) -> None:
        for t in self.build_targets:
            proxy_dict = PbxDict()
            objects_dict.add_item(self.containerproxy_map[t], proxy_dict, 'PBXContainerItemProxy')
            proxy_dict.add_item('isa', 'PBXContainerItemProxy')
            proxy_dict.add_item('containerPortal', self.project_uid, 'Project object')
            proxy_dict.add_item('proxyType', '1')
            proxy_dict.add_item('remoteGlobalIDString', self.native_targets[t])
            proxy_dict.add_item('remoteInfo', t)

    def generate_pbx_file_reference(self, objects_dict: PbxDict) -> None:
        for tname, t in self.build_targets.items():
            for dep in t.get_external_deps():
                if dep.found() and isinstance(dep, AppleFrameworks):
                    for f in dep.frameworks:
                        fw_dict = PbxDict()
                        framework_fileref = self.native_frameworks_fileref[f]
                        if objects_dict.has_item(framework_fileref):
                            continue
                        objects_dict.add_item(framework_fileref, fw_dict, f)
                        fw_dict.add_item('isa', 'PBXFileReference')
                        fw_dict.add_item('lastKnownFileType', 'wrapper.framework')
                        fw_dict.add_item('name', f'{f}.framework')
                        fw_dict.add_item('path', f'System/Library/Frameworks/{f}.framework')
                        fw_dict.add_item('sourceTree', 'SDKROOT')
            for s in t.sources:
                if not isinstance(s, mesonlib.File):
                    continue
                in_build_dir = s.is_built
                s = os.path.join(s.subdir, s.fname)
                idval = self.fileref_ids[(tname, s)]
                fullpath = os.path.join(self.environment.get_source_dir(), s)
                src_dict = PbxDict()
                xcodetype = self.get_xcodetype(s)
                name = os.path.basename(s)
                path = s
                objects_dict.add_item(idval, src_dict, fullpath)
                src_dict.add_item('isa', 'PBXFileReference')
                src_dict.add_item('explicitFileType', xcodetype)
                src_dict.add_item('fileEncoding', '4')
                if in_build_dir:
                    src_dict.add_item('name', name)
                    # This makes no sense. This should say path instead of name
                    # but then the path gets added twice.
                    src_dict.add_item('path', name)
                    src_dict.add_item('sourceTree', 'BUILD_ROOT')
                else:
                    src_dict.add_item('name', name)
                    src_dict.add_item('path', path)
                    src_dict.add_item('sourceTree', 'SOURCE_ROOT')

            generator_id = 0
            for g in t.generated:
                if not isinstance(g, build.GeneratedList):
                    continue
                outputs = self.generator_outputs[(tname, generator_id)]
                ref_ids = self.generator_fileref_ids[tname, generator_id]
                assert len(ref_ids) == len(outputs)
                for o, ref_id in zip(outputs, ref_ids):
                    odict = PbxDict()
                    name = os.path.basename(o)
                    objects_dict.add_item(ref_id, odict, o)
                    xcodetype = self.get_xcodetype(o)
                    rel_name = mesonlib.relpath(o, self.environment.get_source_dir())
                    odict.add_item('isa', 'PBXFileReference')
                    odict.add_item('explicitFileType', xcodetype)
                    odict.add_item('fileEncoding', '4')
                    odict.add_item('name', name)
                    odict.add_item('path', rel_name)
                    odict.add_item('sourceTree', 'SOURCE_ROOT')

                generator_id += 1

            for o in t.objects:
                if isinstance(o, build.ExtractedObjects):
                    # Same as with pbxbuildfile.
                    continue
                if isinstance(o, mesonlib.File):
                    fullpath = o.absolute_path(self.environment.get_source_dir(), self.environment.get_build_dir())
                    o = os.path.join(o.subdir, o.fname)
                elif isinstance(o, str):
                    o = os.path.join(t.subdir, o)
                    fullpath = os.path.join(self.environment.get_source_dir(), o)
                else:
                    # TODO: handle CustomTarget, CustomTargeIndex, and GeneratedList
                    raise MesonBugException('Not implemented, patches highly welcome')
                idval = self.fileref_ids[(tname, o)]
                rel_name = mesonlib.relpath(fullpath, self.environment.get_source_dir())
                o_dict = PbxDict()
                name = os.path.basename(o)
                objects_dict.add_item(idval, o_dict, fullpath)
                o_dict.add_item('isa', 'PBXFileReference')
                o_dict.add_item('explicitFileType', self.get_xcodetype(o))
                o_dict.add_item('fileEncoding', '4')
                o_dict.add_item('name', name)
                o_dict.add_item('path', rel_name)
                o_dict.add_item('sourceTree', 'SOURCE_ROOT')

            for e in t.extra_files:
                if isinstance(e, mesonlib.File):
                    e = os.path.join(e.subdir, e.fname)
                else:
                    e = os.path.join(t.subdir, e)
                idval = self.fileref_ids[(tname, e)]
                fullpath = os.path.join(self.environment.get_source_dir(), e)
                e_dict = PbxDict()
                xcodetype = self.get_xcodetype(e)
                name = os.path.basename(e)
                path = e
                objects_dict.add_item(idval, e_dict, fullpath)
                e_dict.add_item('isa', 'PBXFileReference')
                e_dict.add_item('explicitFileType', xcodetype)
                e_dict.add_item('name', name)
                e_dict.add_item('path', path)
                e_dict.add_item('sourceTree', 'SOURCE_ROOT')
        for tname, idval in self.target_filemap.items():
            target_dict = PbxDict()
            objects_dict.add_item(idval, target_dict, tname)
            t = self.build_targets[tname]
            fname = t.get_filename()
            reftype = 0
            if isinstance(t, build.Executable):
                typestr = 'compiled.mach-o.executable'
                path = fname
            elif isinstance(t, build.SharedLibrary):
                typestr = self.get_xcodetype('dummy.dylib')
                path = fname
            else:
                typestr = self.get_xcodetype(fname)
                path = '"%s"' % t.get_filename()
            target_dict.add_item('isa', 'PBXFileReference')
            target_dict.add_item('explicitFileType', typestr)
            target_dict.add_item('path', path)
            target_dict.add_item('refType', reftype)
            target_dict.add_item('sourceTree', 'BUILT_PRODUCTS_DIR')

        for tname, t in self.custom_targets.items():
            if not isinstance(t, build.CustomTarget):
                continue
            (srcs, ofilenames, cmd) = self.eval_custom_target_command(t)
            for s in t.sources:
                if not isinstance(s, mesonlib.File):
                    continue
                s = os.path.join(s.subdir, s.fname)
                custom_dict = PbxDict()
                typestr = self.get_xcodetype(s)
                custom_dict.add_item('isa', 'PBXFileReference')
                custom_dict.add_item('explicitFileType', typestr)
                custom_dict.add_item('name', s)
                custom_dict.add_item('path', s)
                custom_dict.add_item('refType', 0)
                custom_dict.add_item('sourceTree', 'SOURCE_ROOT')
                objects_dict.add_item(self.fileref_ids[(tname, s)], custom_dict)
            for o in ofilenames:
                custom_dict = PbxDict()
                typestr = self.get_xcodetype(o)
                custom_dict.add_item('isa', 'PBXFileReference')
                custom_dict.add_item('explicitFileType', typestr)
                custom_dict.add_item('name', o)
                custom_dict.add_item('path', os.path.join(self.src_to_build, o))
                custom_dict.add_item('refType', 0)
                custom_dict.add_item('sourceTree', 'SOURCE_ROOT')
                objects_dict.add_item(self.custom_target_output_fileref[o], custom_dict)

        for buildfile in self.build.def_files:
            basename = os.path.split(buildfile)[1]
            buildfile_dict = PbxDict()
            typestr = self.get_xcodetype(buildfile)
            buildfile_dict.add_item('isa', 'PBXFileReference')
            buildfile_dict.add_item('explicitFileType', typestr)
            buildfile_dict.add_item('name', basename)
            buildfile_dict.add_item('path', buildfile)
            buildfile_dict.add_item('refType', 0)
            buildfile_dict.add_item('sourceTree', 'SOURCE_ROOT')
            objects_dict.add_item(self.fileref_ids[buildfile], buildfile_dict)

    def generate_pbx_frameworks_buildphase(self, objects_dict: PbxDict) -> None:
        for t in self.build_targets.values():
            bt_dict = PbxDict()
            objects_dict.add_item(self.buildphase_map[t.id]['Frameworks'], bt_dict, 'Frameworks')
            bt_dict.add_item('isa', 'PBXFrameworksBuildPhase')
            bt_dict.add_item('buildActionMask', 2147483647)
            file_list = PbxArray()
            bt_dict.add_item('files', file_list)
            for dep in t.get_external_deps():
                if dep.found() and isinstance(dep, AppleFrameworks):
                    for f in dep.frameworks:
                        file_list.add_item(self.native_frameworks[f], f'{f}.framework in Frameworks')
            bt_dict.add_item('runOnlyForDeploymentPostprocessing', 0)

    def generate_pbx_group(self, objects_dict: PbxDict) -> None:
        groupmap = {}
        target_src_map = {}
        for t in self.build_targets:
            groupmap[t] = self.gen_id()
            target_src_map[t] = self.gen_id()
        for t in self.custom_targets:
            groupmap[t] = self.gen_id()
            target_src_map[t] = self.gen_id()
        projecttree_id = self.gen_id()
        resources_id = self.gen_id()
        products_id = self.gen_id()
        frameworks_id = self.gen_id()
        main_dict = PbxDict()
        objects_dict.add_item(self.maingroup_id, main_dict)
        main_dict.add_item('isa', 'PBXGroup')
        main_children = PbxArray()
        main_dict.add_item('children', main_children)
        main_children.add_item(projecttree_id, 'Project tree')
        main_children.add_item(resources_id, 'Resources')
        main_children.add_item(products_id, 'Products')
        main_children.add_item(frameworks_id, 'Frameworks')
        main_dict.add_item('sourceTree', '<group>')

        # Define each folder as a group in Xcode. That way, it can build the file tree correctly.
        # This must be done before the project tree group is generated, as source files are added during that phase.
        for (path, target), id in self.foldermap.items():
            folder_dict = PbxDict()
            objects_dict.add_item(id, folder_dict, path)
            folder_dict.add_item('isa', 'PBXGroup')
            folder_children = PbxArray()
            folder_dict.add_item('children', folder_children)
            folder_dict.add_item('name', '"{}"'.format(path.rsplit('/', 1)[-1]))
            folder_dict.add_item('path', f'"{path}"')
            folder_dict.add_item('sourceTree', 'SOURCE_ROOT')

            # Add any detected subdirectories (not declared as subdir()) here, but only one level higher.
            # Example: In "root", add "root/sub", but not "root/sub/subtwo".
            for path_dep, target_dep in self.foldermap:
                if path_dep.startswith(path) and path_dep.split('/', 1)[0] == path.split('/', 1)[0] and path_dep != path and path_dep.count('/') == path.count('/') + 1 and target == target_dep:
                    folder_children.add_item(self.foldermap[(path_dep, target)], path_dep)

        self.add_projecttree(objects_dict, projecttree_id)

        resource_dict = PbxDict()
        objects_dict.add_item(resources_id, resource_dict, 'Resources')
        resource_dict.add_item('isa', 'PBXGroup')
        resource_children = PbxArray()
        resource_dict.add_item('children', resource_children)
        resource_dict.add_item('name', 'Resources')
        resource_dict.add_item('sourceTree', '<group>')

        frameworks_dict = PbxDict()
        objects_dict.add_item(frameworks_id, frameworks_dict, 'Frameworks')
        frameworks_dict.add_item('isa', 'PBXGroup')
        frameworks_children = PbxArray()
        frameworks_dict.add_item('children', frameworks_children)
        # write frameworks

        for t in self.build_targets.values():
            for dep in t.get_external_deps():
                if dep.found() and isinstance(dep, AppleFrameworks):
                    for f in dep.frameworks:
                        frameworks_children.add_item(self.native_frameworks_fileref[f], f)

        frameworks_dict.add_item('name', 'Frameworks')
        frameworks_dict.add_item('sourceTree', '<group>')

        for tname, t in self.custom_targets.items():
            target_dict = PbxDict()
            objects_dict.add_item(groupmap[tname], target_dict, tname)
            target_dict.add_item('isa', 'PBXGroup')
            target_children = PbxArray()
            target_dict.add_item('children', target_children)
            target_children.add_item(target_src_map[tname], 'Source files')
            if t.subproject:
                target_dict.add_item('name', f'{t.subproject} • {t.name}')
            else:
                target_dict.add_item('name', t.name)
            target_dict.add_item('sourceTree', '<group>')
            source_files_dict = PbxDict()
            objects_dict.add_item(target_src_map[tname], source_files_dict, 'Source files')
            source_files_dict.add_item('isa', 'PBXGroup')
            source_file_children = PbxArray()
            source_files_dict.add_item('children', source_file_children)
            for s in t.sources:
                if not isinstance(s, mesonlib.File):
                    continue
                s = os.path.join(s.subdir, s.fname)
                source_file_children.add_item(self.fileref_ids[(tname, s)], s)
            source_files_dict.add_item('name', 'Source files')
            source_files_dict.add_item('sourceTree', '<group>')

        # And finally products
        product_dict = PbxDict()
        objects_dict.add_item(products_id, product_dict, 'Products')
        product_dict.add_item('isa', 'PBXGroup')
        product_children = PbxArray()
        product_dict.add_item('children', product_children)
        for t in self.build_targets:
            product_children.add_item(self.target_filemap[t], t)
        product_dict.add_item('name', 'Products')
        product_dict.add_item('sourceTree', '<group>')

    def write_group_target_entry(self, objects_dict: PbxDict, t: build.BuildTarget) -> str:
        tid = t.get_id()
        group_id = self.gen_id()
        target_dict = PbxDict()
        folder_ids = set()
        objects_dict.add_item(group_id, target_dict, tid)
        target_dict.add_item('isa', 'PBXGroup')
        target_children = PbxArray()
        target_dict.add_item('children', target_children)
        target_dict.add_item('name', f'{t} · target')
        target_dict.add_item('sourceTree', '<group>')
        source_files_dict = PbxDict()
        for s in t.sources:
            if not isinstance(s, mesonlib.File):
                continue
            # If the file is in a folder, add it to the group representing that folder.
            if '/' in s.fname:
                folder = '/'.join(s.fname.split('/')[:-1])
                folder_dict = objects_dict.get_item_value(self.foldermap[(folder, t)], PbxDict)
                folder_children = folder_dict.get_item_value('children', PbxArray)
                temp = os.path.join(s.subdir, s.fname)
                folder_children.add_item(self.fileref_ids[(tid, temp)], temp)
                if self.foldermap[(folder, t)] in folder_ids:
                    continue
                if len(folder.split('/')) == 1:
                    target_children.add_item(self.foldermap[(folder, t)], folder)
                    folder_ids.add(self.foldermap[(folder, t)])
                continue
            s = os.path.join(s.subdir, s.fname)
            target_children.add_item(self.fileref_ids[(tid, s)], s)
        for o in t.objects:
            if isinstance(o, build.ExtractedObjects):
                # Do not show built object files in the project tree.
                continue
            if isinstance(o, mesonlib.File):
                o = os.path.join(o.subdir, o.fname)
            elif isinstance(o, str):
                o = os.path.join(t.subdir, o)
            else:
                # TODO: handle CustomTarget, CustomTargeIndex, and GeneratedList
                raise MesonBugException('Not implemented, patches highly welcome')
            target_children.add_item(self.fileref_ids[(tid, o)], o)
        for e in t.extra_files:
            if isinstance(e, mesonlib.File):
                e = os.path.join(e.subdir, e.fname)
            elif isinstance(e, str):
                e = os.path.join(t.subdir, e)
            else:
                continue
            target_children.add_item(self.fileref_ids[(tid, e)], e)
        source_files_dict.add_item('name', 'Source files')
        source_files_dict.add_item('sourceTree', '<group>')
        return group_id

    def add_projecttree(self, objects_dict: PbxDict, projecttree_id: str) -> None:
        root_dict = PbxDict()
        objects_dict.add_item(projecttree_id, root_dict, "Root of project tree")
        root_dict.add_item('isa', 'PBXGroup')
        target_children = PbxArray()
        root_dict.add_item('children', target_children)
        root_dict.add_item('name', 'Project root')
        root_dict.add_item('sourceTree', '<group>')

        project_tree = self.generate_project_tree()
        self.write_tree(objects_dict, project_tree, target_children, '')

    def write_tree(self, objects_dict: PbxDict, tree_node: FileTreeEntry, children_array: PbxArray, current_subdir: str) -> None:
        for subdir_name, subdir_node in tree_node.subdirs.items():
            subdir_dict = PbxDict()
            subdir_children = PbxArray()
            subdir_id = self.gen_id()
            objects_dict.add_item(subdir_id, subdir_dict)
            children_array.add_item(subdir_id)
            subdir_dict.add_item('isa', 'PBXGroup')
            subdir_dict.add_item('children', subdir_children)
            subdir_dict.add_item('name', subdir_name)
            subdir_dict.add_item('sourceTree', '<group>')
            self.write_tree(objects_dict, subdir_node, subdir_children, os.path.join(current_subdir, subdir_name))
        for target in tree_node.targets:
            group_id = self.write_group_target_entry(objects_dict, target)
            children_array.add_item(group_id)
        potentials = [os.path.join(current_subdir, 'meson.build'),
                      os.path.join(current_subdir, 'meson.options'),
                      os.path.join(current_subdir, 'meson_options.txt')]
        for bf in potentials:
            i = self.fileref_ids.get(bf, None)
            if i:
                children_array.add_item(i)

    def generate_project_tree(self) -> FileTreeEntry:
        tree_info = FileTreeEntry()
        for tname, t in self.build_targets.items():
            self.add_target_to_tree(tree_info, t)
        return tree_info

    def add_target_to_tree(self, tree_root: FileTreeEntry, t: build.BuildTarget) -> None:
        current_node = tree_root
        path_segments = t.subdir.split('/')
        for s in path_segments:
            if not s:
                continue
            if s not in current_node.subdirs:
                current_node.subdirs[s] = FileTreeEntry()
            current_node = current_node.subdirs[s]
        current_node.targets.append(t)

    def generate_pbx_native_target(self, objects_dict: PbxDict) -> None:
        for tname, idval in self.native_targets.items():
            ntarget_dict = PbxDict()
            t = self.build_targets[tname]
            objects_dict.add_item(idval, ntarget_dict, tname)
            ntarget_dict.add_item('isa', 'PBXNativeTarget')
            ntarget_dict.add_item('buildConfigurationList', self.buildconflistmap[tname], f'Build configuration list for PBXNativeTarget "{tname}"')
            buildphases_array = PbxArray()
            ntarget_dict.add_item('buildPhases', buildphases_array)
            generator_id = 0
            for g in t.generated:
                # Custom target are handled via inter-target dependencies.
                # Generators are built as a shellscriptbuildphase.
                if isinstance(g, build.GeneratedList):
                    buildphases_array.add_item(self.shell_targets[(tname, generator_id)], f'Generator {generator_id}/{tname}')
                    generator_id += 1
            for bpname, bpval in self.buildphase_map[t.id].items():
                buildphases_array.add_item(bpval, f'{bpname} yyy')
            build_rules = PbxArray()
            for language, build_rule_idval in self.build_rules[tname].items():
                build_rules.add_item(build_rule_idval, f'{language}')
            ntarget_dict.add_item('buildRules', build_rules)
            dep_array = PbxArray()
            ntarget_dict.add_item('dependencies', dep_array)
            dep_array.add_item(self.regen_dependency_id)
            # These dependencies only tell Xcode that the deps must be built
            # before this one. They don't set up linkage or anything
            # like that. Those are set up in the XCBuildConfiguration.
            for lt in self.build_targets[tname].link_targets:
                # NOT DOCUMENTED, may need to make different links
                # to same target have different targetdependency item.
                if isinstance(lt, (build.CustomTarget, build.CustomTargetIndex)):
                    dep_array.add_item(self.pbx_custom_dep_map[lt.get_id()], lt.get_basename())
                else:
                    idval = self.pbx_dep_map[lt.get_id()]
                    dep_array.add_item(idval, 'PBXTargetDependency')
            for o in t.objects:
                if isinstance(o, build.ExtractedObjects):
                    source_target_id = o.target.get_id()
                    idval = self.pbx_dep_map[source_target_id]
                    dep_array.add_item(idval, 'PBXTargetDependency')
            generator_id = 0
            for o in t.generated:
                if isinstance(o, (build.CustomTarget, build.CustomTargetIndex)):
                    dep_array.add_item(self.pbx_custom_dep_map[o.get_id()], o.get_basename())

                generator_id += 1

            # xcode backend does not support link_early_args
            if isinstance(t, build.BuildTarget) and not isinstance(t, build.StaticLibrary) and t.link_early_args:
                raise MesonException(f'XCode backend does not support link_early_args for {t.get_basename()}')

            ntarget_dict.add_item('name', tname)
            ntarget_dict.add_item('productName', tname)
            ntarget_dict.add_item('productReference', self.target_filemap[tname], tname)
            if isinstance(t, build.Executable):
                typestr = 'com.apple.product-type.tool'
            elif isinstance(t, build.StaticLibrary):
                typestr = 'com.apple.product-type.library.static'
            elif isinstance(t, build.SharedLibrary):
                typestr = 'com.apple.product-type.library.dynamic'
            else:
                raise MesonException('Unknown target type for %s' % tname)
            ntarget_dict.add_item('productType', f'"{typestr}"')

    def generate_pbx_project(self, objects_dict: PbxDict) -> None:
        project_dict = PbxDict()
        objects_dict.add_item(self.project_uid, project_dict, 'Project object')
        project_dict.add_item('isa', 'PBXProject')
        attr_dict = PbxDict()
        project_dict.add_item('attributes', attr_dict)
        attr_dict.add_item('BuildIndependentTargetsInParallel', 'YES')
        project_dict.add_item('buildConfigurationList', self.project_conflist, f'Build configuration list for PBXProject "{self.build.project_name}"')
        project_dict.add_item('buildSettings', PbxDict())
        if self.objversion < 50:
            style_arr = PbxArray()
            project_dict.add_item('buildStyles', style_arr)
            for name, idval in self.buildstylemap.items():
                style_arr.add_item(idval, name)
        project_dict.add_item('compatibilityVersion', self.xcodeversion)
        project_dict.add_item('hasScannedForEncodings', 0)
        project_dict.add_item('mainGroup', self.maingroup_id)
        project_dict.add_item('projectDirPath', self.environment.get_source_dir())
        project_dict.add_item('projectRoot', '')
        targets_arr = PbxArray()
        project_dict.add_item('targets', targets_arr)
        targets_arr.add_item(self.all_id, 'ALL_BUILD')
        targets_arr.add_item(self.test_id, 'RUN_TESTS')
        targets_arr.add_item(self.regen_id, 'REGENERATE')
        for t in self.build_targets:
            targets_arr.add_item(self.native_targets[t], t)
        for t in self.custom_targets:
            targets_arr.add_item(self.custom_aggregate_targets[t], t)

    def generate_pbx_shell_build_phase(self, objects_dict: PbxDict) -> None:
        self.generate_test_shell_build_phase(objects_dict)
        self.generate_regen_shell_build_phase(objects_dict)
        self.generate_custom_target_shell_build_phases(objects_dict)
        self.generate_generator_target_shell_build_phases(objects_dict)

    def generate_test_shell_build_phase(self, objects_dict: PbxDict) -> None:
        shell_dict = PbxDict()
        objects_dict.add_item(self.test_command_id, shell_dict, 'ShellScript')
        shell_dict.add_item('isa', 'PBXShellScriptBuildPhase')
        shell_dict.add_item('buildActionMask', 2147483647)
        shell_dict.add_item('files', PbxArray())
        shell_dict.add_item('inputPaths', PbxArray())
        shell_dict.add_item('outputPaths', PbxArray())
        shell_dict.add_item('runOnlyForDeploymentPostprocessing', 0)
        shell_dict.add_item('shellPath', '/bin/sh')
        cmd = mesonlib.get_meson_command() + ['test', '--no-rebuild', '-C', self.environment.get_build_dir()]
        cmdstr = ' '.join(["'%s'" % i for i in cmd])
        shell_dict.add_item('shellScript', cmdstr)
        shell_dict.add_item('showEnvVarsInLog', 0)

    def generate_regen_shell_build_phase(self, objects_dict: PbxDict) -> None:
        shell_dict = PbxDict()
        objects_dict.add_item(self.regen_command_id, shell_dict, 'ShellScript')
        shell_dict.add_item('isa', 'PBXShellScriptBuildPhase')
        shell_dict.add_item('buildActionMask', 2147483647)
        shell_dict.add_item('files', PbxArray())
        shell_dict.add_item('inputPaths', PbxArray())
        shell_dict.add_item('outputPaths', PbxArray())
        shell_dict.add_item('runOnlyForDeploymentPostprocessing', 0)
        shell_dict.add_item('shellPath', '/bin/sh')
        cmd = mesonlib.get_meson_command() + ['--internal', 'regencheck', os.path.join(self.environment.get_build_dir(), 'meson-private')]
        cmdstr = ' '.join(["'%s'" % i for i in cmd])
        shell_dict.add_item('shellScript', cmdstr)
        shell_dict.add_item('showEnvVarsInLog', 0)

    def generate_custom_target_shell_build_phases(self, objects_dict: PbxDict) -> None:
        # Custom targets are shell build phases in Xcode terminology.
        for tname, t in self.custom_targets.items():
            if not isinstance(t, build.CustomTarget):
                continue
            (srcs, ofilenames, cmd) = self.eval_custom_target_command(t, absolute_outputs=True)
            fixed_cmd, _ = self.as_meson_exe_cmdline(cmd[0],
                                                     cmd[1:],
                                                     capture=ofilenames[0] if t.capture else None,
                                                     feed=srcs[0] if t.feed else None,
                                                     env=t.env)
            custom_dict = PbxDict()
            objects_dict.add_item(self.shell_targets[tname], custom_dict, f'/* Custom target {tname} */')
            custom_dict.add_item('isa', 'PBXShellScriptBuildPhase')
            custom_dict.add_item('buildActionMask', 2147483647)
            custom_dict.add_item('files', PbxArray())
            custom_dict.add_item('inputPaths', PbxArray())
            outarray = PbxArray()
            custom_dict.add_item('name', '"Generate {}."'.format(ofilenames[0]))
            custom_dict.add_item('outputPaths', outarray)
            for o in ofilenames:
                outarray.add_item(os.path.join(self.environment.get_build_dir(), o))
            custom_dict.add_item('runOnlyForDeploymentPostprocessing', 0)
            custom_dict.add_item('shellPath', '/bin/sh')
            workdir = self.environment.get_build_dir()
            quoted_cmd = []
            for c in fixed_cmd:
                quoted_cmd.append(c.replace('"', chr(92) + '"'))
            cmdstr = ' '.join([f"\\'{x}\\'" for x in quoted_cmd])
            custom_dict.add_item('shellScript', f'cd \'{workdir}\'; {cmdstr}')
            custom_dict.add_item('showEnvVarsInLog', 0)

    def generate_generator_target_shell_build_phases(self, objects_dict: PbxDict) -> None:
        for tname, t in self.build_targets.items():
            generator_id = 0
            for genlist in t.generated:
                if isinstance(genlist, build.GeneratedList):
                    self.generate_single_generator_phase(tname, t, genlist, generator_id, objects_dict)
                    generator_id += 1
        for tname, t in self.custom_targets.items():
            generator_id = 0
            for genlist in t.sources:
                if isinstance(genlist, build.GeneratedList):
                    self.generate_single_generator_phase(tname, t, genlist, generator_id, objects_dict)
                    generator_id += 1

    def generate_single_generator_phase(self, tname: str, t: build.AnyTargetType,
                                        genlist: build.GeneratedList, generator_id: int, objects_dict: PbxDict) -> None:
        # TODO: this should be rewritten to use the meson wrapper, like the other generators do
        # Currently it doesn't handle a host binary that requires an exe wrapper correctly.
        generator = genlist.get_generator()
        exe = generator.get_exe()
        exe_arr = self.build_target_to_cmd_array(exe)
        workdir = self.environment.get_build_dir()
        target_private_dir = self.relpath(self.get_target_private_dir(t), self.get_target_dir(t))
        gen_dict = PbxDict()
        objects_dict.add_item(self.shell_targets[(tname, generator_id)], gen_dict, f'Generator {generator_id}/{tname}')
        infilelist = genlist.get_inputs()
        outfilelist = genlist.get_outputs()
        gen_dict.add_item('isa', 'PBXShellScriptBuildPhase')
        gen_dict.add_item('buildActionMask', 2147483647)
        gen_dict.add_item('files', PbxArray())
        gen_dict.add_item('inputPaths', PbxArray())
        gen_dict.add_item('name', f'Generator {generator_id}/{tname}')
        commands = [["cd", workdir]] # Array of arrays, each one a single command, will get concatenated below.
        k = (tname, generator_id)
        ofile_abs = self.generator_outputs[k]
        outarray = PbxArray()
        gen_dict.add_item('outputPaths', outarray)
        for of in ofile_abs:
            outarray.add_item(of)
        for i in infilelist:
            # This might be needed to be added to inputPaths. It's not done yet as it is
            # unclear whether it is necessary, what actually happens when it is defined
            # and currently the build works without it.
            #infile_abs = i.absolute_path(self.environment.get_source_dir(), self.environment.get_build_dir())
            infilename = i.rel_to_builddir(self.build_to_src, target_private_dir)
            base_args = generator.get_arglist(infilename)
            for o_base in genlist.get_outputs_for(i):
                o = os.path.join(self.get_target_private_dir(t), o_base)
                args = []
                for arg in base_args:
                    arg = arg.replace("@INPUT@", infilename)
                    arg = arg.replace('@OUTPUT@', o).replace('@BUILD_DIR@', self.get_target_private_dir(t))
                    arg = arg.replace("@CURRENT_SOURCE_DIR@", os.path.join(self.build_to_src, t.subdir))
                    args.append(arg)
                args = self.replace_outputs(args, self.get_target_private_dir(t), outfilelist)
                args = self.replace_extra_args(args, genlist)
                if generator.capture:
                    # When capturing, stdout is the output. Forward it with the shell.
                    full_command = ['('] + exe_arr + args + ['>', o, ')']
                else:
                    full_command = exe_arr + args
                commands.append(full_command)
        gen_dict.add_item('runOnlyForDeploymentPostprocessing', 0)
        gen_dict.add_item('shellPath', '/bin/sh')
        quoted_cmds = []
        for cmnd in commands:
            q = []
            for c in cmnd:
                if ' ' in c:
                    q.append(f'\\"{c}\\"')
                else:
                    q.append(c)
            quoted_cmds.append(' '.join(q))
        cmdstr = ' && '.join(quoted_cmds)
        gen_dict.add_item('shellScript', cmdstr)
        gen_dict.add_item('showEnvVarsInLog', 0)

    def generate_pbx_sources_build_phase(self, objects_dict: PbxDict) -> None:
        for name in self.source_phase:
            phase_dict = PbxDict()
            t = self.build_targets[name]
            objects_dict.add_item(self.buildphase_map[t.id][name], phase_dict, 'Sources')
            phase_dict.add_item('isa', 'PBXSourcesBuildPhase')
            phase_dict.add_item('buildActionMask', 2147483647)
            file_arr = PbxArray()
            phase_dict.add_item('files', file_arr)
            for s in self.build_targets[name].sources:
                s = os.path.join(s.subdir, s.fname)
                if not compilers.is_header(s):
                    file_arr.add_item(self.buildfile_ids[(name, s)], os.path.join(self.environment.get_source_dir(), s))
            generator_id = 0
            for gt in t.generated:
                if isinstance(gt, build.CustomTarget):
                    (srcs, ofilenames, cmd) = self.eval_custom_target_command(gt)
                    for o in ofilenames:
                        file_arr.add_item(self.custom_target_output_buildfile[o],
                                          os.path.join(self.environment.get_build_dir(), o))
                elif isinstance(gt, build.CustomTargetIndex):
                    output_dir = self.get_custom_target_output_dir(gt)
                    for o in gt.get_outputs():
                        o = os.path.join(output_dir, o)
                        file_arr.add_item(self.custom_target_output_buildfile[o],
                                          os.path.join(self.environment.get_build_dir(), o))
                elif isinstance(gt, build.GeneratedList):
                    genfiles = self.generator_buildfile_ids[(name, generator_id)]
                    generator_id += 1
                    for o in genfiles:
                        file_arr.add_item(o)
                else:
                    raise RuntimeError('Unknown input type: ' + str(gt))
            phase_dict.add_item('runOnlyForDeploymentPostprocessing', 0)

    def generate_pbx_target_dependency(self, objects_dict: PbxDict) -> None:
        all_dict = PbxDict()
        objects_dict.add_item(self.build_all_tdep_id, all_dict, 'ALL_BUILD')
        all_dict.add_item('isa', 'PBXTargetDependency')
        all_dict.add_item('target', self.all_id)
        targets: list[tuple[str, str, str, str | None]] = []
        targets.append((self.regen_dependency_id, self.regen_id, 'REGEN', None))
        for t in self.build_targets:
            idval = self.pbx_dep_map[t] # VERIFY: is this correct?
            targets.append((idval, self.native_targets[t], t, self.containerproxy_map[t]))

        for t in self.custom_targets:
            idval = self.pbx_custom_dep_map[t]
            targets.append((idval, self.custom_aggregate_targets[t], t, None)) # self.containerproxy_map[t]))

        # Sort object by ID
        sorted_targets = sorted(targets, key=operator.itemgetter(0))
        for t in sorted_targets:
            t_dict = PbxDict()
            objects_dict.add_item(t[0], t_dict, 'PBXTargetDependency')
            t_dict.add_item('isa', 'PBXTargetDependency')
            t_dict.add_item('target', t[1], t[2])
            if t[3] is not None:
                t_dict.add_item('targetProxy', t[3], 'PBXContainerItemProxy')

    def generate_xc_build_configuration(self, objects_dict: PbxDict) -> None:
        # First the setup for the toplevel project.
        for buildtype in self.buildtypes:
            bt_dict = PbxDict()
            objects_dict.add_item(self.project_configurations[buildtype], bt_dict, buildtype)
            bt_dict.add_item('isa', 'XCBuildConfiguration')
            settings_dict = PbxDict()
            bt_dict.add_item('buildSettings', settings_dict)
            settings_dict.add_item('ARCHS', self.arch)
            settings_dict.add_item('BUILD_DIR', self.environment.get_build_dir())
            settings_dict.add_item('BUILD_ROOT', '$(BUILD_DIR)')
            settings_dict.add_item('ONLY_ACTIVE_ARCH', 'YES')
            settings_dict.add_item('SWIFT_VERSION', '5.0')
            settings_dict.add_item('SDKROOT', 'macosx')
            settings_dict.add_item('OBJROOT', '$(BUILD_DIR)/build')
            bt_dict.add_item('name', buildtype)

        # Then the all target.
        for buildtype in self.buildtypes:
            bt_dict = PbxDict()
            objects_dict.add_item(self.buildall_configurations[buildtype], bt_dict, buildtype)
            bt_dict.add_item('isa', 'XCBuildConfiguration')
            settings_dict = PbxDict()
            bt_dict.add_item('buildSettings', settings_dict)
            warn_array = PbxArray()
            warn_array.add_item('"$(inherited)"')
            settings_dict.add_item('WARNING_CFLAGS', warn_array)

            bt_dict.add_item('name', buildtype)

        # Then the test target.
        for buildtype in self.buildtypes:
            bt_dict = PbxDict()
            objects_dict.add_item(self.test_configurations[buildtype], bt_dict, buildtype)
            bt_dict.add_item('isa', 'XCBuildConfiguration')
            settings_dict = PbxDict()
            bt_dict.add_item('buildSettings', settings_dict)
            warn_array = PbxArray()
            settings_dict.add_item('WARNING_CFLAGS', warn_array)
            warn_array.add_item('"$(inherited)"')
            bt_dict.add_item('name', buildtype)

        # Now finally targets.
        for target_name, target in self.build_targets.items():
            self.generate_single_build_target(objects_dict, target_name, target)

        for target_name, target in self.custom_targets.items():
            bt_dict = PbxDict()
            objects_dict.add_item(self.buildconfmap[target_name][buildtype], bt_dict, buildtype)
            bt_dict.add_item('isa', 'XCBuildConfiguration')
            settings_dict = PbxDict()
            bt_dict.add_item('buildSettings', settings_dict)
            settings_dict.add_item('ARCHS', self.arch)
            settings_dict.add_item('ONLY_ACTIVE_ARCH', 'YES')
            settings_dict.add_item('SDKROOT', 'macosx')
            bt_dict.add_item('name', buildtype)

    def determine_internal_dep_link_args(self, target: build.BuildTarget, buildtype: str) -> T.Tuple[T.List[str], bool]:
        links_dylib = False
        dep_libs = []
        for l in target.link_targets:
            if isinstance(target, build.SharedModule) and isinstance(l, build.Executable):
                continue
            if isinstance(l, (build.CustomTarget, build.CustomTargetIndex)):
                rel_dir = self.get_custom_target_output_dir(l.get_target())
                libname = l.get_filename()
            else:
                rel_dir = self.get_target_dir(l)
                libname = l.get_filename()
            abs_path = os.path.join(self.environment.get_build_dir(), rel_dir, libname)
            dep_libs.append("'%s'" % abs_path)
            if isinstance(l, build.SharedLibrary):
                links_dylib = True
            if isinstance(l, build.StaticLibrary):
                (sub_libs, sub_links_dylib) = self.determine_internal_dep_link_args(l, buildtype)
                dep_libs += sub_libs
                links_dylib = links_dylib or sub_links_dylib
        return (dep_libs, links_dylib)

    def generate_single_build_target(self, objects_dict: PbxDict, target_name: str, target: build.BuildTarget) -> None:
        for buildtype in self.buildtypes:
            dep_libs: T.List[str] = []
            links_dylib = False
            headerdirs = []
            bridging_header = ""
            is_swift = self.is_swift_target(target)
            langs = set()
            for d in target.include_dirs:
                headerdirs.extend(d.abs_string_list(self.environment.get_source_dir(), self.environment.get_build_dir()))
            # Swift can import declarations from C-based code using bridging headers.
            # There can only be one header, and it must be included as a source file.
            for i in target.get_sources():
                if compilers.is_header(i) and is_swift:
                    relh = i.rel_to_builddir(self.build_to_src)
                    bridging_header = os.path.normpath(os.path.join(self.environment.get_build_dir(), relh))
                    break
            (dep_libs, links_dylib) = self.determine_internal_dep_link_args(target, buildtype)
            if links_dylib:
                dep_libs = ['-Wl,-search_paths_first', '-Wl,-headerpad_max_install_names'] + dep_libs
            dylib_version = None
            if isinstance(target, build.SharedLibrary):
                if isinstance(target, build.SharedModule):
                    ldargs = []
                else:
                    ldargs = ['-dynamiclib']
                ldargs += ['-Wl,-headerpad_max_install_names'] + dep_libs
                install_path = os.path.join(self.environment.get_build_dir(), target.subdir, buildtype)
                dylib_version = target.soversion
            else:
                ldargs = dep_libs
                install_path = ''
            if dylib_version is not None:
                product_name = target.get_basename() + '.' + dylib_version
            else:
                product_name = target.get_basename()
            ldargs += target.link_args
            # Swift is special. Again. You can't mix Swift with other languages
            # in the same target. Thus for Swift we only use
            # TODO: is this still true?
            stdlib_args: list[str]
            if is_swift:
                linker, stdlib_args = target.compilers['swift'], []
            else:
                linker, stdlib_args = self.determine_linker_and_stdlib_args(target)
            if not isinstance(linker, StaticLinker):
                ldargs += linker.get_build_link_args(target, self.build)
            cargs = []
            for dep in target.get_external_deps():
                cargs += dep.get_compile_args()
                ldargs += dep.get_link_args()
            for o in target.objects:
                # Add extracted objects to the link line by hand.
                if isinstance(o, build.ExtractedObjects):
                    added_objs = set()
                    for objname_rel in self.determine_ext_objs(o):
                        objname_abs = os.path.join(self.environment.get_build_dir(), o.target.subdir, objname_rel)
                        if objname_abs not in added_objs:
                            added_objs.add(objname_abs)
                            ldargs += [r'\"' + objname_abs + r'\"']
            generator_id = 0
            for o in target.generated:
                if isinstance(o, build.GeneratedList):
                    outputs = self.generator_outputs[target_name, generator_id]
                    generator_id += 1
                    for o_abs in outputs:
                        if o_abs.endswith('.o') or o_abs.endswith('.obj'):
                            ldargs += [r'\"' + o_abs + r'\"']
                else:
                    if isinstance(o, build.CustomTarget):
                        (srcs, ofilenames, cmd) = self.eval_custom_target_command(o)
                        for ofname in ofilenames:
                            if os.path.splitext(ofname)[-1] in LINKABLE_EXTENSIONS:
                                ldargs += [r'\"' + os.path.join(self.environment.get_build_dir(), ofname) + r'\"']
                    elif isinstance(o, build.CustomTargetIndex):
                        for ofname in o.get_outputs():
                            if os.path.splitext(ofname)[-1] in LINKABLE_EXTENSIONS:
                                ldargs += [r'\"' + os.path.join(self.environment.get_build_dir(), ofname) + r'\"']
                    else:
                        raise RuntimeError(o)
            if isinstance(target, build.SharedModule):
                assert not isinstance(linker, StaticLinker), 'for mypy'
                ldargs += linker.get_std_shared_module_link_args(target)
            elif isinstance(target, build.SharedLibrary):
                assert not isinstance(linker, StaticLinker), 'for mypy'
                ldargs += linker.get_std_shared_lib_link_args()
            ldstr = ' '.join(ldargs)
            valid = self.buildconfmap[target_name][buildtype]
            langargs: T.Dict[str, T.List[str]] = {}
            for lang in self.environment.coredata.compilers[target.for_machine]:
                if lang not in LANGNAMEMAP:
                    continue
                compiler = target.compilers.get(lang)
                if compiler is None:
                    continue
                # Start with warning args
                _warn_level = self.get_target_option(target, 'warning_level')
                assert isinstance(_warn_level, str), 'for mypy'
                warn_args = compiler.get_warn_args(_warn_level)
                std_args = compiler.get_option_compile_args(target, target.subproject)
                std_args += compiler.get_option_std_args(target, target.subproject)
                # Add compile args added using add_project_arguments()
                pargs = self.build.get_project_args(compiler, target)
                # Add compile args added using add_global_arguments()
                # These override per-project arguments
                gargs = self.build.global_args[target.for_machine].get(lang, [])
                targs = target.get_extra_args(lang)
                args = warn_args + std_args + pargs + gargs + targs
                if lang == 'swift':
                    # For some reason putting Swift module dirs in HEADER_SEARCH_PATHS does not work,
                    # but adding -I/path to manual args does work.
                    swift_dep_dirs = self.determine_swift_dep_dirs(target)
                    for d in swift_dep_dirs:
                        args += compiler.get_include_args(d, False)
                if args:
                    cti_args = []
                    if compiler and target.implicit_include_directories:
                        # It is unclear what is the cwd when xcode runs. -I. does not seem to
                        # add the root build dir to the search path. So add an absolute path instead.
                        # This may break reproducible builds, in which case patches are welcome.
                        cti_args = self.get_custom_target_dir_include_args(target, compiler, absolute_path=True)
                    # Xcode cannot handle separate compilation flags for C and ObjectiveC. They are both
                    # put in OTHER_CFLAGS. Same with C++ and ObjectiveC++.
                    if lang == 'objc':
                        lang = 'c'
                    elif lang == 'objcpp':
                        lang = 'cpp'
                    langs.add(lang)
                    langname = LANGNAMEMAP[lang]
                    langargs.setdefault(langname, [])
                    langargs[langname] = cargs + cti_args + args
            symroot = os.path.join(self.environment.get_build_dir(), target.subdir).rstrip('/')
            bt_dict = PbxDict()
            objects_dict.add_item(valid, bt_dict, buildtype)
            bt_dict.add_item('isa', 'XCBuildConfiguration')
            settings_dict = PbxDict()
            bt_dict.add_item('buildSettings', settings_dict)
            settings_dict.add_item('COMBINE_HIDPI_IMAGES', 'YES')
            if isinstance(target, build.SharedModule):
                settings_dict.add_item('DYLIB_CURRENT_VERSION', '')
                settings_dict.add_item('DYLIB_COMPATIBILITY_VERSION', '')
            else:
                if dylib_version is not None:
                    settings_dict.add_item('DYLIB_CURRENT_VERSION', str(dylib_version))
            if target.prefix:
                settings_dict.add_item('EXECUTABLE_PREFIX', target.prefix)
            if target.suffix:
                suffix = '.' + target.suffix
                settings_dict.add_item('EXECUTABLE_SUFFIX', suffix)
            debug = self.get_target_option(target, 'debug')
            assert isinstance(debug, bool), 'for mypy'
            settings_dict.add_item('GCC_GENERATE_DEBUGGING_SYMBOLS', BOOL2XCODEBOOL[debug])
            settings_dict.add_item('GCC_INLINES_ARE_PRIVATE_EXTERN', 'NO')
            opt = self.get_target_option(target, 'optimization')
            assert isinstance(opt, str), 'for mypy'
            opt_flag = OPT2XCODEOPT[opt]
            if opt_flag is not None:
                settings_dict.add_item('GCC_OPTIMIZATION_LEVEL', opt_flag)
            if target.has_pch:
                # Xcode uses GCC_PREFIX_HEADER which only allows one file per target/executable. Precompiling various header files and
                # applying a particular pch to each source file will require custom scripts (as a build phase) and build flags per each
                # file. Since Xcode itself already discourages precompiled headers in favor of modules we don't try much harder here.
                pchs = [t[0] for t in [target.pch['c'], target.pch['cpp']] if t is not None]
                if pchs:
                    if len(pchs) > 1:
                        mlog.warning(f'Unsupported Xcode configuration: More than 1 precompiled header found "{pchs!s}". Target "{target.name}" might not compile correctly.')
                    relative_pch_path = os.path.join(target.get_subdir(), pchs[0]) # Path relative to target so it can be used with "$(PROJECT_DIR)"
                    settings_dict.add_item('GCC_PRECOMPILE_PREFIX_HEADER', 'YES')
                    settings_dict.add_item('GCC_PREFIX_HEADER', f'$(PROJECT_DIR)/{relative_pch_path}')
            settings_dict.add_item('GCC_PREPROCESSOR_DEFINITIONS', '')
            settings_dict.add_item('GCC_SYMBOLS_PRIVATE_EXTERN', 'NO')
            unquoted_headers = [self.get_target_private_dir_abs(target)]
            if target.implicit_include_directories:
                unquoted_headers.append(os.path.join(self.environment.get_build_dir(), target.get_builddir()))
                unquoted_headers.append(os.path.join(self.environment.get_source_dir(), target.get_subdir()))
            unquoted_headers += headerdirs
            settings_dict.add_item('HEADER_SEARCH_PATHS', self.normalize_header_search_paths(unquoted_headers))
            settings_dict.add_item('INSTALL_PATH', install_path)
            settings_dict.add_item('LIBRARY_SEARCH_PATHS', '')
            if isinstance(target, build.SharedModule):
                settings_dict.add_item('LIBRARY_STYLE', 'BUNDLE')
                settings_dict.add_item('MACH_O_TYPE', 'mh_bundle')
            elif isinstance(target, build.SharedLibrary):
                settings_dict.add_item('LIBRARY_STYLE', 'DYNAMIC')
            self.add_otherargs(settings_dict, langargs)
            settings_dict.add_item('OTHER_LDFLAGS', ldstr)
            settings_dict.add_item('OTHER_REZFLAGS', '')
            settings_dict.add_item('PRODUCT_NAME', product_name)
            settings_dict.add_item('SECTORDER_FLAGS', '')
            if is_swift and bridging_header:
                settings_dict.add_item('SWIFT_OBJC_BRIDGING_HEADER', bridging_header)
                if self.objversion >= 60 and target.uses_swift_cpp_interop():
                    settings_dict.add_item('SWIFT_OBJC_INTEROP_MODE', 'objcxx')
            settings_dict.add_item('BUILD_DIR', symroot)
            settings_dict.add_item('OBJROOT', f'{symroot}/build')
            sysheader_arr = PbxArray()
            # XCode will change every -I flag that points inside these directories
            # to an -isystem. Thus set nothing in it since we control our own
            # include flags.
            settings_dict.add_item('SYSTEM_HEADER_SEARCH_PATHS', sysheader_arr)
            settings_dict.add_item('USE_HEADERMAP', 'NO')
            warn_array = PbxArray()
            settings_dict.add_item('WARNING_CFLAGS', warn_array)
            warn_array.add_item('"$(inherited)"')
            bt_dict.add_item('name', buildtype)

    def normalize_header_search_paths(self, header_dirs: T.List[str]) -> PbxArray:
        header_arr = PbxArray()
        for i in header_dirs:
            np = os.path.normpath(i)
            # Make sure Xcode will not split single path into separate entries, escaping space with a slash is not enough
            item = f'"\\\"{np}\\\""' if ' ' in np else f'"{np}"'
            header_arr.add_item(item)
        return header_arr

    def add_otherargs(self, settings_dict: PbxDict, langargs: T.Dict[str, T.List[str]]) -> None:
        for langname, args in langargs.items():
            if args:
                quoted_args = []
                for a in args:
                    # This works but
                    # a) it's ugly as sin
                    # b) I don't know why it works or why every backslash must be escaped into eight backslashes
                    a = a.replace(chr(92), 8*chr(92)) # chr(92) is backslash, this how we smuggle it in without Python's quoting grabbing it.
                    a = a.replace(r'"', r'\\\"')
                    if ' ' in a or "'" in a:
                        a = r'\"' + a + r'\"'
                    quoted_args.append(a)
                settings_dict.add_item(f'OTHER_{langname}FLAGS', ' '.join(quoted_args))

    def generate_xc_configurationList(self, objects_dict: PbxDict) -> None:
        # FIXME: sort items
        conf_dict = PbxDict()
        objects_dict.add_item(self.project_conflist, conf_dict, f'Build configuration list for PBXProject "{self.build.project_name}"')
        conf_dict.add_item('isa', 'XCConfigurationList')
        confs_arr = PbxArray()
        conf_dict.add_item('buildConfigurations', confs_arr)
        for buildtype in self.buildtypes:
            confs_arr.add_item(self.project_configurations[buildtype], buildtype)
        conf_dict.add_item('defaultConfigurationIsVisible', 0)
        conf_dict.add_item('defaultConfigurationName', self.buildtype)

        # Now the all target
        all_dict = PbxDict()
        objects_dict.add_item(self.all_buildconf_id, all_dict, 'Build configuration list for PBXAggregateTarget "ALL_BUILD"')
        all_dict.add_item('isa', 'XCConfigurationList')
        conf_arr = PbxArray()
        all_dict.add_item('buildConfigurations', conf_arr)
        for buildtype in self.buildtypes:
            conf_arr.add_item(self.buildall_configurations[buildtype], buildtype)
        all_dict.add_item('defaultConfigurationIsVisible', 0)
        all_dict.add_item('defaultConfigurationName', self.buildtype)

        # Test target
        test_dict = PbxDict()
        objects_dict.add_item(self.test_buildconf_id, test_dict, 'Build configuration list for PBXAggregateTarget "RUN_TEST"')
        test_dict.add_item('isa', 'XCConfigurationList')
        conf_arr = PbxArray()
        test_dict.add_item('buildConfigurations', conf_arr)
        for buildtype in self.buildtypes:
            conf_arr.add_item(self.test_configurations[buildtype], buildtype)
        test_dict.add_item('defaultConfigurationIsVisible', 0)
        test_dict.add_item('defaultConfigurationName', self.buildtype)

        # Regen target
        regen_dict = PbxDict()
        objects_dict.add_item(self.regen_buildconf_id, test_dict, 'Build configuration list for PBXAggregateTarget "REGENERATE"')
        regen_dict.add_item('isa', 'XCConfigurationList')
        conf_arr = PbxArray()
        regen_dict.add_item('buildConfigurations', conf_arr)
        for buildtype in self.buildtypes:
            conf_arr.add_item(self.test_configurations[buildtype], buildtype)
        regen_dict.add_item('defaultConfigurationIsVisible', 0)
        regen_dict.add_item('defaultConfigurationName', self.buildtype)

        for target_name in self.build_targets:
            t_dict = PbxDict()
            listid = self.buildconflistmap[target_name]
            objects_dict.add_item(listid, t_dict, f'Build configuration list for PBXNativeTarget "{target_name}"')
            t_dict.add_item('isa', 'XCConfigurationList')
            conf_arr = PbxArray()
            t_dict.add_item('buildConfigurations', conf_arr)
            idval = self.buildconfmap[target_name][self.buildtype]
            conf_arr.add_item(idval, self.buildtype)
            t_dict.add_item('defaultConfigurationIsVisible', 0)
            t_dict.add_item('defaultConfigurationName', self.buildtype)

        for target_name in self.custom_targets:
            t_dict = PbxDict()
            listid = self.buildconflistmap[target_name]
            objects_dict.add_item(listid, t_dict, f'Build configuration list for PBXAggregateTarget "{target_name}"')
            t_dict.add_item('isa', 'XCConfigurationList')
            conf_arr = PbxArray()
            t_dict.add_item('buildConfigurations', conf_arr)
            idval = self.buildconfmap[target_name][self.buildtype]
            conf_arr.add_item(idval, self.buildtype)
            t_dict.add_item('defaultConfigurationIsVisible', 0)
            t_dict.add_item('defaultConfigurationName', self.buildtype)

    def generate_prefix(self, pbxdict: PbxDict) -> PbxDict:
        pbxdict.add_item('archiveVersion', '1')
        pbxdict.add_item('classes', PbxDict())
        pbxdict.add_item('objectVersion', self.objversion)
        objects_dict = PbxDict()
        pbxdict.add_item('objects', objects_dict)

        return objects_dict

    def generate_suffix(self, pbxdict: PbxDict) -> None:
        pbxdict.add_item('rootObject', self.project_uid, 'Project object')
