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

  vs_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
      vs_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.
  out_dir = os.path.abspath(get_output_dir())
  args.extend(['--generator-output', out_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 vs_runtime_dll_dirs:
    # The DLLs might be read-only, which will cause an error when attempting to
    # overwrite them. Make them writeable first.
    for path, dirs, files in os.walk(out_dir):
      for f in files:
        if f.endswith('.dll'):
          os.chmod(os.path.join(path, f), stat.S_IWRITE)

    x64_runtime, x86_runtime = vs_runtime_dll_dirs
    vs_toolchain.CopyVsRuntimeDlls(
        os.path.join(os.getenv('CHROME_PATH'), out_dir),
        (x86_runtime, x64_runtime))
