# Copyright (c) 2011 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 filecmp
import gyp.common
import gyp.xcodeproj_file
import errno
import os
import posixpath
import re
import shutil
import subprocess
import tempfile


# Project files generated by this module will use _intermediate_var as a
# custom Xcode setting whose value is a DerivedSources-like directory that's
# project-specific and configuration-specific.  The normal choice,
# DERIVED_FILE_DIR, is target-specific, which is thought to be too restrictive
# as it is likely that multiple targets within a single project file will want
# to access the same set of generated files.  The other option,
# PROJECT_DERIVED_FILE_DIR, is unsuitable because while it is project-specific,
# it is not configuration-specific.  INTERMEDIATE_DIR is defined as
# $(PROJECT_DERIVED_FILE_DIR)/$(CONFIGURATION).
_intermediate_var = 'INTERMEDIATE_DIR'

# SHARED_INTERMEDIATE_DIR is the same, except that it is shared among all
# targets that share the same BUILT_PRODUCTS_DIR.
_shared_intermediate_var = 'SHARED_INTERMEDIATE_DIR'

_library_search_paths_var = 'LIBRARY_SEARCH_PATHS'

generator_default_variables = {
  'EXECUTABLE_PREFIX': '',
  'EXECUTABLE_SUFFIX': '',
  'STATIC_LIB_PREFIX': 'lib',
  'SHARED_LIB_PREFIX': 'lib',
  'STATIC_LIB_SUFFIX': '.a',
  'SHARED_LIB_SUFFIX': '.dylib',
  # INTERMEDIATE_DIR is a place for targets to build up intermediate products.
  # It is specific to each build environment.  It is only guaranteed to exist
  # and be constant within the context of a project, corresponding to a single
  # input file.  Some build environments may allow their intermediate directory
  # to be shared on a wider scale, but this is not guaranteed.
  'INTERMEDIATE_DIR': '$(%s)' % _intermediate_var,
  'OS': 'mac',
  'PRODUCT_DIR': '$(BUILT_PRODUCTS_DIR)',
  'LIB_DIR': '$(BUILT_PRODUCTS_DIR)',
  'RULE_INPUT_ROOT': '$(INPUT_FILE_BASE)',
  'RULE_INPUT_EXT': '$(INPUT_FILE_SUFFIX)',
  'RULE_INPUT_NAME': '$(INPUT_FILE_NAME)',
  'RULE_INPUT_PATH': '$(INPUT_FILE_PATH)',
  'RULE_INPUT_DIRNAME': '$(INPUT_FILE_DIRNAME)',
  'SHARED_INTERMEDIATE_DIR': '$(%s)' % _shared_intermediate_var,
  'CONFIGURATION_NAME': '$(CONFIGURATION)',
}

# The Xcode-specific sections that hold paths.
generator_additional_path_sections = [
  'mac_bundle_resources',
  'mac_framework_headers',
  'mac_framework_private_headers',
  # 'mac_framework_dirs', input already handles _dirs endings.
]

# The Xcode-specific keys that exist on targets and aren't moved down to
# configurations.
generator_additional_non_configuration_keys = [
  'mac_bundle',
  'mac_bundle_resources',
  'mac_framework_headers',
  'mac_framework_private_headers',
  'xcode_create_dependents_test_runner',
]

# We want to let any rules apply to files that are resources also.
generator_extra_sources_for_rules = [
  'mac_bundle_resources',
  'mac_framework_headers',
  'mac_framework_private_headers',
]

# Xcode's standard set of library directories, which don't need to be duplicated
# in LIBRARY_SEARCH_PATHS. This list is not exhaustive, but that's okay.
xcode_standard_library_dirs = frozenset([
  '$(SDKROOT)/usr/lib',
  '$(SDKROOT)/usr/local/lib',
])

def CreateXCConfigurationList(configuration_names):
  xccl = gyp.xcodeproj_file.XCConfigurationList({'buildConfigurations': []})
  if len(configuration_names) == 0:
    configuration_names = ['Default']
  for configuration_name in configuration_names:
    xcbc = gyp.xcodeproj_file.XCBuildConfiguration({
        'name': configuration_name})
    xccl.AppendProperty('buildConfigurations', xcbc)
  xccl.SetProperty('defaultConfigurationName', configuration_names[0])
  return xccl


