#!/usr/bin/env python

# Copyright (c) 2012 Google Inc. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import copy
import gyp.input
import optparse
import os.path
import re
import shlex
import sys
import traceback
from gyp.common import GypError

# Default debug modes for GYP
debug = {}

# List of "official" debug modes, but you can use anything you like.
DEBUG_GENERAL = 'general'
DEBUG_VARIABLES = 'variables'
DEBUG_INCLUDES = 'includes'


def DebugOutput(mode, message, *args):
  if 'all' in gyp.debug or mode in gyp.debug:
    ctx = ('unknown', 0, 'unknown')
    try:
      f = traceback.extract_stack(limit=2)
      if f:
        ctx = f[0][:3]
    except:
      pass
    if args:
      message %= args
    print '%s:%s:%d:%s %s' % (mode.upper(), os.path.basename(ctx[0]),
                              ctx[1], ctx[2], message)

def FindBuildFiles():
  extension = '.gyp'
  files = os.listdir(os.getcwd())
  build_files = []
  for file in files:
    if file.endswith(extension):
      build_files.append(file)
  return build_files


def Load(build_files, format, default_variables={},
         includes=[], depth='.', params=None, check=False,
         circular_check=True, duplicate_basename_check=True):
  """
  Loads one or more specified build files.
  default_variables and includes will be copied before use.
  Returns the generator for the specified format and the
  data returned by loading the specified build files.
  """
  if params is None:
    params = {}

  flavor = None
  if '-' in format:
    format, params['flavor'] = format.split('-', 1)

  default_variables = copy.copy(default_variables)

  # Default variables provided by this program and its modules should be
  # named WITH_CAPITAL_LETTERS to provide a distinct "best practice" namespace,
  # avoiding collisions with user and automatic variables.
  default_variables['GENERATOR'] = format

  # Format can be a custom python file, or by default the name of a module
  # within gyp.generator.
  if format.endswith('.py'):
    generator_name = os.path.splitext(format)[0]
    path, generator_name = os.path.split(generator_name)

    # Make sure the path to the custom generator is in sys.path
    # Don't worry about removing it once we are done.  Keeping the path
    # to each generator that is used in sys.path is likely harmless and
    # arguably a good idea.
    path = os.path.abspath(path)
    if path not in sys.path:
      sys.path.insert(0, path)
  else:
    generator_name = 'gyp.generator.' + format

  # These parameters are passed in order (as opposed to by key)
  # because ActivePython cannot handle key parameters to __import__.
  generator = __import__(generator_name, globals(), locals(), generator_name)
  for (key, val) in generator.generator_default_variables.items():
    default_variables.setdefault(key, val)

  # Give the generator the opportunity to set additional variables based on
  # the params it will receive in the output phase.
  if getattr(generator, 'CalculateVariables', None):
    generator.CalculateVariables(default_variables, params)

  # Give the generator the opportunity to set generator_input_info based on
  # the params it will receive in the output phase.
  if getattr(generator, 'CalculateGeneratorInputInfo', None):
    generator.CalculateGeneratorInputInfo(params)

  # Fetch the generator specific info that gets fed to input, we use getattr
  # so we can default things and the generators only have to provide what
  # they need.
  generator_input_info = {
    'non_configuration_keys':
        getattr(generator, 'generator_additional_non_configuration_keys', []),
    'path_sections':
        getattr(generator, 'generator_additional_path_sections', []),
    'extra_sources_for_rules':
        getattr(generator, 'generator_extra_sources_for_rules', []),
    'generator_supports_multiple_toolsets':
        getattr(generator, 'generator_supports_multiple_toolsets', False),
    'generator_wants_static_library_dependencies_adjusted':
        getattr(generator,
                'generator_wants_static_library_dependencies_adjusted', True),
    'generator_wants_sorted_dependencies':
        getattr(generator, 'generator_wants_sorted_dependencies', False),
    'generator_filelist_paths':
        getattr(generator, 'generator_filelist_paths', None),
  }

  # Process the input specific to this generator.
  result = gyp.input.Load(build_files, default_variables, includes[:],
                          depth, generator_input_info, check, circular_check,
                          duplicate_basename_check,
                          params['parallel'], params['root_targets'])
  return [generator] + result

