# Copyright (c) 2013 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 hashlib
import multiprocessing
import os.path
import pipes
import platform
import re
import signal
import subprocess
import sys
import gyp
import gyp.common
import gyp.msvs_emulation
import gyp.MSVSUtil as MSVSUtil
import gyp.xcode_emulation

from gyp.common import GetEnvironFallback
import gyp.ninja_syntax as ninja_syntax

if sys.platform == 'cygwin':
  import cygpath

generator_default_variables = {
  'EXECUTABLE_PREFIX': '',
  'EXECUTABLE_SUFFIX': '',
  'STATIC_LIB_PREFIX': 'lib',
  'STATIC_LIB_SUFFIX': '.a',
  'SHARED_LIB_PREFIX': 'lib',

  # Gyp expects the following variables to be expandable by the build
  # system to the appropriate locations.  Ninja prefers paths to be
  # known at gyp time.  To resolve this, introduce special
  # variables starting with $! and $| (which begin with a $ so gyp knows it
  # should be treated specially, but is otherwise an invalid
  # ninja/shell variable) that are passed to gyp here but expanded
  # before writing out into the target .ninja files; see
  # ExpandSpecial.
  # $! is used for variables that represent a path and that can only appear at
  # the start of a string, while $| is used for variables that can appear
  # anywhere in a string.
  'INTERMEDIATE_DIR': '$!INTERMEDIATE_DIR',
  'SHARED_INTERMEDIATE_DIR': '$!PRODUCT_DIR/gen',
  'PRODUCT_DIR': '$!PRODUCT_DIR',
  'CONFIGURATION_NAME': '$|CONFIGURATION_NAME',

  # Special variables that may be used by gyp 'rule' targets.
  # We generate definitions for these variables on the fly when processing a
  # rule.
  'RULE_INPUT_ROOT': '${root}',
  'RULE_INPUT_DIRNAME': '${dirname}',
  'RULE_INPUT_PATH': '${source}',
  'RULE_INPUT_EXT': '${ext}',
  'RULE_INPUT_NAME': '${name}',
}

# Placates pylint.
generator_additional_non_configuration_keys = []
generator_additional_path_sections = []
generator_extra_sources_for_rules = []

# TODO: figure out how to not build extra host objects in the non-cross-compile
# case when this is enabled, and enable unconditionally.
generator_supports_multiple_toolsets = (
  os.environ.get('GYP_CROSSCOMPILE') or
  os.environ.get('AR_host') or
  os.environ.get('CC_host') or
  os.environ.get('CXX_host') or
  os.environ.get('AR_target') or
  os.environ.get('CC_target') or
  os.environ.get('CXX_target'))

is_linux = platform.system() == 'Linux'
is_windows = platform.system() == 'Windows'

def StripPrefix(arg, prefix):
  if arg.startswith(prefix):
    return arg[len(prefix):]
  return arg


def QuoteShellArgument(arg, flavor):
  """Quote a string such that it will be interpreted as a single argument
  by the shell."""
  # Rather than attempting to enumerate the bad shell characters, just
  # whitelist common OK ones and quote anything else.
  if re.match(r'^[a-zA-Z0-9_=.\\/-]+$', arg):
    return arg  # No quoting necessary.
  if flavor in ['win', 'xb1']:
    return gyp.msvs_emulation.QuoteForRspFile(arg)
  elif flavor in ['ps3', 'ps4'] :
    # Escape double quotes.
    return '"' + arg.replace('\"', '\\\"') + '"'
  return "'" + arg.replace("'", "'" + '"\'"' + "'")  + "'"


def Define(d, flavor):
  """Takes a preprocessor define and returns a -D parameter that's ninja- and
  shell-escaped."""
  if flavor in ['win', 'xb1']:
    # cl.exe replaces literal # characters with = in preprocesor definitions for
    # some reason. Octal-encode to work around that.
    d = d.replace('#', '\\%03o' % ord('#'))
    return '/D' + gyp.msvs_emulation.QuoteForRspFile(ninja_syntax.escape(d))

  return QuoteShellArgument(ninja_syntax.escape('-D' + d), flavor)


def InvertRelativePath(path):
  """Given a relative path like foo/bar, return the inverse relative path:
  the path from the relative path back to the origin dir.

  E.g. os.path.normpath(os.path.join(path, InvertRelativePath(path)))
  should always produce the empty string."""

  if not path:
    return path
  # Only need to handle relative paths into subdirectories for now.
  assert '..' not in path, path
  depth = len(path.split(os.path.sep))
  return os.path.sep.join(['..'] * depth)


class Target:
  """Target represents the paths used within a single gyp target.

  Conceptually, building a single target A is a series of steps:

  1) actions/rules/copies  generates source/resources/etc.
  2) compiles              generates .o files
  3) link                  generates a binary (library/executable)
  4) bundle                merges the above in a mac bundle

  (Any of these steps can be optional.)

  From a build ordering perspective, a dependent target B could just
  depend on the last output of this series of steps.

  But some dependent commands sometimes need to reach inside the box.
  For example, when linking B it needs to get the path to the static
  library generated by A.

  This object stores those paths.  To keep things simple, member
  variables only store concrete paths to single files, while methods
  compute derived values like "the last output of the target".
  """
  def __init__(self, type):
    # Gyp type ("static_library", etc.) of this target.
    self.type = type
    # File representing whether any input dependencies necessary for
    # dependent actions have completed.
    self.preaction_stamp = None
    # File representing whether any input dependencies necessary for
    # dependent compiles have completed.
    self.precompile_stamp = None
    # File representing the completion of actions/rules/copies, if any.
    self.actions_stamp = None
    # Path to the output of the link step, if any.
    self.binary = None
    # Path to the file representing the completion of building the bundle,
    # if any.
    self.bundle = None
    # On Windows, incremental linking requires linking against all the .objs
    # that compose a .lib (rather than the .lib itself). That list is stored
    # here.
    self.component_objs = None
    # Windows/PS3 only. The import .lib is the output of a build step, but
    # because dependents only link against the lib (not both the lib and the
    # dll) we keep track of the import library here.
    # For PS3, this is the "stub" library.
    self.import_lib = None

  def Linkable(self):
    """Return true if this is a target that can be linked against."""
    return self.type in ('static_library', 'shared_library')

  def UsesToc(self, flavor):
    """Return true if the target should produce a restat rule based on a TOC
    file."""
    # For bundles, the .TOC should be produced for the binary, not for
    # FinalOutput(). But the naive approach would put the TOC file into the
    # bundle, so don't do this for bundles for now.
    if flavor in ['win', 'xb1', 'ps3', 'ps4'] or self.bundle:
      return False
    return self.type in ('shared_library', 'loadable_module')

  def PreActionInput(self, flavor):
    """Return the path, if any, that should be used as a dependency of
    any dependent action step."""
    if self.UsesToc(flavor):
      return self.FinalOutput() + '.TOC'
    return self.FinalOutput() or self.preaction_stamp

  def PreCompileInput(self):
    """Return the path, if any, that should be used as a dependency of
    any dependent compile step."""
    return self.actions_stamp or self.precompile_stamp

  def FinalOutput(self):
    """Return the last output of the target, which depends on all prior
    steps."""
    return self.bundle or self.binary or self.actions_stamp


# A small discourse on paths as used within the Ninja build:
# All files we produce (both at gyp and at build time) appear in the
# build directory (e.g. out/Debug).
#
# Paths within a given .gyp file are always relative to the directory
# containing the .gyp file.  Call these "gyp paths".  This includes
# sources as well as the starting directory a given gyp rule/action
# expects to be run from.  We call the path from the source root to
# the gyp file the "base directory" within the per-.gyp-file
# NinjaWriter code.
#
# All paths as written into the .ninja files are relative to the build
# directory.  Call these paths "ninja paths".
#
# We translate between these two notions of paths with two helper
# functions:
#
# - GypPathToNinja translates a gyp path (i.e. relative to the .gyp file)
#   into the equivalent ninja path.
#
# - GypPathToUniqueOutput translates a gyp path into a ninja path to write
#   an output file; the result can be namespaced such that it is unique
#   to the input file name as well as the output target name.

