# 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.

"""Xcode project file generator.

This module is both an Xcode project file generator and a documentation of the
Xcode project file format.  Knowledge of the project file format was gained
based on extensive experience with Xcode, and by making changes to projects in
Xcode.app and observing the resultant changes in the associated project files.

XCODE PROJECT FILES

The generator targets the file format as written by Xcode 3.2 (specifically,
3.2.6), but past experience has taught that the format has not changed
significantly in the past several years, and future versions of Xcode are able
to read older project files.

Xcode project files are "bundled": the project "file" from an end-user's
perspective is actually a directory with an ".xcodeproj" extension.  The
project file from this module's perspective is actually a file inside this
directory, always named "project.pbxproj".  This file contains a complete
description of the project and is all that is needed to use the xcodeproj.
Other files contained in the xcodeproj directory are simply used to store
per-user settings, such as the state of various UI elements in the Xcode
application.

The project.pbxproj file is a property list, stored in a format almost
identical to the NeXTstep property list format.  The file is able to carry
Unicode data, and is encoded in UTF-8.  The root element in the property list
is a dictionary that contains several properties of minimal interest, and two
properties of immense interest.  The most important property is a dictionary
named "objects".  The entire structure of the project is represented by the
children of this property.  The objects dictionary is keyed by unique 96-bit
values represented by 24 uppercase hexadecimal characters.  Each value in the
objects dictionary is itself a dictionary, describing an individual object.

Each object in the dictionary is a member of a class, which is identified by
the "isa" property of each object.  A variety of classes are represented in a
project file.  Objects can refer to other objects by ID, using the 24-character
hexadecimal object key.  A project's objects form a tree, with a root object
of class PBXProject at the root.  As an example, the PBXProject object serves
as parent to an XCConfigurationList object defining the build configurations
used in the project, a PBXGroup object serving as a container for all files
referenced in the project, and a list of target objects, each of which defines
a target in the project.  There are several different types of target object,
such as PBXNativeTarget and PBXAggregateTarget.  In this module, this
relationship is expressed by having each target type derive from an abstract
base named XCTarget.

The project.pbxproj file's root dictionary also contains a property, sibling to
the "objects" dictionary, named "rootObject".  The value of rootObject is a
24-character object key referring to the root PBXProject object in the
objects dictionary.

In Xcode, every file used as input to a target or produced as a final product
of a target must appear somewhere in the hierarchy rooted at the PBXGroup
object referenced by the PBXProject's mainGroup property.  A PBXGroup is
generally represented as a folder in the Xcode application.  PBXGroups can
contain other PBXGroups as well as PBXFileReferences, which are pointers to
actual files.

Each XCTarget contains a list of build phases, represented in this module by
the abstract base XCBuildPhase.  Examples of concrete XCBuildPhase derivations
are PBXSourcesBuildPhase and PBXFrameworksBuildPhase, which correspond to the
"Compile Sources" and "Link Binary With Libraries" phases displayed in the
Xcode application.  Files used as input to these phases (for example, source
files in the former case and libraries and frameworks in the latter) are
represented by PBXBuildFile objects, referenced by elements of "files" lists
in XCTarget objects.  Each PBXBuildFile object refers to a PBXBuildFile
object as a "weak" reference: it does not "own" the PBXBuildFile, which is
owned by the root object's mainGroup or a descendant group.  In most cases, the
layer of indirection between an XCBuildPhase and a PBXFileReference via a
PBXBuildFile appears extraneous, but there's actually one reason for this:
file-specific compiler flags are added to the PBXBuildFile object so as to
allow a single file to be a member of multiple targets while having distinct
compiler flags for each.  These flags can be modified in the Xcode applciation
in the "Build" tab of a File Info window.

When a project is open in the Xcode application, Xcode will rewrite it.  As
such, this module is careful to adhere to the formatting used by Xcode, to
avoid insignificant changes appearing in the file when it is used in the
Xcode application.  This will keep version control repositories happy, and
makes it possible to compare a project file used in Xcode to one generated by
this module to determine if any significant changes were made in the
application.

Xcode has its own way of assigning 24-character identifiers to each object,
which is not duplicated here.  Because the identifier only is only generated
once, when an object is created, and is then left unchanged, there is no need
to attempt to duplicate Xcode's behavior in this area.  The generator is free
to select any identifier, even at random, to refer to the objects it creates,
and Xcode will retain those identifiers and use them when subsequently
rewriting the project file.  However, the generator would choose new random
identifiers each time the project files are generated, leading to difficulties
comparing "used" project files to "pristine" ones produced by this module,
and causing the appearance of changes as every object identifier is changed
when updated projects are checked in to a version control repository.  To
mitigate this problem, this module chooses identifiers in a more deterministic
way, by hashing a description of each object as well as its parent and ancestor
objects.  This strategy should result in minimal "shift" in IDs as successive
generations of project files are produced.

THIS MODULE

This module introduces several classes, all derived from the XCObject class.
Nearly all of the "brains" are built into the XCObject class, which understands
how to create and modify objects, maintain the proper tree structure, compute
identifiers, and print objects.  For the most part, classes derived from
XCObject need only provide a _schema class object, a dictionary that
expresses what properties objects of the class may contain.

Given this structure, it's possible to build a minimal project file by creating
objects of the appropriate types and making the proper connections:

  config_list = XCConfigurationList()
  group = PBXGroup()
  project = PBXProject({'buildConfigurationList': config_list,
                        'mainGroup': group})

With the project object set up, it can be added to an XCProjectFile object.
XCProjectFile is a pseudo-class in the sense that it is a concrete XCObject
subclass that does not actually correspond to a class type found in a project
file.  Rather, it is used to represent the project file's root dictionary.
Printing an XCProjectFile will print the entire project file, including the
full "objects" dictionary.

  project_file = XCProjectFile({'rootObject': project})
  project_file.ComputeIDs()
  project_file.Print()

Xcode project files are always encoded in UTF-8.  This module will accept
strings of either the str class or the unicode class.  Strings of class str
are assumed to already be encoded in UTF-8.  Obviously, if you're just using
ASCII, you won't encounter difficulties because ASCII is a UTF-8 subset.
Strings of class unicode are handled properly and encoded in UTF-8 when
a project file is output.
"""

import gyp.common
import posixpath
import re
import struct
import sys

# hashlib is supplied as of Python 2.5 as the replacement interface for sha
# and other secure hashes.  In 2.6, sha is deprecated.  Import hashlib if
# available, avoiding a deprecation warning under 2.6.  Import sha otherwise,
# preserving 2.4 compatibility.
try:
  import hashlib
  _new_sha1 = hashlib.sha1
except ImportError:
  import sha
  _new_sha1 = sha.new


# See XCObject._EncodeString.  This pattern is used to determine when a string
# can be printed unquoted.  Strings that match this pattern may be printed
# unquoted.  Strings that do not match must be quoted and may be further
# transformed to be properly encoded.  Note that this expression matches the
# characters listed with "+", for 1 or more occurrences: if a string is empty,
# it must not match this pattern, because it needs to be encoded as "".
_unquoted = re.compile('^[A-Za-z0-9$./_]+$')

# Strings that match this pattern are quoted regardless of what _unquoted says.
# Oddly, Xcode will quote any string with a run of three or more underscores.
_quoted = re.compile('___')

# This pattern should match any character that needs to be escaped by
# XCObject._EncodeString.  See that function.
_escaped = re.compile('[\\\\"]|[^ -~]')


# Used by SourceTreeAndPathFromPath
_path_leading_variable = re.compile('^\$\((.*?)\)(/(.*))?$')

def SourceTreeAndPathFromPath(input_path):
  """Given input_path, returns a tuple with sourceTree and path values.

  Examples:
    input_path     (source_tree, output_path)
    '$(VAR)/path'  ('VAR', 'path')
    '$(VAR)'       ('VAR', None)
    'path'         (None, 'path')
  """

  source_group_match = _path_leading_variable.match(input_path)
  if source_group_match:
    source_tree = source_group_match.group(1)
    output_path = source_group_match.group(3)  # This may be None.
  else:
    source_tree = None
    output_path = input_path

  return (source_tree, output_path)

def ConvertVariablesToShellSyntax(input_string):
  return re.sub('\$\((.*?)\)', '${\\1}', input_string)

