#!/usr/bin/python

# Copyright 2011 The Android Open Source Project
#
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

# This script is a wrapper which invokes gyp with the correct --depth argument,
# and supports the automatic regeneration of build files if all.gyp is
# changed (Linux-only).

import glob
import os
import platform
import shlex
import sys

script_dir = os.path.abspath(os.path.dirname(__file__))

# Directory within which we can find the gyp source.
gyp_source_dir = os.path.join(script_dir, 'third_party', 'externals', 'gyp')

# Directory within which we can find most of Skia's gyp configuration files.
gyp_config_dir = os.path.join(script_dir, 'gyp')

# Ensure we import our current gyp source's module, not any version
# pre-installed in your PYTHONPATH.
sys.path.insert(0, os.path.join(gyp_source_dir, 'pylib'))
import gyp

ENVVAR_GYP_GENERATORS = 'GYP_GENERATORS'
ENVVAR_GYP_GENERATOR_FLAGS = 'GYP_GENERATOR_FLAGS'


def additional_include_files(args=[]):
  # Determine the include files specified on the command line.
  # This doesn't cover all the different option formats you can use,
  # but it's mainly intended to avoid duplicating flags on the automatic
  # makefile regeneration which only uses this format.
  specified_includes = set()
  for arg in args:
    if arg.startswith('-I') and len(arg) > 2:
      specified_includes.add(os.path.realpath(arg[2:]))

  result = []
  def AddInclude(path):
    if os.path.realpath(path) not in specified_includes:
      result.append(path)

  # Always include common.gypi.
  # We do this, rather than including common.gypi explicitly in all our gyp
  # files, so that gyp files we use but do not maintain (e.g.,
  # third_party/externals/libjpeg/libjpeg.gyp) will include common.gypi too.
  AddInclude(os.path.join(gyp_config_dir, 'common.gypi'))

  return result

# Return the directory where all the build files are to be written.
def get_output_dir():
  # SKIA_OUT can be any directory either as a child of the standard out/
  # directory or any given location on the file system (e.g. /tmp/skia)
  output_dir = os.getenv('SKIA_OUT')

  if not output_dir:
    return os.path.join(os.path.abspath(script_dir), 'out')

  if (sys.platform.startswith('darwin') and
      (not os.getenv(ENVVAR_GYP_GENERATORS) or
       'xcode' in os.getenv(ENVVAR_GYP_GENERATORS))):
    print 'ERROR: variable SKIA_OUT is not valid on Mac (using xcodebuild)'
    sys.exit(-1);

  if os.path.isabs(output_dir):
    return output_dir
  else:
    return os.path.join(os.path.abspath(script_dir), output_dir)


if __name__ == '__main__':
  args = sys.argv[1:]

  if not os.getenv(ENVVAR_GYP_GENERATORS):
    print ('%s environment variable not set, using default' %
           ENVVAR_GYP_GENERATORS)
    if sys.platform.startswith('darwin'):
      default_gyp_generators = 'ninja,xcode'
    elif sys.platform.startswith('win'):
      default_gyp_generators = 'ninja,msvs-ninja'
    elif sys.platform.startswith('cygwin'):
      default_gyp_generators = 'ninja,msvs-ninja'
    else:
      default_gyp_generators = 'ninja'
    os.environ[ENVVAR_GYP_GENERATORS] = default_gyp_generators
  print '%s is "%s"' % (ENVVAR_GYP_GENERATORS, os.getenv(ENVVAR_GYP_GENERATORS))

  vs2013_runtime_dll_dirs = None
  if os.getenv('CHROME_HEADLESS', '0') == '1':
    if sys.platform.startswith('win') or sys.platform.startswith('cygwin'):
      chrome_path = os.getenv('CHROME_PATH')
      os.chdir(chrome_path)
      sys.path.append(os.path.join(chrome_path, 'build'))
      sys.path.append(os.path.join(chrome_path, 'tools'))
      import vs_toolchain
      vs2013_runtime_dll_dirs = \
          vs_toolchain.SetEnvironmentAndGetRuntimeDllDirs()

  # Set CWD to the directory containing this script.
  # This allows us to launch it from other directories, in spite of gyp's
  # finickyness about the current working directory.
  # See http://b.corp.google.com/issue?id=5019517 ('Linux make build
  # (from out dir) no longer runs skia_gyp correctly')
  os.chdir(os.path.abspath(script_dir))

  # This could give false positives since it doesn't actually do real option
  # parsing.  Oh well.
  gyp_file_specified = False
  for arg in args:
    if arg.endswith('.gyp'):
      gyp_file_specified = True
      break

  # If we didn't get a file, then fall back to assuming 'skia.gyp' from the
  # same directory as the script.
  # The gypfile must be passed as a relative path, not an absolute path,
  # or else the gyp code doesn't write into the proper output dir.
  if not gyp_file_specified:
    args.append('skia.gyp')

  args.extend(['-I' + i for i in additional_include_files(args)])
  args.extend(['--depth', '.'])

  # Tell gyp to write the build files into output_dir.
  args.extend(['--generator-output', os.path.abspath(get_output_dir())])

  # Tell ninja to write its output into the same directory.
  args.extend(['-Goutput_dir=.'])

  # By default, we build 'most' instead of 'all' or 'everything'. See skia.gyp.
  args.extend(['-Gdefault_target=most'])

  # Fail if any files specified in the project are missing
  if sys.platform.startswith('win'):
    gyp_generator_flags = os.getenv(ENVVAR_GYP_GENERATOR_FLAGS, '')
    if not 'msvs_error_on_missing_sources' in gyp_generator_flags:
      os.environ[ENVVAR_GYP_GENERATOR_FLAGS] = (
          gyp_generator_flags + ' msvs_error_on_missing_sources=1')

  # GYP is very conservative about how many concurrent linker calls it allows,
  # to fit in RAM. We don't need to be nearly as conservative as Chrome.  We'll
  # just turn that feature off.
  os.environ['GYP_LINK_CONCURRENCY'] = '9001'

  print 'Updating projects from gyp files...'
  sys.stdout.flush()

  if '--dry-run' in args:
    args.remove('--dry-run')
    print gyp_source_dir, ' '.join(args)
  else:
    # Off we go...
    res = gyp.main(args)
    if res:
      sys.exit(res)

  # This code is copied from Chrome's build/gyp_chromium. It's not clear why
  # the *_runtime variables are reversed.
  if vs2013_runtime_dll_dirs:
    x64_runtime, x86_runtime = vs2013_runtime_dll_dirs
    vs_toolchain.CopyVsRuntimeDlls(
        os.path.join(os.getenv('CHROME_PATH'), get_output_dir()),
        (x86_runtime, x64_runtime))