class NinjaWriter:
  def __init__(self, qualified_target, target_outputs, base_dir, build_dir,
               output_file, flavor, case_sensitive_filesystem,
               abs_build_dir=None):
    """
    base_dir: path from source root to directory containing this gyp file,
              by gyp semantics, all input paths are relative to this
    build_dir: path from source root to build output
    abs_build_dir: absolute path to the build directory
    """
    self.case_sensitive_filesystem = case_sensitive_filesystem
    self.qualified_target = qualified_target
    self.target_outputs = target_outputs
    self.base_dir = base_dir
    self.build_dir = build_dir
    self.abs_build_dir = abs_build_dir
    self.ninja = ninja_syntax.Writer(output_file)
    self.flavor = flavor
    self.path_module = os.path

    self.abs_build_dir = abs_build_dir
    self.obj_ext = '.obj' if flavor == 'win' else '.o'
    if flavor in ['win', 'ps3', 'xb1', 'ps4']:
      # See docstring of msvs_emulation.GenerateEnvironmentFiles().
      self.win_env = {}
      for arch in ('x86', 'x64'):
        self.win_env[arch] = 'environment.' + arch

    # Relative path from build output dir to base dir.
    self.build_to_base = os.path.join(InvertRelativePath(build_dir), base_dir)
    # Relative path from base dir to build dir.
    self.base_to_build = os.path.join(InvertRelativePath(base_dir), build_dir)

  def ExpandSpecial(self, path, product_dir=None):
    """Expand specials like $!PRODUCT_DIR in |path|.

    If |product_dir| is None, assumes the cwd is already the product
    dir.  Otherwise, |product_dir| is the relative path to the product
    dir.
    """

    PRODUCT_DIR = '$!PRODUCT_DIR'
    if PRODUCT_DIR in path:
      if product_dir:
        path = path.replace(PRODUCT_DIR, product_dir)
      else:
        path = path.replace(PRODUCT_DIR + '/', '')
        path = path.replace(PRODUCT_DIR + '\\', '')
        path = path.replace(PRODUCT_DIR, '.')

    INTERMEDIATE_DIR = '$!INTERMEDIATE_DIR'
    if INTERMEDIATE_DIR in path:
      int_dir = self.GypPathToUniqueOutput('gen')
      # GypPathToUniqueOutput generates a path relative to the product dir,
      # so insert product_dir in front if it is provided.
      path = path.replace(INTERMEDIATE_DIR,
                          os.path.join(product_dir or '', int_dir))

    CONFIGURATION_NAME = '$|CONFIGURATION_NAME'
    path = path.replace(CONFIGURATION_NAME, self.config_name)

    return path

  def ExpandRuleVariables(self, path, root, dirname, source, ext, name):
    if self.flavor == 'win':
      path = self.msvs_settings.ConvertVSMacros(
          path, config=self.config_name)
    path = path.replace(generator_default_variables['RULE_INPUT_ROOT'], root)
    path = path.replace(generator_default_variables['RULE_INPUT_DIRNAME'],
                        dirname)
    path = path.replace(generator_default_variables['RULE_INPUT_PATH'], source)
    path = path.replace(generator_default_variables['RULE_INPUT_EXT'], ext)
    path = path.replace(generator_default_variables['RULE_INPUT_NAME'], name)
    return path

  def GypPathCaseCorrection(self, path):
    # Ninja's depfile handling gets confused when the case of a filename
    # changes on a case-insensitive file system. To work around that, always
    # convert filenames to lowercase on such file systems. See
    # https://github.com/martine/ninja/issues/402 for details.
    if self.case_sensitive_filesystem:
      return path
    else:
      return path.lower()

  def GypPathToNinja(self, path, env=None):
    """Translate a gyp path to a ninja path, optionally expanding environment
    variable references in |path| with |env|.

    See the above discourse on path conversions."""
    if env:
      if self.flavor == 'mac':
        path = gyp.xcode_emulation.ExpandEnvVars(path, env)
      elif self.flavor in ['win', 'xb1']:
        path = gyp.msvs_emulation.ExpandMacros(path, env)
    if path.startswith('$!'):
      expanded = self.ExpandSpecial(path)
      if self.flavor == 'win':
        expanded = os.path.normpath(expanded)
      else:
        expanded = self.path_module.normpath(expanded)
      return self.GypPathCaseCorrection(expanded)
    if '$|' in path:
      path =  self.ExpandSpecial(path)
    assert '$' not in path, path

    # TODO: this needs a proper fix.
    is_absolute = path.startswith('C:') or path.startswith('c:') or path.startswith('/')
    if not is_absolute:
      path = self.path_module.normpath(os.path.join(self.build_to_base, path))

    return self.GypPathCaseCorrection(path)

  def GypPathToUniqueOutput(self, path, qualified=True):
    """Translate a gyp path to a ninja path for writing output.

    If qualified is True, qualify the resulting filename with the name
    of the target.  This is necessary when e.g. compiling the same
    path twice for two separate output targets.

    See the above discourse on path conversions."""

    path = self.ExpandSpecial(path)
    assert not path.startswith('$'), path

    # Translate the path following this scheme:
    #   Input: foo/bar.gyp, target targ, references baz/out.o
    #   Output: obj/foo/baz/targ.out.o (if qualified)
    #           obj/foo/baz/out.o (otherwise)
    #     (and obj.host instead of obj for cross-compiles)
    #
    # Why this scheme and not some other one?
    # 1) for a given input, you can compute all derived outputs by matching
    #    its path, even if the input is brought via a gyp file with '..'.
    # 2) simple files like libraries and stamps have a simple filename.

    obj = 'obj'
    if self.toolset != 'target':
      obj += '.' + self.toolset

    path_dir, path_basename = os.path.split(path)
    if qualified:
      path_basename = self.name + '.' + path_basename
    path = self.path_module.normpath(os.path.join(obj, self.base_dir, path_dir,
                                         path_basename))

    return self.GypPathCaseCorrection(path)

  def WriteCollapsedDependencies(self, name, targets):
    """Given a list of targets, return a path for a single file
    representing the result of building all the targets or None.

    Uses a stamp file if necessary."""

    assert targets == filter(None, targets), targets
    if len(targets) == 0:
      return None
    if len(targets) > 1:
      stamp = self.GypPathToUniqueOutput(name + '.stamp')
      targets = self.ninja.build(stamp, 'stamp', targets)
      self.ninja.newline()
    return targets[0]

  def WriteSpec(self, spec, config_name, generator_flags):
    """The main entry point for NinjaWriter: write the build rules for a spec.

    Returns a Target object, which represents the output paths for this spec.
    Returns None if there are no outputs (e.g. a settings-only 'none' type
    target)."""

    self.config_name = config_name
    self.name = spec['target_name']
    self.toolset = spec['toolset']
    config = spec['configurations'][config_name]
    self.target = Target(spec['type'])
    self.is_standalone_static_library = bool(
        spec.get('standalone_static_library', 0))

    self.is_mac_bundle = gyp.xcode_emulation.IsMacBundle(self.flavor, spec)
    self.xcode_settings = self.msvs_settings = None
    if self.flavor == 'mac':
      self.xcode_settings = gyp.xcode_emulation.XcodeSettings(spec)
    if (self.flavor in ['win', 'ps3', 'xb1', 'ps4']
        and is_windows):
      self.msvs_settings = gyp.msvs_emulation.MsvsSettings(spec,
                                                           generator_flags)
      arch = self.msvs_settings.GetArch(config_name)
      self.ninja.variable('arch', self.win_env[arch])

    # Compute predepends for all rules.
    # actions_depends is the dependencies this target depends on before running
    # any of its action/rule/copy steps.
    # compile_depends is the dependencies this target depends on before running
    # any of its compile steps.
    actions_depends = []
    compile_depends = []
    # TODO(evan): it is rather confusing which things are lists and which
    # are strings.  Fix these.
    if 'dependencies' in spec:
      for dep in spec['dependencies']:
        if dep in self.target_outputs:
          target = self.target_outputs[dep]
          actions_depends.append(target.PreActionInput(self.flavor))
          compile_depends.append(target.PreCompileInput())
      actions_depends = filter(None, actions_depends)
      compile_depends = filter(None, compile_depends)
      actions_depends = self.WriteCollapsedDependencies('actions_depends',
                                                        actions_depends)
      compile_depends = self.WriteCollapsedDependencies('compile_depends',
                                                        compile_depends)
      self.target.preaction_stamp = actions_depends
      self.target.precompile_stamp = compile_depends

    # Write out actions, rules, and copies.  These must happen before we
    # compile any sources, so compute a list of predependencies for sources
    # while we do it.
    extra_sources = []
    mac_bundle_depends = []
    self.target.actions_stamp = self.WriteActionsRulesCopies(
        spec, extra_sources, actions_depends, mac_bundle_depends)

    # If we have actions/rules/copies, we depend directly on those, but
    # otherwise we depend on dependent target's actions/rules/copies etc.
    # We never need to explicitly depend on previous target's link steps,
    # because no compile ever depends on them.
    compile_depends_stamp = (self.target.actions_stamp or compile_depends)

    # Write out the compilation steps, if any.
    link_deps = []
    sources = spec.get('sources', []) + extra_sources
    if sources:
      pch = None
      if self.flavor in ['win', 'xb1']:
        gyp.msvs_emulation.VerifyMissingSources(
            sources, self.abs_build_dir, generator_flags, self.GypPathToNinja)
        pch = gyp.msvs_emulation.PrecompiledHeader(
            self.msvs_settings, config_name, self.GypPathToNinja,
            self.GypPathToUniqueOutput, self.obj_ext)
      else:
        pch = gyp.xcode_emulation.MacPrefixHeader(
            self.xcode_settings, self.GypPathToNinja,
            lambda path, lang: self.GypPathToUniqueOutput(path + '-' + lang))
      link_deps = self.WriteSources(
          config_name, config, sources, compile_depends_stamp, pch, spec)
      # Some actions/rules output 'sources' that are already object files.
      link_deps += [self.GypPathToNinja(f)
          for f in sources if f.endswith(self.obj_ext)]

    if self.flavor in ['win', 'xb1'] and self.target.type == 'static_library':
      self.target.component_objs = link_deps

    # Write out a link step, if needed.
    output = None
    if link_deps or self.target.actions_stamp or actions_depends:
      output = self.WriteTarget(spec, config_name, config, link_deps,
                                self.target.actions_stamp or actions_depends)
      if self.is_mac_bundle:
        mac_bundle_depends.append(output)

    # Bundle all of the above together, if needed.
    if self.is_mac_bundle:
      output = self.WriteMacBundle(spec, mac_bundle_depends)

    if not output:
      return None

    assert self.target.FinalOutput(), output
    return self.target

  def _WinIdlRule(self, source, prebuild, outputs):
    """Handle the implicit VS .idl rule for one source file. Fills |outputs|
    with files that are generated."""
    outdir, output, vars, flags = self.msvs_settings.GetIdlBuildData(
        source, self.config_name)
    outdir = self.GypPathToNinja(outdir)
    def fix_path(path, rel=None):
      path = os.path.join(outdir, path)
      dirname, basename = os.path.split(source)
      root, ext = os.path.splitext(basename)
      path = self.ExpandRuleVariables(
          path, root, dirname, source, ext, basename)
      if rel:
        path = os.path.relpath(path, rel)
      return path
    vars = [(name, fix_path(value, outdir)) for name, value in vars]
    output = [fix_path(p) for p in output]
    vars.append(('outdir', outdir))
    vars.append(('idlflags', flags))
    input = self.GypPathToNinja(source)
    self.ninja.build(output, 'idl', input,
        variables=vars, order_only=prebuild)
    outputs.extend(output)

  def WriteWinIdlFiles(self, spec, prebuild):
    """Writes rules to match MSVS's implicit idl handling."""
    assert self.flavor in ('win', 'xb1')
    if self.msvs_settings.HasExplicitIdlRules(spec):
      return []
    outputs = []
    for source in filter(lambda x: x.endswith('.idl'), spec['sources']):
      self._WinIdlRule(source, prebuild, outputs)
    return outputs

  def WriteActionsRulesCopies(self, spec, extra_sources, prebuild,
                              mac_bundle_depends):
    """Write out the Actions, Rules, and Copies steps.  Return a path
    representing the outputs of these steps."""
    outputs = []
    extra_mac_bundle_resources = []

    if 'actions' in spec:
      outputs += self.WriteActions(spec['actions'], extra_sources, prebuild,
                                   extra_mac_bundle_resources)
    if 'rules' in spec:
      outputs += self.WriteRules(spec['rules'], extra_sources, prebuild,
                                 extra_mac_bundle_resources)
    if 'copies' in spec:
      outputs += self.WriteCopies(spec['copies'], prebuild, mac_bundle_depends)

    if 'sources' in spec and self.flavor in ('win', 'xb1'):
      outputs += self.WriteWinIdlFiles(spec, prebuild)

    stamp = self.WriteCollapsedDependencies('actions_rules_copies', outputs)

    if self.is_mac_bundle:
      mac_bundle_resources = spec.get('mac_bundle_resources', []) + \
                             extra_mac_bundle_resources
      self.WriteMacBundleResources(mac_bundle_resources, mac_bundle_depends)
      self.WriteMacInfoPlist(mac_bundle_depends)

    return stamp

  def GenerateDescription(self, verb, message, fallback):
    """Generate and return a description of a build step.

    |verb| is the short summary, e.g. ACTION or RULE.
    |message| is a hand-written description, or None if not available.
    |fallback| is the gyp-level name of the step, usable as a fallback.
    """
    if self.toolset != 'target':
      verb += '(%s)' % self.toolset
    if message:
      return '%s %s' % (verb, self.ExpandSpecial(message))
    else:
      return '%s %s: %s' % (verb, self.name, fallback)

  def IsCygwinRule(self, action):
    if self.flavor in ['ps3', 'ps4']:
      return str(action.get('msvs_cygwin_shell', 1)) != '0'
    return False

  def WriteActions(self, actions, extra_sources, prebuild,
                   extra_mac_bundle_resources):
    # Actions cd into the base directory.
    env = self.GetSortedXcodeEnv()
    if self.flavor == 'win':
      env = self.msvs_settings.GetVSMacroEnv(
          '$!PRODUCT_DIR', config=self.config_name)
    all_outputs = []
    for action in actions:
      # First write out a rule for the action.
      name = '%s_%s' % (action['action_name'],
                        hashlib.md5(self.qualified_target).hexdigest())
      description = self.GenerateDescription('ACTION',
                                             action.get('message', None),
                                             name)
      is_cygwin = self.IsCygwinRule(action)
      args = action['action']
      rule_name, _ = self.WriteNewNinjaRule(name, args, description,
                                            is_cygwin, env=env)

      inputs = [self.GypPathToNinja(i, env) for i in action['inputs']]
      if int(action.get('process_outputs_as_sources', False)):
        extra_sources += action['outputs']
      if int(action.get('process_outputs_as_mac_bundle_resources', False)):
        extra_mac_bundle_resources += action['outputs']
      outputs = [self.GypPathToNinja(o, env) for o in action['outputs']]

      # Then write out an edge using the rule.
      self.ninja.build(outputs, rule_name, inputs,
                       order_only=prebuild)
      all_outputs += outputs

      self.ninja.newline()

    return all_outputs

  def WriteRules(self, rules, extra_sources, prebuild,
                 extra_mac_bundle_resources):
    env = self.GetSortedXcodeEnv()
    all_outputs = []
    for rule in rules:
      # First write out a rule for the rule action.
      name = '%s_%s' % (rule['rule_name'],
                        hashlib.md5(self.qualified_target).hexdigest())
      # Skip a rule with no action and no inputs.
      if 'action' not in rule and not rule.get('rule_sources', []):
        continue
      args = rule['action']
      description = self.GenerateDescription(
          'RULE',
          rule.get('message', None),
          ('%s ' + generator_default_variables['RULE_INPUT_PATH']) % name)
      is_cygwin = self.IsCygwinRule(rule)
      rule_name, args = self.WriteNewNinjaRule(
          name, args, description, is_cygwin, env=env)

      # TODO: if the command references the outputs directly, we should
      # simplify it to just use $out.

      # Rules can potentially make use of some special variables which
      # must vary per source file.
      # Compute the list of variables we'll need to provide.
      special_locals = ('source', 'root', 'dirname', 'ext', 'name')
      needed_variables = set(['source'])
      for argument in args:
        for var in special_locals:
          if ('${%s}' % var) in argument:
            needed_variables.add(var)

      def cygwin_munge(path):
        if is_cygwin:
          return path.replace('\\', '/')
        return path

      # For each source file, write an edge that generates all the outputs.
      for source in rule.get('rule_sources', []):
        dirname, basename = os.path.split(source)
        root, ext = os.path.splitext(basename)

        # Gather the list of inputs and outputs, expanding $vars if possible.
        outputs = [self.ExpandRuleVariables(o, root, dirname,
                                            source, ext, basename)
                   for o in rule['outputs']]
        inputs = [self.ExpandRuleVariables(i, root, dirname,
                                           source, ext, basename)
                  for i in rule.get('inputs', [])]

        if int(rule.get('process_outputs_as_sources', False)):
          extra_sources += outputs
        if int(rule.get('process_outputs_as_mac_bundle_resources', False)):
          extra_mac_bundle_resources += outputs

        extra_bindings = []
        for var in needed_variables:
          if var == 'root':
            extra_bindings.append(('root', cygwin_munge(root)))
          elif var == 'dirname':
            extra_bindings.append(('dirname', cygwin_munge(dirname)))
          elif var == 'source':
            # '$source' is a parameter to the rule action, which means
            # it shouldn't be converted to a Ninja path.  But we don't
            # want $!PRODUCT_DIR in there either.
            source_expanded = self.ExpandSpecial(source, self.base_to_build)
            extra_bindings.append(('source', cygwin_munge(source_expanded)))
          elif var == 'ext':
            extra_bindings.append(('ext', ext))
          elif var == 'name':
            extra_bindings.append(('name', cygwin_munge(basename)))
          else:
            assert var == None, repr(var)

        inputs = [self.GypPathToNinja(i, env) for i in inputs]
        outputs = [self.GypPathToNinja(o, env) for o in outputs]
        extra_bindings.append(('unique_name',
            hashlib.md5(outputs[0]).hexdigest()))
        self.ninja.build(outputs, rule_name, self.GypPathToNinja(source),
                         implicit=inputs,
                         order_only=prebuild,
                         variables=extra_bindings)

        all_outputs.extend(outputs)

    return all_outputs

  def WriteCopy(self, src, dst, prebuild, env, mac_bundle_depends):
    dst = self.GypPathToNinja(dst, env)
    # Renormalize with the separator character of the os on which ninja will run
    dst = self.path_module.normpath(dst)

    output = self.ninja.build(dst, 'copy', src, order_only=prebuild)
    if self.is_mac_bundle:
      # gyp has mac_bundle_resources to copy things into a bundle's
      # Resources folder, but there's no built-in way to copy files to other
      # places in the bundle. Hence, some targets use copies for this. Check
      # if this file is copied into the current bundle, and if so add it to
      # the bundle depends so that dependent targets get rebuilt if the copy
      # input changes.
      if dst.startswith(self.xcode_settings.GetBundleContentsFolderPath()):
        mac_bundle_depends.append(dst)
    return output

  def WriteCopies(self, copies, prebuild, mac_bundle_depends):
    outputs = []
    env = self.GetSortedXcodeEnv()
    for copy in copies:
      for path in copy['files']:
        # Normalize the path so trailing slashes don't confuse us.
        path = os.path.normpath(path)
        destination = copy['destination']
        basename = os.path.split(path)[1]

        # call GypPathToNinja() to resolve any special GYP $ tokens in src.
        # And figure out where this directory actually is on disk.
        ninja_path = self.GypPathToNinja(path)
        joined_path = os.path.join(self.abs_build_dir, ninja_path)
        joined_path = os.path.normpath(joined_path)

        # If src is a directory, expand it recursively,
        # so we have a build rule for every file.
        if os.path.isdir(joined_path):
          for root, dirs, files in os.walk(joined_path):
            rel_root = os.path.relpath(root, self.abs_build_dir)

            for f in files:
              src = self.GypPathToNinja(os.path.join(rel_root, f), env)
              common_prefix = os.path.commonprefix([joined_path, root])
              subdir = root[len(common_prefix)+1:]

              dst = os.path.join(destination, basename, subdir, f)
              outputs += self.WriteCopy(src, dst,
                prebuild, env, mac_bundle_depends)
        else:
          src = self.GypPathToNinja(path, env)
          dst = os.path.join(destination, basename)
          outputs += self.WriteCopy(src, dst,
            prebuild, env, mac_bundle_depends)

    return outputs

  def WriteMacBundleResources(self, resources, bundle_depends):
    """Writes ninja edges for 'mac_bundle_resources'."""
    for output, res in gyp.xcode_emulation.GetMacBundleResources(
        self.ExpandSpecial(generator_default_variables['PRODUCT_DIR']),
        self.xcode_settings, map(self.GypPathToNinja, resources)):
      self.ninja.build(output, 'mac_tool', res,
                       variables=[('mactool_cmd', 'copy-bundle-resource')])
      bundle_depends.append(output)

  def WriteMacInfoPlist(self, bundle_depends):
    """Write build rules for bundle Info.plist files."""
    info_plist, out, defines, extra_env = gyp.xcode_emulation.GetMacInfoPlist(
        self.ExpandSpecial(generator_default_variables['PRODUCT_DIR']),
        self.xcode_settings, self.GypPathToNinja)
    if not info_plist:
      return
    if defines:
      # Create an intermediate file to store preprocessed results.
      intermediate_plist = self.GypPathToUniqueOutput(
          os.path.basename(info_plist))
      defines = ' '.join([Define(d, self.flavor) for d in defines])
      info_plist = self.ninja.build(intermediate_plist, 'infoplist', info_plist,
                                    variables=[('defines',defines)])

    env = self.GetSortedXcodeEnv(additional_settings=extra_env)
    env = self.ComputeExportEnvString(env)

    self.ninja.build(out, 'mac_tool', info_plist,
                     variables=[('mactool_cmd', 'copy-info-plist'),
                                ('env', env)])
    bundle_depends.append(out)

  def WriteSources(self, config_name, config, sources, predepends,
                   precompiled_header, spec):
    """Write build rules to compile all of |sources|."""
    if self.toolset == 'host':
      self.ninja.variable('ar', '$ar_host')
      self.ninja.variable('cc', '$cc_host')
      self.ninja.variable('cxx', '$cxx_host')
      self.ninja.variable('ld', '$ld_host')

    extra_defines = []
    if self.flavor == 'mac':
      cflags = self.xcode_settings.GetCflags(config_name)
      cflags_c = self.xcode_settings.GetCflagsC(config_name)
      cflags_cc = self.xcode_settings.GetCflagsCC(config_name)
      cflags_objc = ['$cflags_c'] + \
                    self.xcode_settings.GetCflagsObjC(config_name)
      cflags_objcc = ['$cflags_cc'] + \
                     self.xcode_settings.GetCflagsObjCC(config_name)
    elif self.flavor in ['win', 'xb1']:
      cflags = self.msvs_settings.GetCflags(config_name)
      cflags_c = self.msvs_settings.GetCflagsC(config_name)
      cflags_cc = self.msvs_settings.GetCflagsCC(config_name)
      extra_defines = self.msvs_settings.GetComputedDefines(config_name)
      obj = 'obj'
      if self.toolset != 'target':
        obj += '.' + self.toolset
      pdbpath = os.path.normpath(os.path.join(obj, self.base_dir,
                                              self.name + '.pdb'))
      self.WriteVariableList('pdbname', [pdbpath])
      self.WriteVariableList('pchprefix', [self.name])
    else:
      cflags = config.get('cflags', [])
      cflags_c = config.get('cflags_c', [])
      cflags_cc = config.get('cflags_cc', [])

    cflags_host = config.get('cflags_host', cflags)
    cflags_c_host = config.get('cflags_c_host', cflags_c)
    cflags_cc_host = config.get('cflags_cc_host', cflags_cc)

    defines = config.get('defines', []) + extra_defines
    self.WriteVariableList('defines', [Define(d, self.flavor) for d in defines])
    if self.flavor in ['win', 'xb1']:
      self.WriteVariableList('rcflags',
          [QuoteShellArgument(self.ExpandSpecial(f), self.flavor)
           for f in self.msvs_settings.GetRcflags(config_name,
                                                  self.GypPathToNinja)])

    include_dirs = config.get('include_dirs', [])
    include_dirs += config.get('include_dirs_' + self.toolset, [])

    if self.flavor in ['win', 'xb1']:
      include_dirs = self.msvs_settings.AdjustIncludeDirs(include_dirs,
                                                          config_name)
      self.WriteVariableList('includes',
        ['/I' + gyp.msvs_emulation.QuoteForRspFile(self.GypPathToNinja(i))
         for i in include_dirs])
    else:
      self.WriteVariableList('includes',
          [QuoteShellArgument('-I' + self.GypPathToNinja(i), self.flavor)
           for i in include_dirs])

    pch_commands = precompiled_header.GetPchBuildCommands()
    if self.flavor == 'mac':
      self.WriteVariableList('cflags_pch_c',
                             [precompiled_header.GetInclude('c')])
      self.WriteVariableList('cflags_pch_cc',
                             [precompiled_header.GetInclude('cc')])
      self.WriteVariableList('cflags_pch_objc',
                             [precompiled_header.GetInclude('m')])
      self.WriteVariableList('cflags_pch_objcc',
                             [precompiled_header.GetInclude('mm')])

    self.WriteVariableList('cflags', map(self.ExpandSpecial, cflags))
    self.WriteVariableList('cflags_c', map(self.ExpandSpecial, cflags_c))
    self.WriteVariableList('cflags_cc', map(self.ExpandSpecial, cflags_cc))

    self.WriteVariableList('cflags_host', map(self.ExpandSpecial, cflags_host))
    self.WriteVariableList('cflags_c_host', map(self.ExpandSpecial, cflags_c_host))
    self.WriteVariableList('cflags_cc_host', map(self.ExpandSpecial, cflags_cc_host))

    if self.flavor == 'mac':
      self.WriteVariableList('cflags_objc', map(self.ExpandSpecial,
                                                cflags_objc))
      self.WriteVariableList('cflags_objcc', map(self.ExpandSpecial,
                                                 cflags_objcc))
    self.ninja.newline()
    outputs = []
    for source in sources:
      filename, ext = os.path.splitext(source)
      ext = ext[1:]
      obj_ext = self.obj_ext
      if ext in ('cc', 'cpp', 'cxx'):
        command = 'cxx'
      elif ext == 'c' or (ext == 'S' and self.flavor != 'win'):
        command = 'cc'
      elif ext == 's' and self.flavor != 'win':  # Doesn't generate .o.d files.
        command = 'cc_s'
      elif (self.flavor == 'win' and ext == 'asm' and
            self.msvs_settings.GetArch(config_name) == 'x86' and
            not self.msvs_settings.HasExplicitAsmRules(spec)):
        # Asm files only get auto assembled for x86 (not x64).
        command = 'asm'
        # Add the _asm suffix as msvs is capable of handling .cc and
        # .asm files of the same name without collision.
        obj_ext = '_asm.obj'
      elif self.flavor == 'mac' and ext == 'm':
        command = 'objc'
      elif self.flavor == 'mac' and ext == 'mm':
        command = 'objcxx'
      elif self.flavor in ['win', 'xb1'] and ext == 'rc':
        command = 'rc'
        obj_ext = '.res'
      else:
        # Ignore unhandled extensions.
        continue
      if self.toolset != 'target':
        command += '_' + self.toolset

      input = self.GypPathToNinja(source)
      output = self.GypPathToUniqueOutput(filename + obj_ext)
      implicit = precompiled_header.GetObjDependencies([input], [output])
      variables = []
      if self.flavor in ['win', 'xb1']:
        variables, output, implicit = precompiled_header.GetFlagsModifications(
            input, output, implicit, command, cflags_c, cflags_cc,
            self.ExpandSpecial)
      self.ninja.build(output, command, input,
                       implicit=[gch for _, _, gch in implicit],
                       order_only=predepends, variables=variables)
      outputs.append(output)

    self.WritePchTargets(pch_commands)

    self.ninja.newline()
    return outputs

  def WritePchTargets(self, pch_commands):
    """Writes ninja rules to compile prefix headers."""
    if not pch_commands:
      return

    for gch, lang_flag, lang, input in pch_commands:
      var_name = {
        'c': 'cflags_pch_c',
        'cc': 'cflags_pch_cc',
        'm': 'cflags_pch_objc',
        'mm': 'cflags_pch_objcc',
      }[lang]

      map = { 'c': 'cc', 'cc': 'cxx', 'm': 'objc', 'mm': 'objcxx', }
      cmd = map.get(lang)
      self.ninja.build(gch, cmd, input, variables=[(var_name, lang_flag)])

  def WriteLink(self, spec, config_name, config, link_deps):
    """Write out a link step. Fills out target.binary. """

    command = {
      'executable':      'link',
      'loadable_module': 'solink_module',
      'shared_library':  'solink',
    }[spec['type']]

    implicit_deps = set()
    order_only_deps = set()
    solibs = set()

    if 'dependencies' in spec:
      # Two kinds of dependencies:
      # - Linkable dependencies (like a .a or a .so): add them to the link line.
      # - Non-linkable dependencies (like a rule that generates a file
      #   and writes a stamp file): add them to implicit_deps or order_only_deps
      extra_link_deps = []
      for dep in spec['dependencies']:
        target = self.target_outputs.get(dep)
        if not target:
          continue
        linkable = target.Linkable()
        if linkable:
          if (self.flavor in ['win', 'xb1'] and target.component_objs and
              self.msvs_settings.IsUseLibraryDependencyInputs(config_name)):
            extra_link_deps.extend(target.component_objs)
          elif (self.flavor in ['win', 'xb1', 'ps3'] and
                target.import_lib):
            extra_link_deps.append(target.import_lib)
          elif target.UsesToc(self.flavor):
            solibs.add(target.binary)
            implicit_deps.add(target.binary + '.TOC')
          else:
            extra_link_deps.append(target.binary)

        final_output = target.FinalOutput()
        if not linkable or final_output != target.binary:
          order_only_deps.add(final_output)

      # dedup the extra link deps while preserving order
      seen = set()
      extra_link_deps = [ x for x in extra_link_deps if x not in seen and not seen.add(x) ]

      link_deps.extend(extra_link_deps)

    extra_bindings = []
    if self.is_mac_bundle:
      output = self.ComputeMacBundleBinaryOutput()
    else:
      output = self.ComputeOutput(spec)
      extra_bindings.append(('postbuilds',
                             self.GetPostbuildCommand(spec, output, output)))

    if self.flavor == 'mac':
      ldflags = self.xcode_settings.GetLdflags(config_name,
          self.ExpandSpecial(generator_default_variables['PRODUCT_DIR']),
          self.GypPathToNinja)
    elif self.flavor in ['win', 'xb1']:
      libflags = self.msvs_settings.GetLibFlags(config_name,
                                                self.GypPathToNinja)
      self.WriteVariableList(
          'libflags', gyp.common.uniquer(map(self.ExpandSpecial, libflags)))
      is_executable = spec['type'] == 'executable'
      manifest_name = self.GypPathToUniqueOutput(
          self.ComputeOutputFileName(spec))
      ldflags, manifest_files = self.msvs_settings.GetLdflags(config_name,
          self.GypPathToNinja, self.ExpandSpecial, manifest_name, is_executable)
      self.WriteVariableList('manifests', manifest_files)
    else:
      ldflags = config.get('ldflags', [])
      ldflags_host = config.get('ldflags_host', ldflags)

    self.WriteVariableList('ldflags',
                           gyp.common.uniquer(map(self.ExpandSpecial,
                                                  ldflags)))
    if ('ldflags_host' in locals()):
      self.WriteVariableList('ldflags_host',
                             gyp.common.uniquer(map(self.ExpandSpecial,
                                                    ldflags_host)))

    if self.toolset == 'host':
      libs = spec.get('libraries_host', [])
      libs.extend(config.get('libraries_host', []))
    else:
      libs = spec.get('libraries', [])
      libs.extend(config.get('libraries', []))

    libraries = gyp.common.uniquer(map(self.ExpandSpecial, libs))

    if self.flavor == 'mac':
      libraries = self.xcode_settings.AdjustLibraries(libraries)
    elif self.flavor in ['win', 'xb1']:
      libraries = self.msvs_settings.AdjustLibraries(libraries)
    self.WriteVariableList('libs', libraries)

    self.target.binary = output

    if command in ('solink', 'solink_module'):
      extra_bindings.append(('soname', os.path.split(output)[1]))
      extra_bindings.append(('lib',
                            gyp.common.EncodePOSIXShellArgument(output)))
      if self.flavor in ['win', 'xb1']:
        extra_bindings.append(('dll', output))
        if '/NOENTRY' not in ldflags:
          self.target.import_lib = output + '.lib'
          extra_bindings.append(('implibflag',
                                 '/IMPLIB:%s' % self.target.import_lib))
          output = [output, self.target.import_lib]
      elif self.flavor in ['ps3']:
        # Tell Ninja we'll be generating a .sprx and a stub library.
        # Bind the variable '$prx' to our output binary so we can
        # refer to it in the linker rules.
        prx_output = output
        prx_output_base, prx_output_ext = os.path.splitext(prx_output)
        assert prx_output_ext == '.sprx'

        extra_bindings.append(('prx', output))
        # TODO: Figure out how to suppress the "removal" warning
        # generated from the prx generator when we remove a function.
        # For now, we'll just delete the 'verlog.txt' file before linking.
        # Bind it here so we can refer to it as $verlog in the PS3 solink rule.
        verlog = output.replace(prx_output_ext, '_verlog.txt')
        extra_bindings.append(('verlog', verlog))
        self.target.import_lib = output.replace(prx_output_ext, '_stub.a')
        output = [prx_output, self.target.import_lib]

        # For PRXs, we need to convert any c++ exports into C. This is done
        # with an "export pickup" step that runs over the object files
        # and produces a new .c file. That .c file should be compiled and linked
        # into the PRX.
        gen_files_dir = os.path.join(self.ExpandSpecial(
            generator_default_variables['SHARED_INTERMEDIATE_DIR']), 'prx')

        export_pickup_output = os.path.join(
            gen_files_dir, os.path.basename(prx_output_base) + '.prx_export.c')
        prx_export_obj_file = export_pickup_output[:-2] + '.o'
        self.ninja.build(export_pickup_output,
                         'prx_export_pickup',
                         link_deps,
                         implicit=list(implicit_deps),
                         order_only=list(order_only_deps))

        self.ninja.build(prx_export_obj_file, 'cc', export_pickup_output)
        link_deps.append(prx_export_obj_file)

      else:
        output = [output, output + '.TOC']

    if len(solibs):
      extra_bindings.append(('solibs', gyp.common.EncodePOSIXShellList(solibs)))

    if self.toolset != 'target':
      command += '_' + self.toolset

    self.ninja.build(output, command, link_deps,
                     implicit=list(implicit_deps),
                     order_only=list(order_only_deps),
                     variables=extra_bindings)

  def WriteTarget(self, spec, config_name, config, link_deps, compile_deps):
    if spec['type'] == 'none':
      # TODO(evan): don't call this function for 'none' target types, as
      # it doesn't do anything, and we fake out a 'binary' with a stamp file.
      self.target.binary = compile_deps
    elif spec['type'] == 'static_library':
      self.target.binary = self.ComputeOutput(spec)
      variables = []
      if self.flavor in ('win', 'xb1'):
        libflags = self.msvs_settings.GetLibFlags(config_name,
                                                  self.GypPathToNinja)
        variables.append(('libflags', ' '.join(libflags)))
      postbuild = self.GetPostbuildCommand(
          spec, self.target.binary, self.target.binary)
      if postbuild:
        variables.append(('postbuilds', postbuild))
      if self.xcode_settings:
        variables.append(('libtool_flags',
                          self.xcode_settings.GetLibtoolflags(config_name)))
      if (self.flavor not in ('mac', 'win', 'xb1') and not
          self.is_standalone_static_library):
        command = 'alink_thin'
      else:
        command = 'alink'
      if self.toolset != 'target':
        command += '_' + self.toolset
      self.ninja.build(self.target.binary, command, link_deps,
                       order_only=compile_deps, variables=variables)
    else:
      self.WriteLink(spec, config_name, config, link_deps)
    return self.target.binary

  def WriteMacBundle(self, spec, mac_bundle_depends):
    assert self.is_mac_bundle
    package_framework = spec['type'] in ('shared_library', 'loadable_module')
    output = self.ComputeMacBundleOutput()
    postbuild = self.GetPostbuildCommand(spec, output, self.target.binary,
                                         is_command_start=not package_framework)
    variables = []
    if postbuild:
      variables.append(('postbuilds', postbuild))
    if package_framework:
      variables.append(('version', self.xcode_settings.GetFrameworkVersion()))
      self.ninja.build(output, 'package_framework', mac_bundle_depends,
                       variables=variables)
    else:
      self.ninja.build(output, 'stamp', mac_bundle_depends,
                       variables=variables)
    self.target.bundle = output
    return output

  def GetSortedXcodeEnv(self, additional_settings=None):
    """Returns the variables Xcode would set for build steps."""
    assert self.abs_build_dir
    abs_build_dir = self.abs_build_dir
    return gyp.xcode_emulation.GetSortedXcodeEnv(
        self.xcode_settings, abs_build_dir,
        os.path.join(abs_build_dir, self.build_to_base), self.config_name,
        additional_settings)

  def GetSortedXcodePostbuildEnv(self):
    """Returns the variables Xcode would set for postbuild steps."""
    postbuild_settings = {}
    # CHROMIUM_STRIP_SAVE_FILE is a chromium-specific hack.
    # TODO(thakis): It would be nice to have some general mechanism instead.
    strip_save_file = self.xcode_settings.GetPerTargetSetting(
        'CHROMIUM_STRIP_SAVE_FILE')
    if strip_save_file:
      postbuild_settings['CHROMIUM_STRIP_SAVE_FILE'] = strip_save_file
    return self.GetSortedXcodeEnv(additional_settings=postbuild_settings)

  def GetPostbuildCommand(self, spec, output, output_binary,
                          is_command_start=False):
    """Returns a shell command that runs all the postbuilds, and removes
    |output| if any of them fails. If |is_command_start| is False, then the
    returned string will start with ' && '."""
    if not self.xcode_settings or spec['type'] == 'none' or not output:
      return ''
    output = QuoteShellArgument(output, self.flavor)
    target_postbuilds = self.xcode_settings.GetTargetPostbuilds(
        self.config_name,
        os.path.normpath(os.path.join(self.base_to_build, output)),
        QuoteShellArgument(
            os.path.normpath(os.path.join(self.base_to_build, output_binary)),
            self.flavor),
        quiet=True)
    postbuilds = gyp.xcode_emulation.GetSpecPostbuildCommands(spec, quiet=True)
    postbuilds = target_postbuilds + postbuilds
    if not postbuilds:
      return ''
    # Postbuilds expect to be run in the gyp file's directory, so insert an
    # implicit postbuild to cd to there.
    postbuilds.insert(0, gyp.common.EncodePOSIXShellList(
        ['cd', self.build_to_base]))
    env = self.ComputeExportEnvString(self.GetSortedXcodePostbuildEnv())
    # G will be non-null if any postbuild fails. Run all postbuilds in a
    # subshell.
    commands = env + ' (F=0; ' + \
        ' '.join([ninja_syntax.escape(command) + ' || F=$$?;'
                                 for command in postbuilds])
    command_string = (commands + ' exit $$F); G=$$?; '
                      # Remove the final output if any postbuild failed.
                      '((exit $$G) || rm -rf %s) ' % output + '&& exit $$G)')
    if is_command_start:
      return '(' + command_string + ' && '
    else:
      return '$ && (' + command_string

  def ComputeExportEnvString(self, env):
    """Given an environment, returns a string looking like
        'export FOO=foo; export BAR="${FOO} bar;'
    that exports |env| to the shell."""
    export_str = []
    for k, v in env:
      export_str.append('export %s=%s;' %
          (k, ninja_syntax.escape(gyp.common.EncodePOSIXShellArgument(v))))
    return ' '.join(export_str)

  def ComputeMacBundleOutput(self):
    """Return the 'output' (full output path) to a bundle output directory."""
    assert self.is_mac_bundle
    path = self.ExpandSpecial(generator_default_variables['PRODUCT_DIR'])
    return os.path.join(path, self.xcode_settings.GetWrapperName())

  def ComputeMacBundleBinaryOutput(self):
    """Return the 'output' (full output path) to the binary in a bundle."""
    assert self.is_mac_bundle
    path = self.ExpandSpecial(generator_default_variables['PRODUCT_DIR'])
    return os.path.join(path, self.xcode_settings.GetExecutablePath())

  def ComputeOutputFileName(self, spec, type=None):
    """Compute the filename of the final output for the current target."""
    if not type:
      type = spec['type']

    default_variables = copy.copy(generator_default_variables)
    CalculateVariables(default_variables, {'flavor': self.flavor})

    # Compute filename prefix: the product prefix, or a default for
    # the product type.
    DEFAULT_PREFIX = {
      'loadable_module': default_variables['SHARED_LIB_PREFIX'],
      'shared_library': default_variables['SHARED_LIB_PREFIX'],
      'static_library': default_variables['STATIC_LIB_PREFIX'],
      'executable': default_variables['EXECUTABLE_PREFIX'],
      }
    prefix = spec.get('product_prefix', DEFAULT_PREFIX.get(type, ''))

    # Compute filename extension: the product extension, or a default
    # for the product type.
    DEFAULT_EXTENSION = {
        'loadable_module': default_variables['SHARED_LIB_SUFFIX'],
        'shared_library': default_variables['SHARED_LIB_SUFFIX'],
        'static_library': default_variables['STATIC_LIB_SUFFIX'],
        'executable': default_variables['EXECUTABLE_SUFFIX'],
      }
    extension = spec.get('product_extension')
    if extension:
      extension = '.' + extension
    elif self.toolset == 'host':
      if is_linux:
        extension = ''
      elif is_windows:
        extension = '.exe'
    else:
      extension = DEFAULT_EXTENSION.get(type, '')

    if 'product_name' in spec:
      # If we were given an explicit name, use that.
      target = spec['product_name']
    else:
      # Otherwise, derive a name from the target name.
      target = spec['target_name']
      if prefix == 'lib':
        # Snip out an extra 'lib' from libs if appropriate.
        target = StripPrefix(target, 'lib')

    if type in ('static_library', 'loadable_module', 'shared_library',
                        'executable'):
      return '%s%s%s' % (prefix, target, extension)
    elif type == 'none':
      return '%s.stamp' % target
    else:
      raise Exception('Unhandled output type %s' % type)

  def ComputeOutput(self, spec, type=None):
    """Compute the path for the final output of the spec."""
    assert not self.is_mac_bundle or type

    if not type:
      type = spec['type']

    if self.flavor == 'win':
      override = self.msvs_settings.GetOutputName(self.config_name,
                                                  self.ExpandSpecial)
      if override:
        return override

    if self.flavor == 'mac' and type in (
        'static_library', 'executable', 'shared_library', 'loadable_module'):
      filename = self.xcode_settings.GetExecutablePath()
    else:
      filename = self.ComputeOutputFileName(spec, type)

    if 'product_dir' in spec:
      path = os.path.join(spec['product_dir'], filename)
      return self.ExpandSpecial(path)

    # Some products go into the output root, libraries go into shared library
    # dir, and everything else goes into the normal place.
    type_in_output_root = ['executable', 'loadable_module']
    if self.flavor == 'mac' and self.toolset == 'target':
      type_in_output_root += ['shared_library', 'static_library']
    elif self.flavor in ['win', 'ps3'] and self.toolset == 'target':
      type_in_output_root += ['shared_library']

    if type in type_in_output_root or self.is_standalone_static_library:
      return filename
    elif type == 'shared_library':
      libdir = 'lib'
      if self.toolset != 'target':
        libdir = os.path.join('lib', '%s' % self.toolset)
      return os.path.join(libdir, filename)
    else:
      return self.GypPathToUniqueOutput(filename, qualified=False)

  def WriteVariableList(self, var, values):
    assert not isinstance(values, str)
    if values is None:
      values = []
    self.ninja.variable(var, ' '.join(values))

  def WriteNewNinjaRule(self, name, args, description, is_cygwin, env):
    """Write out a new ninja "rule" statement for a given command.

    Returns the name of the new rule, and a copy of |args| with variables
    expanded."""

    if self.flavor == 'win':
      args = [self.msvs_settings.ConvertVSMacros(
                  arg, self.base_to_build, config=self.config_name)
              for arg in args]
      description = self.msvs_settings.ConvertVSMacros(
          description, config=self.config_name)
    elif self.flavor == 'mac':
      # |env| is an empty list on non-mac.
      args = [gyp.xcode_emulation.ExpandEnvVars(arg, env) for arg in args]
      description = gyp.xcode_emulation.ExpandEnvVars(description, env)

    # TODO: we shouldn't need to qualify names; we do it because
    # currently the ninja rule namespace is global, but it really
    # should be scoped to the subninja.
    rule_name = self.name
    if self.toolset == 'target':
      rule_name += '.' + self.toolset
    rule_name += '.' + name
    rule_name = re.sub('[^a-zA-Z0-9_]', '_', rule_name)

    # Remove variable references, but not if they refer to the magic rule
    # variables.  This is not quite right, as it also protects these for
    # actions, not just for rules where they are valid. Good enough.
    protect = [ '${root}', '${dirname}', '${source}', '${ext}', '${name}' ]
    protect = '(?!' + '|'.join(map(re.escape, protect)) + ')'
    description = re.sub(protect + r'\$', '_', description)

    # gyp dictates that commands are run from the base directory.
    # cd into the directory before running, and adjust paths in
    # the arguments to point to the proper locations.
    rspfile = None
    rspfile_content = None
    args = [self.ExpandSpecial(arg, self.base_to_build) for arg in args]
    if (self.flavor in ['win', 'ps3', 'xb1', 'ps4']
        and is_windows):
      rspfile = rule_name + '.$unique_name.rsp'
      # The cygwin case handles this inside the bash sub-shell.
      run_in = '' if is_cygwin else ' ' + self.build_to_base
      if is_cygwin:
        rspfile_content = self.msvs_settings.BuildCygwinBashCommandLine(
            args, self.build_to_base)
      else:
        rspfile_content = gyp.msvs_emulation.EncodeRspFileList(args)

      command = ('%s gyp-win-tool action-wrapper $arch ' % sys.executable +
                 rspfile + run_in)
    else:
      env = self.ComputeExportEnvString(env)
      command = gyp.common.EncodePOSIXShellList(args)
      command = 'cd %s; ' % self.build_to_base + env + command

    # GYP rules/actions express being no-ops by not touching their outputs.
    # Avoid executing downstream dependencies in this case by specifying
    # restat=1 to ninja.
    self.ninja.rule(rule_name, command, description, restat=True,
                    rspfile=rspfile, rspfile_content=rspfile_content)
    self.ninja.newline()

    return rule_name, args