class XCObject(object):
  """The abstract base of all class types used in Xcode project files.

  Class variables:
    _schema: A dictionary defining the properties of this class.  The keys to
             _schema are string property keys as used in project files.  Values
             are a list of four or five elements:
             [ is_list, property_type, is_strong, is_required, default ]
             is_list: True if the property described is a list, as opposed
                      to a single element.
             property_type: The type to use as the value of the property,
                            or if is_list is True, the type to use for each
                            element of the value's list.  property_type must
                            be an XCObject subclass, or one of the built-in
                            types str, int, or dict.
             is_strong: If property_type is an XCObject subclass, is_strong
                        is True to assert that this class "owns," or serves
                        as parent, to the property value (or, if is_list is
                        True, values).  is_strong must be False if
                        property_type is not an XCObject subclass.
             is_required: True if the property is required for the class.
                          Note that is_required being True does not preclude
                          an empty string ("", in the case of property_type
                          str) or list ([], in the case of is_list True) from
                          being set for the property.
             default: Optional.  If is_requried is True, default may be set
                      to provide a default value for objects that do not supply
                      their own value.  If is_required is True and default
                      is not provided, users of the class must supply their own
                      value for the property.
             Note that although the values of the array are expressed in
             boolean terms, subclasses provide values as integers to conserve
             horizontal space.
    _should_print_single_line: False in XCObject.  Subclasses whose objects
                               should be written to the project file in the
                               alternate single-line format, such as
                               PBXFileReference and PBXBuildFile, should
                               set this to True.
    _encode_transforms: Used by _EncodeString to encode unprintable characters.
                        The index into this list is the ordinal of the
                        character to transform; each value is a string
                        used to represent the character in the output.  XCObject
                        provides an _encode_transforms list suitable for most
                        XCObject subclasses.
    _alternate_encode_transforms: Provided for subclasses that wish to use
                                  the alternate encoding rules.  Xcode seems
                                  to use these rules when printing objects in
                                  single-line format.  Subclasses that desire
                                  this behavior should set _encode_transforms
                                  to _alternate_encode_transforms.
    _hashables: A list of XCObject subclasses that can be hashed by ComputeIDs
                to construct this object's ID.  Most classes that need custom
                hashing behavior should do it by overriding Hashables,
                but in some cases an object's parent may wish to push a
                hashable value into its child, and it can do so by appending
                to _hashables.
  Attributes:
    id: The object's identifier, a 24-character uppercase hexadecimal string.
        Usually, objects being created should not set id until the entire
        project file structure is built.  At that point, UpdateIDs() should
        be called on the root object to assign deterministic values for id to
        each object in the tree.
    parent: The object's parent.  This is set by a parent XCObject when a child
            object is added to it.
    _properties: The object's property dictionary.  An object's properties are
                 described by its class' _schema variable.
  """

  _schema = {}
  _should_print_single_line = False

  # See _EncodeString.
  _encode_transforms = []
  i = 0
  while i < ord(' '):
    _encode_transforms.append('\\U%04x' % i)
    i = i + 1
  _encode_transforms[7] = '\\a'
  _encode_transforms[8] = '\\b'
  _encode_transforms[9] = '\\t'
  _encode_transforms[10] = '\\n'
  _encode_transforms[11] = '\\v'
  _encode_transforms[12] = '\\f'
  _encode_transforms[13] = '\\n'

  _alternate_encode_transforms = list(_encode_transforms)
  _alternate_encode_transforms[9] = chr(9)
  _alternate_encode_transforms[10] = chr(10)
  _alternate_encode_transforms[11] = chr(11)

  def __init__(self, properties=None, id=None, parent=None):
    self.id = id
    self.parent = parent
    self._properties = {}
    self._hashables = []
    self._SetDefaultsFromSchema()
    self.UpdateProperties(properties)

  def __repr__(self):
    try:
      name = self.Name()
    except NotImplementedError:
      return '<%s at 0x%x>' % (self.__class__.__name__, id(self))
    return '<%s %r at 0x%x>' % (self.__class__.__name__, name, id(self))

  def Copy(self):
    """Make a copy of this object.

    The new object will have its own copy of lists and dicts.  Any XCObject
    objects owned by this object (marked "strong") will be copied in the
    new object, even those found in lists.  If this object has any weak
    references to other XCObjects, the same references are added to the new
    object without making a copy.
    """

    that = self.__class__(id=self.id, parent=self.parent)
    for key, value in self._properties.iteritems():
      is_strong = self._schema[key][2]

      if isinstance(value, XCObject):
        if is_strong:
          new_value = value.Copy()
          new_value.parent = that
          that._properties[key] = new_value
        else:
          that._properties[key] = value
      elif isinstance(value, str) or isinstance(value, unicode) or \
           isinstance(value, int):
        that._properties[key] = value
      elif isinstance(value, list):
        if is_strong:
          # If is_strong is True, each element is an XCObject, so it's safe to
          # call Copy.
          that._properties[key] = []
          for item in value:
            new_item = item.Copy()
            new_item.parent = that
            that._properties[key].append(new_item)
        else:
          that._properties[key] = value[:]
      elif isinstance(value, dict):
        # dicts are never strong.
        if is_strong:
          raise TypeError, 'Strong dict for key ' + key + ' in ' + \
                           self.__class__.__name__
        else:
          that._properties[key] = value.copy()
      else:
        raise TypeError, 'Unexpected type ' + value.__class__.__name__ + \
                         ' for key ' + key + ' in ' + self.__class__.__name__

    return that

  def Name(self):
    """Return the name corresponding to an object.

    Not all objects necessarily need to be nameable, and not all that do have
    a "name" property.  Override as needed.
    """

    # If the schema indicates that "name" is required, try to access the
    # property even if it doesn't exist.  This will result in a KeyError
    # being raised for the property that should be present, which seems more
    # appropriate than NotImplementedError in this case.
    if 'name' in self._properties or \
        ('name' in self._schema and self._schema['name'][3]):
      return self._properties['name']

    raise NotImplementedError, \
          self.__class__.__name__ + ' must implement Name'

  def Comment(self):
    """Return a comment string for the object.

    Most objects just use their name as the comment, but PBXProject uses
    different values.

    The returned comment is not escaped and does not have any comment marker
    strings applied to it.
    """

    return self.Name()

  def Hashables(self):
    hashables = [self.__class__.__name__]

    name = self.Name()
    if name != None:
      hashables.append(name)

    hashables.extend(self._hashables)

    return hashables

  def HashablesForChild(self):
    return None

  def ComputeIDs(self, recursive=True, overwrite=True, seed_hash=None):
    """Set "id" properties deterministically.

    An object's "id" property is set based on a hash of its class type and
    name, as well as the class type and name of all ancestor objects.  As
    such, it is only advisable to call ComputeIDs once an entire project file
    tree is built.

    If recursive is True, recurse into all descendant objects and update their
    hashes.

    If overwrite is True, any existing value set in the "id" property will be
    replaced.
    """

    def _HashUpdate(hash, data):
      """Update hash with data's length and contents.

      If the hash were updated only with the value of data, it would be
      possible for clowns to induce collisions by manipulating the names of
      their objects.  By adding the length, it's exceedingly less likely that
      ID collisions will be encountered, intentionally or not.
      """

      hash.update(struct.pack('>i', len(data)))
      hash.update(data)

    if seed_hash is None:
      seed_hash = _new_sha1()

    hash = seed_hash.copy()

    hashables = self.Hashables()
    assert len(hashables) > 0
    for hashable in hashables:
      _HashUpdate(hash, hashable)

    if recursive:
      hashables_for_child = self.HashablesForChild()
      if hashables_for_child is None:
        child_hash = hash
      else:
        assert len(hashables_for_child) > 0
        child_hash = seed_hash.copy()
        for hashable in hashables_for_child:
          _HashUpdate(child_hash, hashable)

      for child in self.Children():
        child.ComputeIDs(recursive, overwrite, child_hash)

    if overwrite or self.id is None:
      # Xcode IDs are only 96 bits (24 hex characters), but a SHA-1 digest is
      # is 160 bits.  Instead of throwing out 64 bits of the digest, xor them
      # into the portion that gets used.
      assert hash.digest_size % 4 == 0
      digest_int_count = hash.digest_size / 4
      digest_ints = struct.unpack('>' + 'I' * digest_int_count, hash.digest())
      id_ints = [0, 0, 0]
      for index in xrange(0, digest_int_count):
        id_ints[index % 3] ^= digest_ints[index]
      self.id = '%08X%08X%08X' % tuple(id_ints)

  def EnsureNoIDCollisions(self):
    """Verifies that no two objects have the same ID.  Checks all descendants.
    """

    ids = {}
    descendants = self.Descendants()
    for descendant in descendants:
      if descendant.id in ids:
        other = ids[descendant.id]
        raise KeyError, \
              'Duplicate ID %s, objects "%s" and "%s" in "%s"' % \
              (descendant.id, str(descendant._properties),
               str(other._properties), self._properties['rootObject'].Name())
      ids[descendant.id] = descendant

  def Children(self):
    """Returns a list of all of this object's owned (strong) children."""

    children = []
    for property, attributes in self._schema.iteritems():
      (is_list, property_type, is_strong) = attributes[0:3]
      if is_strong and property in self._properties:
        if not is_list:
          children.append(self._properties[property])
        else:
          children.extend(self._properties[property])
    return children

  def Descendants(self):
    """Returns a list of all of this object's descendants, including this
    object.
    """

    children = self.Children()
    descendants = [self]
    for child in children:
      descendants.extend(child.Descendants())
    return descendants

  def PBXProjectAncestor(self):
    # The base case for recursion is defined at PBXProject.PBXProjectAncestor.
    if self.parent:
      return self.parent.PBXProjectAncestor()
    return None

  def _EncodeComment(self, comment):
    """Encodes a comment to be placed in the project file output, mimicing
    Xcode behavior.
    """

    # This mimics Xcode behavior by wrapping the comment in "/*" and "*/".  If
    # the string already contains a "*/", it is turned into "(*)/".  This keeps
    # the file writer from outputting something that would be treated as the
    # end of a comment in the middle of something intended to be entirely a
    # comment.

    return '/* ' + comment.replace('*/', '(*)/') + ' */'

  def _EncodeTransform(self, match):
    # This function works closely with _EncodeString.  It will only be called
    # by re.sub with match.group(0) containing a character matched by the
    # the _escaped expression.
    char = match.group(0)

    # Backslashes (\) and quotation marks (") are always replaced with a
    # backslash-escaped version of the same.  Everything else gets its
    # replacement from the class' _encode_transforms array.
    if char == '\\':
      return '\\\\'
    if char == '"':
      return '\\"'
    return self._encode_transforms[ord(char)]

  def _EncodeString(self, value):
    """Encodes a string to be placed in the project file output, mimicing
    Xcode behavior.
    """

    # Use quotation marks when any character outside of the range A-Z, a-z, 0-9,
    # $ (dollar sign), . (period), and _ (underscore) is present.  Also use
    # quotation marks to represent empty strings.
    #
    # Escape " (double-quote) and \ (backslash) by preceding them with a
    # backslash.
    #
    # Some characters below the printable ASCII range are encoded specially:
    #     7 ^G BEL is encoded as "\a"
    #     8 ^H BS  is encoded as "\b"
    #    11 ^K VT  is encoded as "\v"
    #    12 ^L NP  is encoded as "\f"
    #   127 ^? DEL is passed through as-is without escaping
    #  - In PBXFileReference and PBXBuildFile objects:
    #     9 ^I HT  is passed through as-is without escaping
    #    10 ^J NL  is passed through as-is without escaping
    #    13 ^M CR  is passed through as-is without escaping
    #  - In other objects:
    #     9 ^I HT  is encoded as "\t"
    #    10 ^J NL  is encoded as "\n"
    #    13 ^M CR  is encoded as "\n" rendering it indistinguishable from
    #              10 ^J NL
    # All other nonprintable characters within the ASCII range (0 through 127
    # inclusive) are encoded as "\U001f" referring to the Unicode code point in
    # hexadecimal.  For example, character 14 (^N SO) is encoded as "\U000e".
    # Characters above the ASCII range are passed through to the output encoded
    # as UTF-8 without any escaping.  These mappings are contained in the
    # class' _encode_transforms list.

    if _unquoted.search(value) and not _quoted.search(value):
      return value

    return '"' + _escaped.sub(self._EncodeTransform, value) + '"'

  def _XCPrint(self, file, tabs, line):
    file.write('\t' * tabs + line)

  def _XCPrintableValue(self, tabs, value, flatten_list=False):
    """Returns a representation of value that may be printed in a project file,
    mimicing Xcode's behavior.

    _XCPrintableValue can handle str and int values, XCObjects (which are
    made printable by returning their id property), and list and dict objects
    composed of any of the above types.  When printing a list or dict, and
    _should_print_single_line is False, the tabs parameter is used to determine
    how much to indent the lines corresponding to the items in the list or
    dict.

    If flatten_list is True, single-element lists will be transformed into
    strings.
    """

    printable = ''
    comment = None

    if self._should_print_single_line:
      sep = ' '
      element_tabs = ''
      end_tabs = ''
    else:
      sep = '\n'
      element_tabs = '\t' * (tabs + 1)
      end_tabs = '\t' * tabs

    if isinstance(value, XCObject):
      printable += value.id
      comment = value.Comment()
    elif isinstance(value, str):
      printable += self._EncodeString(value)
    elif isinstance(value, unicode):
      printable += self._EncodeString(value.encode('utf-8'))
    elif isinstance(value, int):
      printable += str(value)
    elif isinstance(value, list):
      if flatten_list and len(value) <= 1:
        if len(value) == 0:
          printable += self._EncodeString('')
        else:
          printable += self._EncodeString(value[0])
      else:
        printable = '(' + sep
        for item in value:
          printable += element_tabs + \
                       self._XCPrintableValue(tabs + 1, item, flatten_list) + \
                       ',' + sep
        printable += end_tabs + ')'
    elif isinstance(value, dict):
      printable = '{' + sep
      for item_key, item_value in sorted(value.iteritems()):
        printable += element_tabs + \
            self._XCPrintableValue(tabs + 1, item_key, flatten_list) + ' = ' + \
            self._XCPrintableValue(tabs + 1, item_value, flatten_list) + ';' + \
            sep
      printable += end_tabs + '}'
    else:
      raise TypeError, "Can't make " + value.__class__.__name__ + ' printable'

    if comment != None:
      printable += ' ' + self._EncodeComment(comment)

    return printable

  def _XCKVPrint(self, file, tabs, key, value):
    """Prints a key and value, members of an XCObject's _properties dictionary,
    to file.

    tabs is an int identifying the indentation level.  If the class'
    _should_print_single_line variable is True, tabs is ignored and the
    key-value pair will be followed by a space insead of a newline.
    """

    if self._should_print_single_line:
      printable = ''
      after_kv = ' '
    else:
      printable = '\t' * tabs
      after_kv = '\n'

    # Xcode usually prints remoteGlobalIDString values in PBXContainerItemProxy
    # objects without comments.  Sometimes it prints them with comments, but
    # the majority of the time, it doesn't.  To avoid unnecessary changes to
    # the project file after Xcode opens it, don't write comments for
    # remoteGlobalIDString.  This is a sucky hack and it would certainly be
    # cleaner to extend the schema to indicate whether or not a comment should
    # be printed, but since this is the only case where the problem occurs and
    # Xcode itself can't seem to make up its mind, the hack will suffice.
    #
    # Also see PBXContainerItemProxy._schema['remoteGlobalIDString'].
    if key == 'remoteGlobalIDString' and isinstance(self,
                                                    PBXContainerItemProxy):
      value_to_print = value.id
    else:
      value_to_print = value

    # PBXBuildFile's settings property is represented in the output as a dict,
    # but a hack here has it represented as a string. Arrange to strip off the
    # quotes so that it shows up in the output as expected.
    if key == 'settings' and isinstance(self, PBXBuildFile):
      strip_value_quotes = True
    else:
      strip_value_quotes = False

    # In another one-off, let's set flatten_list on buildSettings properties
    # of XCBuildConfiguration objects, because that's how Xcode treats them.
    if key == 'buildSettings' and isinstance(self, XCBuildConfiguration):
      flatten_list = True
    else:
      flatten_list = False

    try:
      printable_key = self._XCPrintableValue(tabs, key, flatten_list)
      printable_value = self._XCPrintableValue(tabs, value_to_print,
                                               flatten_list)
      if strip_value_quotes and len(printable_value) > 1 and \
          printable_value[0] == '"' and printable_value[-1] == '"':
        printable_value = printable_value[1:-1]
      printable += printable_key + ' = ' + printable_value + ';' + after_kv
    except TypeError, e:
      gyp.common.ExceptionAppend(e,
                                 'while printing key "%s"' % key)
      raise

    self._XCPrint(file, 0, printable)

  def Print(self, file=sys.stdout):
    """Prints a reprentation of this object to file, adhering to Xcode output
    formatting.
    """

    self.VerifyHasRequiredProperties()

    if self._should_print_single_line:
      # When printing an object in a single line, Xcode doesn't put any space
      # between the beginning of a dictionary (or presumably a list) and the
      # first contained item, so you wind up with snippets like
      #   ...CDEF = {isa = PBXFileReference; fileRef = 0123...
      # If it were me, I would have put a space in there after the opening
      # curly, but I guess this is just another one of those inconsistencies
      # between how Xcode prints PBXFileReference and PBXBuildFile objects as
      # compared to other objects.  Mimic Xcode's behavior here by using an
      # empty string for sep.
      sep = ''
      end_tabs = 0
    else:
      sep = '\n'
      end_tabs = 2

    # Start the object.  For example, '\t\tPBXProject = {\n'.
    self._XCPrint(file, 2, self._XCPrintableValue(2, self) + ' = {' + sep)

    # "isa" isn't in the _properties dictionary, it's an intrinsic property
    # of the class which the object belongs to.  Xcode always outputs "isa"
    # as the first element of an object dictionary.
    self._XCKVPrint(file, 3, 'isa', self.__class__.__name__)

    # The remaining elements of an object dictionary are sorted alphabetically.
    for property, value in sorted(self._properties.iteritems()):
      self._XCKVPrint(file, 3, property, value)

    # End the object.
    self._XCPrint(file, end_tabs, '};\n')

  def UpdateProperties(self, properties, do_copy=False):
    """Merge the supplied properties into the _properties dictionary.

    The input properties must adhere to the class schema or a KeyError or
    TypeError exception will be raised.  If adding an object of an XCObject
    subclass and the schema indicates a strong relationship, the object's
    parent will be set to this object.

    If do_copy is True, then lists, dicts, strong-owned XCObjects, and
    strong-owned XCObjects in lists will be copied instead of having their
    references added.
    """

    if properties is None:
      return

    for property, value in properties.iteritems():
      # Make sure the property is in the schema.
      if not property in self._schema:
        raise KeyError, property + ' not in ' + self.__class__.__name__

      # Make sure the property conforms to the schema.
      (is_list, property_type, is_strong) = self._schema[property][0:3]
      if is_list:
        if value.__class__ != list:
          raise TypeError, \
                property + ' of ' + self.__class__.__name__ + \
                ' must be list, not ' + value.__class__.__name__
        for item in value:
          if not isinstance(item, property_type) and \
             not (item.__class__ == unicode and property_type == str):
            # Accept unicode where str is specified.  str is treated as
            # UTF-8-encoded.
            raise TypeError, \
                  'item of ' + property + ' of ' + self.__class__.__name__ + \
                  ' must be ' + property_type.__name__ + ', not ' + \
                  item.__class__.__name__
      elif not isinstance(value, property_type) and \
           not (value.__class__ == unicode and property_type == str):
        # Accept unicode where str is specified.  str is treated as
        # UTF-8-encoded.
        raise TypeError, \
              property + ' of ' + self.__class__.__name__ + ' must be ' + \
              property_type.__name__ + ', not ' + value.__class__.__name__

      # Checks passed, perform the assignment.
      if do_copy:
        if isinstance(value, XCObject):
          if is_strong:
            self._properties[property] = value.Copy()
          else:
            self._properties[property] = value
        elif isinstance(value, str) or isinstance(value, unicode) or \
             isinstance(value, int):
          self._properties[property] = value
        elif isinstance(value, list):
          if is_strong:
            # If is_strong is True, each element is an XCObject, so it's safe
            # to call Copy.
            self._properties[property] = []
            for item in value:
              self._properties[property].append(item.Copy())
          else:
            self._properties[property] = value[:]
        elif isinstance(value, dict):
          self._properties[property] = value.copy()
        else:
          raise TypeError, "Don't know how to copy a " + \
                           value.__class__.__name__ + ' object for ' + \
                           property + ' in ' + self.__class__.__name__
      else:
        self._properties[property] = value

      # Set up the child's back-reference to this object.  Don't use |value|
      # any more because it may not be right if do_copy is true.
      if is_strong:
        if not is_list:
          self._properties[property].parent = self
        else:
          for item in self._properties[property]:
            item.parent = self

  def HasProperty(self, key):
    return key in self._properties

  def GetProperty(self, key):
    return self._properties[key]

  def SetProperty(self, key, value):
    self.UpdateProperties({key: value})

  def DelProperty(self, key):
    if key in self._properties:
      del self._properties[key]

  def AppendProperty(self, key, value):
    # TODO(mark): Support ExtendProperty too (and make this call that)?

    # Schema validation.
    if not key in self._schema:
      raise KeyError, key + ' not in ' + self.__class__.__name__

    (is_list, property_type, is_strong) = self._schema[key][0:3]
    if not is_list:
      raise TypeError, key + ' of ' + self.__class__.__name__ + ' must be list'
    if not isinstance(value, property_type):
      raise TypeError, 'item of ' + key + ' of ' + self.__class__.__name__ + \
                       ' must be ' + property_type.__name__ + ', not ' + \
                       value.__class__.__name__

    # If the property doesn't exist yet, create a new empty list to receive the
    # item.
    if not key in self._properties:
      self._properties[key] = []

    # Set up the ownership link.
    if is_strong:
      value.parent = self

    # Store the item.
    self._properties[key].append(value)

  def VerifyHasRequiredProperties(self):
    """Ensure that all properties identified as required by the schema are
    set.
    """

    # TODO(mark): A stronger verification mechanism is needed.  Some
    # subclasses need to perform validation beyond what the schema can enforce.
    for property, attributes in self._schema.iteritems():
      (is_list, property_type, is_strong, is_required) = attributes[0:4]
      if is_required and not property in self._properties:
        raise KeyError, self.__class__.__name__ + ' requires ' + property

  def _SetDefaultsFromSchema(self):
    """Assign object default values according to the schema.  This will not
    overwrite properties that have already been set."""

    defaults = {}
    for property, attributes in self._schema.iteritems():
      (is_list, property_type, is_strong, is_required) = attributes[0:4]
      if is_required and len(attributes) >= 5 and \
          not property in self._properties:
        default = attributes[4]

        defaults[property] = default

    if len(defaults) > 0:
      # Use do_copy=True so that each new object gets its own copy of strong
      # objects, lists, and dicts.
      self.UpdateProperties(defaults, do_copy=True)