def NameValueListToDict(name_value_list):
  """
  Takes an array of strings of the form 'NAME=VALUE' and creates a dictionary
  of the pairs.  If a string is simply NAME, then the value in the dictionary
  is set to True.  If VALUE can be converted to an integer, it is.
  """
  result = { }
  for item in name_value_list:
    tokens = item.split('=', 1)
    if len(tokens) == 2:
      # If we can make it an int, use that, otherwise, use the string.
      try:
        token_value = int(tokens[1])
      except ValueError:
        token_value = tokens[1]
      # Set the variable to the supplied value.
      result[tokens[0]] = token_value
    else:
      # No value supplied, treat it as a boolean and set it.
      result[tokens[0]] = True
  return result

def ShlexEnv(env_name):
  flags = os.environ.get(env_name, [])
  if flags:
    flags = shlex.split(flags)
  return flags

def FormatOpt(opt, value):
  if opt.startswith('--'):
    return '%s=%s' % (opt, value)
  return opt + value

def RegenerateAppendFlag(flag, values, predicate, env_name, options):
  """Regenerate a list of command line flags, for an option of action='append'.

  The |env_name|, if given, is checked in the environment and used to generate
  an initial list of options, then the options that were specified on the
  command line (given in |values|) are appended.  This matches the handling of
  environment variables and command line flags where command line flags override
  the environment, while not requiring the environment to be set when the flags
  are used again.
  """
  flags = []
  if options.use_environment and env_name:
    for flag_value in ShlexEnv(env_name):
      value = FormatOpt(flag, predicate(flag_value))
      if value in flags:
        flags.remove(value)
      flags.append(value)
  if values:
    for flag_value in values:
      flags.append(FormatOpt(flag, predicate(flag_value)))
  return flags

def RegenerateFlags(options):
  """Given a parsed options object, and taking the environment variables into
  account, returns a list of flags that should regenerate an equivalent options
  object (even in the absence of the environment variables.)

  Any path options will be normalized relative to depth.

  The format flag is not included, as it is assumed the calling generator will
  set that as appropriate.
  """
  def FixPath(path):
    path = gyp.common.FixIfRelativePath(path, options.depth)
    if not path:
      return os.path.curdir
    return path

  def Noop(value):
    return value

  # We always want to ignore the environment when regenerating, to avoid
  # duplicate or changed flags in the environment at the time of regeneration.
  flags = ['--ignore-environment']
  for name, metadata in options._regeneration_metadata.iteritems():
    opt = metadata['opt']
    value = getattr(options, name)
    value_predicate = metadata['type'] == 'path' and FixPath or Noop
    action = metadata['action']
    env_name = metadata['env_name']
    if action == 'append':
      flags.extend(RegenerateAppendFlag(opt, value, value_predicate,
                                        env_name, options))
    elif action in ('store', None):  # None is a synonym for 'store'.
      if value:
        flags.append(FormatOpt(opt, value_predicate(value)))
      elif options.use_environment and env_name and os.environ.get(env_name):
        flags.append(FormatOpt(opt, value_predicate(os.environ.get(env_name))))
    elif action in ('store_true', 'store_false'):
      if ((action == 'store_true' and value) or
          (action == 'store_false' and not value)):
        flags.append(opt)
      elif options.use_environment and env_name:
        print >>sys.stderr, ('Warning: environment regeneration unimplemented '
                             'for %s flag %r env_name %r' % (action, opt,
                                                             env_name))
    else:
      print >>sys.stderr, ('Warning: regeneration unimplemented for action %r '
                           'flag %r' % (action, opt))

  return flags