def CalculateVariables(default_variables, params):
  """Calculate additional variables for use in the build (called by gyp)."""
  global generator_additional_non_configuration_keys
  global generator_additional_path_sections
  flavor = gyp.common.GetFlavor(params)
  if flavor == 'mac':
    default_variables.setdefault('OS', 'mac')
    default_variables.setdefault('SHARED_LIB_SUFFIX', '.dylib')
    default_variables.setdefault('SHARED_LIB_DIR',
                                 generator_default_variables['PRODUCT_DIR'])
    default_variables.setdefault('LIB_DIR',
                                 generator_default_variables['PRODUCT_DIR'])

    # Copy additional generator configuration data from Xcode, which is shared
    # by the Mac Ninja generator.
    import gyp.generator.xcode as xcode_generator
    generator_additional_non_configuration_keys = getattr(xcode_generator,
        'generator_additional_non_configuration_keys', [])
    generator_additional_path_sections = getattr(xcode_generator,
        'generator_additional_path_sections', [])
    global generator_extra_sources_for_rules
    generator_extra_sources_for_rules = getattr(xcode_generator,
        'generator_extra_sources_for_rules', [])
  elif flavor in ['win', 'xb1']:
    default_variables.setdefault('OS', 'win')
    default_variables['EXECUTABLE_SUFFIX'] = '.exe'
    default_variables['STATIC_LIB_PREFIX'] = ''
    default_variables['STATIC_LIB_SUFFIX'] = '.lib'
    default_variables['SHARED_LIB_PREFIX'] = ''
    default_variables['SHARED_LIB_SUFFIX'] = '.dll'
    generator_flags = params.get('generator_flags', {})

    # Copy additional generator configuration data from VS, which is shared
    # by the Windows Ninja generator.
    import gyp.generator.msvs as msvs_generator
    generator_additional_non_configuration_keys = getattr(msvs_generator,
        'generator_additional_non_configuration_keys', [])
    generator_additional_path_sections = getattr(msvs_generator,
        'generator_additional_path_sections', [])

    # Set a variable so conditions can be based on msvs_version.
    msvs_version = gyp.msvs_emulation.GetVSVersion(generator_flags)
    default_variables['MSVS_VERSION'] = msvs_version.ShortName()

    # To determine processor word size on Windows, in addition to checking
    # PROCESSOR_ARCHITECTURE (which reflects the word size of the current
    # process), it is also necessary to check PROCESSOR_ARCHITEW6432 (which
    # contains the actual word size of the system when running thru WOW64).
    if ('64' in os.environ.get('PROCESSOR_ARCHITECTURE', '') or
        '64' in os.environ.get('PROCESSOR_ARCHITEW6432', '')):
      default_variables['MSVS_OS_BITS'] = 64
    else:
      default_variables['MSVS_OS_BITS'] = 32
  elif flavor in ['ps3']:
    if is_windows:
      # This is required for BuildCygwinBashCommandLine() to work.
      import gyp.generator.msvs as msvs_generator
      generator_additional_non_configuration_keys = getattr(msvs_generator,
          'generator_additional_non_configuration_keys', [])
      generator_additional_path_sections = getattr(msvs_generator,
          'generator_additional_path_sections', [])

    default_variables['SHARED_LIB_PREFIX'] = ''
    default_variables['SHARED_LIB_SUFFIX'] = '.sprx'
    generator_flags = params.get('generator_flags', {})

  elif flavor == 'ps4':
    if is_windows:
      # This is required for BuildCygwinBashCommandLine() to work.
      import gyp.generator.msvs as msvs_generator
      generator_additional_non_configuration_keys = getattr(msvs_generator,
          'generator_additional_non_configuration_keys', [])
      generator_additional_path_sections = getattr(msvs_generator,
          'generator_additional_path_sections', [])

    default_variables['EXECUTABLE_SUFFIX'] = '.elf'
    default_variables['SHARED_LIB_PREFIX'] = 'lib'
    default_variables['SHARED_LIB_SUFFIX'] = '.so'

    # Copy additional generator configuration data from VS, which is shared
    # by the Windows Ninja generator.
    import gyp.generator.msvs as msvs_generator
    generator_additional_non_configuration_keys = getattr(msvs_generator,
        'generator_additional_non_configuration_keys', [])
    generator_additional_path_sections = getattr(msvs_generator,
        'generator_additional_path_sections', [])
  else:
    operating_system = flavor
    if flavor == 'android':
      operating_system = 'linux'  # Keep this legacy behavior for now.
    default_variables.setdefault('OS', operating_system)
    default_variables.setdefault('SHARED_LIB_SUFFIX', '.so')
    default_variables.setdefault('SHARED_LIB_DIR',
                                 os.path.join('$!PRODUCT_DIR', 'lib'))
    default_variables.setdefault('LIB_DIR',
                                 os.path.join('$!PRODUCT_DIR', 'obj'))