class XcodeProject(object):
  def __init__(self, gyp_path, path, build_file_dict):
    self.gyp_path = gyp_path
    self.path = path
    self.project = gyp.xcodeproj_file.PBXProject(path=path)
    projectDirPath = gyp.common.RelativePath(
                         os.path.dirname(os.path.abspath(self.gyp_path)),
                         os.path.dirname(path) or '.')
    self.project.SetProperty('projectDirPath', projectDirPath)
    self.project_file = \
        gyp.xcodeproj_file.XCProjectFile({'rootObject': self.project})
    self.build_file_dict = build_file_dict

    # TODO(mark): add destructor that cleans up self.path if created_dir is
    # True and things didn't complete successfully.  Or do something even
    # better with "try"?
    self.created_dir = False
    try:
      os.makedirs(self.path)
      self.created_dir = True
    except OSError, e:
      if e.errno != errno.EEXIST:
        raise

  def Finalize1(self, xcode_targets, serialize_all_tests):
    # Collect a list of all of the build configuration names used by the
    # various targets in the file.  It is very heavily advised to keep each
    # target in an entire project (even across multiple project files) using
    # the same set of configuration names.
    configurations = []
    for xct in self.project.GetProperty('targets'):
      xccl = xct.GetProperty('buildConfigurationList')
      xcbcs = xccl.GetProperty('buildConfigurations')
      for xcbc in xcbcs:
        name = xcbc.GetProperty('name')
        if name not in configurations:
          configurations.append(name)

    # Replace the XCConfigurationList attached to the PBXProject object with
    # a new one specifying all of the configuration names used by the various
    # targets.
    try:
      xccl = CreateXCConfigurationList(configurations)
      self.project.SetProperty('buildConfigurationList', xccl)
    except:
      import sys
      sys.stderr.write("Problem with gyp file %s\n" % self.gyp_path)
      raise

    # The need for this setting is explained above where _intermediate_var is
    # defined.  The comments below about wanting to avoid project-wide build
    # settings apply here too, but this needs to be set on a project-wide basis
    # so that files relative to the _intermediate_var setting can be displayed
    # properly in the Xcode UI.
    #
    # Note that for configuration-relative files such as anything relative to
    # _intermediate_var, for the purposes of UI tree view display, Xcode will
    # only resolve the configuration name once, when the project file is
    # opened.  If the active build configuration is changed, the project file
    # must be closed and reopened if it is desired for the tree view to update.
    # This is filed as Apple radar 6588391.
    xccl.SetBuildSetting(_intermediate_var,
                         '$(PROJECT_DERIVED_FILE_DIR)/$(CONFIGURATION)')
    xccl.SetBuildSetting(_shared_intermediate_var,
                         '$(SYMROOT)/DerivedSources/$(CONFIGURATION)')

    # Set user-specified project-wide build settings and config files.  This
    # is intended to be used very sparingly.  Really, almost everything should
    # go into target-specific build settings sections.  The project-wide
    # settings are only intended to be used in cases where Xcode attempts to
    # resolve variable references in a project context as opposed to a target
    # context, such as when resolving sourceTree references while building up
    # the tree tree view for UI display.
    # Any values set globally are applied to all configurations, then any
    # per-configuration values are applied.
    for xck, xcv in self.build_file_dict.get('xcode_settings', {}).iteritems():
      xccl.SetBuildSetting(xck, xcv)
    if 'xcode_config_file' in self.build_file_dict:
      config_ref = self.project.AddOrGetFileInRootGroup(
          self.build_file_dict['xcode_config_file'])
      xccl.SetBaseConfiguration(config_ref)
    build_file_configurations = self.build_file_dict.get('configurations', {})
    if build_file_configurations:
      for config_name in configurations:
        build_file_configuration_named = \
            build_file_configurations.get(config_name, {})
        if build_file_configuration_named:
          xcc = xccl.ConfigurationNamed(config_name)
          for xck, xcv in build_file_configuration_named.get('xcode_settings',
                                                             {}).iteritems():
            xcc.SetBuildSetting(xck, xcv)
          if 'xcode_config_file' in build_file_configuration_named:
            config_ref = self.project.AddOrGetFileInRootGroup(
                build_file_configurations[config_name]['xcode_config_file'])
            xcc.SetBaseConfiguration(config_ref)

    # Sort the targets based on how they appeared in the input.
    # TODO(mark): Like a lot of other things here, this assumes internal
    # knowledge of PBXProject - in this case, of its "targets" property.

    # ordinary_targets are ordinary targets that are already in the project
    # file. run_test_targets are the targets that run unittests and should be
    # used for the Run All Tests target.  support_targets are the action/rule
    # targets used by GYP file targets, just kept for the assert check.
    ordinary_targets = []
    run_test_targets = []
    support_targets = []

    # targets is full list of targets in the project.
    targets = []

    # does the it define it's own "all"?
    has_custom_all = False

    # targets_for_all is the list of ordinary_targets that should be listed
    # in this project's "All" target.  It includes each non_runtest_target
    # that does not have suppress_wildcard set.
    targets_for_all = []

    for target in self.build_file_dict['targets']:
      target_name = target['target_name']
      toolset = target['toolset']
      qualified_target = gyp.common.QualifiedTarget(self.gyp_path, target_name,
                                                    toolset)
      xcode_target = xcode_targets[qualified_target]
      # Make sure that the target being added to the sorted list is already in
      # the unsorted list.
      assert xcode_target in self.project._properties['targets']
      targets.append(xcode_target)
      ordinary_targets.append(xcode_target)
      if xcode_target.support_target:
        support_targets.append(xcode_target.support_target)
        targets.append(xcode_target.support_target)

      if not int(target.get('suppress_wildcard', False)):
        targets_for_all.append(xcode_target)

      if target_name.lower() == 'all':
        has_custom_all = True;

      # If this target has a 'run_as' attribute, add its target to the
      # targets, and add it to the test targets.
      if target.get('run_as'):
        # Make a target to run something.  It should have one
        # dependency, the parent xcode target.
        xccl = CreateXCConfigurationList(configurations)
        run_target = gyp.xcodeproj_file.PBXAggregateTarget({
              'name':                   'Run ' + target_name,
              'productName':            xcode_target.GetProperty('productName'),
              'buildConfigurationList': xccl,
            },
            parent=self.project)
        run_target.AddDependency(xcode_target)

        command = target['run_as']
        script = ''
        if command.get('working_directory'):
          script = script + 'cd "%s"\n' % \
                   gyp.xcodeproj_file.ConvertVariablesToShellSyntax(
                       command.get('working_directory'))

        if command.get('environment'):
          script = script + "\n".join(
            ['export %s="%s"' %
             (key, gyp.xcodeproj_file.ConvertVariablesToShellSyntax(val))
             for (key, val) in command.get('environment').iteritems()]) + "\n"

        # Some test end up using sockets, files on disk, etc. and can get
        # confused if more then one test runs at a time.  The generator
        # flag 'xcode_serialize_all_test_runs' controls the forcing of all
        # tests serially.  It defaults to True.  To get serial runs this
        # little bit of python does the same as the linux flock utility to
        # make sure only one runs at a time.
        command_prefix = ''
        if serialize_all_tests:
          command_prefix = \
