#!/usr/bin/env python3

# Copyright 2020 The Crashpad Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import argparse
import configparser
import convert_gn_xcodeproj
import errno
import io
import os
import platform
import re
import shutil
import subprocess
import sys
import tempfile


SUPPORTED_TARGETS = ('iphoneos', 'iphonesimulator', 'maccatalyst')
SUPPORTED_CONFIGS = ('Debug', 'Release', 'Profile', 'Official')

# Pattern matching lines from ~/.lldbinit that must not be copied to the
# generated .lldbinit file. They match what the user were told to add to
# their global ~/.lldbinit file before setup-gn.py was updated to generate
# a project specific file and thus must not be copied as they would cause
# the settings to be overwritten.
LLDBINIT_SKIP_PATTERNS = (
    re.compile('^script sys.path\\[:0\\] = \\[\'.*/src/tools/lldb\'\\]$'),
    re.compile('^script import lldbinit$'),
    re.compile('^settings append target.source-map .* /google/src/.*$'),
)


def HostCpuArch():
  '''Returns the arch of the host cpu for GN.'''
  HOST_CPU_ARCH = {
    'arm64': '"arm64"',
    'x86_64': '"x64"',
  }
  return HOST_CPU_ARCH[platform.machine()]


class ConfigParserWithStringInterpolation(configparser.ConfigParser):

  '''A .ini file parser that supports strings and environment variables.'''

  ENV_VAR_PATTERN = re.compile(r'\$([A-Za-z0-9_]+)')

  def values(self, section):
    return filter(
        lambda val: val != '',
        map(lambda kv: self._UnquoteString(self._ExpandEnvVar(kv[1])),
            configparser.ConfigParser.items(self, section)))

  def getstring(self, section, option, fallback=''):
    try:
      raw_value = self.get(section, option)
    except configparser.NoOptionError:
      return fallback
    return self._UnquoteString(self._ExpandEnvVar(raw_value))

  def _UnquoteString(self, string):
    if not string or string[0] != '"' or string[-1] != '"':
      return string
    return string[1:-1]

  def _ExpandEnvVar(self, value):
    match = self.ENV_VAR_PATTERN.search(value)
    if not match:
      return value
    name, (begin, end) = match.group(1), match.span(0)
    prefix, suffix = value[:begin], self._ExpandEnvVar(value[end:])
    return prefix + os.environ.get(name, '') + suffix