class XCHierarchicalElement(XCObject):
  """Abstract base for PBXGroup and PBXFileReference.  Not represented in a
  project file."""

  # TODO(mark): Do name and path belong here?  Probably so.
  # If path is set and name is not, name may have a default value.  Name will
  # be set to the basename of path, if the basename of path is different from
  # the full value of path.  If path is already just a leaf name, name will
  # not be set.
  _schema = XCObject._schema.copy()
  _schema.update({
    'comments':       [0, str, 0, 0],
    'fileEncoding':   [0, str, 0, 0],
    'includeInIndex': [0, int, 0, 0],
    'indentWidth':    [0, int, 0, 0],
    'lineEnding':     [0, int, 0, 0],
    'sourceTree':     [0, str, 0, 1, '<group>'],
    'tabWidth':       [0, int, 0, 0],
    'usesTabs':       [0, int, 0, 0],
    'wrapsLines':     [0, int, 0, 0],
  })

  def __init__(self, properties=None, id=None, parent=None):
    # super
    XCObject.__init__(self, properties, id, parent)
    if 'path' in self._properties and not 'name' in self._properties:
      path = self._properties['path']
      name = posixpath.basename(path)
      if name != '' and path != name:
        self.SetProperty('name', name)

    if 'path' in self._properties and \
        (not 'sourceTree' in self._properties or \
         self._properties['sourceTree'] == '<group>'):
      # If the pathname begins with an Xcode variable like "$(SDKROOT)/", take
      # the variable out and make the path be relative to that variable by
      # assigning the variable name as the sourceTree.
      (source_tree, path) = SourceTreeAndPathFromPath(self._properties['path'])
      if source_tree != None:
        self._properties['sourceTree'] = source_tree
      if path != None:
        self._properties['path'] = path
      if source_tree != None and path is None and \
         not 'name' in self._properties:
        # The path was of the form "$(SDKROOT)" with no path following it.
        # This object is now relative to that variable, so it has no path
        # attribute of its own.  It does, however, keep a name.
        del self._properties['path']
        self._properties['name'] = source_tree

  def Name(self):
    if 'name' in self._properties:
      return self._properties['name']
    elif 'path' in self._properties:
      return self._properties['path']
    else:
      # This happens in the case of the root PBXGroup.
      return None

  def Hashables(self):
    """Custom hashables for XCHierarchicalElements.

    XCHierarchicalElements are special.  Generally, their hashes shouldn't
    change if the paths don't change.  The normal XCObject implementation of
    Hashables adds a hashable for each object, which means that if
    the hierarchical structure changes (possibly due to changes caused when
    TakeOverOnlyChild runs and encounters slight changes in the hierarchy),
    the hashes will change.  For example, if a project file initially contains
    a/b/f1 and a/b becomes collapsed into a/b, f1 will have a single parent
    a/b.  If someone later adds a/f2 to the project file, a/b can no longer be
    collapsed, and f1 winds up with parent b and grandparent a.  That would
    be sufficient to change f1's hash.

    To counteract this problem, hashables for all XCHierarchicalElements except
    for the main group (which has neither a name nor a path) are taken to be
    just the set of path components.  Because hashables are inherited from
    parents, this provides assurance that a/b/f1 has the same set of hashables
    whether its parent is b or a/b.

    The main group is a special case.  As it is permitted to have no name or
    path, it is permitted to use the standard XCObject hash mechanism.  This
    is not considered a problem because there can be only one main group.
    """

    if self == self.PBXProjectAncestor()._properties['mainGroup']:
      # super
      return XCObject.Hashables(self)

    hashables = []

    # Put the name in first, ensuring that if TakeOverOnlyChild collapses
    # children into a top-level group like "Source", the name always goes
    # into the list of hashables without interfering with path components.
    if 'name' in self._properties:
      # Make it less likely for people to manipulate hashes by following the
      # pattern of always pushing an object type value onto the list first.
      hashables.append(self.__class__.__name__ + '.name')
      hashables.append(self._properties['name'])

    # NOTE: This still has the problem that if an absolute path is encountered,
    # including paths with a sourceTree, they'll still inherit their parents'
    # hashables, even though the paths aren't relative to their parents.  This
    # is not expected to be much of a problem in practice.
    path = self.PathFromSourceTreeAndPath()
    if path != None:
      components = path.split(posixpath.sep)
      for component in components:
        hashables.append(self.__class__.__name__ + '.path')
        hashables.append(component)

    hashables.extend(self._hashables)

    return hashables

  def Compare(self, other):
    # Allow comparison of these types.  PBXGroup has the highest sort rank;
    # PBXVariantGroup is treated as equal to PBXFileReference.
    valid_class_types = {
      PBXFileReference: 'file',
      PBXGroup:         'group',
      PBXVariantGroup:  'file',
    }
    self_type = valid_class_types[self.__class__]
    other_type = valid_class_types[other.__class__]

    if self_type == other_type:
      # If the two objects are of the same sort rank, compare their names.
      return cmp(self.Name(), other.Name())

    # Otherwise, sort groups before everything else.
    if self_type == 'group':
      return -1
    return 1

  def CompareRootGroup(self, other):
    # This function should be used only to compare direct children of the
    # containing PBXProject's mainGroup.  These groups should appear in the
    # listed order.
    # TODO(mark): "Build" is used by gyp.generator.xcode, perhaps the
    # generator should have a way of influencing this list rather than having
    # to hardcode for the generator here.
    order = ['Source', 'Intermediates', 'Projects', 'Frameworks', 'Products',
             'Build']

    # If the groups aren't in the listed order, do a name comparison.
    # Otherwise, groups in the listed order should come before those that
    # aren't.
    self_name = self.Name()
    other_name = other.Name()
    self_in = isinstance(self, PBXGroup) and self_name in order
    other_in = isinstance(self, PBXGroup) and other_name in order
    if not self_in and not other_in:
      return self.Compare(other)
    if self_name in order and not other_name in order:
      return -1
    if other_name in order and not self_name in order:
      return 1

    # If both groups are in the listed order, go by the defined order.
    self_index = order.index(self_name)
    other_index = order.index(other_name)
    if self_index < other_index:
      return -1
    if self_index > other_index:
      return 1
    return 0

  def PathFromSourceTreeAndPath(self):
    # Turn the object's sourceTree and path properties into a single flat
    # string of a form comparable to the path parameter.  If there's a
    # sourceTree property other than "<group>", wrap it in $(...) for the
    # comparison.
    components = []
    if self._properties['sourceTree'] != '<group>':
      components.append('$(' + self._properties['sourceTree'] + ')')
    if 'path' in self._properties:
      components.append(self._properties['path'])

    if len(components) > 0:
      return posixpath.join(*components)

    return None

  def FullPath(self):
    # Returns a full path to self relative to the project file, or relative
    # to some other source tree.  Start with self, and walk up the chain of
    # parents prepending their paths, if any, until no more parents are
    # available (project-relative path) or until a path relative to some
    # source tree is found.
    xche = self
    path = None
    while isinstance(xche, XCHierarchicalElement) and \
          (path is None or \
           (not path.startswith('/') and not path.startswith('$'))):
      this_path = xche.PathFromSourceTreeAndPath()
      if this_path != None and path != None:
        path = posixpath.join(this_path, path)
      elif this_path != None:
        path = this_path
      xche = xche.parent

    return path