def OpenOutput(path, mode='w'):
  """Open |path| for writing, creating directories if necessary."""
  try:
    os.makedirs(os.path.dirname(path))
  except OSError:
    pass
  return open(path, mode)


def GetDefaultConcurrentLinks():
  """Returns a best-guess for a number of concurrent links."""
  pool_size = int(os.getenv('GYP_LINK_CONCURRENCY', 0))
  if pool_size:
    return pool_size

  if sys.platform in ('win32', 'cygwin'):
    import ctypes

    class MEMORYSTATUSEX(ctypes.Structure):
      _fields_ = [
        ("dwLength", ctypes.c_ulong),
        ("dwMemoryLoad", ctypes.c_ulong),
        ("ullTotalPhys", ctypes.c_ulonglong),
        ("ullAvailPhys", ctypes.c_ulonglong),
        ("ullTotalPageFile", ctypes.c_ulonglong),
        ("ullAvailPageFile", ctypes.c_ulonglong),
        ("ullTotalVirtual", ctypes.c_ulonglong),
        ("ullAvailVirtual", ctypes.c_ulonglong),
        ("sullAvailExtendedVirtual", ctypes.c_ulonglong),
      ]

    stat = MEMORYSTATUSEX()
    stat.dwLength = ctypes.sizeof(stat)
    ctypes.windll.kernel32.GlobalMemoryStatusEx(ctypes.byref(stat))

    # VS 2015 uses 20% more working set than VS 2013 and can consume all RAM
    # on a 64 GB machine.
    mem_limit = max(1, stat.ullTotalPhys / (5 * (2 ** 30)))  # total / 5GB
    hard_cap = max(1, int(os.getenv('GYP_LINK_CONCURRENCY_MAX', 2**32)))
    return min(mem_limit, hard_cap)
  elif sys.platform.startswith('linux'):
    if os.path.exists("/proc/meminfo"):
      with open("/proc/meminfo") as meminfo:
        memtotal_re = re.compile(r'^MemTotal:\s*(\d*)\s*kB')
        for line in meminfo:
          match = memtotal_re.match(line)
          if not match:
            continue
          # Allow 6Gb per link on Linux because Gold is quite memory hungry
          return max(1, int(match.group(1)) / (6 * (2 ** 20)))
    return 1
  elif sys.platform == 'darwin':
    try:
      avail_bytes = int(subprocess.check_output(['sysctl', '-n', 'hw.memsize']))
      # A static library debug build of Chromium's unit_tests takes ~2.7GB, so
      # 4GB per ld process allows for some more bloat.
      return max(1, avail_bytes / (4 * (2 ** 30)))  # total / 4GB
    except:
      return 1
  else:
    # TODO(scottmg): Implement this for other platforms.
    return 1


