#!/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')

# Allow the user to override the directory where gyp should produce its output
# Default to the current directory.
gyp_output_dir = os.environ.get('SKIA_GYP_OUTPUT_DIR', '.')

# 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=%s' % gyp_output_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))