"""python -c "import fcntl, subprocess, sys
file = open('$TMPDIR/GYP_serialize_test_runs', 'a')
fcntl.flock(file.fileno(), fcntl.LOCK_EX)
sys.exit(subprocess.call(sys.argv[1:]))" """

        # If we were unable to exec for some reason, we want to exit
        # with an error, and fixup variable references to be shell
        # syntax instead of xcode syntax.
        script = script + 'exec ' + command_prefix + '%s\nexit 1\n' % \
                 gyp.xcodeproj_file.ConvertVariablesToShellSyntax(
                     gyp.common.EncodePOSIXShellList(command.get('action')))

        ssbp = gyp.xcodeproj_file.PBXShellScriptBuildPhase({
              'shellScript':      script,
              'showEnvVarsInLog': 0,
            })
        run_target.AppendProperty('buildPhases', ssbp)

        # Add the run target to the project file.
        targets.append(run_target)
        run_test_targets.append(run_target)
        xcode_target.test_runner = run_target


    # Make sure that the list of targets being replaced is the same length as
    # the one replacing it, but allow for the added test runner targets.
    assert len(self.project._properties['targets']) == \
      len(ordinary_targets) + len(support_targets)

    self.project._properties['targets'] = targets

    # Get rid of unnecessary levels of depth in groups like the Source group.
    self.project.RootGroupsTakeOverOnlyChildren(True)

    # Sort the groups nicely.  Do this after sorting the targets, because the
    # Products group is sorted based on the order of the targets.
    self.project.SortGroups()

    # Create an "All" target if there's more than one target in this project
    # file and the project didn't define its own "All" target.  Put a generated
    # "All" target first so that people opening up the project for the first
    # time will build everything by default.
    if len(targets_for_all) > 1 and not has_custom_all:
      xccl = CreateXCConfigurationList(configurations)
      all_target = gyp.xcodeproj_file.PBXAggregateTarget(
          {
            'buildConfigurationList': xccl,
            'name':                   'All',
          },
          parent=self.project)

      for target in targets_for_all:
        all_target.AddDependency(target)

      # TODO(mark): This is evil because it relies on internal knowledge of
      # PBXProject._properties.  It's important to get the "All" target first,
      # though.
      self.project._properties['targets'].insert(0, all_target)

    # The same, but for run_test_targets.
    if len(run_test_targets) > 1:
      xccl = CreateXCConfigurationList(configurations)
      run_all_tests_target = gyp.xcodeproj_file.PBXAggregateTarget(
          {
            'buildConfigurationList': xccl,
            'name':                   'Run All Tests',
          },
          parent=self.project)
      for run_test_target in run_test_targets:
        run_all_tests_target.AddDependency(run_test_target)

      # Insert after the "All" target, which must exist if there is more than
      # one run_test_target.
      self.project._properties['targets'].insert(1, run_all_tests_target)

  def Finalize2(self, xcode_targets, xcode_target_to_target_dict):
    # Finalize2 needs to happen in a separate step because the process of
    # updating references to other projects depends on the ordering of targets
    # within remote project files.  Finalize1 is responsible for sorting duty,
    # and once all project files are sorted, Finalize2 can come in and update
    # these references.

    # To support making a "test runner" target that will run all the tests
    # that are direct dependents of any given target, we look for
    # xcode_create_dependents_test_runner being set on an Aggregate target,
    # and generate a second target that will run the tests runners found under
    # the marked target.
    for bf_tgt in self.build_file_dict['targets']:
      if int(bf_tgt.get('xcode_create_dependents_test_runner', 0)):
        tgt_name = bf_tgt['target_name']
        toolset = bf_tgt['toolset']
        qualified_target = gyp.common.QualifiedTarget(self.gyp_path,
                                                      tgt_name, toolset)
        xcode_target = xcode_targets[qualified_target]
        if isinstance(xcode_target, gyp.xcodeproj_file.PBXAggregateTarget):
          # Collect all the run test targets.
          all_run_tests = []
          pbxtds = xcode_target.GetProperty('dependencies')
          for pbxtd in pbxtds:
            pbxcip = pbxtd.GetProperty('targetProxy')
            dependency_xct = pbxcip.GetProperty('remoteGlobalIDString')
            if hasattr(dependency_xct, 'test_runner'):
              all_run_tests.append(dependency_xct.test_runner)

          # Directly depend on all the runners as they depend on the target
          # that builds them.
          if len(all_run_tests) > 0:
            run_all_target = gyp.xcodeproj_file.PBXAggregateTarget({
                  'name':        'Run %s Tests' % tgt_name,
                  'productName': tgt_name,
                },
                parent=self.project)
            for run_test_target in all_run_tests:
              run_all_target.AddDependency(run_test_target)

            # Insert the test runner after the related target.
            idx = self.project._properties['targets'].index(xcode_target)
            self.project._properties['targets'].insert(idx + 1, run_all_target)

    # Update all references to other projects, to make sure that the lists of
    # remote products are complete.  Otherwise, Xcode will fill them in when
    # it opens the project file, which will result in unnecessary diffs.
    # TODO(mark): This is evil because it relies on internal knowledge of
    # PBXProject._other_pbxprojects.
    for other_pbxproject in self.project._other_pbxprojects.keys():
      self.project.AddOrGetProjectReference(other_pbxproject)

    self.project.SortRemoteProductReferences()

    # Give everything an ID.
    self.project_file.ComputeIDs()

    # Make sure that no two objects in the project file have the same ID.  If
    # multiple objects wind up with the same ID, upon loading the file, Xcode
    # will only recognize one object (the last one in the file?) and the
    # results are unpredictable.
    self.project_file.EnsureNoIDCollisions()

  def Write(self):
    # Write the project file to a temporary location first.  Xcode watches for
    # changes to the project file and presents a UI sheet offering to reload
    # the project when it does change.  However, in some cases, especially when
    # multiple projects are open or when Xcode is busy, things don't work so
    # seamlessly.  Sometimes, Xcode is able to detect that a project file has
    # changed but can't unload it because something else is referencing it.
    # To mitigate this problem, and to avoid even having Xcode present the UI
    # sheet when an open project is rewritten for inconsequential changes, the
    # project file is written to a temporary file in the xcodeproj directory
    # first.  The new temporary file is then compared to the existing project
    # file, if any.  If they differ, the new file replaces the old; otherwise,
    # the new project file is simply deleted.  Xcode properly detects a file
    # being renamed over an open project file as a change and so it remains
    # able to present the "project file changed" sheet under this system.
    # Writing to a temporary file first also avoids the possible problem of
    # Xcode rereading an incomplete project file.
    (output_fd, new_pbxproj_path) = \
        tempfile.mkstemp(suffix='.tmp', prefix='project.pbxproj.gyp.',
                         dir=self.path)

    try:
      output_file = os.fdopen(output_fd, 'wb')

      self.project_file.Print(output_file)
      output_file.close()

      pbxproj_path = os.path.join(self.path, 'project.pbxproj')

      same = False
      try:
        same = filecmp.cmp(pbxproj_path, new_pbxproj_path, False)
      except OSError, e:
        if e.errno != errno.ENOENT:
          raise

      if same:
        # The new file is identical to the old one, just get rid of the new
        # one.
        os.unlink(new_pbxproj_path)
      else:
        # The new file is different from the old one, or there is no old one.
        # Rename the new file to the permanent name.
        #
        # tempfile.mkstemp uses an overly restrictive mode, resulting in a
        # file that can only be read by the owner, regardless of the umask.
        # There's no reason to not respect the umask here, which means that
        # an extra hoop is required to fetch it and reset the new file's mode.
        #
        # No way to get the umask without setting a new one?  Set a safe one
        # and then set it back to the old value.
        umask = os.umask(077)
        os.umask(umask)

        os.chmod(new_pbxproj_path, 0666 & ~umask)
        os.rename(new_pbxproj_path, pbxproj_path)

    except Exception:
      # Don't leave turds behind.  In fact, if this code was responsible for
      # creating the xcodeproj directory, get rid of that too.
      os.unlink(new_pbxproj_path)
      if self.created_dir:
        shutil.rmtree(self.path, True)
      raise


