# Copyright (c) 2009 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.
  Attribues:
    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 ComputeIDs(self, recursive=True, overwrite=True, 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 hash == None:
      hash = _new_sha1()

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

    if recursive:
      for child in self.Children():
        child.ComputeIDs(recursive, overwrite, hash.copy())

    if overwrite or self.id == 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 == 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 == 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 == 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 _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
    normpath = posixpath.normpath(path)
    if is_dir:
      normpath = path + '/'
    else:
      normpath = 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 == 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 == None:
        # Add or get a PBXFileReference.
        file_ref = self.GetChildByPath(normpath)
        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',
        '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 == None:
        has = configuration_has
      elif has != configuration_has:
        return -1

      if configuration_has:
        configuration_value = configuration.GetBuildSetting(key)
        if value == 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 == 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 == 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:
      # The easy case.  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:
      # The hard case.  Add a dependency to a target in a different project
      # file.  Actually, this case isn't really so hard.
      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 == 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 == None
        the_phase = phase

    return the_phase

  def HeadersPhase(self):
    headers_phase = self.GetBuildPhaseByType(PBXHeadersBuildPhase)
    if headers_phase == 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 == 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 == None:
      sources_phase = PBXSourcesBuildPhase()
      self.AppendProperty('buildPhases', sources_phase)

    return sources_phase

  def FrameworksPhase(self):
    frameworks_phase = self.GetBuildPhaseByType(PBXFrameworksBuildPhase)
    if frameworks_phase == 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 == 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) == 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')
