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

import filecmp
import gyp.common
import gyp.xcodeproj_file
import gyp.xcode_ninja
import errno
import os
import sys
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 = [
  'ios_app_extension',
  'mac_bundle',
  'mac_bundle_resources',
  'mac_framework_headers',
  'mac_framework_private_headers',
  'mac_xctest_bundle',
  '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:
      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


def AddSourceToTarget(source, type, 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 and type != 'none':
    xct.SourcesPhase().AddFile(source)
  elif ext in library_extensions and type != 'none':
    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


_xcode_define_re = re.compile(r'([\\\"\' ])')
def EscapeXcodeDefine(s):
  """We must escape the defines that we give to XCode so that it knows not to
     split on spaces and to respect backslash and quote literals. However, we
     must not quote the define, or Xcode will incorrectly intepret variables
     especially $(inherited)."""
  return re.sub(_xcode_define_re, r'\\\1', s)


def PerformBuild(data, configurations, params):
  options = params['options']

  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)

  for config in configurations:
    arguments = ['xcodebuild', '-project', xcodeproj_path]
    arguments += ['-configuration', config]
    print "Building [%s]: %s" % (config, arguments)
    subprocess.check_call(arguments)


def GenerateOutput(target_list, target_dicts, data, params):
  # Optionally configure each spec to use ninja as the external builder.
  ninja_wrapper = params.get('flavor') == 'ninja'
  if ninja_wrapper:
    (target_list, target_dicts, data) = \
        gyp.xcode_ninja.CreateWrapper(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)

    # Add gyp/gypi files to project
    if not generator_flags.get('standalone'):
      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',
      'loadable_module+xctest':      'com.apple.product-type.bundle.unit-test',
      'shared_library+bundle':       'com.apple.product-type.framework',
      'executable+extension+bundle': 'com.apple.product-type.app-extension',
    }

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

    type = spec['type']
    is_xctest = int(spec.get('mac_xctest_bundle', 0))
    is_bundle = int(spec.get('mac_bundle', 0)) or is_xctest
    is_extension = int(spec.get('ios_app_extension', 0))
    if type != 'none':
      type_bundle_key = type
      if is_xctest:
        type_bundle_key += '+xctest'
        assert type == 'loadable_module', (
            'mac_xctest_bundle targets must have type loadable_module '
            '(target %s)' % target_name)
      elif is_extension:
        assert is_bundle, ('ios_app_extension flag requires mac_bundle '
            '(target %s)' % target_name)
        type_bundle_key += '+extension+bundle'
      elif 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)
      assert not is_xctest, (
          'mac_xctest_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 is 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
    # The Xcode "issues" don't affect xcode-ninja builds, since the dependency
    # logic all happens in ninja.  Don't bother creating the extra targets in
    # that case.
    if type != 'none' and (spec_actions or spec_rules) and not ninja_wrapper:
      support_xccl = CreateXCConfigurationList(configuration_names);
      support_target_suffix = generator_flags.get(
          'support_target_suffix', ' Support')
      support_target_properties = {
        'buildConfigurationList': support_xccl,
        'name':                   target_name + support_target_suffix,
      }
      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, type, 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, type, 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.make' % re.sub(
            '[^a-zA-Z0-9_]', '_' , '%s_%s' % (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 xcrun 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, type, pbxp, xct)
      else:
        pbxp.AddOrGetFileInRootGroup(source)

    # Add "mac_bundle_resources" 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_private_headers', []):
        AddHeaderToTarget(header, pbxp, xct, False)

    # Add "mac_framework_headers". These can be valid for both frameworks
    # and static libraries.
    if is_bundle or type == 'static_library':
      for header in spec.get('mac_framework_headers', []):
        AddHeaderToTarget(header, pbxp, xct, True)

    # Add "copies".
    pbxcp_dict = {}
    for copy_group in spec.get('copies', []):
      dest = copy_group['destination']
      if dest[0] not in ('/', '$'):
        # Relative paths are relative to $(SRCROOT).
        dest = '$(SRCROOT)/' + dest

      # Coalesce multiple "copies" sections in the same target with the same
      # "destination" property into the same PBXCopyFilesBuildPhase, otherwise
      # they'll wind up with ID collisions.
      pbxcp = pbxcp_dict.get(dest, None)
      if pbxcp is None:
        pbxcp = gyp.xcodeproj_file.PBXCopyFilesBuildPhase({
              'name': 'Copy to ' + copy_group['destination']
            },
            parent=xct)
        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)

        pbxcp_dict[dest] = 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)
      for library_dir in configuration.get('library_dirs', []):
        if library_dir not in xcode_standard_library_dirs and (
            not xcbc.HasBuildSetting(_library_search_paths_var) or
            library_dir not in xcbc.GetBuildSetting(_library_search_paths_var)):
          xcbc.AppendBuildSetting(_library_search_paths_var, library_dir)

      if 'defines' in configuration:
        for define in configuration['defines']:
          set_define = EscapeXcodeDefine(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()