cached_xcode_version = None
def InstalledXcodeVersion():
  """Fetches the installed version of Xcode, returns empty string if it is
  unable to figure it out."""

  global cached_xcode_version
  if not cached_xcode_version is None:
    return cached_xcode_version

  # Default to an empty string
  cached_xcode_version = ''

  # Collect the xcodebuild's version information.
  try:
    import subprocess
    cmd = ['/usr/bin/xcodebuild', '-version']
    proc = subprocess.Popen(cmd, stdout=subprocess.PIPE)
    xcodebuild_version_info = proc.communicate()[0]
    # Any error, return empty string
    if proc.returncode:
      xcodebuild_version_info = ''
  except OSError:
    # We failed to launch the tool
    xcodebuild_version_info = ''

  # Pull out the Xcode version itself.
  match_line = re.search('^Xcode (.*)$', xcodebuild_version_info, re.MULTILINE)
  if match_line:
    cached_xcode_version = match_line.group(1)
  # Done!
  return cached_xcode_version


def AddSourceToTarget(source, pbxp, xct):
  # TODO(mark): Perhaps source_extensions and library_extensions can be made a
  # little bit fancier.
  source_extensions = ['c', 'cc', 'cpp', 'cxx', 'm', 'mm', 's']

  # .o is conceptually more of a "source" than a "library," but Xcode thinks
  # of "sources" as things to compile and "libraries" (or "frameworks") as
  # things to link with. Adding an object file to an Xcode target's frameworks
  # phase works properly.
  library_extensions = ['a', 'dylib', 'framework', 'o']

  basename = posixpath.basename(source)
  (root, ext) = posixpath.splitext(basename)
  if ext != '':
    ext = ext[1:].lower()

  if ext in source_extensions:
    xct.SourcesPhase().AddFile(source)
  elif ext in library_extensions:
    xct.FrameworksPhase().AddFile(source)
  else:
    # Files that aren't added to a sources or frameworks build phase can still
    # go into the project file, just not as part of a build phase.
    pbxp.AddOrGetFileInRootGroup(source)


def AddResourceToTarget(resource, pbxp, xct):
  # TODO(mark): Combine with AddSourceToTarget above?  Or just inline this call
  # where it's used.
  xct.ResourcesPhase().AddFile(resource)


def AddHeaderToTarget(header, pbxp, xct, is_public):
  # TODO(mark): Combine with AddSourceToTarget above?  Or just inline this call
  # where it's used.
  settings = '{ATTRIBUTES = (%s, ); }' % ('Private', 'Public')[is_public]
  xct.HeadersPhase().AddFile(header, settings)


_xcode_variable_re = re.compile('(\$\((.*?)\))')
def ExpandXcodeVariables(string, expansions):
  """Expands Xcode-style $(VARIABLES) in string per the expansions dict.

  In some rare cases, it is appropriate to expand Xcode variables when a
  project file is generated.  For any substring $(VAR) in string, if VAR is a
  key in the expansions dict, $(VAR) will be replaced with expansions[VAR].
  Any $(VAR) substring in string for which VAR is not a key in the expansions
  dict will remain in the returned string.
  """

  matches = _xcode_variable_re.findall(string)
  if matches == None:
    return string

  matches.reverse()
  for match in matches:
    (to_replace, variable) = match
    if not variable in expansions:
      continue

    replacement = expansions[variable]
    string = re.sub(re.escape(to_replace), replacement, string)

  return string


def EscapeXCodeArgument(s):
  """We must escape the arguments that we give to XCode so that it knows not to
     split on spaces and to respect backslash and quote literals."""
  s = s.replace('\\', '\\\\')
  s = s.replace('"', '\\"')
  return '"' + s + '"'


