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


from . import util


# XCode build is listed in parentheses after the version at
# https://developer.apple.com/news/releases/, or on Wikipedia here:
# https://en.wikipedia.org/wiki/Xcode#Version_comparison_table
# Use lowercase letters.
# When updating XCODE_BUILD_VERSION, you will also need to update
# XCODE_CLANG_VERSION.
XCODE_BUILD_VERSION = '10g8'
# Wikipedia lists the Clang version here:
# https://en.wikipedia.org/wiki/Xcode#Toolchain_versions
XCODE_CLANG_VERSION = '10.0.1'


def build_command_buffer(api, chrome_dir, skia_dir, out):
  api.run(api.python, 'build command_buffer',
      script=skia_dir.join('tools', 'build_command_buffer.py'),
      args=[
        '--chrome-dir', chrome_dir,
        '--output-dir', out,
        '--extra-gn-args', 'mac_sdk_min="10.13"',
        '--no-sync', '--no-hooks', '--make-output-dir'])


def compile_swiftshader(api, extra_tokens, swiftshader_root, cc, cxx, out):
  """Build SwiftShader with CMake.

  Building SwiftShader works differently from any other Skia third_party lib.
  See discussion in skia:7671 for more detail.

  Args:
    swiftshader_root: root of the SwiftShader checkout.
    cc, cxx: compiler binaries to use
    out: target directory for libEGL.so and libGLESv2.so
  """
  swiftshader_opts = ['-DBUILD_TESTS=OFF', '-DWARNINGS_AS_ERRORS=0']
  cmake_bin = str(api.vars.slave_dir.join('cmake_linux', 'bin'))
  env = {
      'CC': cc,
      'CXX': cxx,
      'PATH': '%%(PATH)s:%s' % cmake_bin
  }

  # Extra flags for MSAN, if necessary.
  if 'MSAN' in extra_tokens:
    clang_linux = str(api.vars.slave_dir.join('clang_linux'))
    libcxx_msan = clang_linux + '/msan'
    msan_cflags = ' '.join([
      '-fsanitize=memory',
      '-stdlib=libc++',
      '-L%s/lib' % libcxx_msan,
      '-lc++abi',
      '-I%s/include' % libcxx_msan,
      '-I%s/include/c++/v1' % libcxx_msan,
    ])
    swiftshader_opts.extend([
      '-DMSAN=ON',
      '-DCMAKE_C_FLAGS=%s' % msan_cflags,
      '-DCMAKE_CXX_FLAGS=%s' % msan_cflags,
    ])

  # Build SwiftShader.
  api.file.ensure_directory('makedirs swiftshader_out', out)
  with api.context(cwd=out, env=env):
    api.run(api.step, 'swiftshader cmake',
            cmd=['cmake'] + swiftshader_opts + [swiftshader_root, '-GNinja'])
    api.run(api.step, 'swiftshader ninja',
            cmd=['ninja', '-C', out, 'libEGL.so', 'libGLESv2.so'])