class PBXGroup(XCHierarchicalElement):
  """
  Attributes:
    _children_by_path: Maps pathnames of children of this PBXGroup to the
      actual child XCHierarchicalElement objects.
    _variant_children_by_name_and_path: Maps (name, path) tuples of
      PBXVariantGroup children to the actual child PBXVariantGroup objects.
  """

  _schema = XCHierarchicalElement._schema.copy()
  _schema.update({
    'children': [1, XCHierarchicalElement, 1, 1, []],
    'name':     [0, str,                   0, 0],
    'path':     [0, str,                   0, 0],
  })

  def __init__(self, properties=None, id=None, parent=None):
    # super
    XCHierarchicalElement.__init__(self, properties, id, parent)
    self._children_by_path = {}
    self._variant_children_by_name_and_path = {}
    for child in self._properties.get('children', []):
      self._AddChildToDicts(child)

  def Hashables(self):
    # super
    hashables = XCHierarchicalElement.Hashables(self)

    # It is not sufficient to just rely on name and parent to build a unique
    # hashable : a node could have two child PBXGroup sharing a common name.
    # To add entropy the hashable is enhanced with the names of all its
    # children.
    for child in self._properties.get('children', []):
      child_name = child.Name()
      if child_name != None:
        hashables.append(child_name)

    return hashables

  def HashablesForChild(self):
    # To avoid a circular reference the hashables used to compute a child id do
    # not include the child names.
    return XCHierarchicalElement.Hashables(self)

  def _AddChildToDicts(self, child):
    # Sets up this PBXGroup object's dicts to reference the child properly.
    child_path = child.PathFromSourceTreeAndPath()
    if child_path:
      if child_path in self._children_by_path:
        raise ValueError, 'Found multiple children with path ' + child_path
      self._children_by_path[child_path] = child

    if isinstance(child, PBXVariantGroup):
      child_name = child._properties.get('name', None)
      key = (child_name, child_path)
      if key in self._variant_children_by_name_and_path:
        raise ValueError, 'Found multiple PBXVariantGroup children with ' + \
                          'name ' + str(child_name) + ' and path ' + \
                          str(child_path)
      self._variant_children_by_name_and_path[key] = child

  def AppendChild(self, child):
    # Callers should use this instead of calling
    # AppendProperty('children', child) directly because this function
    # maintains the group's dicts.
    self.AppendProperty('children', child)
    self._AddChildToDicts(child)

  def GetChildByName(self, name):
    # This is not currently optimized with a dict as GetChildByPath is because
    # it has few callers.  Most callers probably want GetChildByPath.  This
    # function is only useful to get children that have names but no paths,
    # which is rare.  The children of the main group ("Source", "Products",
    # etc.) is pretty much the only case where this likely to come up.
    #
    # TODO(mark): Maybe this should raise an error if more than one child is
    # present with the same name.
    if not 'children' in self._properties:
      return None

    for child in self._properties['children']:
      if child.Name() == name:
        return child

    return None

  def GetChildByPath(self, path):
    if not path:
      return None

    if path in self._children_by_path:
      return self._children_by_path[path]

    return None

  def GetChildByRemoteObject(self, remote_object):
    # This method is a little bit esoteric.  Given a remote_object, which
    # should be a PBXFileReference in another project file, this method will
    # return this group's PBXReferenceProxy object serving as a local proxy
    # for the remote PBXFileReference.
    #
    # This function might benefit from a dict optimization as GetChildByPath
    # for some workloads, but profiling shows that it's not currently a
    # problem.
    if not 'children' in self._properties:
      return None

    for child in self._properties['children']:
      if not isinstance(child, PBXReferenceProxy):
        continue

      container_proxy = child._properties['remoteRef']
      if container_proxy._properties['remoteGlobalIDString'] == remote_object:
        return child

    return None

  def AddOrGetFileByPath(self, path, hierarchical):
    """Returns an existing or new file reference corresponding to path.

    If hierarchical is True, this method will create or use the necessary
    hierarchical group structure corresponding to path.  Otherwise, it will
    look in and create an item in the current group only.

    If an existing matching reference is found, it is returned, otherwise, a
    new one will be created, added to the correct group, and returned.

    If path identifies a directory by virtue of carrying a trailing slash,
    this method returns a PBXFileReference of "folder" type.  If path
    identifies a variant, by virtue of it identifying a file inside a directory
    with an ".lproj" extension, this method returns a PBXVariantGroup
    containing the variant named by path, and possibly other variants.  For
    all other paths, a "normal" PBXFileReference will be returned.
    """

    # Adding or getting a directory?  Directories end with a trailing slash.
    is_dir = False
    if path.endswith('/'):
      is_dir = True
    path = posixpath.normpath(path)
    if is_dir:
      path = path + '/'

    # Adding or getting a variant?  Variants are files inside directories
    # with an ".lproj" extension.  Xcode uses variants for localization.  For
    # a variant path/to/Language.lproj/MainMenu.nib, put a variant group named
    # MainMenu.nib inside path/to, and give it a variant named Language.  In
    # this example, grandparent would be set to path/to and parent_root would
    # be set to Language.
    variant_name = None
    parent = posixpath.dirname(path)
    grandparent = posixpath.dirname(parent)
    parent_basename = posixpath.basename(parent)
    (parent_root, parent_ext) = posixpath.splitext(parent_basename)
    if parent_ext == '.lproj':
      variant_name = parent_root
    if grandparent == '':
      grandparent = None

    # Putting a directory inside a variant group is not currently supported.
    assert not is_dir or variant_name is None

    path_split = path.split(posixpath.sep)
    if len(path_split) == 1 or \
       ((is_dir or variant_name != None) and len(path_split) == 2) or \
       not hierarchical:
      # The PBXFileReference or PBXVariantGroup will be added to or gotten from
      # this PBXGroup, no recursion necessary.
      if variant_name is None:
        # Add or get a PBXFileReference.
        file_ref = self.GetChildByPath(path)
        if file_ref != None:
          assert file_ref.__class__ == PBXFileReference
        else:
          file_ref = PBXFileReference({'path': path})
          self.AppendChild(file_ref)
      else:
        # Add or get a PBXVariantGroup.  The variant group name is the same
        # as the basename (MainMenu.nib in the example above).  grandparent
        # specifies the path to the variant group itself, and path_split[-2:]
        # is the path of the specific variant relative to its group.
        variant_group_name = posixpath.basename(path)
        variant_group_ref = self.AddOrGetVariantGroupByNameAndPath(
            variant_group_name, grandparent)
        variant_path = posixpath.sep.join(path_split[-2:])
        variant_ref = variant_group_ref.GetChildByPath(variant_path)
        if variant_ref != None:
          assert variant_ref.__class__ == PBXFileReference
        else:
          variant_ref = PBXFileReference({'name': variant_name,
                                          'path': variant_path})
          variant_group_ref.AppendChild(variant_ref)
        # The caller is interested in the variant group, not the specific
        # variant file.
        file_ref = variant_group_ref
      return file_ref
    else:
      # Hierarchical recursion.  Add or get a PBXGroup corresponding to the
      # outermost path component, and then recurse into it, chopping off that
      # path component.
      next_dir = path_split[0]
      group_ref = self.GetChildByPath(next_dir)
      if group_ref != None:
        assert group_ref.__class__ == PBXGroup
      else:
        group_ref = PBXGroup({'path': next_dir})
        self.AppendChild(group_ref)
      return group_ref.AddOrGetFileByPath(posixpath.sep.join(path_split[1:]),
                                          hierarchical)

  def AddOrGetVariantGroupByNameAndPath(self, name, path):
    """Returns an existing or new PBXVariantGroup for name and path.

    If a PBXVariantGroup identified by the name and path arguments is already
    present as a child of this object, it is returned.  Otherwise, a new
    PBXVariantGroup with the correct properties is created, added as a child,
    and returned.

    This method will generally be called by AddOrGetFileByPath, which knows
    when to create a variant group based on the structure of the pathnames
    passed to it.
    """

    key = (name, path)
    if key in self._variant_children_by_name_and_path:
      variant_group_ref = self._variant_children_by_name_and_path[key]
      assert variant_group_ref.__class__ == PBXVariantGroup
      return variant_group_ref

    variant_group_properties = {'name': name}
    if path != None:
      variant_group_properties['path'] = path
    variant_group_ref = PBXVariantGroup(variant_group_properties)
    self.AppendChild(variant_group_ref)

    return variant_group_ref

  def TakeOverOnlyChild(self, recurse=False):
    """If this PBXGroup has only one child and it's also a PBXGroup, take
    it over by making all of its children this object's children.

    This function will continue to take over only children when those children
    are groups.  If there are three PBXGroups representing a, b, and c, with
    c inside b and b inside a, and a and b have no other children, this will
    result in a taking over both b and c, forming a PBXGroup for a/b/c.

    If recurse is True, this function will recurse into children and ask them
    to collapse themselves by taking over only children as well.  Assuming
    an example hierarchy with files at a/b/c/d1, a/b/c/d2, and a/b/c/d3/e/f
    (d1, d2, and f are files, the rest are groups), recursion will result in
    a group for a/b/c containing a group for d3/e.
    """

    # At this stage, check that child class types are PBXGroup exactly,
    # instead of using isinstance.  The only subclass of PBXGroup,
    # PBXVariantGroup, should not participate in reparenting in the same way:
    # reparenting by merging different object types would be wrong.
    while len(self._properties['children']) == 1 and \
          self._properties['children'][0].__class__ == PBXGroup:
      # Loop to take over the innermost only-child group possible.

      child = self._properties['children'][0]

      # Assume the child's properties, including its children.  Save a copy
      # of this object's old properties, because they'll still be needed.
      # This object retains its existing id and parent attributes.
      old_properties = self._properties
      self._properties = child._properties
      self._children_by_path = child._children_by_path

      if not 'sourceTree' in self._properties or \
         self._properties['sourceTree'] == '<group>':
        # The child was relative to its parent.  Fix up the path.  Note that
        # children with a sourceTree other than "<group>" are not relative to
        # their parents, so no path fix-up is needed in that case.
        if 'path' in old_properties:
          if 'path' in self._properties:
            # Both the original parent and child have paths set.
            self._properties['path'] = posixpath.join(old_properties['path'],
                                                      self._properties['path'])
          else:
            # Only the original parent has a path, use it.
            self._properties['path'] = old_properties['path']
        if 'sourceTree' in old_properties:
          # The original parent had a sourceTree set, use it.
          self._properties['sourceTree'] = old_properties['sourceTree']

      # If the original parent had a name set, keep using it.  If the original
      # parent didn't have a name but the child did, let the child's name
      # live on.  If the name attribute seems unnecessary now, get rid of it.
      if 'name' in old_properties and old_properties['name'] != None and \
         old_properties['name'] != self.Name():
        self._properties['name'] = old_properties['name']
      if 'name' in self._properties and 'path' in self._properties and \
         self._properties['name'] == self._properties['path']:
        del self._properties['name']

      # Notify all children of their new parent.
      for child in self._properties['children']:
        child.parent = self

    # If asked to recurse, recurse.
    if recurse:
      for child in self._properties['children']:
        if child.__class__ == PBXGroup:
          child.TakeOverOnlyChild(recurse)

  def SortGroup(self):
    self._properties['children'] = \
        sorted(self._properties['children'], cmp=lambda x,y: x.Compare(y))

    # Recurse.
    for child in self._properties['children']:
      if isinstance(child, PBXGroup):
        child.SortGroup()


class XCFileLikeElement(XCHierarchicalElement):
  # Abstract base for objects that can be used as the fileRef property of
  # PBXBuildFile.

  def PathHashables(self):
    # A PBXBuildFile that refers to this object will call this method to
    # obtain additional hashables specific to this XCFileLikeElement.  Don't
    # just use this object's hashables, they're not specific and unique enough
    # on their own (without access to the parent hashables.)  Instead, provide
    # hashables that identify this object by path by getting its hashables as
    # well as the hashables of ancestor XCHierarchicalElement objects.

    hashables = []
    xche = self
    while xche != None and isinstance(xche, XCHierarchicalElement):
      xche_hashables = xche.Hashables()
      for index in xrange(0, len(xche_hashables)):
        hashables.insert(index, xche_hashables[index])
      xche = xche.parent
    return hashables


class XCContainerPortal(XCObject):
  # Abstract base for objects that can be used as the containerPortal property
  # of PBXContainerItemProxy.
  pass


class XCRemoteObject(XCObject):
  # Abstract base for objects that can be used as the remoteGlobalIDString
  # property of PBXContainerItemProxy.
  pass


