# Copyright 2023 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import argparse
import collections
import contextlib
import hashlib
import io
import json
import multiprocessing
import os
import re
import shutil
import subprocess
import sys
import tempfile


class ArgumentForwarder(object):
  """Class used to abstract forwarding arguments from to the swiftc compiler.

  Arguments:
    - arg_name: string corresponding to the argument to pass to the compiler
    - arg_join: function taking the compiler name and returning whether the
                argument value is attached to the argument or separated
    - to_swift: function taking the argument value and returning whether it
                must be passed to the swift compiler
    - to_clang: function taking the argument value and returning whether it
                must be passed to the clang compiler
  """

  def __init__(self, arg_name, arg_join, to_swift, to_clang):
    self._arg_name = arg_name
    self._arg_join = arg_join
    self._to_swift = to_swift
    self._to_clang = to_clang

  def forward(self, swiftc_args, values, target_triple):
    if not values:
      return

    is_catalyst = target_triple.endswith('macabi')
    for value in values:
      if self._to_swift(value):
        if self._arg_join('swift'):
          swiftc_args.append(f'{self._arg_name}{value}')
        else:
          swiftc_args.append(self._arg_name)
          swiftc_args.append(value)

      if self._to_clang(value) and not is_catalyst:
        if self._arg_join('clang'):
          swiftc_args.append('-Xcc')
          swiftc_args.append(f'{self._arg_name}{value}')
        else:
          swiftc_args.append('-Xcc')
          swiftc_args.append(self._arg_name)
          swiftc_args.append('-Xcc')
          swiftc_args.append(value)


class IncludeArgumentForwarder(ArgumentForwarder):
  """Argument forwarder for -I and -isystem."""

  def __init__(self, arg_name):
    ArgumentForwarder.__init__(self,
                               arg_name,
                               arg_join=lambda _: len(arg_name) == 1,
                               to_swift=lambda _: arg_name != '-isystem',
                               to_clang=lambda _: True)


class FrameworkArgumentForwarder(ArgumentForwarder):
  """Argument forwarder for -F and -Fsystem."""

  def __init__(self, arg_name):
    ArgumentForwarder.__init__(self,
                               arg_name,
                               arg_join=lambda _: len(arg_name) == 1,
                               to_swift=lambda _: True,
                               to_clang=lambda _: True)


class DefineArgumentForwarder(ArgumentForwarder):
  """Argument forwarder for -D."""

  def __init__(self, arg_name):
    ArgumentForwarder.__init__(self,
                               arg_name,
                               arg_join=lambda _: _ == 'clang',
                               to_swift=lambda _: '=' not in _,
                               to_clang=lambda _: True)


# Dictionary mapping argument names to their ArgumentForwarder.
ARGUMENT_FORWARDER_FOR_ATTR = (
    ('include_dirs', IncludeArgumentForwarder('-I')),
    ('system_include_dirs', IncludeArgumentForwarder('-isystem')),
    ('framework_dirs', FrameworkArgumentForwarder('-F')),
    ('system_framework_dirs', FrameworkArgumentForwarder('-Fsystem')),
    ('defines', DefineArgumentForwarder('-D')),
)

# Regexp used to parse #import lines.
IMPORT_LINE_REGEXP = re.compile('#import "([^"]*)"')


class FileWriter(contextlib.AbstractContextManager):
  """
  FileWriter is a file-like object that only write data to disk if changed.

  This object implements the context manager protocols and thus can be used
  in a with-clause. The data is written to disk when the context is exited,
  and only if the content is different from current file content.

    with FileWriter(path) as stream:
      stream.write('...')

  If the with-clause ends with an exception, no data is written to the disk
  and any existing file is left untouched.
  """

  def __init__(self, filepath, encoding='utf8'):
    self._stringio = io.StringIO()
    self._filepath = filepath
    self._encoding = encoding

  def __exit__(self, exc_type, exc_value, traceback):
    if exc_type or exc_value or traceback:
      return

    new_content = self._stringio.getvalue()
    if os.path.exists(self._filepath):
      with open(self._filepath, encoding=self._encoding) as stream:
        old_content = stream.read()

      if old_content == new_content:
        return

    with open(self._filepath, 'w', encoding=self._encoding) as stream:
      stream.write(new_content)

  def write(self, data):
    self._stringio.write(data)