def compile_fn(api, checkout_root, out_dir):
  skia_dir      = checkout_root.join('skia')
  compiler      = api.vars.builder_cfg.get('compiler',      '')
  configuration = api.vars.builder_cfg.get('configuration', '')
  extra_tokens  = api.vars.extra_tokens
  os            = api.vars.builder_cfg.get('os',            '')
  target_arch   = api.vars.builder_cfg.get('target_arch',   '')

  clang_linux      = str(api.vars.slave_dir.join('clang_linux'))
  win_toolchain    = str(api.vars.slave_dir.join('win_toolchain'))
  moltenvk         = str(api.vars.slave_dir.join('moltenvk'))

  cc, cxx = None, None
  extra_cflags = []
  extra_ldflags = []
  args = {'werror': 'true'}
  env = {}

  if os == 'Mac':
    extra_cflags.append(
        '-DDUMMY_xcode_build_version=%s' % XCODE_BUILD_VERSION)
    mac_toolchain_cmd = api.vars.slave_dir.join(
        'mac_toolchain', 'mac_toolchain')
    xcode_app_path = api.vars.cache_dir.join('Xcode.app')
    # Copied from
    # https://chromium.googlesource.com/chromium/tools/build/+/e19b7d9390e2bb438b566515b141ed2b9ed2c7c2/scripts/slave/recipe_modules/ios/api.py#322
    with api.step.nest('ensure xcode') as step_result:
      step_result.presentation.step_text = (
          'Ensuring Xcode version %s in %s' % (
              XCODE_BUILD_VERSION, xcode_app_path))
      install_xcode_cmd = [
          mac_toolchain_cmd, 'install',
          # "ios" is needed for simulator builds
          # (Build-Mac-Clang-x64-Release-iOS).
          '-kind', 'ios',
          '-xcode-version', XCODE_BUILD_VERSION,
          '-output-dir', xcode_app_path,
      ]
      api.step('install xcode', install_xcode_cmd)
      api.step('select xcode', [
          'sudo', 'xcode-select', '-switch', xcode_app_path])
      if 'iOS' in extra_tokens:
        if target_arch == 'arm':
          # Can only compile for 32-bit up to iOS 10.
          env['IPHONEOS_DEPLOYMENT_TARGET'] = '10.0'
        else:
          # Our iOS devices are on an older version.
          # Can't compile for Metal before 11.0.
          env['IPHONEOS_DEPLOYMENT_TARGET'] = '11.0'
      else:
        # We have some bots on 10.13.
        env['MACOSX_DEPLOYMENT_TARGET'] = '10.13'

  if compiler == 'Clang' and api.vars.is_linux:
    cc  = clang_linux + '/bin/clang'
    cxx = clang_linux + '/bin/clang++'
    extra_cflags .append('-B%s/bin' % clang_linux)
    extra_ldflags.append('-B%s/bin' % clang_linux)
    extra_ldflags.append('-fuse-ld=lld')
    extra_cflags.append('-DDUMMY_clang_linux_version=%s' %
                        api.run.asset_version('clang_linux', skia_dir))
    if 'Static' in extra_tokens:
      extra_ldflags.extend(['-static-libstdc++', '-static-libgcc'])

  elif compiler == 'Clang':
    cc, cxx = 'clang', 'clang++'
  elif compiler == 'GCC':
    if target_arch in ['mips64el', 'loongson3a']:
      mips64el_toolchain_linux = str(api.vars.slave_dir.join(
          'mips64el_toolchain_linux'))
      cc  = mips64el_toolchain_linux + '/bin/mips64el-linux-gnuabi64-gcc-8'
      cxx = mips64el_toolchain_linux + '/bin/mips64el-linux-gnuabi64-g++-8'
      env['LD_LIBRARY_PATH'] = (
          mips64el_toolchain_linux + '/lib/x86_64-linux-gnu/')
      extra_ldflags.append('-L' + mips64el_toolchain_linux +
                           '/mips64el-linux-gnuabi64/lib')
      extra_cflags.extend([
          ('-DDUMMY_mips64el_toolchain_linux_version=%s' %
           api.run.asset_version('mips64el_toolchain_linux', skia_dir))
      ])
      args.update({
        'skia_use_system_freetype2': 'false',
        'skia_use_fontconfig':       'false',
        'skia_enable_gpu':           'false',
        'werror':                    'false',
      })
    else:
      cc, cxx = 'gcc', 'g++'

  if 'Tidy' in extra_tokens:
    # Swap in clang-tidy.sh for clang++, but update PATH so it can find clang++.
    cxx = skia_dir.join("tools/clang-tidy.sh")
    env['PATH'] = '%s:%%(PATH)s' % (clang_linux + '/bin')

  if 'Coverage' in extra_tokens:
    # See https://clang.llvm.org/docs/SourceBasedCodeCoverage.html for
    # more info on using llvm to gather coverage information.
    extra_cflags.append('-fprofile-instr-generate')
    extra_cflags.append('-fcoverage-mapping')
    extra_ldflags.append('-fprofile-instr-generate')
    extra_ldflags.append('-fcoverage-mapping')

  if compiler != 'MSVC' and configuration == 'Debug':
    extra_cflags.append('-O1')

  if 'Exceptions' in extra_tokens:
    extra_cflags.append('/EHsc')
  if 'Fast' in extra_tokens:
    extra_cflags.extend(['-march=native', '-fomit-frame-pointer', '-O3',
                         '-ffp-contract=off'])

  if len(extra_tokens) == 1 and extra_tokens[0].startswith('SK'):
    extra_cflags.append('-D' + extra_tokens[0])
    # If we're limiting Skia at all, drop skcms to portable code.
    if 'SK_CPU_LIMIT' in extra_tokens[0]:
      extra_cflags.append('-DSKCMS_PORTABLE')


  if 'MSAN' in extra_tokens:
    extra_ldflags.append('-L' + clang_linux + '/msan')

  if configuration != 'Debug':
    args['is_debug'] = 'false'
  if 'ANGLE' in extra_tokens:
    args['skia_use_angle'] = 'true'
  if 'SwiftShader' in extra_tokens:
    swiftshader_root = skia_dir.join('third_party', 'externals', 'swiftshader')
    swiftshader_out = out_dir.join('swiftshader_out')
    compile_swiftshader(api, extra_tokens, swiftshader_root, cc, cxx, swiftshader_out)
    args['skia_use_egl'] = 'true'
    extra_cflags.extend([
        '-DGR_EGL_TRY_GLES3_THEN_GLES2',
        '-I%s' % skia_dir.join(
            'third_party', 'externals', 'egl-registry', 'api'),
        '-I%s' % skia_dir.join(
            'third_party', 'externals', 'opengl-registry', 'api'),
    ])
    extra_ldflags.extend([
        '-L%s' % swiftshader_out,
    ])
  if 'CommandBuffer' in extra_tokens:
    # CommandBuffer runs against GLES version of CommandBuffer also, so
    # include both.
    args.update({
      'skia_gl_standard': '""',
    })
    chrome_dir = checkout_root
    api.run.run_once(build_command_buffer, api, chrome_dir, skia_dir, out_dir)
  if 'MSAN' in extra_tokens:
    args['skia_use_fontconfig'] = 'false'
  if 'ASAN' in extra_tokens or 'UBSAN' in extra_tokens:
    args['skia_enable_spirv_validation'] = 'false'
  if 'NoDEPS' in extra_tokens:
    args.update({
      'is_official_build':         'true',
      'skia_enable_fontmgr_empty': 'true',
      'skia_enable_gpu':           'true',

      'skia_enable_pdf':        'false',
      'skia_use_expat':         'false',
      'skia_use_freetype':      'false',
      'skia_use_harfbuzz':      'false',
      'skia_use_libjpeg_turbo': 'false',
      'skia_use_libpng':        'false',
      'skia_use_libwebp':       'false',
      'skia_use_vulkan':        'false',
      'skia_use_zlib':          'false',
    })
  if 'NoGPU' in extra_tokens:
    args['skia_enable_gpu'] = 'false'
  if 'Shared' in extra_tokens:
    args['is_component_build'] = 'true'
  if 'Vulkan' in extra_tokens and not 'Android' in extra_tokens:
    args['skia_use_vulkan'] = 'true'
    args['skia_enable_vulkan_debug_layers'] = 'false'
    if 'MoltenVK' in extra_tokens:
      args['skia_moltenvk_path'] = '"%s"' % moltenvk
  if 'Metal' in extra_tokens:
    args['skia_use_metal'] = 'true'
  if 'OpenCL' in extra_tokens:
    args['skia_use_opencl'] = 'true'
    if api.vars.is_linux:
      extra_cflags.append(
          '-isystem%s' % api.vars.slave_dir.join('opencl_headers'))
      extra_ldflags.append(
          '-L%s' % api.vars.slave_dir.join('opencl_ocl_icd_linux'))
    elif 'Win' in os:
      extra_cflags.append(
          '-imsvc%s' % api.vars.slave_dir.join('opencl_headers'))
      extra_ldflags.append(
          '/LIBPATH:%s' %
          skia_dir.join('third_party', 'externals', 'opencl-lib', '3-0', 'lib',
                        'x86_64'))
  if 'iOS' in extra_tokens:
    # Bots use Chromium signing cert.
    args['skia_ios_identity'] = '".*GS9WA.*"'
    # Get mobileprovision via the CIPD package.
    args['skia_ios_profile'] = '"%s"' % api.vars.slave_dir.join(
        'provisioning_profile_ios',
        'Upstream_Testing_Provisioning_Profile.mobileprovision')
  if 'CheckGeneratedFiles' in extra_tokens:
    args['skia_compile_processors'] = 'true'
    args['skia_generate_workarounds'] = 'true'
  if compiler == 'Clang' and 'Win' in os:
    args['clang_win'] = '"%s"' % api.vars.slave_dir.join('clang_win')
    extra_cflags.append('-DDUMMY_clang_win_version=%s' %
                        api.run.asset_version('clang_win', skia_dir))

  sanitize = ''
  for t in extra_tokens:
    if t.endswith('SAN'):
      sanitize = t
      if api.vars.is_linux and t == 'ASAN':
        # skia:8712 and skia:8713
        extra_cflags.append('-DSK_ENABLE_SCOPED_LSAN_SUPPRESSIONS')
  if 'SafeStack' in extra_tokens:
    assert sanitize == ''
    sanitize = 'safe-stack'

  if 'Wuffs' in extra_tokens:
    args['skia_use_wuffs'] = 'true'

  for (k,v) in {
    'cc':  cc,
    'cxx': cxx,
    'sanitize': sanitize,
    'target_cpu': target_arch,
    'target_os': 'ios' if 'iOS' in extra_tokens else '',
    'win_sdk': win_toolchain + '/win_sdk' if 'Win' in os else '',
    'win_vc': win_toolchain + '/VC' if 'Win' in os else '',
  }.iteritems():
    if v:
      args[k] = '"%s"' % v
  if extra_cflags:
    args['extra_cflags'] = repr(extra_cflags).replace("'", '"')
  if extra_ldflags:
    args['extra_ldflags'] = repr(extra_ldflags).replace("'", '"')

  gn_args = ' '.join('%s=%s' % (k,v) for (k,v) in sorted(args.iteritems()))
  gn = skia_dir.join('bin', 'gn')

  with api.context(cwd=skia_dir):
    api.run(api.python,
            'fetch-gn',
            script=skia_dir.join('bin', 'fetch-gn'),
            infra_step=True)
    if 'CheckGeneratedFiles' in extra_tokens:
      env['PATH'] = '%s:%%(PATH)s' % skia_dir.join('bin')
      api.run(api.python,
              'fetch-clang-format',
              script=skia_dir.join('bin', 'fetch-clang-format'),
              infra_step=True)

    with api.env(env):
      api.run(api.step, 'gn gen',
              cmd=[gn, 'gen', out_dir, '--args=' + gn_args])
      api.run(api.step, 'ninja', cmd=['ninja', '-C', out_dir])