class GnGenerator(object):

  '''Holds configuration for a build and method to generate gn default files.'''

  FAT_BUILD_DEFAULT_ARCH = '64-bit'

  TARGET_CPU_VALUES = {
    'iphoneos': '"arm64"',
    'iphonesimulator': HostCpuArch(),
    'maccatalyst': HostCpuArch(),
  }

  TARGET_ENVIRONMENT_VALUES = {
    'iphoneos': '"device"',
    'iphonesimulator': '"simulator"',
    'maccatalyst': '"catalyst"'
  }

  def __init__(self, settings, config, target):
    assert target in SUPPORTED_TARGETS
    assert config in SUPPORTED_CONFIGS
    self._settings = settings
    self._config = config
    self._target = target

  def _GetGnArgs(self):
    """Build the list of arguments to pass to gn.

    Returns:
      A list of tuple containing gn variable names and variable values (it
      is not a dictionary as the order needs to be preserved).
    """
    args = []

    is_debug = self._config == 'Debug'
    official = self._config == 'Official'
    is_optim = self._config in ('Profile', 'Official')

    args.append(('target_os', '"ios"'))
    args.append(('is_debug', is_debug))

    if os.environ.get('FORCE_MAC_TOOLCHAIN', '0') == '1':
      args.append(('use_system_xcode', False))

    args.append(('target_cpu', self.TARGET_CPU_VALUES[self._target]))
    args.append((
        'target_environment',
        self.TARGET_ENVIRONMENT_VALUES[self._target]))

    # Add user overrides after the other configurations so that they can
    # refer to them and override them.
    args.extend(self._settings.items('gn_args'))
    return args


  def Generate(self, gn_path, proj_name, root_path, build_dir):
    self.WriteArgsGn(build_dir, xcode_project_name=proj_name)
    subprocess.check_call(self.GetGnCommand(
        gn_path, root_path, build_dir, xcode_project_name=proj_name))

  def CreateGnRules(self, gn_path, root_path, build_dir):
    gn_command = self.GetGnCommand(gn_path, root_path, build_dir)
    self.WriteArgsGn(build_dir)
    self.WriteBuildNinja(gn_command, build_dir)
    self.WriteBuildNinjaDeps(build_dir)

  def WriteArgsGn(self, build_dir, xcode_project_name=None):
    with open(os.path.join(build_dir, 'args.gn'), 'w') as stream:
      stream.write('# This file was generated by setup-gn.py. Do not edit\n')
      stream.write('# but instead use ~/.setup-gn or $repo/.setup-gn files\n')
      stream.write('# to configure settings.\n')
      stream.write('\n')

      if self._target != 'maccatalyst':
        if self._settings.has_section('$imports$'):
          for import_rule in self._settings.values('$imports$'):
            stream.write('import("%s")\n' % import_rule)
          stream.write('\n')

      gn_args = self._GetGnArgs()

      for name, value in gn_args:
        if isinstance(value, bool):
          stream.write('%s = %s\n' % (name, str(value).lower()))
        elif isinstance(value, list):
          stream.write('%s = [%s' % (name, '\n' if len(value) > 1 else ''))
          if len(value) == 1:
            prefix = ' '
            suffix = ' '
          else:
            prefix = '  '
            suffix = ',\n'
          for item in value:
            if isinstance(item, bool):
              stream.write('%s%s%s' % (prefix, str(item).lower(), suffix))
            else:
              stream.write('%s%s%s' % (prefix, item, suffix))
          stream.write(']\n')
        else:
          # ConfigParser removes quote around empty string which confuse
          # `gn gen` so restore them.
          if not value:
            value = '""'
          stream.write('%s = %s\n' % (name, value))

  def WriteBuildNinja(self, gn_command, build_dir):
    with open(os.path.join(build_dir, 'build.ninja'), 'w') as stream:
      stream.write('ninja_required_version = 1.7.2\n')
      stream.write('\n')
      stream.write('rule gn\n')
      stream.write('  command = %s\n' % NinjaEscapeCommand(gn_command))
      stream.write('  description = Regenerating ninja files\n')
      stream.write('\n')
      stream.write('build build.ninja: gn\n')
      stream.write('  generator = 1\n')
      stream.write('  depfile = build.ninja.d\n')

  def WriteBuildNinjaDeps(self, build_dir):
    with open(os.path.join(build_dir, 'build.ninja.d'), 'w') as stream:
      stream.write('build.ninja: nonexistant_file.gn\n')

  def GetGnCommand(self, gn_path, src_path, out_path, xcode_project_name=None):
    gn_command = [ gn_path, '--root=%s' % os.path.realpath(src_path), '-q' ]
    if xcode_project_name is not None:
      gn_command.append('--ide=xcode')
      gn_command.append('--ninja-executable=autoninja')
      gn_command.append('--xcode-build-system=new')
      gn_command.append('--xcode-project=%s' % xcode_project_name)
      gn_command.append('--xcode-additional-files-patterns=*.md')
      gn_command.append('--xcode-configs=' + ';'.join(SUPPORTED_CONFIGS))
      gn_command.append('--xcode-config-build-dir='
                        '//out/${CONFIGURATION}${EFFECTIVE_PLATFORM_NAME}')
      if self._settings.has_section('filters'):
        target_filters = self._settings.values('filters')
        if target_filters:
          gn_command.append('--filters=%s' % ';'.join(target_filters))
    else:
      gn_command.append('--check')
    gn_command.append('gen')
    gn_command.append('//%s' %
        os.path.relpath(os.path.abspath(out_path), os.path.abspath(src_path)))
    return gn_command


def NinjaNeedEscape(arg):
  '''Returns True if |arg| needs to be escaped when written to .ninja file.'''
  return ':' in arg or '*' in arg or ';' in arg


def NinjaEscapeCommand(command):
  '''Escapes |command| in order to write it to .ninja file.'''
  result = []
  for arg in command:
    if NinjaNeedEscape(arg):
      arg = arg.replace(':', '$:')
      arg = arg.replace(';', '\\;')
      arg = arg.replace('*', '\\*')
    else:
      result.append(arg)
  return ' '.join(result)


def FindGn():
  '''Returns absolute path to gn binary looking at the PATH env variable.'''
  for path in os.environ['PATH'].split(os.path.pathsep):
    gn_path = os.path.join(path, 'gn')
    if os.path.isfile(gn_path) and os.access(gn_path, os.X_OK):
      return gn_path
  return None


def GenerateXcodeProject(gn_path, root_dir, proj_name, out_dir, settings):
  '''Generate Xcode project with Xcode and convert to multi-configurations.'''
  prefix = os.path.abspath(os.path.join(out_dir, '_temp'))
  temp_path = tempfile.mkdtemp(prefix=prefix)
  try:
    generator = GnGenerator(settings, 'Debug', 'iphonesimulator')
    generator.Generate(gn_path, proj_name, root_dir, temp_path)
    convert_gn_xcodeproj.ConvertGnXcodeProject(
        root_dir,
        '%s.xcodeproj' % proj_name,
        os.path.join(temp_path),
        os.path.join(out_dir, 'build'),
        SUPPORTED_CONFIGS)
  finally:
    if os.path.exists(temp_path):
      shutil.rmtree(temp_path)