@contextlib.contextmanager
def existing_directory(path):
  """Returns a context manager wrapping an existing directory."""
  yield path


def create_stamp_file(path):
  """Writes an empty stamp file at path."""
  with FileWriter(path) as stream:
    stream.write('')


def create_build_cache_dir(args, build_signature):
  """Creates the build cache directory according to `args`.

  This function returns an object that implements the context manager
  protocol and thus can be used in a with-clause. If -derived-data-dir
  argument is not used, the returned directory is a temporary directory
  that will be deleted when the with-clause is exited.
  """
  if not args.derived_data_dir:
    return tempfile.TemporaryDirectory()

  # The derived data cache can be quite large, so delete any obsolete
  # files or directories.
  stamp_name = f'{args.module_name}.stamp'
  if os.path.isdir(args.derived_data_dir):
    for name in os.listdir(args.derived_data_dir):
      if name not in (build_signature, stamp_name):
        path = os.path.join(args.derived_data_dir, name)
        if os.path.isdir(path):
          shutil.rmtree(path)
        else:
          os.unlink(path)

  ensure_directory(args.derived_data_dir)
  create_stamp_file(os.path.join(args.derived_data_dir, stamp_name))

  return existing_directory(
      ensure_directory(os.path.join(args.derived_data_dir, build_signature)))


def ensure_directory(path):
  """Creates directory at `path` if it does not exists."""
  if not os.path.isdir(path):
    os.makedirs(path)
  return os.path.abspath(path)


def build_signature(env, args):
  """Generates the build signature from `env` and `args`.

  This allow re-using the derived data dir between builds while still
  forcing the data to be recreated from scratch in case of significant
  changes to the build settings (different arguments or tool versions).
  """
  m = hashlib.sha1()
  for key in sorted(env):
    if key.endswith('_VERSION') or key == 'DEVELOPER_DIR':
      m.update(f'{key}={env[key]}'.encode('utf8'))
  for i, arg in enumerate(args):
    m.update(f'{i}={arg}'.encode('utf8'))
  return m.hexdigest()


def generate_source_output_file_map_fragment(args, filename):
  """Generates source OutputFileMap.json fragment according to `args`.

  Create the fragment for a single .swift source file for OutputFileMap.
  The output depends on whether -whole-module-optimization argument is
  used or not.
  """
  assert os.path.splitext(filename)[1] == '.swift', filename
  basename = os.path.splitext(os.path.basename(filename))[0]
  rel_name = os.path.join(args.target_out_dir, basename)
  out_name = rel_name

  fragment = {
      'index-unit-output-path': f'/{rel_name}.o',
      'object': f'{out_name}.o',
  }

  if not args.whole_module_optimization:
    fragment.update({
        'const-values': f'{out_name}.swiftconstvalues',
        'dependencies': f'{out_name}.d',
        'diagnostics': f'{out_name}.dia',
        'swift-dependencies': f'{out_name}.swiftdeps',
    })

  return fragment


def generate_module_output_file_map_fragment(args):
  """Generates module OutputFileMap.json fragment according to `args`.

  Create the fragment for the module itself for OutputFileMap. The output
  depends on whether -whole-module-optimization argument is used or not.
  """
  out_name = os.path.join(args.target_out_dir, args.module_name)

  if args.whole_module_optimization:
    fragment = {
        'const-values': f'{out_name}.swiftconstvalues',
        'dependencies': f'{out_name}.d',
        'diagnostics': f'{out_name}.dia',
        'swift-dependencies': f'{out_name}.swiftdeps',
    }
  else:
    fragment = {
        'emit-module-dependencies': f'{out_name}.d',
        'emit-module-diagnostics': f'{out_name}.dia',
        'swift-dependencies': f'{out_name}.swiftdeps',
    }

  return fragment