class PBXFileReference(XCFileLikeElement, XCContainerPortal, XCRemoteObject):
  _schema = XCFileLikeElement._schema.copy()
  _schema.update({
    'explicitFileType':  [0, str, 0, 0],
    'lastKnownFileType': [0, str, 0, 0],
    'name':              [0, str, 0, 0],
    'path':              [0, str, 0, 1],
  })

  # Weird output rules for PBXFileReference.
  _should_print_single_line = True
  # super
  _encode_transforms = XCFileLikeElement._alternate_encode_transforms

  def __init__(self, properties=None, id=None, parent=None):
    # super
    XCFileLikeElement.__init__(self, properties, id, parent)
    if 'path' in self._properties and self._properties['path'].endswith('/'):
      self._properties['path'] = self._properties['path'][:-1]
      is_dir = True
    else:
      is_dir = False

    if 'path' in self._properties and \
        not 'lastKnownFileType' in self._properties and \
        not 'explicitFileType' in self._properties:
      # TODO(mark): This is the replacement for a replacement for a quick hack.
      # It is no longer incredibly sucky, but this list needs to be extended.
      extension_map = {
        'a':           'archive.ar',
        'app':         'wrapper.application',
        'bdic':        'file',
        'bundle':      'wrapper.cfbundle',
        'c':           'sourcecode.c.c',
        'cc':          'sourcecode.cpp.cpp',
        'cpp':         'sourcecode.cpp.cpp',
        'css':         'text.css',
        'cxx':         'sourcecode.cpp.cpp',
        'dylib':       'compiled.mach-o.dylib',
        'framework':   'wrapper.framework',
        'h':           'sourcecode.c.h',
        'hxx':         'sourcecode.cpp.h',
        'icns':        'image.icns',
        'java':        'sourcecode.java',
        'js':          'sourcecode.javascript',
        'm':           'sourcecode.c.objc',
        'mm':          'sourcecode.cpp.objcpp',
        'nib':         'wrapper.nib',
        'o':           'compiled.mach-o.objfile',
        'pdf':         'image.pdf',
        'pl':          'text.script.perl',
        'plist':       'text.plist.xml',
        'pm':          'text.script.perl',
        'png':         'image.png',
        'py':          'text.script.python',
        'r':           'sourcecode.rez',
        'rez':         'sourcecode.rez',
        's':           'sourcecode.asm',
        'strings':     'text.plist.strings',
        'ttf':         'file',
        'xcconfig':    'text.xcconfig',
        'xcdatamodel': 'wrapper.xcdatamodel',
        'xib':         'file.xib',
        'y':           'sourcecode.yacc',
      }

      if is_dir:
        file_type = 'folder'
      else:
        basename = posixpath.basename(self._properties['path'])
        (root, ext) = posixpath.splitext(basename)
        # Check the map using a lowercase extension.
        # TODO(mark): Maybe it should try with the original case first and fall
        # back to lowercase, in case there are any instances where case
        # matters.  There currently aren't.
        if ext != '':
          ext = ext[1:].lower()

        # TODO(mark): "text" is the default value, but "file" is appropriate
        # for unrecognized files not containing text.  Xcode seems to choose
        # based on content.
        file_type = extension_map.get(ext, 'text')

      self._properties['lastKnownFileType'] = file_type


class PBXVariantGroup(PBXGroup, XCFileLikeElement):
  """PBXVariantGroup is used by Xcode to represent localizations."""
  # No additions to the schema relative to PBXGroup.
  pass


# PBXReferenceProxy is also an XCFileLikeElement subclass.  It is defined below
# because it uses PBXContainerItemProxy, defined below.


class XCBuildConfiguration(XCObject):
  _schema = XCObject._schema.copy()
  _schema.update({
    'baseConfigurationReference': [0, PBXFileReference, 0, 0],
    'buildSettings':              [0, dict, 0, 1, {}],
    'name':                       [0, str,  0, 1],
  })

  def HasBuildSetting(self, key):
    return key in self._properties['buildSettings']

  def GetBuildSetting(self, key):
    return self._properties['buildSettings'][key]

  def SetBuildSetting(self, key, value):
    # TODO(mark): If a list, copy?
    self._properties['buildSettings'][key] = value

  def AppendBuildSetting(self, key, value):
    if not key in self._properties['buildSettings']:
      self._properties['buildSettings'][key] = []
    self._properties['buildSettings'][key].append(value)

  def DelBuildSetting(self, key):
    if key in self._properties['buildSettings']:
      del self._properties['buildSettings'][key]

  def SetBaseConfiguration(self, value):
    self._properties['baseConfigurationReference'] = value

class XCConfigurationList(XCObject):
  # _configs is the default list of configurations.
  _configs = [ XCBuildConfiguration({'name': 'Debug'}),
               XCBuildConfiguration({'name': 'Release'}) ]

  _schema = XCObject._schema.copy()
  _schema.update({
    'buildConfigurations':           [1, XCBuildConfiguration, 1, 1, _configs],
    'defaultConfigurationIsVisible': [0, int,                  0, 1, 1],
    'defaultConfigurationName':      [0, str,                  0, 1, 'Release'],
  })

  def Name(self):
    return 'Build configuration list for ' + \
           self.parent.__class__.__name__ + ' "' + self.parent.Name() + '"'

  def ConfigurationNamed(self, name):
    """Convenience accessor to obtain an XCBuildConfiguration by name."""
    for configuration in self._properties['buildConfigurations']:
      if configuration._properties['name'] == name:
        return configuration

    raise KeyError, name

  def DefaultConfiguration(self):
    """Convenience accessor to obtain the default XCBuildConfiguration."""
    return self.ConfigurationNamed(self._properties['defaultConfigurationName'])

  def HasBuildSetting(self, key):
    """Determines the state of a build setting in all XCBuildConfiguration
    child objects.

    If all child objects have key in their build settings, and the value is the
    same in all child objects, returns 1.

    If no child objects have the key in their build settings, returns 0.

    If some, but not all, child objects have the key in their build settings,
    or if any children have different values for the key, returns -1.
    """

    has = None
    value = None
    for configuration in self._properties['buildConfigurations']:
      configuration_has = configuration.HasBuildSetting(key)
      if has is None:
        has = configuration_has
      elif has != configuration_has:
        return -1

      if configuration_has:
        configuration_value = configuration.GetBuildSetting(key)
        if value is None:
          value = configuration_value
        elif value != configuration_value:
          return -1

    if not has:
      return 0

    return 1

  def GetBuildSetting(self, key):
    """Gets the build setting for key.

    All child XCConfiguration objects must have the same value set for the
    setting, or a ValueError will be raised.
    """

    # TODO(mark): This is wrong for build settings that are lists.  The list
    # contents should be compared (and a list copy returned?)

    value = None
    for configuration in self._properties['buildConfigurations']:
      configuration_value = configuration.GetBuildSetting(key)
      if value is None:
        value = configuration_value
      else:
        if value != configuration_value:
          raise ValueError, 'Variant values for ' + key

    return value

  def SetBuildSetting(self, key, value):
    """Sets the build setting for key to value in all child
    XCBuildConfiguration objects.
    """

    for configuration in self._properties['buildConfigurations']:
      configuration.SetBuildSetting(key, value)

  def AppendBuildSetting(self, key, value):
    """Appends value to the build setting for key, which is treated as a list,
    in all child XCBuildConfiguration objects.
    """

    for configuration in self._properties['buildConfigurations']:
      configuration.AppendBuildSetting(key, value)

  def DelBuildSetting(self, key):
    """Deletes the build setting key from all child XCBuildConfiguration
    objects.
    """

    for configuration in self._properties['buildConfigurations']:
      configuration.DelBuildSetting(key)

  def SetBaseConfiguration(self, value):
    """Sets the build configuration in all child XCBuildConfiguration objects.
    """

    for configuration in self._properties['buildConfigurations']:
      configuration.SetBaseConfiguration(value)


class PBXBuildFile(XCObject):
  _schema = XCObject._schema.copy()
  _schema.update({
    'fileRef':  [0, XCFileLikeElement, 0, 1],
    'settings': [0, str,               0, 0],  # hack, it's a dict
  })

  # Weird output rules for PBXBuildFile.
  _should_print_single_line = True
  _encode_transforms = XCObject._alternate_encode_transforms

  def Name(self):
    # Example: "main.cc in Sources"
    return self._properties['fileRef'].Name() + ' in ' + self.parent.Name()

  def Hashables(self):
    # super
    hashables = XCObject.Hashables(self)

    # It is not sufficient to just rely on Name() to get the
    # XCFileLikeElement's name, because that is not a complete pathname.
    # PathHashables returns hashables unique enough that no two
    # PBXBuildFiles should wind up with the same set of hashables, unless
    # someone adds the same file multiple times to the same target.  That
    # would be considered invalid anyway.
    hashables.extend(self._properties['fileRef'].PathHashables())

    return hashables


class XCBuildPhase(XCObject):
  """Abstract base for build phase classes.  Not represented in a project
  file.

  Attributes:
    _files_by_path: A dict mapping each path of a child in the files list by
      path (keys) to the corresponding PBXBuildFile children (values).
    _files_by_xcfilelikeelement: A dict mapping each XCFileLikeElement (keys)
      to the corresponding PBXBuildFile children (values).
  """

  # TODO(mark): Some build phase types, like PBXShellScriptBuildPhase, don't
  # actually have a "files" list.  XCBuildPhase should not have "files" but
  # another abstract subclass of it should provide this, and concrete build
  # phase types that do have "files" lists should be derived from that new
  # abstract subclass.  XCBuildPhase should only provide buildActionMask and
  # runOnlyForDeploymentPostprocessing, and not files or the various
  # file-related methods and attributes.

  _schema = XCObject._schema.copy()
  _schema.update({
    'buildActionMask':                    [0, int,          0, 1, 0x7fffffff],
    'files':                              [1, PBXBuildFile, 1, 1, []],
    'runOnlyForDeploymentPostprocessing': [0, int,          0, 1, 0],
  })

  def __init__(self, properties=None, id=None, parent=None):
    # super
    XCObject.__init__(self, properties, id, parent)

    self._files_by_path = {}
    self._files_by_xcfilelikeelement = {}
    for pbxbuildfile in self._properties.get('files', []):
      self._AddBuildFileToDicts(pbxbuildfile)

  def FileGroup(self, path):
    # Subclasses must override this by returning a two-element tuple.  The
    # first item in the tuple should be the PBXGroup to which "path" should be
    # added, either as a child or deeper descendant.  The second item should
    # be a boolean indicating whether files should be added into hierarchical
    # groups or one single flat group.
    raise NotImplementedError, \
          self.__class__.__name__ + ' must implement FileGroup'

  def _AddPathToDict(self, pbxbuildfile, path):
    """Adds path to the dict tracking paths belonging to this build phase.

    If the path is already a member of this build phase, raises an exception.
    """

    if path in self._files_by_path:
      raise ValueError, 'Found multiple build files with path ' + path
    self._files_by_path[path] = pbxbuildfile

  def _AddBuildFileToDicts(self, pbxbuildfile, path=None):
    """Maintains the _files_by_path and _files_by_xcfilelikeelement dicts.

    If path is specified, then it is the path that is being added to the
    phase, and pbxbuildfile must contain either a PBXFileReference directly
    referencing that path, or it must contain a PBXVariantGroup that itself
    contains a PBXFileReference referencing the path.

    If path is not specified, either the PBXFileReference's path or the paths
    of all children of the PBXVariantGroup are taken as being added to the
    phase.

    If the path is already present in the phase, raises an exception.

    If the PBXFileReference or PBXVariantGroup referenced by pbxbuildfile
    are already present in the phase, referenced by a different PBXBuildFile
    object, raises an exception.  This does not raise an exception when
    a PBXFileReference or PBXVariantGroup reappear and are referenced by the
    same PBXBuildFile that has already introduced them, because in the case
    of PBXVariantGroup objects, they may correspond to multiple paths that are
    not all added simultaneously.  When this situation occurs, the path needs
    to be added to _files_by_path, but nothing needs to change in
    _files_by_xcfilelikeelement, and the caller should have avoided adding
    the PBXBuildFile if it is already present in the list of children.
    """

    xcfilelikeelement = pbxbuildfile._properties['fileRef']

    paths = []
    if path != None:
      # It's best when the caller provides the path.
      if isinstance(xcfilelikeelement, PBXVariantGroup):
        paths.append(path)
    else:
      # If the caller didn't provide a path, there can be either multiple
      # paths (PBXVariantGroup) or one.
      if isinstance(xcfilelikeelement, PBXVariantGroup):
        for variant in xcfilelikeelement._properties['children']:
          paths.append(variant.FullPath())
      else:
        paths.append(xcfilelikeelement.FullPath())

    # Add the paths first, because if something's going to raise, the
    # messages provided by _AddPathToDict are more useful owing to its
    # having access to a real pathname and not just an object's Name().
    for a_path in paths:
      self._AddPathToDict(pbxbuildfile, a_path)

    # If another PBXBuildFile references this XCFileLikeElement, there's a
    # problem.
    if xcfilelikeelement in self._files_by_xcfilelikeelement and \
       self._files_by_xcfilelikeelement[xcfilelikeelement] != pbxbuildfile:
      raise ValueError, 'Found multiple build files for ' + \
                        xcfilelikeelement.Name()
    self._files_by_xcfilelikeelement[xcfilelikeelement] = pbxbuildfile

  def AppendBuildFile(self, pbxbuildfile, path=None):
    # Callers should use this instead of calling
    # AppendProperty('files', pbxbuildfile) directly because this function
    # maintains the object's dicts.  Better yet, callers can just call AddFile
    # with a pathname and not worry about building their own PBXBuildFile
    # objects.
    self.AppendProperty('files', pbxbuildfile)
    self._AddBuildFileToDicts(pbxbuildfile, path)

  def AddFile(self, path, settings=None):
    (file_group, hierarchical) = self.FileGroup(path)
    file_ref = file_group.AddOrGetFileByPath(path, hierarchical)

    if file_ref in self._files_by_xcfilelikeelement and \
       isinstance(file_ref, PBXVariantGroup):
      # There's already a PBXBuildFile in this phase corresponding to the
      # PBXVariantGroup.  path just provides a new variant that belongs to
      # the group.  Add the path to the dict.
      pbxbuildfile = self._files_by_xcfilelikeelement[file_ref]
      self._AddBuildFileToDicts(pbxbuildfile, path)
    else:
      # Add a new PBXBuildFile to get file_ref into the phase.
      if settings is None:
        pbxbuildfile = PBXBuildFile({'fileRef': file_ref})
      else:
        pbxbuildfile = PBXBuildFile({'fileRef': file_ref, 'settings': settings})
      self.AppendBuildFile(pbxbuildfile, path)