class RegeneratableOptionParser(optparse.OptionParser):
  def __init__(self):
    self.__regeneratable_options = {}
    optparse.OptionParser.__init__(self)

  def add_option(self, *args, **kw):
    """Add an option to the parser.

    This accepts the same arguments as OptionParser.add_option, plus the
    following:
      regenerate: can be set to False to prevent this option from being included
                  in regeneration.
      env_name: name of environment variable that additional values for this
                option come from.
      type: adds type='path', to tell the regenerator that the values of
            this option need to be made relative to options.depth
    """
    env_name = kw.pop('env_name', None)
    if 'dest' in kw and kw.pop('regenerate', True):
      dest = kw['dest']

      # The path type is needed for regenerating, for optparse we can just treat
      # it as a string.
      type = kw.get('type')
      if type == 'path':
        kw['type'] = 'string'

      self.__regeneratable_options[dest] = {
          'action': kw.get('action'),
          'type': type,
          'env_name': env_name,
          'opt': args[0],
        }

    optparse.OptionParser.add_option(self, *args, **kw)

  def parse_args(self, *args):
    values, args = optparse.OptionParser.parse_args(self, *args)
    values._regeneration_metadata = self.__regeneratable_options
    return values, args

def gyp_main(args):
  my_name = os.path.basename(sys.argv[0])

  parser = RegeneratableOptionParser()
  usage = 'usage: %s [options ...] [build_file ...]'
  parser.set_usage(usage.replace('%s', '%prog'))
  parser.add_option('--build', dest='configs', action='append',
                    help='configuration for build after project generation')
  parser.add_option('--check', dest='check', action='store_true',
                    help='check format of gyp files')
  parser.add_option('--config-dir', dest='config_dir', action='store',
                    env_name='GYP_CONFIG_DIR', default=None,
                    help='The location for configuration files like '
                    'include.gypi.')
  parser.add_option('-d', '--debug', dest='debug', metavar='DEBUGMODE',
                    action='append', default=[], help='turn on a debugging '
                    'mode for debugging GYP.  Supported modes are "variables", '
                    '"includes" and "general" or "all" for all of them.')
  parser.add_option('-D', dest='defines', action='append', metavar='VAR=VAL',
                    env_name='GYP_DEFINES',
                    help='sets variable VAR to value VAL')
  parser.add_option('--depth', dest='depth', metavar='PATH', type='path',
                    help='set DEPTH gyp variable to a relative path to PATH')
  parser.add_option('-f', '--format', dest='formats', action='append',
                    env_name='GYP_GENERATORS', regenerate=False,
                    help='output formats to generate')
  parser.add_option('-G', dest='generator_flags', action='append', default=[],
                    metavar='FLAG=VAL', env_name='GYP_GENERATOR_FLAGS',
                    help='sets generator flag FLAG to VAL')
  parser.add_option('--generator-output', dest='generator_output',
                    action='store', default=None, metavar='DIR', type='path',
                    env_name='GYP_GENERATOR_OUTPUT',
                    help='puts generated build files under DIR')
  parser.add_option('--ignore-environment', dest='use_environment',
                    action='store_false', default=True, regenerate=False,
                    help='do not read options from environment variables')
  parser.add_option('-I', '--include', dest='includes', action='append',
                    metavar='INCLUDE', type='path',
                    help='files to include in all loaded .gyp files')
  # --no-circular-check disables the check for circular relationships between
  # .gyp files.  These relationships should not exist, but they've only been
  # observed to be harmful with the Xcode generator.  Chromium's .gyp files
  # currently have some circular relationships on non-Mac platforms, so this
  # option allows the strict behavior to be used on Macs and the lenient
  # behavior to be used elsewhere.
  # TODO(mark): Remove this option when http://crbug.com/35878 is fixed.
  parser.add_option('--no-circular-check', dest='circular_check',
                    action='store_false', default=True, regenerate=False,
                    help="don't check for circular relationships between files")
  # --no-duplicate-basename-check disables the check for duplicate basenames
  # in a static_library/shared_library project. Visual C++ 2008 generator
  # doesn't support this configuration. Libtool on Mac also generates warnings
  # when duplicate basenames are passed into Make generator on Mac.
  # TODO(yukawa): Remove this option when these legacy generators are
  # deprecated.
  parser.add_option('--no-duplicate-basename-check',
                    dest='duplicate_basename_check', action='store_false',
                    default=True, regenerate=False,
                    help="don't check for duplicate basenames")
  parser.add_option('--no-parallel', action='store_true', default=False,
                    help='Disable multiprocessing')
  parser.add_option('-S', '--suffix', dest='suffix', default='',
                    help='suffix to add to generated files')
  parser.add_option('--toplevel-dir', dest='toplevel_dir', action='store',
                    default=None, metavar='DIR', type='path',
                    help='directory to use as the root of the source tree')
  parser.add_option('-R', '--root-target', dest='root_targets',
                    action='append', metavar='TARGET',
                    help='include only TARGET and its deep dependencies')

  options, build_files_arg = parser.parse_args(args)
  build_files = build_files_arg

  # Set up the configuration directory (defaults to ~/.gyp)
  if not options.config_dir:
    home = None
    home_dot_gyp = None
    if options.use_environment:
      home_dot_gyp = os.environ.get('GYP_CONFIG_DIR', None)
      if home_dot_gyp:
        home_dot_gyp = os.path.expanduser(home_dot_gyp)

    if not home_dot_gyp:
      home_vars = ['HOME']
      if sys.platform in ('cygwin', 'win32'):
        home_vars.append('USERPROFILE')
      for home_var in home_vars:
        home = os.getenv(home_var)
        if home != None:
          home_dot_gyp = os.path.join(home, '.gyp')
          if not os.path.exists(home_dot_gyp):
            home_dot_gyp = None
          else:
            break
  else:
    home_dot_gyp = os.path.expanduser(options.config_dir)

  if home_dot_gyp and not os.path.exists(home_dot_gyp):
    home_dot_gyp = None

  if not options.formats:
    # If no format was given on the command line, then check the env variable.
    generate_formats = []
    if options.use_environment:
      generate_formats = os.environ.get('GYP_GENERATORS', [])
    if generate_formats:
      generate_formats = re.split('[\s,]', generate_formats)
    if generate_formats:
      options.formats = generate_formats
    else:
      # Nothing in the variable, default based on platform.
      if sys.platform == 'darwin':
        options.formats = ['xcode']
      elif sys.platform in ('win32', 'cygwin'):
        options.formats = ['msvs']
      else:
        options.formats = ['make']

  if not options.generator_output and options.use_environment:
    g_o = os.environ.get('GYP_GENERATOR_OUTPUT')
    if g_o:
      options.generator_output = g_o

  options.parallel = not options.no_parallel

  for mode in options.debug:
    gyp.debug[mode] = 1

  # Do an extra check to avoid work when we're not debugging.
  if DEBUG_GENERAL in gyp.debug:
    DebugOutput(DEBUG_GENERAL, 'running with these options:')
    for option, value in sorted(options.__dict__.items()):
      if option[0] == '_':
        continue
      if isinstance(value, basestring):
        DebugOutput(DEBUG_GENERAL, "  %s: '%s'", option, value)
      else:
        DebugOutput(DEBUG_GENERAL, "  %s: %s", option, value)

  if not build_files:
    build_files = FindBuildFiles()
  if not build_files:
    raise GypError((usage + '\n\n%s: error: no build_file') %
                   (my_name, my_name))

  # TODO(mark): Chromium-specific hack!
  # For Chromium, the gyp "depth" variable should always be a relative path
  # to Chromium's top-level "src" directory.  If no depth variable was set
  # on the command line, try to find a "src" directory by looking at the
  # absolute path to each build file's directory.  The first "src" component
  # found will be treated as though it were the path used for --depth.
  if not options.depth:
    for build_file in build_files:
      build_file_dir = os.path.abspath(os.path.dirname(build_file))
      build_file_dir_components = build_file_dir.split(os.path.sep)
      components_len = len(build_file_dir_components)
      for index in xrange(components_len - 1, -1, -1):
        if build_file_dir_components[index] == 'src':
          options.depth = os.path.sep.join(build_file_dir_components)
          break
        del build_file_dir_components[index]

      # If the inner loop found something, break without advancing to another
      # build file.
      if options.depth:
        break

    if not options.depth:
      raise GypError('Could not automatically locate src directory.  This is'
                     'a temporary Chromium feature that will be removed.  Use'
                     '--depth as a workaround.')

  # If toplevel-dir is not set, we assume that depth is the root of our source
  # tree.
  if not options.toplevel_dir:
    options.toplevel_dir = options.depth

  # -D on the command line sets variable defaults - D isn't just for define,
  # it's for default.  Perhaps there should be a way to force (-F?) a
  # variable's value so that it can't be overridden by anything else.
  cmdline_default_variables = {}
  defines = []
  if options.use_environment:
    defines += ShlexEnv('GYP_DEFINES')
  if options.defines:
    defines += options.defines
  cmdline_default_variables = NameValueListToDict(defines)
  if DEBUG_GENERAL in gyp.debug:
    DebugOutput(DEBUG_GENERAL,
                "cmdline_default_variables: %s", cmdline_default_variables)

  # Set up includes.
  includes = []

  # If ~/.gyp/include.gypi exists, it'll be forcibly included into every
  # .gyp file that's loaded, before anything else is included.
  if home_dot_gyp != None:
    default_include = os.path.join(home_dot_gyp, 'include.gypi')
    if os.path.exists(default_include):
      print 'Using overrides found in ' + default_include
      includes.append(default_include)

  # Command-line --include files come after the default include.
  if options.includes:
    includes.extend(options.includes)

  # Generator flags should be prefixed with the target generator since they
  # are global across all generator runs.
  gen_flags = []
  if options.use_environment:
    gen_flags += ShlexEnv('GYP_GENERATOR_FLAGS')
  if options.generator_flags:
    gen_flags += options.generator_flags
  generator_flags = NameValueListToDict(gen_flags)
  if DEBUG_GENERAL in gyp.debug.keys():
    DebugOutput(DEBUG_GENERAL, "generator_flags: %s", generator_flags)

  # Generate all requested formats (use a set in case we got one format request
  # twice)
  for format in set(options.formats):
    params = {'options': options,
              'build_files': build_files,
              'generator_flags': generator_flags,
              'cwd': os.getcwd(),
              'build_files_arg': build_files_arg,
              'gyp_binary': sys.argv[0],
              'home_dot_gyp': home_dot_gyp,
              'parallel': options.parallel,
              'root_targets': options.root_targets}

    # Start with the default variables from the command line.
    [generator, flat_list, targets, data] = Load(
        build_files, format, cmdline_default_variables, includes, options.depth,
        params, options.check, options.circular_check,
        options.duplicate_basename_check)

    # TODO(mark): Pass |data| for now because the generator needs a list of
    # build files that came in.  In the future, maybe it should just accept
    # a list, and not the whole data dict.
    # NOTE: flat_list is the flattened dependency graph specifying the order
    # that targets may be built.  Build systems that operate serially or that
    # need to have dependencies defined before dependents reference them should
    # generate targets in the order specified in flat_list.
    generator.GenerateOutput(flat_list, targets, data, params)

    if options.configs:
      valid_configs = targets[flat_list[0]]['configurations'].keys()
      for conf in options.configs:
        if conf not in valid_configs:
          raise GypError('Invalid config specified via --build: %s' % conf)
      generator.PerformBuild(data, options.configs, params)

  # Done
  return 0


def main(args):
  try:
    return gyp_main(args)
  except GypError, e:
    sys.stderr.write("gyp: %s\n" % e)
    return 1

# NOTE: setuptools generated console_scripts calls function with no arguments
def script_main():
  return main(sys.argv[1:])

if __name__ == '__main__':
  sys.exit(script_main())
