#!/usr/bin/env 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 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):
    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 environment variable not set, using default, %s' %
           (ENVVAR_GYP_GENERATORS, default_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'

  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))
