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

"""Xcode project file generator.

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

XCODE PROJECT FILES

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

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

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

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

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

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

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

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

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

THIS MODULE

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

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

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

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

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

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

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

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


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

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

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


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

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(r'\$\((.*?)\)', '${\\1}', input_string)

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

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

  _schema = {}
  _should_print_single_line = False

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

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

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

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

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

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

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

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

    return that

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

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

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

    raise NotImplementedError(self.__class__.__name__ + ' must implement Name')

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

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

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

    return self.Name()

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

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

    hashables.extend(self._hashables)

    return hashables

  def HashablesForChild(self):
    return None

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

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

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

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

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

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

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

    if seed_hash is None:
      seed_hash = _new_sha1()

    hash = seed_hash.copy()

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    printable = ''
    comment = None

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

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

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

    return printable

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

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

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

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

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

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

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

    self._XCPrint(file, 0, printable)

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

    self.VerifyHasRequiredProperties()

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

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

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

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

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

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

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

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

    if properties is None:
      return

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        defaults[property] = default

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


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

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

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

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

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

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

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

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

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

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

    hashables = []

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

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

    hashables.extend(self._hashables)

    return hashables

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

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

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

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

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

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

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

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

    return None

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

    return path


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

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

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

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

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

    return hashables

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

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

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

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

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

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

    return None

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

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

    return None

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

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

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

    return None

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

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

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

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

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

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

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

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

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

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

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

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

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

    return variant_group_ref

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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


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


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


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

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

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

    if 'path' in self._properties and \
        not 'lastKnownFileType' in self._properties and \
        not 'explicitFileType' in self._properties:
      # TODO(mark): This is the replacement for a replacement for a quick hack.
      # It is no longer incredibly sucky, but this list needs to be extended.
      extension_map = {
        'a':           'archive.ar',
        'app':         'wrapper.application',
        'bdic':        'file',
        'bundle':      'wrapper.cfbundle',
        'c':           'sourcecode.c.c',
        'cc':          'sourcecode.cpp.cpp',
        'cpp':         'sourcecode.cpp.cpp',
        'css':         'text.css',
        'cxx':         'sourcecode.cpp.cpp',
        'dart':        'sourcecode',
        'dylib':       'compiled.mach-o.dylib',
        'framework':   'wrapper.framework',
        'gyp':         'sourcecode',
        'gypi':        'sourcecode',
        'h':           'sourcecode.c.h',
        'hxx':         'sourcecode.cpp.h',
        'icns':        'image.icns',
        'java':        'sourcecode.java',
        'js':          'sourcecode.javascript',
        'kext':        'wrapper.kext',
        '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',
        'storyboard':  'file.storyboard',
        'strings':     'text.plist.strings',
        'swift':       'sourcecode.swift',
        'ttf':         'file',
        'xcassets':    'folder.assetcatalog',
        'xcconfig':    'text.xcconfig',
        'xcdatamodel': 'wrapper.xcdatamodel',
        'xcdatamodeld':'wrapper.xcdatamodeld',
        'xib':         'file.xib',
        'y':           'sourcecode.yacc',
      }

      prop_map = {
        'dart':        'explicitFileType',
        'gyp':         'explicitFileType',
        'gypi':        'explicitFileType',
      }

      if is_dir:
        file_type = 'folder'
        prop_name = 'lastKnownFileType'
      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')
        prop_name = prop_map.get(ext, 'lastKnownFileType')

      self._properties[prop_name] = file_type


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


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


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

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

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

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

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

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

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

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

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

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

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

    raise KeyError(name)

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

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

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

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

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

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

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

    if not has:
      return 0

    return 1

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

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

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

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

    return value

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

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

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

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

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

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

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

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


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

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

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

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

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

    return hashables


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    xcfilelikeelement = pbxbuildfile._properties['fileRef']

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

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

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

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

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

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


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

  def Name(self):
    return 'Headers'

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


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

  def Name(self):
    return 'Resources'

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


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

  def Name(self):
    return 'Sources'

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


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

  def Name(self):
    return 'Frameworks'

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


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

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

    return 'ShellScript'


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

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

  # path_tree_to_subfolder maps names of Xcode variables to the associated
  # dstSubfolderSpec property value used in a PBXCopyFilesBuildPhase object.
  path_tree_to_subfolder = {
    'BUILT_FRAMEWORKS_DIR': 10,  # Frameworks Directory
    '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
    # : 11,  # Shared Frameworks
    # : 12,  # Shared Support
    # : 13,  # PlugIns
  }

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

    return 'CopyFiles'

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

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

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

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

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

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


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

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

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

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


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

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

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

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

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


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

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

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

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

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


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


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

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

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

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

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

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

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

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

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

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

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

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

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


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


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

  # Mapping from Xcode product-types to settings.  The settings are:
  #  filetype : used for explicitFileType in the project file
  #  prefix : the prefix for the file name
  #  suffix : the suffix for the file name
  _product_filetypes = {
    'com.apple.product-type.application':           ['wrapper.application',
                                                     '', '.app'],
    'com.apple.product-type.application.watchapp':  ['wrapper.application',
                                                     '', '.app'],
    'com.apple.product-type.watchkit-extension':    ['wrapper.app-extension',
                                                     '', '.appex'],
    'com.apple.product-type.app-extension':         ['wrapper.app-extension',
                                                     '', '.appex'],
    '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.apple.product-type.bundle.unit-test':  ['wrapper.cfbundle',
                                                 '', '.xctest'],
    'com.apple.product-type.bundle.ui-testing':  ['wrapper.cfbundle',
                                                  '', '.xctest'],
    'com.googlecode.gyp.xcode.bundle':          ['compiled.mach-o.dylib',
                                                 '', '.so'],
    'com.apple.product-type.kernel-extension':  ['wrapper.kext',
                                                 '', '.kext'],
  }

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

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

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

        if self._properties['productType'] == \
           'com.apple.product-type-bundle.unit.test' or \
           self._properties['productType'] == \
           'com.apple.product-type-bundle.ui-testing':
          if force_extension is None:
            force_extension = suffix[1:]

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

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

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

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

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

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

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

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

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

    return the_phase

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

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

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

    return headers_phase

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

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

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

    return resources_phase

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

    return sources_phase

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

    return frameworks_phase

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

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

      file_ref = other.GetProperty('productReference')

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

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


class PBXAggregateTarget(XCTarget):
  pass


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

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

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

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

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

  def Path(self):
    return self.path

  def Comment(self):
    return 'Project object'

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

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

    return children

  def PBXProjectAncestor(self):
    return self

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

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

    return group

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

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

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

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

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

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

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

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

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

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

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

    return (self.SourceGroup(), True)

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

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

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

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

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

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

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

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

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

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

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

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

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

    product_group = None
    project_ref = None

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

      # ProductGroup is strong.
      product_group.parent = self

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

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

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

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

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

    self._SetUpProductReferences(other_pbxproject, product_group, project_ref)

    inherit_unique_symroot = self._AllSymrootsUnique(other_pbxproject, False)
    targets = other_pbxproject.GetProperty('targets')
    if all(self._AllSymrootsUnique(t, inherit_unique_symroot) for t in targets):
      dir_path = project_ref._properties['path']
      product_group._hashables.extend(dir_path)

    return [product_group, project_ref]

  def _AllSymrootsUnique(self, target, inherit_unique_symroot):
    # Returns True if all configurations have a unique 'SYMROOT' attribute.
    # The value of inherit_unique_symroot decides, if a configuration is assumed
    # to inherit a unique 'SYMROOT' attribute from its parent, if it doesn't
    # define an explicit value for 'SYMROOT'.
    symroots = self._DefinedSymroots(target)
    for s in self._DefinedSymroots(target):
      if (s is not None and not self._IsUniqueSymrootForTarget(s) or
          s is None and not inherit_unique_symroot):
        return False
    return True if symroots else inherit_unique_symroot

  def _DefinedSymroots(self, target):
    # Returns all values for the 'SYMROOT' attribute defined in all
    # configurations for this target. If any configuration doesn't define the
    # 'SYMROOT' attribute, None is added to the returned set. If all
    # configurations don't define the 'SYMROOT' attribute, an empty set is
    # returned.
    config_list = target.GetProperty('buildConfigurationList')
    symroots = set()
    for config in config_list.GetProperty('buildConfigurations'):
      setting = config.GetProperty('buildSettings')
      if 'SYMROOT' in setting:
        symroots.add(setting['SYMROOT'])
      else:
        symroots.add(None)
    if len(symroots) == 1 and None in symroots:
      return set()
    return symroots

  def _IsUniqueSymrootForTarget(self, symroot):
    # This method returns True if all configurations in target contain a
    # 'SYMROOT' attribute that is unique for the given target. A value is
    # unique, if the Xcode macro '$SRCROOT' appears in it in any form.
    uniquifier = ['$SRCROOT', '$(SRCROOT)']
    if any(x in symroot for x in uniquifier):
      return True
    return False

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

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

        product_group.AppendChild(reference_proxy)

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

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

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

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

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


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, 46],
    'rootObject':     [0, PBXProject, 1, 1],
  })

  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')