def GenerateOutputForConfig(target_list, target_dicts, data, params,
                            config_name):
  options = params['options']
  flavor = gyp.common.GetFlavor(params)

  generator_flags = params.get('generator_flags', {})

  # generator_dir: relative path from pwd to where make puts build files.
  # Makes migrating from make to ninja easier, ninja doesn't put anything here.
  generator_dir = os.path.relpath(params['options'].generator_output or '.')

  # output_dir: relative path from generator_dir to the build directory.
  output_dir = generator_flags.get('output_dir', 'out')

  # build_dir: relative path from source root to our output files.
  # e.g. "out/Debug"
  build_dir = os.path.normpath(os.path.join(generator_dir,
                                            output_dir,
                                            config_name))

  toplevel_build = os.path.join(options.toplevel_dir, build_dir)

  master_ninja = ninja_syntax.Writer(
      OpenOutput(os.path.join(toplevel_build, 'build.ninja')),
      width=120)
  case_sensitive_filesystem = True

  # Put build-time support tools in out/{config_name}.
  gyp.common.CopyTool(flavor, toplevel_build)

  # Grab make settings for CC/CXX.
  # The rules are
  # - The priority from low to high is gcc/g++, the 'make_global_settings' in
  #   gyp, the environment variable.
  # - If there is no 'make_global_settings' for CC.host/CXX.host or
  #   'CC_host'/'CXX_host' enviroment variable, cc_host/cxx_host should be set
  #   to cc/cxx.
  if (flavor == 'win' or (flavor in ['ps3', 'ps4'] and is_windows)):
    cc = 'cl.exe'
    cxx = 'cl.exe'
    ld = 'link.exe'
    gyp.msvs_emulation.GenerateEnvironmentFiles(
        toplevel_build, generator_flags, OpenOutput)
    ld_host = '$ld'
  elif flavor == 'xb1':
    cc = 'cl.exe'
    cxx = 'cl.exe'
    ld = 'link.exe'
    gyp.msvs_emulation.GenerateXB1EnvironmentFiles(
        toplevel_build, generator_flags, OpenOutput)
    ld_host = '$ld'
  else:
    cc = 'gcc'
    cxx = 'g++'
    ld = '$cxx'
    ld_host = '$cxx_host'

  cc_host = None
  cxx_host = None
  cc_host_global_setting = None
  cxx_host_global_setting = None

  build_file, _, _ = gyp.common.ParseQualifiedTarget(target_list[0])
  make_global_settings = data[build_file].get('make_global_settings', [])
  build_to_root = InvertRelativePath(build_dir)
  for key, value in make_global_settings:
    if key == 'CC':
      cc = os.path.join(build_to_root, value)
    if key == 'CXX':
      cxx = os.path.join(build_to_root, value)
    if key == 'LD':
      ld = os.path.join(build_to_root, value)
    if key == 'CC.host':
      cc_host = os.path.join(build_to_root, value)
      cc_host_global_setting = value
    if key == 'CXX.host':
      cxx_host = os.path.join(build_to_root, value)
      cxx_host_global_setting = value
    if key == 'LD.host':
      ld_host = os.path.join(build_to_root, value)

  flock = 'flock'
  if flavor == 'mac':
    flock = './gyp-mac-tool flock'
  cc = GetEnvironFallback(['CC_target', 'CC'], cc)
  master_ninja.variable('cc', cc)
  cxx = GetEnvironFallback(['CXX_target', 'CXX'], cxx)
  master_ninja.variable('cxx', cxx)
  ld = GetEnvironFallback(['LD_target', 'LD'], ld)

  if not cc_host:
    cc_host = cc
  if not cxx_host:
    cxx_host = cxx

  # gyp-win-tool wrappers have a winpython only flock implementation.
  if sys.platform == 'cygwin':
    python_exec = '$python'
  else:
    python_exec = sys.executable

  ar_flags = ''
  if flavor in ['win', 'xb1']:
    master_ninja.variable('ld', ld)
    master_ninja.variable('idl', 'midl.exe')
    master_ninja.variable('ar', os.environ.get('AR', 'ar'))
    master_ninja.variable('rc', 'rc.exe')
    master_ninja.variable('asm', 'ml.exe')
    master_ninja.variable('mt', 'mt.exe')
    master_ninja.variable('use_dep_database', '1')
  elif flavor in ['ps3', 'ps4']:
    # Require LD to be set.
    master_ninja.variable('ld', os.environ.get('LD'))
    master_ninja.variable('ar', os.environ.get('AR', 'ar'))
    if flavor in ['ps3']:
      master_ninja.variable('prx_export_pickup', os.environ['PRX_EXPORT_PICKUP'])
    ar_flags = os.environ.get('ARFLAGS', 'rcs')
    master_ninja.variable('arFlags', ar_flags)
    # On the PS3, when we use ps3snarl.exe with a response file, we cannot
    # pass it flags (like 'rcs'), so ARFLAGS is likely set to '' for this
    # platform.  In that case, do not append the thin archive 'T' flag
    # to the flags string.
    # Likewise for PS4, but using orbis-snarl.exe
    thin_flag_to_add = ''
    if len(ar_flags) >= 1 and ar_flags.find('T') == -1:
      thin_flag_to_add = 'T'
    master_ninja.variable('arThinFlags', ar_flags + thin_flag_to_add)

  else:
    master_ninja.variable('ld', ld)
    master_ninja.variable('ar', GetEnvironFallback(['AR_target', 'AR'], 'ar'))
    ar_flags = os.environ.get('ARFLAGS', 'rcs')
    master_ninja.variable('arFlags', ar_flags)
    thin_flag_to_add = ''
    if ar_flags.find('T') == -1:
      thin_flag_to_add = 'T'
    master_ninja.variable('arThinFlags', ar_flags + thin_flag_to_add)
  master_ninja.variable('ar_host', GetEnvironFallback(['AR_host'], 'ar'))
  cc_host = GetEnvironFallback(['CC_host'], cc_host)
  cxx_host = GetEnvironFallback(['CXX_host'], cxx_host)
  ld_host = GetEnvironFallback(['LD_host'], ld_host)
  arflags_host = GetEnvironFallback(['ARFLAGS_host'], ar_flags)
  arthinflags_host = GetEnvironFallback(['ARTHINFLAGS_host'], arflags_host)

  # The environment variable could be used in 'make_global_settings', like
  # ['CC.host', '$(CC)'] or ['CXX.host', '$(CXX)'], transform them here.
  if '$(CC)' in cc_host and cc_host_global_setting:
    cc_host = cc_host_global_setting.replace('$(CC)', cc)
  if '$(CXX)' in cxx_host and cxx_host_global_setting:
    cxx_host = cxx_host_global_setting.replace('$(CXX)', cxx)
  master_ninja.variable('cc_host', cc_host)
  master_ninja.variable('cxx_host', cxx_host)
  master_ninja.variable('arFlags_host', arflags_host)
  master_ninja.variable('arThinFlags_host', arthinflags_host)
  master_ninja.variable('ld_host', ld_host)

  if sys.platform == 'cygwin':
    python_path = cygpath.to_nt('/cygdrive/c/python_27_amd64/files/python.exe')
  else:
    python_path = 'python'
  master_ninja.variable('python', python_path)
  master_ninja.newline()

  master_ninja.pool('link_pool', depth=GetDefaultConcurrentLinks())
  master_ninja.newline()

  if flavor not in ['win', 'xb1']:
    if flavor in ['ps3', 'ps4'] :
      # uca := Unnamed Console A
      dep_format = 'snc' if (flavor in ['ps3']) else 'uca'
      master_ninja.rule(
        'cc',
        description='CC $out',
        command=('$cc @$out.rsp'),
        rspfile='$out.rsp',
        rspfile_content=('-c $in -o $out '
                         '-MMD $defines $includes $cflags $cflags_c '
                        '$cflags_pch_c'),
        depfile='$out_no_ext.d',
        deps='gcc',
        depformat=dep_format)
      master_ninja.rule(
        'cxx',
        description='CXX $out',
        command=('$cxx @$out.rsp'),
        rspfile='$out.rsp',
        rspfile_content=('-c $in -o $out '
                         '-MMD $defines $includes $cflags $cflags_cc '
                        '$cflags_pch_cc'),
        depfile='$out_no_ext.d',
        deps='gcc',
        depformat=dep_format)
    else:
      master_ninja.rule(
        'cc',
        description='CC $out',
        command=('$cc -MMD -MF $out.d $defines $includes $cflags $cflags_c '
                '$cflags_pch_c -c $in -o $out'),
        deps='gcc',
        depfile='$out.d')
      master_ninja.rule(
        'cc_s',
        description='CC $out',
        command=('$cc $defines $includes $cflags $cflags_c '
                '$cflags_pch_c -c $in -o $out'))
      master_ninja.rule(
        'cxx',
        description='CXX $out',
        command=('$cxx -MMD -MF $out.d $defines $includes $cflags $cflags_cc '
                '$cflags_pch_cc -c $in -o $out'),
        deps='gcc',
        depfile='$out.d')

  else:
    cc_command = ('$cc /nologo /showIncludes /FC '
                  '@$out.rsp /c $in /Fo$out /Fd$pdbname ')
    cxx_command = ('$cxx /nologo /showIncludes /FC '
                   '@$out.rsp /c $in /Fo$out /Fd$pdbname ')
    master_ninja.rule(
      'cc',
      description='CC $out',
      command=cc_command,
      deps='msvc',
      rspfile='$out.rsp',
      rspfile_content='$defines $includes $cflags $cflags_c')
    master_ninja.rule(
      'cxx',
      description='CXX $out',
      command=cxx_command,
      deps='msvc',
      rspfile='$out.rsp',
      rspfile_content='$defines $includes $cflags $cflags_cc')

    master_ninja.rule(
      'idl',
      description='IDL $in',
      command=('%s gyp-win-tool midl-wrapper $arch $outdir '
               '$tlb $h $dlldata $iid $proxy $in '
               '$idlflags' % python_exec))
    master_ninja.rule(
      'rc',
      description='RC $in',
      # Note: $in must be last otherwise rc.exe complains.
      command=('%s gyp-win-tool rc-wrapper '
               '$arch $rc $defines $includes $rcflags /fo$out $in' %
               python_exec))
    master_ninja.rule(
      'asm',
      description='ASM $in',
      command=('%s gyp-win-tool asm-wrapper '
               '$arch $asm $defines $includes /c /Fo $out $in' %
               python_exec))

  if flavor not in ['mac', 'win', 'xb1']:
    alink_command = 'rm -f $out && $ar $arFlags $out @$out.rsp'
    # TODO: Use rcsT on Linux only.
    alink_thin_command = 'rm -f $out && $ar $arThinFlags $out @$out.rsp'

    ld_cmd = '$ld'

    if flavor in ['ps3', 'ps4'] and is_windows:
      alink_command = 'cmd.exe /c ' + alink_command
      alink_thin_command = 'cmd.exe /c ' + alink_thin_command
      ld_cmd = '%s gyp-win-tool link-wrapper $arch $ld' % python_exec

    master_ninja.rule(
      'alink',
      description='AR $out',
      command=alink_command,
      rspfile='$out.rsp',
      rspfile_content='$in_newline')
    master_ninja.rule(
      'alink_thin',
      description='AR $out',
      command=alink_thin_command,
      rspfile='$out.rsp',
      rspfile_content='$in_newline')

    if flavor in ['ps3']:
      # TODO: Can we suppress the warnings from verlog.txt rather than
      # rm'ing it?
      ld_cmd = 'rm -f $verlog && ' + ld_cmd
      if is_windows:
        ld_cmd = 'cmd.exe /c ' + ld_cmd

      prx_flags = '--oformat=fsprx --prx-with-runtime --zgenprx -zgenstub'
      master_ninja.rule(
        'solink',
        description='LINK(PRX) $lib',
        restat=True,
        command=ld_cmd + ' @$prx.rsp',
        rspfile='$prx.rsp',
        rspfile_content='$ldflags %s -o $prx $in $libs' % prx_flags,
        pool='link_pool'
      )
      master_ninja.rule(
        'prx_export_pickup',
        description='PRX-EXPORT-PICKUP $out',
        command='$prx_export_pickup --output-src=$out $in')

    else:  # Assume it is a Linux platform
      # This allows targets that only need to depend on $lib's API to declare an
      # order-only dependency on $lib.TOC and avoid relinking such downstream
      # dependencies when $lib changes only in non-public ways.
      # The resulting string leaves an uninterpolated %{suffix} which
      # is used in the final substitution below.
      mtime_preserving_solink_base = (
          'if [ ! -e $lib -o ! -e ${lib}.TOC ]; then '
          '%(solink)s && %(extract_toc)s > ${lib}.TOC; else '
          '%(solink)s && %(extract_toc)s > ${lib}.tmp && '
          'if ! cmp -s ${lib}.tmp ${lib}.TOC; then mv ${lib}.tmp ${lib}.TOC ; '
          'fi; fi'
          % { 'solink':
                (ld_cmd +
                 ' -shared $ldflags -o $lib -Wl,-soname=$soname %(suffix)s'),
              'extract_toc':
                ('{ readelf -d ${lib} | grep SONAME ; '
                 'nm -gD -f p ${lib} | cut -f1-2 -d\' \'; }')})

      master_ninja.rule(
        'solink',
        description='SOLINK $lib',
        restat=True,
        command=(mtime_preserving_solink_base % {
            'suffix': '-Wl,--whole-archive $in $solibs -Wl,--no-whole-archive '
            '$libs'}))
      master_ninja.rule(
        'solink_module',
        description='SOLINK(module) $lib',
        restat=True,
        command=(mtime_preserving_solink_base % {
            'suffix': '-Wl,--start-group $in $solibs -Wl,--end-group $libs'}))

    if flavor in ['ps3', 'ps4']:
      # PS3 and PS4 linkers don't know about rpath.
      rpath = ''
    else:
      rpath = r'-Wl,-rpath=\$$ORIGIN/lib'

    master_ninja.rule(
      'link',
      description='LINK $out',
      command=(ld_cmd +' @$out.rsp'),
      rspfile='$out.rsp',
      rspfile_content=('$ldflags -o $out %s -Wl,--start-group $in $solibs '
                       '-Wl,--end-group $libs' % rpath),
      pool='link_pool')
  elif flavor in ['win', 'xb1']:
    master_ninja.rule(
        'alink',
        description='LIB $out',
        command=('%s gyp-win-tool link-wrapper $arch '
                 '$ar /nologo /ignore:4221 /OUT:$out @$out.rsp' %
                 python_exec),
        rspfile='$out.rsp',
        rspfile_content='$in_newline $libflags')
    dlldesc = 'LINK(DLL) $dll'
    dllcmd = ('%s gyp-win-tool link-wrapper $arch '
              '$ld /nologo $implibflag /DLL /OUT:$dll '
              '/PDB:$dll.pdb @$dll.rsp' % python_exec)
    if flavor != 'xb1':
      # XB1 doesn't need a manifest.
      dllcmd += (' && %s gyp-win-tool manifest-wrapper $arch '
                 '$mt -nologo -manifest $manifests -out:$dll.manifest' %
                 python_exec)
    master_ninja.rule('solink', description=dlldesc, command=dllcmd,
                      rspfile='$dll.rsp',
                      rspfile_content='$libs $in_newline $ldflags',
                      restat=True)
    master_ninja.rule('solink_module', description=dlldesc, command=dllcmd,
                      rspfile='$dll.rsp',
                      rspfile_content='$libs $in_newline $ldflags',
                      restat=True)
    # Note that ldflags goes at the end so that it has the option of
    # overriding default settings earlier in the command line.
    if flavor == 'win':
      link_command=('%s gyp-win-tool link-wrapper $arch '
                   '$ld /nologo /OUT:$out /PDB:$out.pdb @$out.rsp && '
                   '%s gyp-win-tool manifest-wrapper $arch '
                   '$mt -nologo -manifest $manifests -out:$out.manifest' %
                   (python_exec, python_exec))
    else:
      assert flavor == 'xb1'
      # XB1 doesn't need a manifest.
      link_command=('%s gyp-win-tool link-wrapper $arch '
                   '$ld /nologo /OUT:$out /PDB:$out.pdb @$out.rsp' %
                   (python_exec))

    master_ninja.rule(
        'link',
        description='LINK $out',
        command=link_command,
        rspfile='$out.rsp',
        rspfile_content='$in_newline $libs $ldflags',
        pool='link_pool')
  else:
    master_ninja.rule(
      'objc',
      description='OBJC $out',
      command=('$cc -MMD -MF $out.d $defines $includes $cflags $cflags_objc '
               '$cflags_pch_objc -c $in -o $out'),
      depfile='$out.d')
    master_ninja.rule(
      'objcxx',
      description='OBJCXX $out',
      command=('$cxx -MMD -MF $out.d $defines $includes $cflags $cflags_objcc '
               '$cflags_pch_objcc -c $in -o $out'),
      depfile='$out.d')
    master_ninja.rule(
      'alink',
      description='LIBTOOL-STATIC $out, POSTBUILDS',
      command='rm -f $out && '
              './gyp-mac-tool filter-libtool libtool $libtool_flags '
              '-static -o $out $in'
              '$postbuilds')

    # Record the public interface of $lib in $lib.TOC. See the corresponding
    # comment in the posix section above for details.
    mtime_preserving_solink_base = (
        'if [ ! -e $lib -o ! -e ${lib}.TOC ] || '
             # Always force dependent targets to relink if this library
             # reexports something. Handling this correctly would require
             # recursive TOC dumping but this is rare in practice, so punt.
             'otool -l $lib | grep -q LC_REEXPORT_DYLIB ; then '
          '%(solink)s && %(extract_toc)s > ${lib}.TOC; '
        'else '
          '%(solink)s && %(extract_toc)s > ${lib}.tmp && '
          'if ! cmp -s ${lib}.tmp ${lib}.TOC; then '
            'mv ${lib}.tmp ${lib}.TOC ; '
          'fi; '
        'fi'
        % { 'solink': '$ld -shared $ldflags -o $lib %(suffix)s',
            'extract_toc':
              '{ otool -l $lib | grep LC_ID_DYLIB -A 5; '
              'nm -gP $lib | cut -f1-2 -d\' \' | grep -v U$$; true; }'})

    # TODO(thakis): The solink_module rule is likely wrong. Xcode seems to pass
    # -bundle -single_module here (for osmesa.so).
    master_ninja.rule(
      'solink',
      description='SOLINK $lib, POSTBUILDS',
      restat=True,
      command=(mtime_preserving_solink_base % {
          'suffix': '$in $solibs $libs$postbuilds'}))
    master_ninja.rule(
      'solink_module',
      description='SOLINK(module) $lib, POSTBUILDS',
      restat=True,
      command=(mtime_preserving_solink_base % {
          'suffix': '$in $solibs $libs$postbuilds'}))

    master_ninja.rule(
      'link',
      description='LINK $out, POSTBUILDS',
      command=('$ld $ldflags -o $out '
               '$in $solibs $libs$postbuilds'),
      pool='link_pool')
    master_ninja.rule(
      'infoplist',
      description='INFOPLIST $out',
      command=('$cc -E -P -Wno-trigraphs -x c $defines $in -o $out && '
               'plutil -convert xml1 $out $out'))
    master_ninja.rule(
      'mac_tool',
      description='MACTOOL $mactool_cmd $in',
      command='$env ./gyp-mac-tool $mactool_cmd $in $out')
    master_ninja.rule(
      'package_framework',
      description='PACKAGE FRAMEWORK $out, POSTBUILDS',
      command='./gyp-mac-tool package-framework $out $version$postbuilds '
              '&& touch $out')
  if flavor in ['win', 'xb1']:
    master_ninja.rule(
      'stamp',
      description='STAMP $out',
      command='%s gyp-win-tool stamp $out' % python_exec)
    master_ninja.rule(
      'copy',
      description='COPY $in $out',
      command='%s gyp-win-tool recursive-mirror $in $out' % python_exec)
  elif sys.platform in ['cygwin', 'win32']:
    master_ninja.rule(
      'stamp',
      description='STAMP $out',
      command='$python gyp-win-tool stamp $out')
    master_ninja.rule(
      'copy',
      description='COPY $in $out',
      command='$python gyp-win-tool recursive-mirror $in $out')
  else:
    master_ninja.rule(
      'stamp',
      description='STAMP $out',
      command='${postbuilds}touch $out')
    master_ninja.rule(
      'copy',
      description='COPY $in $out',
      command='rm -rf $out && cp -af $in $out')
  master_ninja.newline()

  # Output host building rules
  if is_windows:
    cc_command = ('$cc /nologo /showIncludes /FC '
                  '@$out.rsp /c $in /Fo$out /Fd$pdbname ')
    cxx_command = ('$cxx /nologo /showIncludes /FC '
                   '@$out.rsp /c $in /Fo$out /Fd$pdbname ')
    master_ninja.rule(
      'cc_host',
      description='CC_HOST $out',
      command=cc_command,
      deps='msvc',
      rspfile='$out.rsp',
      rspfile_content='$defines $includes $cflags_host $cflags_c_host')
    master_ninja.rule(
      'cxx_host',
      description='CXX_HOST $out',
      command=cxx_command,
      deps='msvc',
      rspfile='$out.rsp',
      rspfile_content='$defines $includes $cflags_host $cflags_cc_host')

    master_ninja.rule(
        'alink_host',
        description='LIB_HOST $out',
        command=('%s gyp-win-tool link-wrapper $arch '
                 '$ar /nologo /ignore:4221 /OUT:$out @$out.rsp' %
                 python_exec),
        rspfile='$out.rsp',
        rspfile_content='$in_newline $libflags_host')

    master_ninja.rule(
        'alink_thin_host',
        description='LIB_HOST $out',
        command=('%s gyp-win-tool link-wrapper $arch '
                 '$ar /nologo /ignore:4221 /OUT:$out @$out.rsp' %
                 python_exec),
        rspfile='$out.rsp',
        rspfile_content='$in_newline $libflags_host')

    link_command=('%s gyp-win-tool link-wrapper $arch '
                 '$ld /nologo /OUT:$out /PDB:$out.pdb @$out.rsp' %
                 (python_exec))

    master_ninja.rule(
        'link_host',
        description='LINK_HOST $out',
        command=link_command,
        rspfile='$out.rsp',
        rspfile_content='$in_newline $libs $ldflags',
        pool='link_pool')
  else:
    cc_command = 'bash -c "$cc_host @$out.rsp"'
    cxx_command = 'bash -c "$cxx_host @$out.rsp"'
    master_ninja.rule(
      'cc_host',
      description='CC_HOST $out',
      command=cc_command,
      rspfile='$out.rsp',
      rspfile_content=('-MMD -MF $out.d $defines $includes $cflags_host '
                       '$cflags_c_host $cflags_pch_c -c $in -o $out'),
      depfile='$out.d')
    master_ninja.rule(
      'cxx_host',
      description='CXX_HOST $out',
      command=cxx_command,
      rspfile='$out.rsp',
      rspfile_content=('-MMD -MF $out.d $defines $includes $cflags_host '
                       '$cflags_cc_host $cflags_pch_cc -c $in -o $out'),
      depfile='$out.d')

    alink_command = 'rm -f $out && $ar_host $arFlags_host $out @$out.rsp'
    alink_thin_command = ('rm -f $out && $ar_host $arThinFlags_host $out '
                          '@$out.rsp')

    master_ninja.rule(
      'alink_host',
      description='AR_HOST $out',
      command='bash -c "' + alink_command + '"',
      rspfile='$out.rsp',
      rspfile_content='$in_newline')
    master_ninja.rule(
      'alink_thin_host',
      description='AR_HOST $out',
      command='bash -c "' + alink_thin_command + '"',
      rspfile='$out.rsp',
      rspfile_content='$in_newline')
    beginlinkinlibs = ''
    endlinkinlibs = ''
    if is_linux:
      beginlinkinlibs = '-Wl,--start-group'
      endlinkinlibs = '-Wl,--end-group'
    rpath = '-Wl,-rpath=\$$ORIGIN/lib'
    master_ninja.rule(
      'link_host',
      description='LINK_HOST $out',
      command=('bash -c "$ld_host $ldflags_host -o $out %s '
               '%s $in $solibs %s $libs"' % (rpath,
                                             beginlinkinlibs, endlinkinlibs)))

  all_targets = set()
  for build_file in params['build_files']:
    for target in gyp.common.AllTargets(target_list,
                                        target_dicts,
                                        os.path.normpath(build_file)):
      all_targets.add(target)
  all_outputs = set()

  # target_outputs is a map from qualified target name to a Target object.
  target_outputs = {}
  # target_short_names is a map from target short name to a list of Target
  # objects.
  target_short_names = {}
  default_project = None
  for qualified_target in target_list:
    # qualified_target is like: third_party/icu/icu.gyp:icui18n#target
    build_file, name, toolset = \
        gyp.common.ParseQualifiedTarget(qualified_target)

    this_make_global_settings = data[build_file].get('make_global_settings', [])
    assert make_global_settings == this_make_global_settings, (
        "make_global_settings needs to be the same for all targets.")

    spec = target_dicts[qualified_target]

    if spec.get('default_project', 0):
      if default_project is None or default_project == name:
        default_project = name
      else:
        raise Exception('More than one default_project specified.'
          'First in {0} and now in {1}'.format(default_project, name))

    if flavor == 'mac':
      gyp.xcode_emulation.MergeGlobalXcodeSettingsToSpec(data[build_file], spec)

    build_file = gyp.common.RelativePath(build_file, options.toplevel_dir)

    base_path = os.path.dirname(build_file)
    obj = 'obj'
    if toolset != 'target':
      obj += '.' + toolset
    output_file = os.path.join(obj, base_path, name + '.ninja')

    abs_build_dir = os.path.abspath(toplevel_build)
    writer = NinjaWriter(qualified_target, target_outputs, base_path, build_dir,
                         OpenOutput(os.path.join(toplevel_build, output_file)),
                         flavor, case_sensitive_filesystem,
                         abs_build_dir=abs_build_dir)
    master_ninja.subninja(output_file)

    target = writer.WriteSpec(
        spec, config_name, generator_flags)
    if target:
      if name != target.FinalOutput():
        out_name = name
        if toolset != 'target':
          out_name = out_name + '.' + toolset
        target_short_names.setdefault(out_name, []).append(target)
      target_outputs[qualified_target] = target
      if qualified_target in all_targets:
        all_outputs.add(target.FinalOutput())

  if target_short_names:
    # Write a short name to build this target.  This benefits both the
    # "build chrome" case as well as the gyp tests, which expect to be
    # able to run actions and build libraries by their short name.
    master_ninja.newline()
    master_ninja.comment('Short names for targets.')
    for short_name in target_short_names:
      master_ninja.build(short_name, 'phony', [x.FinalOutput() for x in
                                               target_short_names[short_name]])

  if all_outputs:
    master_ninja.newline()
    master_ninja.build('all', 'phony', list(all_outputs))
    if default_project:
      master_ninja.default(default_project)
    else:
      master_ninja.default('all')