def generate_output_file_map(args):
  """Generates OutputFileMap.json according to `args`.

  Returns the mapping as a python dictionary that can be serialized to
  disk as JSON.
  """
  output_file_map = {'': generate_module_output_file_map_fragment(args)}
  for filename in args.sources:
    fragment = generate_source_output_file_map_fragment(args, filename)
    output_file_map[filename] = fragment
  return output_file_map


def fix_generated_header(header_path, output_path, src_dir, gen_dir):
  """Fix the Objective-C header generated by the Swift compiler.

  The Swift compiler assumes that the generated Objective-C header will be
  imported from code compiled with module support enabled (-fmodules). The
  generated code thus uses @import and provides no fallback if modules are
  not enabled.

  The Swift compiler also uses absolute path when including the bridging
  header or another module's generated header. This causes issues with the
  distributed compiler (i.e. reclient or siso) who expects all paths to be
  relative to the build directory

  This method fix the generated header to use relative path for #import
  and to use #import instead of @import when using system frameworks.

  The header is read at `header_path` and written to `output_path`.
  """

  header_contents = []
  with open(header_path, 'r', encoding='utf8') as header_file:

    imports_section = None
    for line in header_file:
      # Handle #import lines.
      match = IMPORT_LINE_REGEXP.match(line)
      if match:
        import_path = match.group(1)
        for root in (gen_dir, src_dir):
          if import_path.startswith(root):
            import_path = os.path.relpath(import_path, root)
        if import_path != match.group(1):
          span = match.span(1)
          line = line[:span[0]] + import_path + line[span[1]:]

      # Handle @import lines.
      if line.startswith('#if __has_feature(objc_modules)'):
        assert imports_section is None
        imports_section = (len(header_contents) + 1, 1)
      elif imports_section:
        section_start, nesting_level = imports_section
        if line.startswith('#if'):
          imports_section = (section_start, nesting_level + 1)
        elif line.startswith('#endif'):
          if nesting_level > 1:
            imports_section = (section_start, nesting_level - 1)
          else:
            imports_section = None
            section_end = len(header_contents)
            header_contents.append('#else\n')
            for index in range(section_start, section_end):
              l = header_contents[index]
              if l.startswith('@import'):
                name = l.split()[1].split(';')[0]
                if name != 'ObjectiveC':
                  header_contents.append(f'#import <{name}/{name}.h>\n')
              else:
                header_contents.append(l)

      header_contents.append(line)

  with FileWriter(output_path) as header_file:
    for line in header_contents:
      header_file.write(line)