def GenerateOutput(target_list, target_dicts, data, params):
  options = params['options']
  generator_flags = params.get('generator_flags', {})
  parallel_builds = generator_flags.get('xcode_parallel_builds', True)
  serialize_all_tests = \
      generator_flags.get('xcode_serialize_all_test_runs', True)
  project_version = generator_flags.get('xcode_project_version', None)
  skip_excluded_files = \
      not generator_flags.get('xcode_list_excluded_files', True)
  xcode_projects = {}
  for build_file, build_file_dict in data.iteritems():
    (build_file_root, build_file_ext) = os.path.splitext(build_file)
    if build_file_ext != '.gyp':
      continue
    xcodeproj_path = build_file_root + options.suffix + '.xcodeproj'
    if options.generator_output:
      xcodeproj_path = os.path.join(options.generator_output, xcodeproj_path)
    xcp = XcodeProject(build_file, xcodeproj_path, build_file_dict)
    xcode_projects[build_file] = xcp
    pbxp = xcp.project

    if parallel_builds:
      pbxp.SetProperty('attributes',
                       {'BuildIndependentTargetsInParallel': 'YES'})
    if project_version:
      xcp.project_file.SetXcodeVersion(project_version)

    main_group = pbxp.GetProperty('mainGroup')
    build_group = gyp.xcodeproj_file.PBXGroup({'name': 'Build'})
    main_group.AppendChild(build_group)
    for included_file in build_file_dict['included_files']:
      build_group.AddOrGetFileByPath(included_file, False)

  xcode_targets = {}
  xcode_target_to_target_dict = {}
  for qualified_target in target_list:
    [build_file, target_name, toolset] = \
        gyp.common.ParseQualifiedTarget(qualified_target)

    spec = target_dicts[qualified_target]
    if spec['toolset'] != 'target':
      raise Exception(
          'Multiple toolsets not supported in xcode build (target %s)' %
          qualified_target)
    configuration_names = [spec['default_configuration']]
    for configuration_name in sorted(spec['configurations'].keys()):
      if configuration_name not in configuration_names:
        configuration_names.append(configuration_name)
    xcp = xcode_projects[build_file]
    pbxp = xcp.project

    # Set up the configurations for the target according to the list of names
    # supplied.
    xccl = CreateXCConfigurationList(configuration_names)

    # Create an XCTarget subclass object for the target. The type with
    # "+bundle" appended will be used if the target has "mac_bundle" set.
    # loadable_modules not in a mac_bundle are mapped to
    # com.googlecode.gyp.xcode.bundle, a pseudo-type that xcode.py interprets
    # to create a single-file mh_bundle.
    _types = {
      'executable':             'com.apple.product-type.tool',
      'loadable_module':        'com.googlecode.gyp.xcode.bundle',
      'shared_library':         'com.apple.product-type.library.dynamic',
      'static_library':         'com.apple.product-type.library.static',
      'executable+bundle':      'com.apple.product-type.application',
      'loadable_module+bundle': 'com.apple.product-type.bundle',
      'shared_library+bundle':  'com.apple.product-type.framework',
    }

    target_properties = {
      'buildConfigurationList': xccl,
      'name':                   target_name,
    }

    type = spec['type']
    is_bundle = int(spec.get('mac_bundle', 0))
    if type != 'none':
      type_bundle_key = type
      if is_bundle:
        type_bundle_key += '+bundle'
      xctarget_type = gyp.xcodeproj_file.PBXNativeTarget
      try:
        target_properties['productType'] = _types[type_bundle_key]
      except KeyError, e:
        gyp.common.ExceptionAppend(e, "-- unknown product type while "
                                   "writing target %s" % target_name)
        raise
    else:
      xctarget_type = gyp.xcodeproj_file.PBXAggregateTarget
      assert not is_bundle, (
          'mac_bundle targets cannot have type none (target "%s")' %
          target_name)

    target_product_name = spec.get('product_name')
    if target_product_name is not None:
      target_properties['productName'] = target_product_name

    xct = xctarget_type(target_properties, parent=pbxp,
                        force_outdir=spec.get('product_dir'),
                        force_prefix=spec.get('product_prefix'),
                        force_extension=spec.get('product_extension'))
    pbxp.AppendProperty('targets', xct)
    xcode_targets[qualified_target] = xct
    xcode_target_to_target_dict[xct] = spec

    spec_actions = spec.get('actions', [])
    spec_rules = spec.get('rules', [])

    # Xcode has some "issues" with checking dependencies for the "Compile
    # sources" step with any source files/headers generated by actions/rules.
    # To work around this, if a target is building anything directly (not
    # type "none"), then a second target as used to run the GYP actions/rules
    # and is made a dependency of this target.  This way the work is done
    # before the dependency checks for what should be recompiled.
    support_xct = None
    if type != 'none' and (spec_actions or spec_rules):
      support_xccl = CreateXCConfigurationList(configuration_names);
      support_target_properties = {
        'buildConfigurationList': support_xccl,
        'name':                   target_name + ' Support',
      }
      if target_product_name:
        support_target_properties['productName'] = \
            target_product_name + ' Support'
      support_xct = \
          gyp.xcodeproj_file.PBXAggregateTarget(support_target_properties,
                                                parent=pbxp)
      pbxp.AppendProperty('targets', support_xct)
      xct.AddDependency(support_xct)
    # Hang the support target off the main target so it can be tested/found
    # by the generator during Finalize.
    xct.support_target = support_xct

    prebuild_index = 0

    # Add custom shell script phases for "actions" sections.
    for action in spec_actions:
      # There's no need to write anything into the script to ensure that the
      # output directories already exist, because Xcode will look at the
      # declared outputs and automatically ensure that they exist for us.

      # Do we have a message to print when this action runs?
      message = action.get('message')
      if message:
        message = 'echo note: ' + gyp.common.EncodePOSIXShellArgument(message)
      else:
        message = ''

      # Turn the list into a string that can be passed to a shell.
      action_string = gyp.common.EncodePOSIXShellList(action['action'])

      # Convert Xcode-type variable references to sh-compatible environment
      # variable references.
      message_sh = gyp.xcodeproj_file.ConvertVariablesToShellSyntax(message)
      action_string_sh = gyp.xcodeproj_file.ConvertVariablesToShellSyntax(
        action_string)

      script = ''
      # Include the optional message
      if message_sh:
        script += message_sh + '\n'
      # Be sure the script runs in exec, and that if exec fails, the script
      # exits signalling an error.
      script += 'exec ' + action_string_sh + '\nexit 1\n'
      ssbp = gyp.xcodeproj_file.PBXShellScriptBuildPhase({
            'inputPaths': action['inputs'],
            'name': 'Action "' + action['action_name'] + '"',
            'outputPaths': action['outputs'],
            'shellScript': script,
            'showEnvVarsInLog': 0,
          })

      if support_xct:
        support_xct.AppendProperty('buildPhases', ssbp)
      else:
        # TODO(mark): this assumes too much knowledge of the internals of
        # xcodeproj_file; some of these smarts should move into xcodeproj_file
        # itself.
        xct._properties['buildPhases'].insert(prebuild_index, ssbp)
        prebuild_index = prebuild_index + 1

      # TODO(mark): Should verify that at most one of these is specified.
      if int(action.get('process_outputs_as_sources', False)):
        for output in action['outputs']:
          AddSourceToTarget(output, pbxp, xct)

      if int(action.get('process_outputs_as_mac_bundle_resources', False)):
        for output in action['outputs']:
          AddResourceToTarget(output, pbxp, xct)

    # tgt_mac_bundle_resources holds the list of bundle resources so
    # the rule processing can check against it.
    if is_bundle:
      tgt_mac_bundle_resources = spec.get('mac_bundle_resources', [])
    else:
      tgt_mac_bundle_resources = []

    # Add custom shell script phases driving "make" for "rules" sections.
    #
    # Xcode's built-in rule support is almost powerful enough to use directly,
    # but there are a few significant deficiencies that render them unusable.
    # There are workarounds for some of its inadequacies, but in aggregate,
    # the workarounds added complexity to the generator, and some workarounds
    # actually require input files to be crafted more carefully than I'd like.
    # Consequently, until Xcode rules are made more capable, "rules" input
    # sections will be handled in Xcode output by shell script build phases
    # performed prior to the compilation phase.
    #
    # The following problems with Xcode rules were found.  The numbers are
    # Apple radar IDs.  I hope that these shortcomings are addressed, I really
    # liked having the rules handled directly in Xcode during the period that
    # I was prototyping this.
    #
    # 6588600 Xcode compiles custom script rule outputs too soon, compilation
    #         fails.  This occurs when rule outputs from distinct inputs are
    #         interdependent.  The only workaround is to put rules and their
    #         inputs in a separate target from the one that compiles the rule
    #         outputs.  This requires input file cooperation and it means that
    #         process_outputs_as_sources is unusable.
    # 6584932 Need to declare that custom rule outputs should be excluded from
    #         compilation.  A possible workaround is to lie to Xcode about a
    #         rule's output, giving it a dummy file it doesn't know how to
    #         compile.  The rule action script would need to touch the dummy.
    # 6584839 I need a way to declare additional inputs to a custom rule.
    #         A possible workaround is a shell script phase prior to
    #         compilation that touches a rule's primary input files if any
    #         would-be additional inputs are newer than the output.  Modifying
    #         the source tree - even just modification times - feels dirty.
    # 6564240 Xcode "custom script" build rules always dump all environment
    #         variables.  This is a low-prioroty problem and is not a
    #         show-stopper.
    rules_by_ext = {}
    for rule in spec_rules:
      rules_by_ext[rule['extension']] = rule

      # First, some definitions:
      #
      # A "rule source" is a file that was listed in a target's "sources"
      # list and will have a rule applied to it on the basis of matching the
      # rule's "extensions" attribute.  Rule sources are direct inputs to
      # rules.
      #
      # Rule definitions may specify additional inputs in their "inputs"
      # attribute.  These additional inputs are used for dependency tracking
      # purposes.
      #
      # A "concrete output" is a rule output with input-dependent variables
      # resolved.  For example, given a rule with:
      #   'extension': 'ext', 'outputs': ['$(INPUT_FILE_BASE).cc'],
      # if the target's "sources" list contained "one.ext" and "two.ext",
      # the "concrete output" for rule input "two.ext" would be "two.cc".  If
      # a rule specifies multiple outputs, each input file that the rule is
      # applied to will have the same number of concrete outputs.
      #
      # If any concrete outputs are outdated or missing relative to their
      # corresponding rule_source or to any specified additional input, the
      # rule action must be performed to generate the concrete outputs.

      # concrete_outputs_by_rule_source will have an item at the same index
      # as the rule['rule_sources'] that it corresponds to.  Each item is a
      # list of all of the concrete outputs for the rule_source.
      concrete_outputs_by_rule_source = []

      # concrete_outputs_all is a flat list of all concrete outputs that this
      # rule is able to produce, given the known set of input files
      # (rule_sources) that apply to it.
      concrete_outputs_all = []

      # messages & actions are keyed by the same indices as rule['rule_sources']
      # and concrete_outputs_by_rule_source.  They contain the message and
      # action to perform after resolving input-dependent variables.  The
      # message is optional, in which case None is stored for each rule source.
      messages = []
      actions = []

      for rule_source in rule.get('rule_sources', []):
        rule_source_dirname, rule_source_basename = \
            posixpath.split(rule_source)
        (rule_source_root, rule_source_ext) = \
            posixpath.splitext(rule_source_basename)

        # These are the same variable names that Xcode uses for its own native
        # rule support.  Because Xcode's rule engine is not being used, they
        # need to be expanded as they are written to the makefile.
        rule_input_dict = {
          'INPUT_FILE_BASE':   rule_source_root,
          'INPUT_FILE_SUFFIX': rule_source_ext,
          'INPUT_FILE_NAME':   rule_source_basename,
          'INPUT_FILE_PATH':   rule_source,
          'INPUT_FILE_DIRNAME': rule_source_dirname,
        }

        concrete_outputs_for_this_rule_source = []
        for output in rule.get('outputs', []):
          # Fortunately, Xcode and make both use $(VAR) format for their
          # variables, so the expansion is the only transformation necessary.
          # Any remaning $(VAR)-type variables in the string can be given
          # directly to make, which will pick up the correct settings from
          # what Xcode puts into the environment.
          concrete_output = ExpandXcodeVariables(output, rule_input_dict)
          concrete_outputs_for_this_rule_source.append(concrete_output)

          # Add all concrete outputs to the project.
          pbxp.AddOrGetFileInRootGroup(concrete_output)

        concrete_outputs_by_rule_source.append( \
            concrete_outputs_for_this_rule_source)
        concrete_outputs_all.extend(concrete_outputs_for_this_rule_source)

        # TODO(mark): Should verify that at most one of these is specified.
        if int(rule.get('process_outputs_as_sources', False)):
          for output in concrete_outputs_for_this_rule_source:
            AddSourceToTarget(output, pbxp, xct)

        # If the file came from the mac_bundle_resources list or if the rule
        # is marked to process outputs as bundle resource, do so.
        was_mac_bundle_resource = rule_source in tgt_mac_bundle_resources
        if was_mac_bundle_resource or \
            int(rule.get('process_outputs_as_mac_bundle_resources', False)):
          for output in concrete_outputs_for_this_rule_source:
            AddResourceToTarget(output, pbxp, xct)

        # Do we have a message to print when this rule runs?
        message = rule.get('message')
        if message:
          message = gyp.common.EncodePOSIXShellArgument(message)
          message = ExpandXcodeVariables(message, rule_input_dict)
        messages.append(message)

        # Turn the list into a string that can be passed to a shell.
        action_string = gyp.common.EncodePOSIXShellList(rule['action'])

        action = ExpandXcodeVariables(action_string, rule_input_dict)
        actions.append(action)

      if len(concrete_outputs_all) > 0:
        # TODO(mark): There's a possibilty for collision here.  Consider
        # target "t" rule "A_r" and target "t_A" rule "r".
        makefile_name = '%s_%s.make' % (target_name, rule['rule_name'])
        makefile_path = os.path.join(xcode_projects[build_file].path,
                                     makefile_name)
        # TODO(mark): try/close?  Write to a temporary file and swap it only
        # if it's got changes?
        makefile = open(makefile_path, 'wb')

        # make will build the first target in the makefile by default.  By
        # convention, it's called "all".  List all (or at least one)
        # concrete output for each rule source as a prerequisite of the "all"
        # target.
        makefile.write('all: \\\n')
        for concrete_output_index in \
            xrange(0, len(concrete_outputs_by_rule_source)):
          # Only list the first (index [0]) concrete output of each input
          # in the "all" target.  Otherwise, a parallel make (-j > 1) would
          # attempt to process each input multiple times simultaneously.
          # Otherwise, "all" could just contain the entire list of
          # concrete_outputs_all.
          concrete_output = \
              concrete_outputs_by_rule_source[concrete_output_index][0]
          if concrete_output_index == len(concrete_outputs_by_rule_source) - 1:
            eol = ''
          else:
            eol = ' \\'
          makefile.write('    %s%s\n' % (concrete_output, eol))

        for (rule_source, concrete_outputs, message, action) in \
            zip(rule['rule_sources'], concrete_outputs_by_rule_source,
                messages, actions):
          makefile.write('\n')

          # Add a rule that declares it can build each concrete output of a
          # rule source.  Collect the names of the directories that are
          # required.
          concrete_output_dirs = []
          for concrete_output_index in xrange(0, len(concrete_outputs)):
            concrete_output = concrete_outputs[concrete_output_index]
            if concrete_output_index == 0:
              bol = ''
            else:
              bol = '    '
            makefile.write('%s%s \\\n' % (bol, concrete_output))

            concrete_output_dir = posixpath.dirname(concrete_output)
            if (concrete_output_dir and
                concrete_output_dir not in concrete_output_dirs):
              concrete_output_dirs.append(concrete_output_dir)

          makefile.write('    : \\\n')

          # The prerequisites for this rule are the rule source itself and
          # the set of additional rule inputs, if any.
          prerequisites = [rule_source]
          prerequisites.extend(rule.get('inputs', []))
          for prerequisite_index in xrange(0, len(prerequisites)):
            prerequisite = prerequisites[prerequisite_index]
            if prerequisite_index == len(prerequisites) - 1:
              eol = ''
            else:
              eol = ' \\'
            makefile.write('    %s%s\n' % (prerequisite, eol))

          # Make sure that output directories exist before executing the rule
          # action.
          if len(concrete_output_dirs) > 0:
            makefile.write('\t@mkdir -p "%s"\n' %
                           '" "'.join(concrete_output_dirs))

          # The rule message and action have already had the necessary variable
          # substitutions performed.
          if message:
            # Mark it with note: so Xcode picks it up in build output.
            makefile.write('\t@echo note: %s\n' % message)
          makefile.write('\t%s\n' % action)

        makefile.close()

        # It might be nice to ensure that needed output directories exist
        # here rather than in each target in the Makefile, but that wouldn't
        # work if there ever was a concrete output that had an input-dependent
        # variable anywhere other than in the leaf position.

        # Don't declare any inputPaths or outputPaths.  If they're present,
        # Xcode will provide a slight optimization by only running the script
        # phase if any output is missing or outdated relative to any input.
        # Unfortunately, it will also assume that all outputs are touched by
        # the script, and if the outputs serve as files in a compilation
        # phase, they will be unconditionally rebuilt.  Since make might not
        # rebuild everything that could be declared here as an output, this
        # extra compilation activity is unnecessary.  With inputPaths and
        # outputPaths not supplied, make will always be called, but it knows
        # enough to not do anything when everything is up-to-date.

        # To help speed things up, pass -j COUNT to make so it does some work
        # in parallel.  Don't use ncpus because Xcode will build ncpus targets
        # in parallel and if each target happens to have a rules step, there
        # would be ncpus^2 things going.  With a machine that has 2 quad-core
        # Xeons, a build can quickly run out of processes based on
        # scheduling/other tasks, and randomly failing builds are no good.
        script = \