class PBXHeadersBuildPhase(XCBuildPhase):
  # No additions to the schema relative to XCBuildPhase.

  def Name(self):
    return 'Headers'

  def FileGroup(self, path):
    return self.PBXProjectAncestor().RootGroupForPath(path)


class PBXResourcesBuildPhase(XCBuildPhase):
  # No additions to the schema relative to XCBuildPhase.

  def Name(self):
    return 'Resources'

  def FileGroup(self, path):
    return self.PBXProjectAncestor().RootGroupForPath(path)


class PBXSourcesBuildPhase(XCBuildPhase):
  # No additions to the schema relative to XCBuildPhase.

  def Name(self):
    return 'Sources'

  def FileGroup(self, path):
    return self.PBXProjectAncestor().RootGroupForPath(path)


class PBXFrameworksBuildPhase(XCBuildPhase):
  # No additions to the schema relative to XCBuildPhase.

  def Name(self):
    return 'Frameworks'

  def FileGroup(self, path):
    (root, ext) = posixpath.splitext(path)
    if ext != '':
      ext = ext[1:].lower()
    if ext == 'o':
      # .o files are added to Xcode Frameworks phases, but conceptually aren't
      # frameworks, they're more like sources or intermediates. Redirect them
      # to show up in one of those other groups.
      return self.PBXProjectAncestor().RootGroupForPath(path)
    else:
      return (self.PBXProjectAncestor().FrameworksGroup(), False)


class PBXShellScriptBuildPhase(XCBuildPhase):
  _schema = XCBuildPhase._schema.copy()
  _schema.update({
    'inputPaths':       [1, str, 0, 1, []],
    'name':             [0, str, 0, 0],
    'outputPaths':      [1, str, 0, 1, []],
    'shellPath':        [0, str, 0, 1, '/bin/sh'],
    'shellScript':      [0, str, 0, 1],
    'showEnvVarsInLog': [0, int, 0, 0],
  })

  def Name(self):
    if 'name' in self._properties:
      return self._properties['name']

    return 'ShellScript'


class PBXCopyFilesBuildPhase(XCBuildPhase):
  _schema = XCBuildPhase._schema.copy()
  _schema.update({
    'dstPath':          [0, str, 0, 1],
    'dstSubfolderSpec': [0, int, 0, 1],
    'name':             [0, str, 0, 0],
  })

  # path_tree_re matches "$(DIR)/path" or just "$(DIR)".  Match group 1 is
  # "DIR", match group 3 is "path" or None.
  path_tree_re = re.compile('^\\$\\((.*)\\)(/(.*)|)$')

  # path_tree_to_subfolder maps names of Xcode variables to the associated
  # dstSubfolderSpec property value used in a PBXCopyFilesBuildPhase object.
  path_tree_to_subfolder = {
    'BUILT_PRODUCTS_DIR': 16,  # Products Directory
    # Other types that can be chosen via the Xcode UI.
    # TODO(mark): Map Xcode variable names to these.
    # : 1,  # Wrapper
    # : 6,  # Executables: 6
    # : 7,  # Resources
    # : 15,  # Java Resources
    # : 10,  # Frameworks
    # : 11,  # Shared Frameworks
    # : 12,  # Shared Support
    # : 13,  # PlugIns
  }

  def Name(self):
    if 'name' in self._properties:
      return self._properties['name']

    return 'CopyFiles'

  def FileGroup(self, path):
    return self.PBXProjectAncestor().RootGroupForPath(path)

  def SetDestination(self, path):
    """Set the dstSubfolderSpec and dstPath properties from path.

    path may be specified in the same notation used for XCHierarchicalElements,
    specifically, "$(DIR)/path".
    """

    path_tree_match = self.path_tree_re.search(path)
    if path_tree_match:
      # Everything else needs to be relative to an Xcode variable.
      path_tree = path_tree_match.group(1)
      relative_path = path_tree_match.group(3)

      if path_tree in self.path_tree_to_subfolder:
        subfolder = self.path_tree_to_subfolder[path_tree]
        if relative_path is None:
          relative_path = ''
      else:
        # The path starts with an unrecognized Xcode variable
        # name like $(SRCROOT).  Xcode will still handle this
        # as an "absolute path" that starts with the variable.
        subfolder = 0
        relative_path = path
    elif path.startswith('/'):
      # Special case.  Absolute paths are in dstSubfolderSpec 0.
      subfolder = 0
      relative_path = path[1:]
    else:
      raise ValueError, 'Can\'t use path %s in a %s' % \
                        (path, self.__class__.__name__)

    self._properties['dstPath'] = relative_path
    self._properties['dstSubfolderSpec'] = subfolder


class PBXBuildRule(XCObject):
  _schema = XCObject._schema.copy()
  _schema.update({
    'compilerSpec': [0, str, 0, 1],
    'filePatterns': [0, str, 0, 0],
    'fileType':     [0, str, 0, 1],
    'isEditable':   [0, int, 0, 1, 1],
    'outputFiles':  [1, str, 0, 1, []],
    'script':       [0, str, 0, 0],
  })

  def Name(self):
    # Not very inspired, but it's what Xcode uses.
    return self.__class__.__name__

  def Hashables(self):
    # super
    hashables = XCObject.Hashables(self)

    # Use the hashables of the weak objects that this object refers to.
    hashables.append(self._properties['fileType'])
    if 'filePatterns' in self._properties:
      hashables.append(self._properties['filePatterns'])
    return hashables


class PBXContainerItemProxy(XCObject):
  # When referencing an item in this project file, containerPortal is the
  # PBXProject root object of this project file.  When referencing an item in
  # another project file, containerPortal is a PBXFileReference identifying
  # the other project file.
  #
  # When serving as a proxy to an XCTarget (in this project file or another),
  # proxyType is 1.  When serving as a proxy to a PBXFileReference (in another
  # project file), proxyType is 2.  Type 2 is used for references to the
  # producs of the other project file's targets.
  #
  # Xcode is weird about remoteGlobalIDString.  Usually, it's printed without
  # a comment, indicating that it's tracked internally simply as a string, but
  # sometimes it's printed with a comment (usually when the object is initially
  # created), indicating that it's tracked as a project file object at least
  # sometimes.  This module always tracks it as an object, but contains a hack
  # to prevent it from printing the comment in the project file output.  See
  # _XCKVPrint.
  _schema = XCObject._schema.copy()
  _schema.update({
    'containerPortal':      [0, XCContainerPortal, 0, 1],
    'proxyType':            [0, int,               0, 1],
    'remoteGlobalIDString': [0, XCRemoteObject,    0, 1],
    'remoteInfo':           [0, str,               0, 1],
  })

  def __repr__(self):
    props = self._properties
    name = '%s.gyp:%s' % (props['containerPortal'].Name(), props['remoteInfo'])
    return '<%s %r at 0x%x>' % (self.__class__.__name__, name, id(self))

  def Name(self):
    # Admittedly not the best name, but it's what Xcode uses.
    return self.__class__.__name__

  def Hashables(self):
    # super
    hashables = XCObject.Hashables(self)

    # Use the hashables of the weak objects that this object refers to.
    hashables.extend(self._properties['containerPortal'].Hashables())
    hashables.extend(self._properties['remoteGlobalIDString'].Hashables())
    return hashables


class PBXTargetDependency(XCObject):
  # The "target" property accepts an XCTarget object, and obviously not
  # NoneType.  But XCTarget is defined below, so it can't be put into the
  # schema yet.  The definition of PBXTargetDependency can't be moved below
  # XCTarget because XCTarget's own schema references PBXTargetDependency.
  # Python doesn't deal well with this circular relationship, and doesn't have
  # a real way to do forward declarations.  To work around, the type of
  # the "target" property is reset below, after XCTarget is defined.
  #
  # At least one of "name" and "target" is required.
  _schema = XCObject._schema.copy()
  _schema.update({
    'name':        [0, str,                   0, 0],
    'target':      [0, None.__class__,        0, 0],
    'targetProxy': [0, PBXContainerItemProxy, 1, 1],
  })

  def __repr__(self):
    name = self._properties.get('name') or self._properties['target'].Name()
    return '<%s %r at 0x%x>' % (self.__class__.__name__, name, id(self))

  def Name(self):
    # Admittedly not the best name, but it's what Xcode uses.
    return self.__class__.__name__

  def Hashables(self):
    # super
    hashables = XCObject.Hashables(self)

    # Use the hashables of the weak objects that this object refers to.
    hashables.extend(self._properties['targetProxy'].Hashables())
    return hashables


class PBXReferenceProxy(XCFileLikeElement):
  _schema = XCFileLikeElement._schema.copy()
  _schema.update({
    'fileType':  [0, str,                   0, 1],
    'path':      [0, str,                   0, 1],
    'remoteRef': [0, PBXContainerItemProxy, 1, 1],
  })


class XCTarget(XCRemoteObject):
  # An XCTarget is really just an XCObject, the XCRemoteObject thing is just
  # to allow PBXProject to be used in the remoteGlobalIDString property of
  # PBXContainerItemProxy.
  #
  # Setting a "name" property at instantiation may also affect "productName",
  # which may in turn affect the "PRODUCT_NAME" build setting in children of
  # "buildConfigurationList".  See __init__ below.
  _schema = XCRemoteObject._schema.copy()
  _schema.update({
    'buildConfigurationList': [0, XCConfigurationList, 1, 1,
                               XCConfigurationList()],
    'buildPhases':            [1, XCBuildPhase,        1, 1, []],
    'dependencies':           [1, PBXTargetDependency, 1, 1, []],
    'name':                   [0, str,                 0, 1],
    'productName':            [0, str,                 0, 1],
  })

  def __init__(self, properties=None, id=None, parent=None,
               force_outdir=None, force_prefix=None, force_extension=None):
    # super
    XCRemoteObject.__init__(self, properties, id, parent)

    # Set up additional defaults not expressed in the schema.  If a "name"
    # property was supplied, set "productName" if it is not present.  Also set
    # the "PRODUCT_NAME" build setting in each configuration, but only if
    # the setting is not present in any build configuration.
    if 'name' in self._properties:
      if not 'productName' in self._properties:
        self.SetProperty('productName', self._properties['name'])

    if 'productName' in self._properties:
      if 'buildConfigurationList' in self._properties:
        configs = self._properties['buildConfigurationList']
        if configs.HasBuildSetting('PRODUCT_NAME') == 0:
          configs.SetBuildSetting('PRODUCT_NAME',
                                  self._properties['productName'])

  def AddDependency(self, other):
    pbxproject = self.PBXProjectAncestor()
    other_pbxproject = other.PBXProjectAncestor()
    if pbxproject == other_pbxproject:
      # Add a dependency to another target in the same project file.
      container = PBXContainerItemProxy({'containerPortal':      pbxproject,
                                         'proxyType':            1,
                                         'remoteGlobalIDString': other,
                                         'remoteInfo':           other.Name()})
      dependency = PBXTargetDependency({'target':      other,
                                        'targetProxy': container})
      self.AppendProperty('dependencies', dependency)
    else:
      # Add a dependency to a target in a different project file.
      other_project_ref = \
          pbxproject.AddOrGetProjectReference(other_pbxproject)[1]
      container = PBXContainerItemProxy({
            'containerPortal':      other_project_ref,
            'proxyType':            1,
            'remoteGlobalIDString': other,
            'remoteInfo':           other.Name(),
          })
      dependency = PBXTargetDependency({'name':        other.Name(),
                                        'targetProxy': container})
      self.AppendProperty('dependencies', dependency)

  # Proxy all of these through to the build configuration list.

  def ConfigurationNamed(self, name):
    return self._properties['buildConfigurationList'].ConfigurationNamed(name)

  def DefaultConfiguration(self):
    return self._properties['buildConfigurationList'].DefaultConfiguration()

  def HasBuildSetting(self, key):
    return self._properties['buildConfigurationList'].HasBuildSetting(key)

  def GetBuildSetting(self, key):
    return self._properties['buildConfigurationList'].GetBuildSetting(key)

  def SetBuildSetting(self, key, value):
    return self._properties['buildConfigurationList'].SetBuildSetting(key, \
                                                                      value)

  def AppendBuildSetting(self, key, value):
    return self._properties['buildConfigurationList'].AppendBuildSetting(key, \
                                                                         value)

  def DelBuildSetting(self, key):
    return self._properties['buildConfigurationList'].DelBuildSetting(key)