def CreateLLDBInitFile(root_dir, out_dir, settings):
  '''
  Generate an .lldbinit file for the project that load the script that fixes
  the mapping of source files (see docs/ios/build_instructions.md#debugging).
  '''
  with open(os.path.join(out_dir, 'build', '.lldbinit'), 'w') as lldbinit:
    lldb_script_dir = os.path.join(os.path.abspath(root_dir), 'tools', 'lldb')
    lldbinit.write('script sys.path[:0] = [\'%s\']\n' % lldb_script_dir)
    lldbinit.write('script import lldbinit\n')

    workspace_name = settings.getstring(
        'gn_args',
        'ios_internal_citc_workspace_name')

    if workspace_name != '':
      username = os.environ['USER']
      for shortname in ('googlemac', 'third_party', 'blaze-out'):
        lldbinit.write('settings append target.source-map %s %s\n' % (
            shortname,
            '/google/src/cloud/%s/%s/google3/%s' % (
                username, workspace_name, shortname)))

    # Append the content of //ios/build/tools/lldbinit.defaults if it exists.
    tools_dir = os.path.join(root_dir, 'ios', 'build', 'tools')
    defaults_lldbinit_path = os.path.join(tools_dir, 'lldbinit.defaults')
    if os.path.isfile(defaults_lldbinit_path):
      with open(defaults_lldbinit_path) as defaults_lldbinit:
        for line in defaults_lldbinit:
          lldbinit.write(line)

    # Append the content of ~/.lldbinit if it exists. Line that look like they
    # are trying to configure source mapping are skipped as they probably date
    # back from when setup-gn.py was not generating an .lldbinit file.
    global_lldbinit_path = os.path.join(os.environ['HOME'], '.lldbinit')
    if os.path.isfile(global_lldbinit_path):
      with open(global_lldbinit_path) as global_lldbinit:
        for line in global_lldbinit:
          if any(pattern.match(line) for pattern in LLDBINIT_SKIP_PATTERNS):
            continue
          lldbinit.write(line)


def GenerateGnBuildRules(gn_path, root_dir, out_dir, settings):
  '''Generates all template configurations for gn.'''
  for config in SUPPORTED_CONFIGS:
    for target in SUPPORTED_TARGETS:
      build_dir = os.path.join(out_dir, '%s-%s' % (config, target))
      if not os.path.isdir(build_dir):
        os.makedirs(build_dir)

      generator = GnGenerator(settings, config, target)
      generator.CreateGnRules(gn_path, root_dir, build_dir)


def Main(args):
  default_root = os.path.normpath(os.path.join(
      os.path.dirname(__file__), os.pardir, os.pardir))

  parser = argparse.ArgumentParser(
      description='Generate build directories for use with gn.')
  parser.add_argument(
      'root', default=default_root, nargs='?',
      help='root directory where to generate multiple out configurations')
  parser.add_argument(
      '--import', action='append', dest='import_rules', default=[],
      help='path to file defining default gn variables')
  parser.add_argument(
      '--gn-path', default=None,
      help='path to gn binary (default: look up in $PATH)')
  parser.add_argument(
      '--build-dir', default='out',
      help='path where the build should be created (default: %(default)s)')
  parser.add_argument(
      '--config-path', default=os.path.expanduser('~/.setup-gn'),
      help='path to the user config file (default: %(default)s)')
  parser.add_argument(
      '--system-config-path', default=os.path.splitext(__file__)[0] + '.config',
      help='path to the default config file (default: %(default)s)')
  parser.add_argument(
      '--project-name', default='all', dest='proj_name',
      help='name of the generated Xcode project (default: %(default)s)')
  parser.add_argument(
      '--no-xcode-project', action='store_true', default=False,
      help='do not generate the build directory with XCode project')
  args = parser.parse_args(args)

  # Load configuration (first global and then any user overrides).
  settings = ConfigParserWithStringInterpolation()
  settings.read([
      args.system_config_path,
      args.config_path,
  ])

  # Add private sections corresponding to --import argument.
  if args.import_rules:
    settings.add_section('$imports$')
    for i, import_rule in enumerate(args.import_rules):
      if not import_rule.startswith('//'):
        import_rule = '//%s' % os.path.relpath(
            os.path.abspath(import_rule), os.path.abspath(args.root))
      settings.set('$imports$', '$rule%d$' % i, import_rule)

  # Validate settings.
  if settings.getstring('build', 'arch') not in ('64-bit', '32-bit', 'fat'):
    sys.stderr.write('ERROR: invalid value for build.arch: %s\n' %
        settings.getstring('build', 'arch'))
    sys.exit(1)

  # Find path to gn binary either from command-line or in PATH.
  if args.gn_path:
    gn_path = args.gn_path
  else:
    gn_path = FindGn()
    if gn_path is None:
      sys.stderr.write('ERROR: cannot find gn in PATH\n')
      sys.exit(1)

  out_dir = os.path.join(args.root, args.build_dir)
  if not os.path.isdir(out_dir):
    os.makedirs(out_dir)

  if not args.no_xcode_project:
    GenerateXcodeProject(gn_path, args.root, args.proj_name, out_dir, settings)
    CreateLLDBInitFile(args.root, out_dir, settings)
  GenerateGnBuildRules(gn_path, args.root, out_dir, settings)


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