"""JOB_COUNT="$(/usr/sbin/sysctl -n hw.ncpu)"
if [ "${JOB_COUNT}" -gt 4 ]; then
  JOB_COUNT=4
fi
exec "${DEVELOPER_BIN_DIR}/make" -f "${PROJECT_FILE_PATH}/%s" -j "${JOB_COUNT}"
exit 1
""" % makefile_name
        ssbp = gyp.xcodeproj_file.PBXShellScriptBuildPhase({
              'name': 'Rule "' + rule['rule_name'] + '"',
              'shellScript': script,
              'showEnvVarsInLog': 0,
            })

        if support_xct:
          support_xct.AppendProperty('buildPhases', ssbp)
        else:
          # TODO(mark): this assumes too much knowledge of the internals of
          # xcodeproj_file; some of these smarts should move into xcodeproj_file
          # itself.
          xct._properties['buildPhases'].insert(prebuild_index, ssbp)
          prebuild_index = prebuild_index + 1

      # Extra rule inputs also go into the project file.  Concrete outputs were
      # already added when they were computed.
      groups = ['inputs', 'inputs_excluded']
      if skip_excluded_files:
        groups = [x for x in groups if not x.endswith('_excluded')]
      for group in groups:
        for item in rule.get(group, []):
          pbxp.AddOrGetFileInRootGroup(item)

    # Add "sources".
    for source in spec.get('sources', []):
      (source_root, source_extension) = posixpath.splitext(source)
      if source_extension[1:] not in rules_by_ext:
        # AddSourceToTarget will add the file to a root group if it's not
        # already there.
        AddSourceToTarget(source, pbxp, xct)
      else:
        pbxp.AddOrGetFileInRootGroup(source)

    # Add "mac_bundle_resources", "mac_framework_headers", and
    # "mac_framework_private_headers" if it's a bundle of any type.
    if is_bundle:
      for resource in tgt_mac_bundle_resources:
        (resource_root, resource_extension) = posixpath.splitext(resource)
        if resource_extension[1:] not in rules_by_ext:
          AddResourceToTarget(resource, pbxp, xct)
        else:
          pbxp.AddOrGetFileInRootGroup(resource)

      for header in spec.get('mac_framework_headers', []):
        AddHeaderToTarget(header, pbxp, xct, True)

      for header in spec.get('mac_framework_private_headers', []):
        AddHeaderToTarget(header, pbxp, xct, False)

    # Add "copies".
    for copy_group in spec.get('copies', []):
      pbxcp = gyp.xcodeproj_file.PBXCopyFilesBuildPhase({
            'name': 'Copy to ' + copy_group['destination']
          },
          parent=xct)
      dest = copy_group['destination']
      if dest[0] not in ('/', '$'):
        # Relative paths are relative to $(SRCROOT).
        dest = '$(SRCROOT)/' + dest
      pbxcp.SetDestination(dest)

      # TODO(mark): The usual comment about this knowing too much about
      # gyp.xcodeproj_file internals applies.
      xct._properties['buildPhases'].insert(prebuild_index, pbxcp)

      for file in copy_group['files']:
        pbxcp.AddFile(file)

    # Excluded files can also go into the project file.
    if not skip_excluded_files:
      for key in ['sources', 'mac_bundle_resources', 'mac_framework_headers',
                  'mac_framework_private_headers']:
        excluded_key = key + '_excluded'
        for item in spec.get(excluded_key, []):
          pbxp.AddOrGetFileInRootGroup(item)

    # So can "inputs" and "outputs" sections of "actions" groups.
    groups = ['inputs', 'inputs_excluded', 'outputs', 'outputs_excluded']
    if skip_excluded_files:
      groups = [x for x in groups if not x.endswith('_excluded')]
    for action in spec.get('actions', []):
      for group in groups:
        for item in action.get(group, []):
          # Exclude anything in BUILT_PRODUCTS_DIR.  They're products, not
          # sources.
          if not item.startswith('$(BUILT_PRODUCTS_DIR)/'):
            pbxp.AddOrGetFileInRootGroup(item)

    for postbuild in spec.get('postbuilds', []):
      action_string_sh = gyp.common.EncodePOSIXShellList(postbuild['action'])
      script = 'exec ' + action_string_sh + '\nexit 1\n'

      # Make the postbuild step depend on the output of ld or ar from this
      # target. Apparently putting the script step after the link step isn't
      # sufficient to ensure proper ordering in all cases. With an input
      # declared but no outputs, the script step should run every time, as
      # desired.
      ssbp = gyp.xcodeproj_file.PBXShellScriptBuildPhase({
            'inputPaths': ['$(BUILT_PRODUCTS_DIR)/$(EXECUTABLE_PATH)'],
            'name': 'Postbuild "' + postbuild['postbuild_name'] + '"',
            'shellScript': script,
            'showEnvVarsInLog': 0,
          })
      xct.AppendProperty('buildPhases', ssbp)

    # Add dependencies before libraries, because adding a dependency may imply
    # adding a library.  It's preferable to keep dependencies listed first
    # during a link phase so that they can override symbols that would
    # otherwise be provided by libraries, which will usually include system
    # libraries.  On some systems, ld is finicky and even requires the
    # libraries to be ordered in such a way that unresolved symbols in
    # earlier-listed libraries may only be resolved by later-listed libraries.
    # The Mac linker doesn't work that way, but other platforms do, and so
    # their linker invocations need to be constructed in this way.  There's
    # no compelling reason for Xcode's linker invocations to differ.

    if 'dependencies' in spec:
      for dependency in spec['dependencies']:
        xct.AddDependency(xcode_targets[dependency])
        # The support project also gets the dependencies (in case they are
        # needed for the actions/rules to work).
        if support_xct:
          support_xct.AddDependency(xcode_targets[dependency])

    if 'libraries' in spec:
      for library in spec['libraries']:
        xct.FrameworksPhase().AddFile(library)
        # Add the library's directory to LIBRARY_SEARCH_PATHS if necessary.
        # I wish Xcode handled this automatically.
        library_dir = posixpath.dirname(library)
        if library_dir not in xcode_standard_library_dirs and (
            not xct.HasBuildSetting(_library_search_paths_var) or
            library_dir not in xct.GetBuildSetting(_library_search_paths_var)):
          xct.AppendBuildSetting(_library_search_paths_var, library_dir)

    for configuration_name in configuration_names:
      configuration = spec['configurations'][configuration_name]
      xcbc = xct.ConfigurationNamed(configuration_name)
      for include_dir in configuration.get('mac_framework_dirs', []):
        xcbc.AppendBuildSetting('FRAMEWORK_SEARCH_PATHS', include_dir)
      for include_dir in configuration.get('include_dirs', []):
        xcbc.AppendBuildSetting('HEADER_SEARCH_PATHS', include_dir)
      if 'defines' in configuration:
        for define in configuration['defines']:
          set_define = EscapeXCodeArgument(define)
          xcbc.AppendBuildSetting('GCC_PREPROCESSOR_DEFINITIONS', set_define)
      if 'xcode_settings' in configuration:
        for xck, xcv in configuration['xcode_settings'].iteritems():
          xcbc.SetBuildSetting(xck, xcv)
      if 'xcode_config_file' in configuration:
        config_ref = pbxp.AddOrGetFileInRootGroup(
            configuration['xcode_config_file'])
        xcbc.SetBaseConfiguration(config_ref)

  build_files = []
  for build_file, build_file_dict in data.iteritems():
    if build_file.endswith('.gyp'):
      build_files.append(build_file)

  for build_file in build_files:
    xcode_projects[build_file].Finalize1(xcode_targets, serialize_all_tests)

  for build_file in build_files:
    xcode_projects[build_file].Finalize2(xcode_targets,
                                         xcode_target_to_target_dict)

  for build_file in build_files:
    xcode_projects[build_file].Write()