# Redefine the type of the "target" property.  See PBXTargetDependency._schema
# above.
PBXTargetDependency._schema['target'][1] = XCTarget


class PBXNativeTarget(XCTarget):
  # buildPhases is overridden in the schema to be able to set defaults.
  #
  # NOTE: Contrary to most objects, it is advisable to set parent when
  # constructing PBXNativeTarget.  A parent of an XCTarget must be a PBXProject
  # object.  A parent reference is required for a PBXNativeTarget during
  # construction to be able to set up the target defaults for productReference,
  # because a PBXBuildFile object must be created for the target and it must
  # be added to the PBXProject's mainGroup hierarchy.
  _schema = XCTarget._schema.copy()
  _schema.update({
    'buildPhases':      [1, XCBuildPhase,     1, 1,
                         [PBXSourcesBuildPhase(), PBXFrameworksBuildPhase()]],
    'buildRules':       [1, PBXBuildRule,     1, 1, []],
    'productReference': [0, PBXFileReference, 0, 1],
    'productType':      [0, str,              0, 1],
  })

  # Mapping from Xcode product-types to settings.  The settings are:
  #  filetype : used for explicitFileType in the project file
  #  prefix : the prefix for the file name
  #  suffix : the suffix for the filen ame
  _product_filetypes = {
    'com.apple.product-type.application':     ['wrapper.application',
                                               '', '.app'],
    'com.apple.product-type.bundle':          ['wrapper.cfbundle',
                                               '', '.bundle'],
    'com.apple.product-type.framework':       ['wrapper.framework',
                                               '', '.framework'],
    'com.apple.product-type.library.dynamic': ['compiled.mach-o.dylib',
                                               'lib', '.dylib'],
    'com.apple.product-type.library.static':  ['archive.ar',
                                               'lib', '.a'],
    'com.apple.product-type.tool':            ['compiled.mach-o.executable',
                                               '', ''],
    'com.googlecode.gyp.xcode.bundle':        ['compiled.mach-o.dylib',
                                               '', '.so'],
  }

  def __init__(self, properties=None, id=None, parent=None,
               force_outdir=None, force_prefix=None, force_extension=None):
    # super
    XCTarget.__init__(self, properties, id, parent)

    if 'productName' in self._properties and \
       'productType' in self._properties and \
       not 'productReference' in self._properties and \
       self._properties['productType'] in self._product_filetypes:
      products_group = None
      pbxproject = self.PBXProjectAncestor()
      if pbxproject != None:
        products_group = pbxproject.ProductsGroup()

      if products_group != None:
        (filetype, prefix, suffix) = \
            self._product_filetypes[self._properties['productType']]
        # Xcode does not have a distinct type for loadable modules that are
        # pure BSD targets (not in a bundle wrapper). GYP allows such modules
        # to be specified by setting a target type to loadable_module without
        # having mac_bundle set. These are mapped to the pseudo-product type
        # com.googlecode.gyp.xcode.bundle.
        #
        # By picking up this special type and converting it to a dynamic
        # library (com.apple.product-type.library.dynamic) with fix-ups,
        # single-file loadable modules can be produced.
        #
        # MACH_O_TYPE is changed to mh_bundle to produce the proper file type
        # (as opposed to mh_dylib). In order for linking to succeed,
        # DYLIB_CURRENT_VERSION and DYLIB_COMPATIBILITY_VERSION must be
        # cleared. They are meaningless for type mh_bundle.
        #
        # Finally, the .so extension is forcibly applied over the default
        # (.dylib), unless another forced extension is already selected.
        # .dylib is plainly wrong, and .bundle is used by loadable_modules in
        # bundle wrappers (com.apple.product-type.bundle). .so seems an odd
        # choice because it's used as the extension on many other systems that
        # don't distinguish between linkable shared libraries and non-linkable
        # loadable modules, but there's precedent: Python loadable modules on
        # Mac OS X use an .so extension.
        if self._properties['productType'] == 'com.googlecode.gyp.xcode.bundle':
          self._properties['productType'] = \
              'com.apple.product-type.library.dynamic'
          self.SetBuildSetting('MACH_O_TYPE', 'mh_bundle')
          self.SetBuildSetting('DYLIB_CURRENT_VERSION', '')
          self.SetBuildSetting('DYLIB_COMPATIBILITY_VERSION', '')
          if force_extension is None:
            force_extension = suffix[1:]

        if force_extension is not None:
          # If it's a wrapper (bundle), set WRAPPER_EXTENSION.
          if filetype.startswith('wrapper.'):
            self.SetBuildSetting('WRAPPER_EXTENSION', force_extension)
          else:
            # Extension override.
            suffix = '.' + force_extension
            self.SetBuildSetting('EXECUTABLE_EXTENSION', force_extension)

          if filetype.startswith('compiled.mach-o.executable'):
            product_name = self._properties['productName']
            product_name += suffix
            suffix = ''
            self.SetProperty('productName', product_name)
            self.SetBuildSetting('PRODUCT_NAME', product_name)

        # Xcode handles most prefixes based on the target type, however there
        # are exceptions.  If a "BSD Dynamic Library" target is added in the
        # Xcode UI, Xcode sets EXECUTABLE_PREFIX.  This check duplicates that
        # behavior.
        if force_prefix is not None:
          prefix = force_prefix
        if filetype.startswith('wrapper.'):
          self.SetBuildSetting('WRAPPER_PREFIX', prefix)
        else:
          self.SetBuildSetting('EXECUTABLE_PREFIX', prefix)

        if force_outdir is not None:
          self.SetBuildSetting('TARGET_BUILD_DIR', force_outdir)

        # TODO(tvl): Remove the below hack.
        #    http://code.google.com/p/gyp/issues/detail?id=122

        # Some targets include the prefix in the target_name.  These targets
        # really should just add a product_name setting that doesn't include
        # the prefix.  For example:
        #  target_name = 'libevent', product_name = 'event'
        # This check cleans up for them.
        product_name = self._properties['productName']
        prefix_len = len(prefix)
        if prefix_len and (product_name[:prefix_len] == prefix):
          product_name = product_name[prefix_len:]
          self.SetProperty('productName', product_name)
          self.SetBuildSetting('PRODUCT_NAME', product_name)

        ref_props = {
          'explicitFileType': filetype,
          'includeInIndex':   0,
          'path':             prefix + product_name + suffix,
          'sourceTree':       'BUILT_PRODUCTS_DIR',
        }
        file_ref = PBXFileReference(ref_props)
        products_group.AppendChild(file_ref)
        self.SetProperty('productReference', file_ref)

  def GetBuildPhaseByType(self, type):
    if not 'buildPhases' in self._properties:
      return None

    the_phase = None
    for phase in self._properties['buildPhases']:
      if isinstance(phase, type):
        # Some phases may be present in multiples in a well-formed project file,
        # but phases like PBXSourcesBuildPhase may only be present singly, and
        # this function is intended as an aid to GetBuildPhaseByType.  Loop
        # over the entire list of phases and assert if more than one of the
        # desired type is found.
        assert the_phase is None
        the_phase = phase

    return the_phase

  def HeadersPhase(self):
    headers_phase = self.GetBuildPhaseByType(PBXHeadersBuildPhase)
    if headers_phase is None:
      headers_phase = PBXHeadersBuildPhase()

      # The headers phase should come before the resources, sources, and
      # frameworks phases, if any.
      insert_at = len(self._properties['buildPhases'])
      for index in xrange(0, len(self._properties['buildPhases'])):
        phase = self._properties['buildPhases'][index]
        if isinstance(phase, PBXResourcesBuildPhase) or \
           isinstance(phase, PBXSourcesBuildPhase) or \
           isinstance(phase, PBXFrameworksBuildPhase):
          insert_at = index
          break

      self._properties['buildPhases'].insert(insert_at, headers_phase)
      headers_phase.parent = self

    return headers_phase

  def ResourcesPhase(self):
    resources_phase = self.GetBuildPhaseByType(PBXResourcesBuildPhase)
    if resources_phase is None:
      resources_phase = PBXResourcesBuildPhase()

      # The resources phase should come before the sources and frameworks
      # phases, if any.
      insert_at = len(self._properties['buildPhases'])
      for index in xrange(0, len(self._properties['buildPhases'])):
        phase = self._properties['buildPhases'][index]
        if isinstance(phase, PBXSourcesBuildPhase) or \
           isinstance(phase, PBXFrameworksBuildPhase):
          insert_at = index
          break

      self._properties['buildPhases'].insert(insert_at, resources_phase)
      resources_phase.parent = self

    return resources_phase

  def SourcesPhase(self):
    sources_phase = self.GetBuildPhaseByType(PBXSourcesBuildPhase)
    if sources_phase is None:
      sources_phase = PBXSourcesBuildPhase()
      self.AppendProperty('buildPhases', sources_phase)

    return sources_phase

  def FrameworksPhase(self):
    frameworks_phase = self.GetBuildPhaseByType(PBXFrameworksBuildPhase)
    if frameworks_phase is None:
      frameworks_phase = PBXFrameworksBuildPhase()
      self.AppendProperty('buildPhases', frameworks_phase)

    return frameworks_phase

  def AddDependency(self, other):
    # super
    XCTarget.AddDependency(self, other)

    static_library_type = 'com.apple.product-type.library.static'
    shared_library_type = 'com.apple.product-type.library.dynamic'
    framework_type = 'com.apple.product-type.framework'
    if isinstance(other, PBXNativeTarget) and \
       'productType' in self._properties and \
       self._properties['productType'] != static_library_type and \
       'productType' in other._properties and \
       (other._properties['productType'] == static_library_type or \
        ((other._properties['productType'] == shared_library_type or \
          other._properties['productType'] == framework_type) and \
         ((not other.HasBuildSetting('MACH_O_TYPE')) or
          other.GetBuildSetting('MACH_O_TYPE') != 'mh_bundle'))):

      file_ref = other.GetProperty('productReference')

      pbxproject = self.PBXProjectAncestor()
      other_pbxproject = other.PBXProjectAncestor()
      if pbxproject != other_pbxproject:
        other_project_product_group = \
            pbxproject.AddOrGetProjectReference(other_pbxproject)[0]
        file_ref = other_project_product_group.GetChildByRemoteObject(file_ref)

      self.FrameworksPhase().AppendProperty('files',
                                            PBXBuildFile({'fileRef': file_ref}))


class PBXAggregateTarget(XCTarget):
  pass