def copy_build_products(api, src, dst):
  util.copy_listed_files(api, src, dst, util.DEFAULT_BUILD_PRODUCTS)
  extra_tokens  = api.vars.extra_tokens
  os            = api.vars.builder_cfg.get('os', '')

  if 'SwiftShader' in extra_tokens:
    util.copy_listed_files(api,
        src.join('swiftshader_out'),
        api.vars.swarming_out_dir.join('swiftshader_out'),
        util.DEFAULT_BUILD_PRODUCTS)

  if os == 'Mac' and any('SAN' in t for t in extra_tokens):
    # Hardcoding this path because it should only change when we upgrade to a
    # new Xcode.
    lib_dir = api.vars.cache_dir.join(
        'Xcode.app', 'Contents', 'Developer', 'Toolchains',
        'XcodeDefault.xctoolchain', 'usr', 'lib', 'clang', XCODE_CLANG_VERSION,
        'lib', 'darwin')
    dylibs = api.file.glob_paths('find xSAN dylibs', lib_dir,
                                 'libclang_rt.*san_osx_dynamic.dylib',
                                 test_data=[
                                     'libclang_rt.asan_osx_dynamic.dylib',
                                     'libclang_rt.tsan_osx_dynamic.dylib',
                                     'libclang_rt.ubsan_osx_dynamic.dylib',
                                 ])
    for f in dylibs:
      api.file.copy('copy %s' % api.path.basename(f), f, dst)