def invoke_swift_compiler(args, extras_args, build_cache_dir, output_file_map):
  """Invokes Swift compiler to compile module according to `args`.

  The `build_cache_dir` and `output_file_map` should be path to existing
  directory to use for writing intermediate build artifact (optionally
  a temporary directory) and path to $module-OutputFileMap.json file that
  lists the outputs to generate for the module and each source file.

  If -fix-module-imports argument is passed, the generated header for the
  module is written to a temporary location and then modified to replace
  @import by corresponding #import.
  """

  # Write the $module.SwiftFileList file.
  swift_file_list_path = os.path.join(args.target_out_dir,
                                      f'{args.module_name}.SwiftFileList')

  with FileWriter(swift_file_list_path) as stream:
    for filename in sorted(args.sources):
      stream.write(f'"{filename}"\n')

  header_path = args.header_path
  if args.fix_generated_header:
    header_path = os.path.join(build_cache_dir, os.path.basename(header_path))

  swiftc_args = [
      '-parse-as-library',
      '-module-name',
      args.module_name,
      f'@{swift_file_list_path}',
      '-sdk',
      args.sdk_path,
      '-target',
      args.target_triple,
      '-swift-version',
      args.swift_version,
      '-c',
      '-output-file-map',
      output_file_map,
      '-save-temps',
      '-no-color-diagnostics',
      '-serialize-diagnostics',
      '-emit-dependencies',
      '-emit-module',
      '-emit-module-path',
      os.path.join(args.target_out_dir, f'{args.module_name}.swiftmodule'),
      '-emit-objc-header',
      '-emit-objc-header-path',
      header_path,
      '-working-directory',
      os.getcwd(),
      '-index-store-path',
      ensure_directory(os.path.join(build_cache_dir, 'Index.noindex')),
      '-module-cache-path',
      ensure_directory(os.path.join(build_cache_dir, 'ModuleCache.noindex')),
      '-pch-output-dir',
      ensure_directory(os.path.join(build_cache_dir, 'PrecompiledHeaders')),
  ]

  # Handle optional -bridge-header flag.
  if args.bridge_header:
    swiftc_args.extend(('-import-objc-header', args.bridge_header))

  # Handle swift const values extraction.
  swiftc_args.extend(['-emit-const-values'])
  swiftc_args.extend([
      '-Xfrontend',
      '-const-gather-protocols-file',
      '-Xfrontend',
      args.const_gather_protocols_file,
  ])

  # Handle -I, -F, -isystem, -Fsystem and -D arguments.
  for (attr_name, forwarder) in ARGUMENT_FORWARDER_FOR_ATTR:
    forwarder.forward(swiftc_args, getattr(args, attr_name), args.target_triple)

  # Handle -whole-module-optimization flag.
  num_threads = max(1, multiprocessing.cpu_count() // 2)
  if args.whole_module_optimization:
    swiftc_args.extend([
        '-whole-module-optimization',
        '-no-emit-module-separately-wmo',
        '-num-threads',
        f'{num_threads}',
    ])
  else:
    swiftc_args.extend([
        '-enable-batch-mode',
        '-incremental',
        '-experimental-emit-module-separately',
        '-disable-cmo',
        f'-j{num_threads}',
    ])

  # Handle -file-prefix-map flag unless --swift-keep-intermediate-files is set.
  if args.file_prefix_map and not args.swift_keep_intermediate_files:
    swiftc_args.extend([
        '-file-prefix-map',
        args.file_prefix_map,
    ])

  swift_toolchain_path = args.swift_toolchain_path
  if not swift_toolchain_path:
    swift_toolchain_path = os.path.join(os.path.dirname(args.sdk_path),
                                        'XcodeDefault.xctoolchain')
    if not os.path.isdir(swift_toolchain_path):
      swift_toolchain_path = ''

  command = [f'{swift_toolchain_path}/usr/bin/swiftc'] + swiftc_args
  if extras_args:
    command.extend(extras_args)

  process = subprocess.Popen(command)
  process.communicate()

  if process.returncode:
    sys.exit(process.returncode)

  if args.fix_generated_header:
    fix_generated_header(header_path,
                         args.header_path,
                         src_dir=os.path.abspath(args.src_dir) + os.path.sep,
                         gen_dir=os.path.abspath(args.gen_dir) + os.path.sep)


def generate_depfile(args, output_file_map):
  """Generates compilation depfile according to `args`.

  Parses all intermediate depfile generated by the Swift compiler and
  replaces absolute path by relative paths (since ninja compares paths
  as strings and does not resolve relative paths to absolute).

  Converts path to the SDK and toolchain files to the sdk/xcode_link
  symlinks if possible and available.
  """
  xcode_paths = {}
  if os.path.islink(args.sdk_path):
    xcode_links = os.path.dirname(args.sdk_path)
    for link_name in os.listdir(xcode_links):
      link_path = os.path.join(xcode_links, link_name)
      if os.path.islink(link_path):
        xcode_paths[os.path.realpath(link_path) + os.sep] = link_path + os.sep

  out_dir = os.getcwd() + os.path.sep
  src_dir = os.path.abspath(args.src_dir) + os.path.sep

  depfile_content = collections.defaultdict(set)
  for value in output_file_map.values():
    partial_depfile_path = value.get('dependencies', None)
    if partial_depfile_path:
      with open(partial_depfile_path, encoding='utf8') as stream:
        for line in stream:
          output, inputs = line.split(' : ', 2)
          output = os.path.relpath(output, out_dir)

          # The depfile format uses '\' to quote space in filename. Split the
          # list of file while respecting this convention.
          for path in re.split(r'(?<!\\) ', inputs):
            for xcode_path in xcode_paths:
              if path.startswith(xcode_path):
                path = xcode_paths[xcode_path] + path[len(xcode_path):]
            if path.startswith(src_dir) or path.startswith(out_dir):
              path = os.path.relpath(path, out_dir)
            depfile_content[output].add(path)

  with FileWriter(args.depfile_path) as stream:
    for output, inputs in sorted(depfile_content.items()):
      stream.write(f'{output}: {" ".join(sorted(inputs))}\n')


def compile_module(args, extras_args, build_signature):
  """Compiles Swift module according to `args`."""
  for path in (args.target_out_dir, os.path.dirname(args.header_path)):
    ensure_directory(path)

  # Write the $module-OutputFileMap.json file.
  output_file_map = generate_output_file_map(args)
  output_file_map_path = os.path.join(args.target_out_dir,
                                      f'{args.module_name}-OutputFileMap.json')

  with FileWriter(output_file_map_path) as stream:
    json.dump(output_file_map, stream, indent=' ', sort_keys=True)

  # Invoke Swift compiler.
  with create_build_cache_dir(args, build_signature) as build_cache_dir:
    invoke_swift_compiler(args,
                          extras_args,
                          build_cache_dir=build_cache_dir,
                          output_file_map=output_file_map_path)

  # Generate the depfile.
  generate_depfile(args, output_file_map)


def main(args):
  parser = argparse.ArgumentParser(allow_abbrev=False, add_help=False)

  # Required arguments.
  parser.add_argument('--module-name',
                      required=True,
                      help='name of the Swift module')

  parser.add_argument('--src-dir',
                      required=True,
                      help='path to the source directory')

  parser.add_argument('--gen-dir',
                      required=True,
                      help='path to the gen directory root')

  parser.add_argument('--target-out-dir',
                      required=True,
                      help='path to the object directory')

  parser.add_argument('--header-path',
                      required=True,
                      help='path to the generated header file')

  parser.add_argument('--bridge-header',
                      required=True,
                      help='path to the Objective-C bridge header file')

  parser.add_argument('--depfile-path',
                      required=True,
                      help='path to the output dependency file')

  parser.add_argument('--const-gather-protocols-file',
                      required=True,
                      help='path to file containing const values protocols')

  # Optional arguments.
  parser.add_argument('--derived-data-dir',
                      help='path to the derived data directory')

  parser.add_argument('--fix-generated-header',
                      default=False,
                      action='store_true',
                      help='fix imports in generated header')

  parser.add_argument('--swift-toolchain-path',
                      default='',
                      help='path to the Swift toolchain to use')

  parser.add_argument('--whole-module-optimization',
                      default=False,
                      action='store_true',
                      help='enable whole module optimisation')

  parser.add_argument('--swift-keep-intermediate-files',
                      default=False,
                      action='store_true',
                      help='keep intermediate files')

  # Required arguments (forwarded to the Swift compiler).
  parser.add_argument('-target',
                      required=True,
                      dest='target_triple',
                      help='generate code for the given target')

  parser.add_argument('-sdk',
                      required=True,
                      dest='sdk_path',
                      help='path to the iOS SDK')

  # Optional arguments (forwarded to the Swift compiler).
  parser.add_argument('-I',
                      action='append',
                      dest='include_dirs',
                      help='add directory to header search path')

  parser.add_argument('-isystem',
                      action='append',
                      dest='system_include_dirs',
                      help='add directory to system header search path')

  parser.add_argument('-F',
                      action='append',
                      dest='framework_dirs',
                      help='add directory to framework search path')

  parser.add_argument('-Fsystem',
                      action='append',
                      dest='system_framework_dirs',
                      help='add directory to system framework search path')

  parser.add_argument('-D',
                      action='append',
                      dest='defines',
                      help='add preprocessor define')

  parser.add_argument('-swift-version',
                      default='5',
                      help='version of the Swift language')

  parser.add_argument(
      '-file-prefix-map',
      help='remap source paths in debug, coverage, and index info')

  # Positional arguments.
  parser.add_argument('sources',
                      nargs='+',
                      help='Swift source files to compile')

  parsed, extras = parser.parse_known_args(args)
  compile_module(parsed, extras, build_signature(os.environ, args))


if __name__ == '__main__':
  sys.exit(main(sys.argv[1:]))