class PBXProject(XCContainerPortal):
  # A PBXProject is really just an XCObject, the XCContainerPortal thing is
  # just to allow PBXProject to be used in the containerPortal property of
  # PBXContainerItemProxy.
  """

  Attributes:
    path: "sample.xcodeproj".  TODO(mark) Document me!
    _other_pbxprojects: A dictionary, keyed by other PBXProject objects.  Each
                        value is a reference to the dict in the
                        projectReferences list associated with the keyed
                        PBXProject.
  """

  _schema = XCContainerPortal._schema.copy()
  _schema.update({
    'attributes':             [0, dict,                0, 0],
    'buildConfigurationList': [0, XCConfigurationList, 1, 1,
                               XCConfigurationList()],
    'compatibilityVersion':   [0, str,                 0, 1, 'Xcode 3.2'],
    'hasScannedForEncodings': [0, int,                 0, 1, 1],
    'mainGroup':              [0, PBXGroup,            1, 1, PBXGroup()],
    'projectDirPath':         [0, str,                 0, 1, ''],
    'projectReferences':      [1, dict,                0, 0],
    'projectRoot':            [0, str,                 0, 1, ''],
    'targets':                [1, XCTarget,            1, 1, []],
  })

  def __init__(self, properties=None, id=None, parent=None, path=None):
    self.path = path
    self._other_pbxprojects = {}
    # super
    return XCContainerPortal.__init__(self, properties, id, parent)

  def Name(self):
    name = self.path
    if name[-10:] == '.xcodeproj':
      name = name[:-10]
    return posixpath.basename(name)

  def Path(self):
    return self.path

  def Comment(self):
    return 'Project object'

  def Children(self):
    # super
    children = XCContainerPortal.Children(self)

    # Add children that the schema doesn't know about.  Maybe there's a more
    # elegant way around this, but this is the only case where we need to own
    # objects in a dictionary (that is itself in a list), and three lines for
    # a one-off isn't that big a deal.
    if 'projectReferences' in self._properties:
      for reference in self._properties['projectReferences']:
        children.append(reference['ProductGroup'])

    return children

  def PBXProjectAncestor(self):
    return self

  def _GroupByName(self, name):
    if not 'mainGroup' in self._properties:
      self.SetProperty('mainGroup', PBXGroup())

    main_group = self._properties['mainGroup']
    group = main_group.GetChildByName(name)
    if group is None:
      group = PBXGroup({'name': name})
      main_group.AppendChild(group)

    return group

  # SourceGroup and ProductsGroup are created by default in Xcode's own
  # templates.
  def SourceGroup(self):
    return self._GroupByName('Source')

  def ProductsGroup(self):
    return self._GroupByName('Products')

  # IntermediatesGroup is used to collect source-like files that are generated
  # by rules or script phases and are placed in intermediate directories such
  # as DerivedSources.
  def IntermediatesGroup(self):
    return self._GroupByName('Intermediates')

  # FrameworksGroup and ProjectsGroup are top-level groups used to collect
  # frameworks and projects.
  def FrameworksGroup(self):
    return self._GroupByName('Frameworks')

  def ProjectsGroup(self):
    return self._GroupByName('Projects')

  def RootGroupForPath(self, path):
    """Returns a PBXGroup child of this object to which path should be added.

    This method is intended to choose between SourceGroup and
    IntermediatesGroup on the basis of whether path is present in a source
    directory or an intermediates directory.  For the purposes of this
    determination, any path located within a derived file directory such as
    PROJECT_DERIVED_FILE_DIR is treated as being in an intermediates
    directory.

    The returned value is a two-element tuple.  The first element is the
    PBXGroup, and the second element specifies whether that group should be
    organized hierarchically (True) or as a single flat list (False).
    """

    # TODO(mark): make this a class variable and bind to self on call?
    # Also, this list is nowhere near exhaustive.
    # INTERMEDIATE_DIR and SHARED_INTERMEDIATE_DIR are used by
    # gyp.generator.xcode.  There should probably be some way for that module
    # to push the names in, rather than having to hard-code them here.
    source_tree_groups = {
      'DERIVED_FILE_DIR':         (self.IntermediatesGroup, True),
      'INTERMEDIATE_DIR':         (self.IntermediatesGroup, True),
      'PROJECT_DERIVED_FILE_DIR': (self.IntermediatesGroup, True),
      'SHARED_INTERMEDIATE_DIR':  (self.IntermediatesGroup, True),
    }

    (source_tree, path) = SourceTreeAndPathFromPath(path)
    if source_tree != None and source_tree in source_tree_groups:
      (group_func, hierarchical) = source_tree_groups[source_tree]
      group = group_func()
      return (group, hierarchical)

    # TODO(mark): make additional choices based on file extension.

    return (self.SourceGroup(), True)

  def AddOrGetFileInRootGroup(self, path):
    """Returns a PBXFileReference corresponding to path in the correct group
    according to RootGroupForPath's heuristics.

    If an existing PBXFileReference for path exists, it will be returned.
    Otherwise, one will be created and returned.
    """

    (group, hierarchical) = self.RootGroupForPath(path)
    return group.AddOrGetFileByPath(path, hierarchical)

  def RootGroupsTakeOverOnlyChildren(self, recurse=False):
    """Calls TakeOverOnlyChild for all groups in the main group."""

    for group in self._properties['mainGroup']._properties['children']:
      if isinstance(group, PBXGroup):
        group.TakeOverOnlyChild(recurse)

  def SortGroups(self):
    # Sort the children of the mainGroup (like "Source" and "Products")
    # according to their defined order.
    self._properties['mainGroup']._properties['children'] = \
        sorted(self._properties['mainGroup']._properties['children'],
               cmp=lambda x,y: x.CompareRootGroup(y))

    # Sort everything else by putting group before files, and going
    # alphabetically by name within sections of groups and files.  SortGroup
    # is recursive.
    for group in self._properties['mainGroup']._properties['children']:
      if not isinstance(group, PBXGroup):
        continue

      if group.Name() == 'Products':
        # The Products group is a special case.  Instead of sorting
        # alphabetically, sort things in the order of the targets that
        # produce the products.  To do this, just build up a new list of
        # products based on the targets.
        products = []
        for target in self._properties['targets']:
          if not isinstance(target, PBXNativeTarget):
            continue
          product = target._properties['productReference']
          # Make sure that the product is already in the products group.
          assert product in group._properties['children']
          products.append(product)

        # Make sure that this process doesn't miss anything that was already
        # in the products group.
        assert len(products) == len(group._properties['children'])
        group._properties['children'] = products
      else:
        group.SortGroup()

  def AddOrGetProjectReference(self, other_pbxproject):
    """Add a reference to another project file (via PBXProject object) to this
    one.

    Returns [ProductGroup, ProjectRef].  ProductGroup is a PBXGroup object in
    this project file that contains a PBXReferenceProxy object for each
    product of each PBXNativeTarget in the other project file.  ProjectRef is
    a PBXFileReference to the other project file.

    If this project file already references the other project file, the
    existing ProductGroup and ProjectRef are returned.  The ProductGroup will
    still be updated if necessary.
    """

    if not 'projectReferences' in self._properties:
      self._properties['projectReferences'] = []

    product_group = None
    project_ref = None

    if not other_pbxproject in self._other_pbxprojects:
      # This project file isn't yet linked to the other one.  Establish the
      # link.
      product_group = PBXGroup({'name': 'Products'})

      # ProductGroup is strong.
      product_group.parent = self

      # There's nothing unique about this PBXGroup, and if left alone, it will
      # wind up with the same set of hashables as all other PBXGroup objects
      # owned by the projectReferences list.  Add the hashables of the
      # remote PBXProject that it's related to.
      product_group._hashables.extend(other_pbxproject.Hashables())

      # The other project reports its path as relative to the same directory
      # that this project's path is relative to.  The other project's path
      # is not necessarily already relative to this project.  Figure out the
      # pathname that this project needs to use to refer to the other one.
      this_path = posixpath.dirname(self.Path())
      projectDirPath = self.GetProperty('projectDirPath')
      if projectDirPath:
        if posixpath.isabs(projectDirPath[0]):
          this_path = projectDirPath
        else:
          this_path = posixpath.join(this_path, projectDirPath)
      other_path = gyp.common.RelativePath(other_pbxproject.Path(), this_path)

      # ProjectRef is weak (it's owned by the mainGroup hierarchy).
      project_ref = PBXFileReference({
            'lastKnownFileType': 'wrapper.pb-project',
            'path':              other_path,
            'sourceTree':        'SOURCE_ROOT',
          })
      self.ProjectsGroup().AppendChild(project_ref)

      ref_dict = {'ProductGroup': product_group, 'ProjectRef': project_ref}
      self._other_pbxprojects[other_pbxproject] = ref_dict
      self.AppendProperty('projectReferences', ref_dict)

      # Xcode seems to sort this list case-insensitively
      self._properties['projectReferences'] = \
          sorted(self._properties['projectReferences'], cmp=lambda x,y:
                 cmp(x['ProjectRef'].Name().lower(),
                     y['ProjectRef'].Name().lower()))
    else:
      # The link already exists.  Pull out the relevnt data.
      project_ref_dict = self._other_pbxprojects[other_pbxproject]
      product_group = project_ref_dict['ProductGroup']
      project_ref = project_ref_dict['ProjectRef']

    self._SetUpProductReferences(other_pbxproject, product_group, project_ref)

    return [product_group, project_ref]

  def _SetUpProductReferences(self, other_pbxproject, product_group,
                              project_ref):
    # TODO(mark): This only adds references to products in other_pbxproject
    # when they don't exist in this pbxproject.  Perhaps it should also
    # remove references from this pbxproject that are no longer present in
    # other_pbxproject.  Perhaps it should update various properties if they
    # change.
    for target in other_pbxproject._properties['targets']:
      if not isinstance(target, PBXNativeTarget):
        continue

      other_fileref = target._properties['productReference']
      if product_group.GetChildByRemoteObject(other_fileref) is None:
        # Xcode sets remoteInfo to the name of the target and not the name
        # of its product, despite this proxy being a reference to the product.
        container_item = PBXContainerItemProxy({
              'containerPortal':      project_ref,
              'proxyType':            2,
              'remoteGlobalIDString': other_fileref,
              'remoteInfo':           target.Name()
            })
        # TODO(mark): Does sourceTree get copied straight over from the other
        # project?  Can the other project ever have lastKnownFileType here
        # instead of explicitFileType?  (Use it if so?)  Can path ever be
        # unset?  (I don't think so.)  Can other_fileref have name set, and
        # does it impact the PBXReferenceProxy if so?  These are the questions
        # that perhaps will be answered one day.
        reference_proxy = PBXReferenceProxy({
              'fileType':   other_fileref._properties['explicitFileType'],
              'path':       other_fileref._properties['path'],
              'sourceTree': other_fileref._properties['sourceTree'],
              'remoteRef':  container_item,
            })

        product_group.AppendChild(reference_proxy)

  def SortRemoteProductReferences(self):
    # For each remote project file, sort the associated ProductGroup in the
    # same order that the targets are sorted in the remote project file.  This
    # is the sort order used by Xcode.

    def CompareProducts(x, y, remote_products):
      # x and y are PBXReferenceProxy objects.  Go through their associated
      # PBXContainerItem to get the remote PBXFileReference, which will be
      # present in the remote_products list.
      x_remote = x._properties['remoteRef']._properties['remoteGlobalIDString']
      y_remote = y._properties['remoteRef']._properties['remoteGlobalIDString']
      x_index = remote_products.index(x_remote)
      y_index = remote_products.index(y_remote)

      # Use the order of each remote PBXFileReference in remote_products to
      # determine the sort order.
      return cmp(x_index, y_index)

    for other_pbxproject, ref_dict in self._other_pbxprojects.iteritems():
      # Build up a list of products in the remote project file, ordered the
      # same as the targets that produce them.
      remote_products = []
      for target in other_pbxproject._properties['targets']:
        if not isinstance(target, PBXNativeTarget):
          continue
        remote_products.append(target._properties['productReference'])

      # Sort the PBXReferenceProxy children according to the list of remote
      # products.
      product_group = ref_dict['ProductGroup']
      product_group._properties['children'] = sorted(
          product_group._properties['children'],
          cmp=lambda x, y: CompareProducts(x, y, remote_products))


class XCProjectFile(XCObject):
  _schema = XCObject._schema.copy()
  _schema.update({
    'archiveVersion': [0, int,        0, 1, 1],
    'classes':        [0, dict,       0, 1, {}],
    'objectVersion':  [0, int,        0, 1, 45],
    'rootObject':     [0, PBXProject, 1, 1],
  })

  def SetXcodeVersion(self, version):
    version_to_object_version = {
      '2.4': 45,
      '3.0': 45,
      '3.1': 45,
      '3.2': 46,
    }
    if not version in version_to_object_version:
      supported_str = ', '.join(sorted(version_to_object_version.keys()))
      raise Exception(
          'Unsupported Xcode version %s (supported: %s)' %
          ( version, supported_str ) )
    compatibility_version = 'Xcode %s' % version
    self._properties['rootObject'].SetProperty('compatibilityVersion',
                                               compatibility_version)
    self.SetProperty('objectVersion', version_to_object_version[version]);

  def ComputeIDs(self, recursive=True, overwrite=True, hash=None):
    # Although XCProjectFile is implemented here as an XCObject, it's not a
    # proper object in the Xcode sense, and it certainly doesn't have its own
    # ID.  Pass through an attempt to update IDs to the real root object.
    if recursive:
      self._properties['rootObject'].ComputeIDs(recursive, overwrite, hash)

  def Print(self, file=sys.stdout):
    self.VerifyHasRequiredProperties()

    # Add the special "objects" property, which will be caught and handled
    # separately during printing.  This structure allows a fairly standard
    # loop do the normal printing.
    self._properties['objects'] = {}
    self._XCPrint(file, 0, '// !$*UTF8*$!\n')
    if self._should_print_single_line:
      self._XCPrint(file, 0, '{ ')
    else:
      self._XCPrint(file, 0, '{\n')
    for property, value in sorted(self._properties.iteritems(),
                                  cmp=lambda x, y: cmp(x, y)):
      if property == 'objects':
        self._PrintObjects(file)
      else:
        self._XCKVPrint(file, 1, property, value)
    self._XCPrint(file, 0, '}\n')
    del self._properties['objects']

  def _PrintObjects(self, file):
    if self._should_print_single_line:
      self._XCPrint(file, 0, 'objects = {')
    else:
      self._XCPrint(file, 1, 'objects = {\n')

    objects_by_class = {}
    for object in self.Descendants():
      if object == self:
        continue
      class_name = object.__class__.__name__
      if not class_name in objects_by_class:
        objects_by_class[class_name] = []
      objects_by_class[class_name].append(object)

    for class_name in sorted(objects_by_class):
      self._XCPrint(file, 0, '\n')
      self._XCPrint(file, 0, '/* Begin ' + class_name + ' section */\n')
      for object in sorted(objects_by_class[class_name],
                           cmp=lambda x, y: cmp(x.id, y.id)):
        object.Print(file)
      self._XCPrint(file, 0, '/* End ' + class_name + ' section */\n')

    if self._should_print_single_line:
      self._XCPrint(file, 0, '}; ')
    else:
      self._XCPrint(file, 1, '};\n')
