#!/usr/bin/env python
#
# Copyright 2012 the V8 project authors. All rights reserved.
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
#     * Redistributions of source code must retain the above copyright
#       notice, this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above
#       copyright notice, this list of conditions and the following
#       disclaimer in the documentation and/or other materials provided
#       with the distribution.
#     * Neither the name of Google Inc. nor the names of its
#       contributors may be used to endorse or promote products derived
#       from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

# This script is wrapper for V8 that adds some support for how GYP
# is invoked by V8 beyond what can be done in the gclient hooks.

import glob
import os
import platform
import shlex
import subprocess
import sys

script_dir = os.path.dirname(os.path.realpath(__file__))
v8_root = os.path.abspath(os.path.join(script_dir, os.pardir))

sys.path.insert(0, os.path.join(v8_root, 'build', 'gyp', 'pylib'))
import gyp

# Add paths so that pymod_do_main(...) can import files.
sys.path.insert(
    1, os.path.abspath(os.path.join(v8_root, 'tools', 'generate_shim_headers')))


def apply_gyp_environment(file_path=None):
  """
  Reads in a *.gyp_env file and applies the valid keys to os.environ.
  """
  if not file_path or not os.path.exists(file_path):
    return
  file_contents = open(file_path).read()
  try:
    file_data = eval(file_contents, {'__builtins__': None}, None)
  except SyntaxError, e:
    e.filename = os.path.abspath(file_path)
    raise
  supported_vars = ( 'V8_GYP_FILE',
                     'V8_GYP_SYNTAX_CHECK',
                     'GYP_DEFINES',
                     'GYP_GENERATOR_FLAGS',
                     'GYP_GENERATOR_OUTPUT', )
  for var in supported_vars:
    val = file_data.get(var)
    if val:
      if var in os.environ:
        print 'INFO: Environment value for "%s" overrides value in %s.' % (
            var, os.path.abspath(file_path)
        )
      else:
        os.environ[var] = val


def additional_include_files(args=[]):
  """
  Returns a list of additional (.gypi) files to include, without
  duplicating ones that are already specified on the command line.
  """
  # 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 standalone.gypi
  AddInclude(os.path.join(v8_root, 'build', 'standalone.gypi'))

  # Optionally add supplemental .gypi files if present.
  supplements = glob.glob(os.path.join(v8_root, '*', 'supplement.gypi'))
  for supplement in supplements:
    AddInclude(supplement)

  return result


def run_gyp(args):
  rc = gyp.main(args)

  # Check for landmines (reasons to clobber the build). This must be run here,
  # rather than a separate runhooks step so that any environment modifications
  # from above are picked up.
  print 'Running build/landmines.py...'
  subprocess.check_call(
      [sys.executable, os.path.join(script_dir, 'landmines.py')])

  if rc != 0:
    print 'Error running GYP'
    sys.exit(rc)


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

  if 'SKIP_V8_GYP_ENV' not in os.environ:
    # Update the environment based on v8.gyp_env
    gyp_env_path = os.path.join(os.path.dirname(v8_root), 'v8.gyp_env')
    apply_gyp_environment(gyp_env_path)

  # 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, check an env var, and then fall back to
  # assuming 'all.gyp' from the same directory as the script.
  if not gyp_file_specified:
    gyp_file = os.environ.get('V8_GYP_FILE')
    if gyp_file:
      # Note that V8_GYP_FILE values can't have backslashes as
      # path separators even on Windows due to the use of shlex.split().
      args.extend(shlex.split(gyp_file))
    else:
      args.append(os.path.join(script_dir, 'all.gyp'))

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

  # There shouldn't be a circular dependency relationship between .gyp files
  args.append('--no-circular-check')

  # Set the GYP DEPTH variable to the root of the V8 project.
  args.append('--depth=' + os.path.relpath(v8_root))

  # If V8_GYP_SYNTAX_CHECK is set to 1, it will invoke gyp with --check
  # to enfore syntax checking.
  syntax_check = os.environ.get('V8_GYP_SYNTAX_CHECK')
  if syntax_check and int(syntax_check):
    args.append('--check')

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

  # Generate for the architectures supported on the given platform.
  gyp_args = list(args)
  gyp_generators = os.environ.get('GYP_GENERATORS')
  if platform.system() == 'Linux' and gyp_generators != 'ninja':
    # Work around for crbug.com/331475.
    for f in glob.glob(os.path.join(v8_root, 'out', 'Makefile.*')):
      os.unlink(f)
    # --generator-output defines where the Makefile goes.
    gyp_args.append('--generator-output=out')
    # -Goutput_dir defines where the build output goes, relative to the
    # Makefile. Set it to . so that the build output doesn't end up in out/out.
    gyp_args.append('-Goutput_dir=.')
  run_gyp(gyp_args)