def PerformBuild(data, configurations, params):
  options = params['options']
  for config in configurations:
    builddir = os.path.join(options.toplevel_dir, 'out', config)
    arguments = ['ninja', '-C', builddir]
    print 'Building [%s]: %s' % (config, arguments)
    subprocess.check_call(arguments)


def CallGenerateOutputForConfig(arglist):
  # Ignore the interrupt signal so that the parent process catches it and
  # kills all multiprocessing children.
  signal.signal(signal.SIGINT, signal.SIG_IGN)

  (target_list, target_dicts, data, params, config_name) = arglist
  GenerateOutputForConfig(target_list, target_dicts, data, params, config_name)


def GenerateOutput(target_list, target_dicts, data, params):
  user_config = params.get('generator_flags', {}).get('config', None)
  if gyp.common.GetFlavor(params) in ['win', 'xb1']:
    target_list, target_dicts = MSVSUtil.ShardTargets(target_list, target_dicts)
  if user_config:
    GenerateOutputForConfig(target_list, target_dicts, data, params,
                            user_config)
  else:
    config_names = target_dicts[target_list[0]]['configurations'].keys()
    if params['parallel']:
      try:
        pool = multiprocessing.Pool(len(config_names))
        arglists = []
        for config_name in config_names:
          arglists.append(
              (target_list, target_dicts, data, params, config_name))
          pool.map(CallGenerateOutputForConfig, arglists)
      except KeyboardInterrupt, e:
        pool.terminate()
        raise e
    else:
      for config_name in config_names:
        GenerateOutputForConfig(target_list, target_dicts, data, params,
                                config_name)
