xcodeproj 0.9.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/ext/xcodeproj/extconf.rb +8 -0
- data/lib/xcodeproj.rb +2 -2
- data/lib/xcodeproj/config.rb +3 -3
- data/lib/xcodeproj/constants.rb +1 -1
- data/lib/xcodeproj/gem_version.rb +6 -0
- data/lib/xcodeproj/project.rb +163 -90
- data/lib/xcodeproj/project/object.rb +17 -4
- data/lib/xcodeproj/project/object/configuration_list.rb +15 -2
- data/lib/xcodeproj/project/object/file_reference.rb +60 -14
- data/lib/xcodeproj/project/object/group.rb +100 -168
- data/lib/xcodeproj/project/object/helpers/file_references_factory.rb +182 -0
- data/lib/xcodeproj/project/object/helpers/groupable_helper.rb +210 -0
- data/lib/xcodeproj/project/object/native_target.rb +23 -0
- data/lib/xcodeproj/project/project_helper.rb +44 -43
- data/lib/xcodeproj/project/xcproj_helper.rb +55 -0
- metadata +8 -4
| @@ -0,0 +1,182 @@ | |
| 1 | 
            +
            require 'xcodeproj/project/object/helpers/groupable_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Xcodeproj
         | 
| 4 | 
            +
              class Project
         | 
| 5 | 
            +
                module Object
         | 
| 6 | 
            +
                  class FileReferencesFactory
         | 
| 7 | 
            +
                    class << self
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                      # Creates a new reference with the given path and adds it to the
         | 
| 10 | 
            +
                      # given group. The reference is configured according to the extension
         | 
| 11 | 
            +
                      # of the path.
         | 
| 12 | 
            +
                      #
         | 
| 13 | 
            +
                      # @param  [PBXGroup] group
         | 
| 14 | 
            +
                      #         The group to which to add the reference.
         | 
| 15 | 
            +
                      #
         | 
| 16 | 
            +
                      # @param  [#to_s] path
         | 
| 17 | 
            +
                      #         The, preferably absolute, path of the reference.
         | 
| 18 | 
            +
                      #
         | 
| 19 | 
            +
                      # @param  [Symbol] source_tree
         | 
| 20 | 
            +
                      #         The source tree key to use to configure the path (@see
         | 
| 21 | 
            +
                      #         GroupableHelper::SOURCE_TREES_BY_KEY).
         | 
| 22 | 
            +
                      #
         | 
| 23 | 
            +
                      # @return [PBXFileReference, XCVersionGroup] The new reference.
         | 
| 24 | 
            +
                      #
         | 
| 25 | 
            +
                      def new_reference(group, path, source_tree)
         | 
| 26 | 
            +
                        if File.extname(path).downcase == '.xcdatamodeld'
         | 
| 27 | 
            +
                          ref = new_xcdatamodeld(group, path, source_tree)
         | 
| 28 | 
            +
                        else
         | 
| 29 | 
            +
                          ref = new_file_reference(group, path, source_tree)
         | 
| 30 | 
            +
                        end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                        configure_defaults_for_file_reference(ref)
         | 
| 33 | 
            +
                        ref
         | 
| 34 | 
            +
                      end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                      # Creates a file reference to a static library and adds it to the
         | 
| 37 | 
            +
                      # given group.
         | 
| 38 | 
            +
                      #
         | 
| 39 | 
            +
                      # @param  [PBXGroup] group
         | 
| 40 | 
            +
                      #         The group to which to add the reference.
         | 
| 41 | 
            +
                      #
         | 
| 42 | 
            +
                      # @param  [#to_s] product_name
         | 
| 43 | 
            +
                      #         The name of the static library.
         | 
| 44 | 
            +
                      #
         | 
| 45 | 
            +
                      # @return [PBXFileReference] The new file reference.
         | 
| 46 | 
            +
                      #
         | 
| 47 | 
            +
                      def new_static_library(group, product_name)
         | 
| 48 | 
            +
                        ref = new_reference(group, "lib#{product_name}.a", :built_products)
         | 
| 49 | 
            +
                        ref.include_in_index = '0'
         | 
| 50 | 
            +
                        ref.set_explicit_file_type
         | 
| 51 | 
            +
                        ref
         | 
| 52 | 
            +
                      end
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                      # Creates a file reference to a new bundle and adds it to the given
         | 
| 55 | 
            +
                      # group.
         | 
| 56 | 
            +
                      #
         | 
| 57 | 
            +
                      # @param  [PBXGroup] group
         | 
| 58 | 
            +
                      #         The group to which to add the reference.
         | 
| 59 | 
            +
                      #
         | 
| 60 | 
            +
                      # @param  [#to_s] product_name
         | 
| 61 | 
            +
                      #         The name of the bundle.
         | 
| 62 | 
            +
                      #
         | 
| 63 | 
            +
                      # @return [PBXFileReference] The new file reference.
         | 
| 64 | 
            +
                      #
         | 
| 65 | 
            +
                      def new_bundle(group, product_name)
         | 
| 66 | 
            +
                        ref = new_reference(group, "#{product_name}.bundle", :built_products)
         | 
| 67 | 
            +
                        ref.include_in_index = '0'
         | 
| 68 | 
            +
                        ref.set_explicit_file_type("wrapper.cfbundle")
         | 
| 69 | 
            +
                        ref
         | 
| 70 | 
            +
                      end
         | 
| 71 | 
            +
             | 
| 72 | 
            +
             | 
| 73 | 
            +
                      private
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                      # @group Private Helpers
         | 
| 76 | 
            +
                      #-------------------------------------------------------------------#
         | 
| 77 | 
            +
             | 
| 78 | 
            +
                      # Creates a new file reference with the given path and adds it to the
         | 
| 79 | 
            +
                      # given group.
         | 
| 80 | 
            +
                      #
         | 
| 81 | 
            +
                      # @param  [PBXGroup] group
         | 
| 82 | 
            +
                      #         The group to which to add the reference.
         | 
| 83 | 
            +
                      #
         | 
| 84 | 
            +
                      # @param  [#to_s] path
         | 
| 85 | 
            +
                      #         The, preferably absolute, path of the reference.
         | 
| 86 | 
            +
                      #
         | 
| 87 | 
            +
                      # @param  [Symbol] source_tree
         | 
| 88 | 
            +
                      #         The source tree key to use to configure the path (@see
         | 
| 89 | 
            +
                      #         GroupableHelper::SOURCE_TREES_BY_KEY).
         | 
| 90 | 
            +
                      #
         | 
| 91 | 
            +
                      # @return [PBXFileReference] The new file reference.
         | 
| 92 | 
            +
                      #
         | 
| 93 | 
            +
                      def new_file_reference(group, path, source_tree)
         | 
| 94 | 
            +
                        path = Pathname.new(path)
         | 
| 95 | 
            +
                        ref = group.project.new(PBXFileReference)
         | 
| 96 | 
            +
                        group.children << ref
         | 
| 97 | 
            +
                        GroupableHelper.set_path_with_source_tree(ref, path, source_tree)
         | 
| 98 | 
            +
                        ref.set_last_known_file_type
         | 
| 99 | 
            +
                        ref
         | 
| 100 | 
            +
                      end
         | 
| 101 | 
            +
             | 
| 102 | 
            +
                      # Creates a new version group reference to an xcdatamodeled adding
         | 
| 103 | 
            +
                      # the xcdatamodel files included in the wrapper as children file
         | 
| 104 | 
            +
                      # references.
         | 
| 105 | 
            +
                      #
         | 
| 106 | 
            +
                      # @param  [PBXGroup] group
         | 
| 107 | 
            +
                      #         The group to which to add the reference.
         | 
| 108 | 
            +
                      #
         | 
| 109 | 
            +
                      # @param  [#to_s] path
         | 
| 110 | 
            +
                      #         The, preferably absolute, path of the reference.
         | 
| 111 | 
            +
                      #
         | 
| 112 | 
            +
                      # @param  [Symbol] source_tree
         | 
| 113 | 
            +
                      #         The source tree key to use to configure the path (@see
         | 
| 114 | 
            +
                      #         GroupableHelper::SOURCE_TREES_BY_KEY).
         | 
| 115 | 
            +
                      #
         | 
| 116 | 
            +
                      # @note  To match Xcode behaviour the current version is read from
         | 
| 117 | 
            +
                      #         the .xccurrentversion file, if it doesn't exist the last
         | 
| 118 | 
            +
                      #         xcdatamodel according to its path is set as the current
         | 
| 119 | 
            +
                      #         version.
         | 
| 120 | 
            +
                      #
         | 
| 121 | 
            +
                      # @return [XCVersionGroup] The new reference.
         | 
| 122 | 
            +
                      #
         | 
| 123 | 
            +
                      def new_xcdatamodeld(group, path, source_tree)
         | 
| 124 | 
            +
                        path = Pathname.new(path)
         | 
| 125 | 
            +
                        ref = group.project.new(XCVersionGroup)
         | 
| 126 | 
            +
                        group.children << ref
         | 
| 127 | 
            +
                        GroupableHelper.set_path_with_source_tree(ref, path, source_tree)
         | 
| 128 | 
            +
                        ref.version_group_type = 'wrapper.xcdatamodel'
         | 
| 129 | 
            +
             | 
| 130 | 
            +
                        current_version_name = nil
         | 
| 131 | 
            +
                        if path.exist?
         | 
| 132 | 
            +
                          path.children.each do |child_path|
         | 
| 133 | 
            +
                            if File.extname(child_path) == '.xcdatamodel'
         | 
| 134 | 
            +
                              child_ref = new_file_reference(ref, child_path, :group)
         | 
| 135 | 
            +
                              last_child_ref = child_ref
         | 
| 136 | 
            +
                            elsif File.basename(child_path) == '.xccurrentversion'
         | 
| 137 | 
            +
                              full_path = path + child_path
         | 
| 138 | 
            +
                              xccurrentversion = Xcodeproj.read_plist(full_path)
         | 
| 139 | 
            +
                              current_version_name = xccurrentversion['_XCCurrentVersionName']
         | 
| 140 | 
            +
                            end
         | 
| 141 | 
            +
                          end
         | 
| 142 | 
            +
             | 
| 143 | 
            +
                          if current_version_name
         | 
| 144 | 
            +
                            ref.current_version = ref.children.find do |obj|
         | 
| 145 | 
            +
                                obj.path.split('/').last == current_version_name
         | 
| 146 | 
            +
                            end
         | 
| 147 | 
            +
                          end
         | 
| 148 | 
            +
                        end
         | 
| 149 | 
            +
             | 
| 150 | 
            +
                        ref
         | 
| 151 | 
            +
                      end
         | 
| 152 | 
            +
             | 
| 153 | 
            +
                      # Configures a file reference according to the extension to math
         | 
| 154 | 
            +
                      # Xcode behaviour.
         | 
| 155 | 
            +
                      #
         | 
| 156 | 
            +
                      # @param  [PBXFileReference] ref
         | 
| 157 | 
            +
                      #         The file reference to configure.
         | 
| 158 | 
            +
                      #
         | 
| 159 | 
            +
                      # @note   To closely match the Xcode behaviour the name attribute of
         | 
| 160 | 
            +
                      #         the file reference is set only if the path of the file is
         | 
| 161 | 
            +
                      #         not equal to the path of the group.
         | 
| 162 | 
            +
                      #
         | 
| 163 | 
            +
                      # @return [void]
         | 
| 164 | 
            +
                      #
         | 
| 165 | 
            +
                      def configure_defaults_for_file_reference(ref)
         | 
| 166 | 
            +
                        if ref.path.include?('/')
         | 
| 167 | 
            +
                          ref.name = ref.path.split('/').last
         | 
| 168 | 
            +
                        end
         | 
| 169 | 
            +
             | 
| 170 | 
            +
                        if File.extname(ref.path).downcase == '.framework'
         | 
| 171 | 
            +
                          ref.include_in_index = nil
         | 
| 172 | 
            +
                        end
         | 
| 173 | 
            +
                      end
         | 
| 174 | 
            +
             | 
| 175 | 
            +
                      #-------------------------------------------------------------------#
         | 
| 176 | 
            +
             | 
| 177 | 
            +
                    end
         | 
| 178 | 
            +
                  end
         | 
| 179 | 
            +
                end
         | 
| 180 | 
            +
              end
         | 
| 181 | 
            +
            end
         | 
| 182 | 
            +
             | 
| @@ -0,0 +1,210 @@ | |
| 1 | 
            +
            module Xcodeproj
         | 
| 2 | 
            +
              class Project
         | 
| 3 | 
            +
                module Object
         | 
| 4 | 
            +
                  class GroupableHelper
         | 
| 5 | 
            +
                    class << self
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                      # @param  [PBXGroup, PBXFileReference] object
         | 
| 8 | 
            +
                      #         The object to analyze.
         | 
| 9 | 
            +
                      #
         | 
| 10 | 
            +
                      # @return [PBXGroup, PBXProject] The parent of the object.
         | 
| 11 | 
            +
                      #
         | 
| 12 | 
            +
                      def parent(object)
         | 
| 13 | 
            +
                        check_parents_integrity(object)
         | 
| 14 | 
            +
                        object.referrers.first
         | 
| 15 | 
            +
                      end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                      # @param  [PBXGroup, PBXFileReference] object
         | 
| 18 | 
            +
                      #         The object to analyze.
         | 
| 19 | 
            +
                      #
         | 
| 20 | 
            +
                      # @return [Array<PBXGroup, PBXProject>] The parents of the object.
         | 
| 21 | 
            +
                      #
         | 
| 22 | 
            +
                      def parents(object)
         | 
| 23 | 
            +
                        if main_group?(object)
         | 
| 24 | 
            +
                          []
         | 
| 25 | 
            +
                        else
         | 
| 26 | 
            +
                          parent = parent(object)
         | 
| 27 | 
            +
                          parents(parent).push(parent)
         | 
| 28 | 
            +
                        end
         | 
| 29 | 
            +
                      end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                      # @param  [PBXGroup, PBXFileReference] object
         | 
| 32 | 
            +
                      #         The object to analyze.
         | 
| 33 | 
            +
                      #
         | 
| 34 | 
            +
                      # @return [String] A representation of the group hierarchy.
         | 
| 35 | 
            +
                      #
         | 
| 36 | 
            +
                      def hierarchy_path(object)
         | 
| 37 | 
            +
                        unless main_group?(object)
         | 
| 38 | 
            +
                          "#{parent(object).hierarchy_path}/#{object.display_name}"
         | 
| 39 | 
            +
                        end
         | 
| 40 | 
            +
                      end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                      # @param  [PBXGroup, PBXFileReference] object
         | 
| 43 | 
            +
                      #         The object to analyze.
         | 
| 44 | 
            +
                      #
         | 
| 45 | 
            +
                      # @return [Bool] Wether the object is the main group of the project.
         | 
| 46 | 
            +
                      #
         | 
| 47 | 
            +
                      def main_group?(object)
         | 
| 48 | 
            +
                        object.equal?(object.project.main_group)
         | 
| 49 | 
            +
                      end
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                      # Moves the object to a new parent.
         | 
| 52 | 
            +
                      #
         | 
| 53 | 
            +
                      # @param  [PBXGroup, PBXFileReference] object
         | 
| 54 | 
            +
                      #         The object to move.
         | 
| 55 | 
            +
                      #
         | 
| 56 | 
            +
                      # @param  [PBXGroup] new_parent
         | 
| 57 | 
            +
                      #         The new parent.
         | 
| 58 | 
            +
                      #
         | 
| 59 | 
            +
                      # @return [void]
         | 
| 60 | 
            +
                      #
         | 
| 61 | 
            +
                      def move(object, new_parent)
         | 
| 62 | 
            +
                        unless object
         | 
| 63 | 
            +
                          raise "[Xcodeproj] Attempt to move nil object to `#{new_parent}`."
         | 
| 64 | 
            +
                        end
         | 
| 65 | 
            +
                        unless new_parent
         | 
| 66 | 
            +
                          raise "[Xcodeproj] Attempt to move object `#{object}` to nil parent."
         | 
| 67 | 
            +
                        end
         | 
| 68 | 
            +
                        if new_parent.equal?(object)
         | 
| 69 | 
            +
                          raise "[Xcodeproj] Attempt to move object `#{object}` to itself."
         | 
| 70 | 
            +
                        end
         | 
| 71 | 
            +
                        if parents(new_parent).include?(object)
         | 
| 72 | 
            +
                          raise "[Xcodeproj] Attempt to move object `#{object}` to a child object `#{new_parent}`."
         | 
| 73 | 
            +
                        end
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                        object.parent.children.delete(object)
         | 
| 76 | 
            +
                        new_parent << object
         | 
| 77 | 
            +
                      end
         | 
| 78 | 
            +
             | 
| 79 | 
            +
                      # @param  [PBXGroup, PBXFileReference] object
         | 
| 80 | 
            +
                      #         The object to analyze.
         | 
| 81 | 
            +
                      #
         | 
| 82 | 
            +
                      # @return [Pathname] The absolute path of the object resolving the
         | 
| 83 | 
            +
                      #         source tree.
         | 
| 84 | 
            +
                      #
         | 
| 85 | 
            +
                      def real_path(object)
         | 
| 86 | 
            +
                        source_tree = source_tree_real_path(object)
         | 
| 87 | 
            +
                        path = object.path || ''
         | 
| 88 | 
            +
                        if source_tree
         | 
| 89 | 
            +
                          source_tree + path
         | 
| 90 | 
            +
                        else
         | 
| 91 | 
            +
                          Pathname(path)
         | 
| 92 | 
            +
                        end
         | 
| 93 | 
            +
                      end
         | 
| 94 | 
            +
             | 
| 95 | 
            +
                      # @param  [PBXGroup, PBXFileReference] object
         | 
| 96 | 
            +
                      #         The object to analyze.
         | 
| 97 | 
            +
                      #
         | 
| 98 | 
            +
                      # @return [Pathname] The absolute path of the source tree of the
         | 
| 99 | 
            +
                      #         object.
         | 
| 100 | 
            +
                      #
         | 
| 101 | 
            +
                      def source_tree_real_path(object)
         | 
| 102 | 
            +
                        case object.source_tree
         | 
| 103 | 
            +
                        when '<group>'
         | 
| 104 | 
            +
                          if parent(object).isa == 'PBXProject'
         | 
| 105 | 
            +
                            object.project.path.dirname
         | 
| 106 | 
            +
                          else
         | 
| 107 | 
            +
                            real_path(parent(object))
         | 
| 108 | 
            +
                          end
         | 
| 109 | 
            +
                        when 'SOURCE_ROOT'
         | 
| 110 | 
            +
                          object.project.path.dirname
         | 
| 111 | 
            +
                        when '<absolute>', 'BUILT_PRODUCTS_DIR', 'DEVELOPER_DIR'
         | 
| 112 | 
            +
                          nil
         | 
| 113 | 
            +
                        else
         | 
| 114 | 
            +
                          raise "[Xcodeproj] Unable to compute the source tree for " \
         | 
| 115 | 
            +
                            " `#{object.display_name}`: `#{object.source_tree}`"
         | 
| 116 | 
            +
                        end
         | 
| 117 | 
            +
                      end
         | 
| 118 | 
            +
             | 
| 119 | 
            +
                      # @return [Hash{Symbol => String}] The source tree values by they
         | 
| 120 | 
            +
                      #         symbol representation.
         | 
| 121 | 
            +
                      #
         | 
| 122 | 
            +
                      SOURCE_TREES_BY_KEY = {
         | 
| 123 | 
            +
                        :absolute        => '<absolute>',
         | 
| 124 | 
            +
                        :group           => '<group>',
         | 
| 125 | 
            +
                        :project         => 'SOURCE_ROOT',
         | 
| 126 | 
            +
                        :built_products  => 'BUILT_PRODUCTS_DIR',
         | 
| 127 | 
            +
                        :developer_dir   => 'DEVELOPER_DIR',
         | 
| 128 | 
            +
                        :sdk_root        => 'SDKROOT',
         | 
| 129 | 
            +
                      }.freeze
         | 
| 130 | 
            +
             | 
| 131 | 
            +
                      # Sets the path of the given object according to the provided source
         | 
| 132 | 
            +
                      # tree key. The path is converted to relative according to the real
         | 
| 133 | 
            +
                      # path of the source tree for group and project source trees, if both
         | 
| 134 | 
            +
                      # paths are relative or absolute. Otherwise the path is set as
         | 
| 135 | 
            +
                      # provided.
         | 
| 136 | 
            +
                      #
         | 
| 137 | 
            +
                      # @param  [PBXGroup, PBXFileReference] object
         | 
| 138 | 
            +
                      #         The object whose path needs to be set.
         | 
| 139 | 
            +
                      #
         | 
| 140 | 
            +
                      # @param  [#to_s] path
         | 
| 141 | 
            +
                      #         The path.
         | 
| 142 | 
            +
                      #
         | 
| 143 | 
            +
                      # @param  [Symbol] source_tree_key
         | 
| 144 | 
            +
                      #         The source tree type, see {SOURCE_TREES_BY_KEY} for
         | 
| 145 | 
            +
                      #         acceptable values.
         | 
| 146 | 
            +
                      #
         | 
| 147 | 
            +
                      # @return [void]
         | 
| 148 | 
            +
                      #
         | 
| 149 | 
            +
                      def set_path_with_source_tree(object, path, source_tree_key)
         | 
| 150 | 
            +
                        path = Pathname.new(path)
         | 
| 151 | 
            +
                        source_tree = SOURCE_TREES_BY_KEY[source_tree_key]
         | 
| 152 | 
            +
                        object.source_tree = source_tree
         | 
| 153 | 
            +
             | 
| 154 | 
            +
                        unless source_tree
         | 
| 155 | 
            +
                          raise "[Xcodeproj] Unrecognized source tree option `#{source_tree_key}` for path `#{path}`"
         | 
| 156 | 
            +
                        end
         | 
| 157 | 
            +
             | 
| 158 | 
            +
                        if source_tree_key == :absolute
         | 
| 159 | 
            +
                          unless path.absolute?
         | 
| 160 | 
            +
                            raise "[Xcodeproj] Attempt to set a relative path with an " \
         | 
| 161 | 
            +
                              "absolute source tree: `#{path}`"
         | 
| 162 | 
            +
                          end
         | 
| 163 | 
            +
                          object.path = path.to_s
         | 
| 164 | 
            +
                        elsif source_tree_key == :group || source_tree_key == :project
         | 
| 165 | 
            +
                          source_tree_real_path = GroupableHelper.source_tree_real_path(object)
         | 
| 166 | 
            +
                          if source_tree_real_path && source_tree_real_path.absolute? == path.absolute?
         | 
| 167 | 
            +
                            relative_path = path.relative_path_from(source_tree_real_path)
         | 
| 168 | 
            +
                            object.path = relative_path.to_s
         | 
| 169 | 
            +
                          else
         | 
| 170 | 
            +
                            object.path = path.to_s
         | 
| 171 | 
            +
                          end
         | 
| 172 | 
            +
                        else
         | 
| 173 | 
            +
                          object.path = path.to_s
         | 
| 174 | 
            +
                        end
         | 
| 175 | 
            +
                      end
         | 
| 176 | 
            +
             | 
| 177 | 
            +
                      private
         | 
| 178 | 
            +
             | 
| 179 | 
            +
                      # @group Helpers
         | 
| 180 | 
            +
                      #-------------------------------------------------------------------#
         | 
| 181 | 
            +
             | 
| 182 | 
            +
                      # Checks whether there is a single identifiable parent and raises
         | 
| 183 | 
            +
                      # otherwise.
         | 
| 184 | 
            +
                      #
         | 
| 185 | 
            +
                      # @return [void]
         | 
| 186 | 
            +
                      #
         | 
| 187 | 
            +
                      def check_parents_integrity(object)
         | 
| 188 | 
            +
                        referrers_count = object.referrers.count
         | 
| 189 | 
            +
                        if referrers_count > 1
         | 
| 190 | 
            +
                          referrers_count = object.referrers.select{ |obj| obj.isa == 'PBXGroup' }.count
         | 
| 191 | 
            +
                        end
         | 
| 192 | 
            +
             | 
| 193 | 
            +
                        if referrers_count == 0
         | 
| 194 | 
            +
                          raise "[Xcodeproj] Consistency issue: no parent " \
         | 
| 195 | 
            +
                            "for object `#{object.display_name}`: "\
         | 
| 196 | 
            +
                            "#{object.referrers}"
         | 
| 197 | 
            +
                        elsif referrers_count > 1
         | 
| 198 | 
            +
                          raise "[Xcodeproj] Consistency issue: unexpected multiple parents " \
         | 
| 199 | 
            +
                            "for object `#{object.display_name}`: "\
         | 
| 200 | 
            +
                            "#{object.referrers}"
         | 
| 201 | 
            +
                        end
         | 
| 202 | 
            +
                      end
         | 
| 203 | 
            +
             | 
| 204 | 
            +
                      #-------------------------------------------------------------------#
         | 
| 205 | 
            +
             | 
| 206 | 
            +
                    end
         | 
| 207 | 
            +
                  end
         | 
| 208 | 
            +
                end
         | 
| 209 | 
            +
              end
         | 
| 210 | 
            +
            end
         | 
| @@ -71,6 +71,29 @@ module Xcodeproj | |
| 71 71 | 
             
                      build_configuration_list.build_configurations
         | 
| 72 72 | 
             
                    end
         | 
| 73 73 |  | 
| 74 | 
            +
                    # Adds a new build configuration to the target and populates its with
         | 
| 75 | 
            +
                    # default settings according to the provided type.
         | 
| 76 | 
            +
                    #
         | 
| 77 | 
            +
                    # @note   If a build configuration with the given name is already
         | 
| 78 | 
            +
                    #         present no new build configuration is added.
         | 
| 79 | 
            +
                    #
         | 
| 80 | 
            +
                    # @param  [String] name
         | 
| 81 | 
            +
                    #         The name of the build configuration.
         | 
| 82 | 
            +
                    #
         | 
| 83 | 
            +
                    # @param  [Symbol] type
         | 
| 84 | 
            +
                    #         The type of the build configuration used to populate the build
         | 
| 85 | 
            +
                    #         settings, must be :debug or :release.
         | 
| 86 | 
            +
                    #
         | 
| 87 | 
            +
                    def add_build_configuration(name, type, skip_existing_names = true)
         | 
| 88 | 
            +
                      unless build_configuration_list[name]
         | 
| 89 | 
            +
                        build_configuration = project.new(XCBuildConfiguration)
         | 
| 90 | 
            +
                        build_configuration.name = name
         | 
| 91 | 
            +
                        build_configuration.build_settings = ProjectHelper.common_build_settings(type, platform_name, deployment_target, product_type)
         | 
| 92 | 
            +
                        build_configuration_list.build_configurations << build_configuration
         | 
| 93 | 
            +
                        build_configuration
         | 
| 94 | 
            +
                      end
         | 
| 95 | 
            +
                    end
         | 
| 96 | 
            +
             | 
| 74 97 | 
             
                    # @param  [String] build_configuration_name
         | 
| 75 98 | 
             
                    #         the name of a build configuration.
         | 
| 76 99 | 
             
                    #
         | 
| @@ -49,16 +49,14 @@ module Xcodeproj | |
| 49 49 | 
             
                    product = product_group.new_static_library(name)
         | 
| 50 50 | 
             
                    target.product_reference = product
         | 
| 51 51 |  | 
| 52 | 
            +
                    # Build phases
         | 
| 53 | 
            +
                    target.build_phases << project.new(PBXSourcesBuildPhase)
         | 
| 54 | 
            +
                    target.build_phases << project.new(PBXFrameworksBuildPhase)
         | 
| 55 | 
            +
             | 
| 52 56 | 
             
                    # Frameworks
         | 
| 53 57 | 
             
                    framework_name = (platform == :ios) ? 'Foundation' : 'Cocoa'
         | 
| 54 58 | 
             
                    framework_ref = project.add_system_framework(framework_name, target)
         | 
| 55 59 |  | 
| 56 | 
            -
                    # Build phases
         | 
| 57 | 
            -
                    target.build_phases << project.new(PBXSourcesBuildPhase)
         | 
| 58 | 
            -
                    frameworks_phase = project.new(PBXFrameworksBuildPhase)
         | 
| 59 | 
            -
                    frameworks_phase.add_file_reference(framework_ref)
         | 
| 60 | 
            -
                    target.build_phases << frameworks_phase
         | 
| 61 | 
            -
             | 
| 62 60 | 
             
                    target
         | 
| 63 61 | 
             
                  end
         | 
| 64 62 |  | 
| @@ -88,20 +86,9 @@ module Xcodeproj | |
| 88 86 | 
             
                    target.product_name = name
         | 
| 89 87 | 
             
                    target.product_type = Constants::PRODUCT_TYPE_UTI[:bundle]
         | 
| 90 88 |  | 
| 91 | 
            -
                     | 
| 92 | 
            -
                    build_settings = {
         | 
| 93 | 
            -
                      'PRODUCT_NAME' => '$(TARGET_NAME)',
         | 
| 94 | 
            -
                      'WRAPPER_EXTENSION' => 'bundle',
         | 
| 95 | 
            -
                      'SKIP_INSTALL' => 'YES'
         | 
| 96 | 
            -
                    }
         | 
| 97 | 
            -
             | 
| 98 | 
            -
                    if platform == :osx
         | 
| 99 | 
            -
                      build_settings['COMBINE_HIDPI_IMAGES'] = 'YES'
         | 
| 100 | 
            -
                      build_settings['SDKROOT'] = 'macosx'
         | 
| 101 | 
            -
                    else
         | 
| 102 | 
            -
                      build_settings['SDKROOT'] = 'iphoneos'
         | 
| 103 | 
            -
                    end
         | 
| 89 | 
            +
                    build_settings = common_build_settings(nil, platform, nil, target.product_type)
         | 
| 104 90 |  | 
| 91 | 
            +
                    # Configuration List
         | 
| 105 92 | 
             
                    cl = project.new(XCConfigurationList)
         | 
| 106 93 | 
             
                    cl.default_configuration_is_visible = '0'
         | 
| 107 94 | 
             
                    cl.default_configuration_name = 'Release'
         | 
| @@ -132,10 +119,8 @@ module Xcodeproj | |
| 132 119 |  | 
| 133 120 | 
             
                  #-----------------------------------------------------------------------#
         | 
| 134 121 |  | 
| 135 | 
            -
                  # Adds a file reference for a system framework to the project | 
| 136 | 
            -
                  #
         | 
| 137 | 
            -
                  # The file reference can then be added to the build files of a
         | 
| 138 | 
            -
                  # {PBXFrameworksBuildPhase}.
         | 
| 122 | 
            +
                  # Adds a file reference for a system framework to the project if needed
         | 
| 123 | 
            +
                  # and adds it to the {PBXFrameworksBuildPhase} of the given target.
         | 
| 139 124 | 
             
                  #
         | 
| 140 125 | 
             
                  # @param  [Project] project
         | 
| 141 126 | 
             
                  #         the project to which the configuration list should be added.
         | 
| @@ -144,12 +129,12 @@ module Xcodeproj | |
| 144 129 | 
             
                  #         The name of a framework.
         | 
| 145 130 | 
             
                  #
         | 
| 146 131 | 
             
                  # @param  [PBXNativeTarget] target
         | 
| 147 | 
            -
                  #         The target  | 
| 132 | 
            +
                  #         The target to which to add the framework.
         | 
| 148 133 | 
             
                  #
         | 
| 149 134 | 
             
                  # @note   This method adds a reference to the highest know SDK for the
         | 
| 150 135 | 
             
                  #         given platform.
         | 
| 151 136 | 
             
                  #
         | 
| 152 | 
            -
                  # @return [PBXFileReference] The  | 
| 137 | 
            +
                  # @return [PBXFileReference] The file reference of the framework.
         | 
| 153 138 | 
             
                  #
         | 
| 154 139 | 
             
                  def self.add_system_framework(project, name, target)
         | 
| 155 140 | 
             
                    sdk = target.sdk
         | 
| @@ -171,13 +156,13 @@ module Xcodeproj | |
| 171 156 | 
             
                    end
         | 
| 172 157 |  | 
| 173 158 | 
             
                    path = base_dir + "System/Library/Frameworks/#{name}.framework"
         | 
| 174 | 
            -
                     | 
| 175 | 
            -
             | 
| 176 | 
            -
             | 
| 177 | 
            -
                      ref = project.frameworks_group.new_file(path)
         | 
| 178 | 
            -
                      ref.source_tree = 'DEVELOPER_DIR'
         | 
| 179 | 
            -
                      ref
         | 
| 159 | 
            +
                    ref = project.frameworks_group.files.find { |f| f.path == path }
         | 
| 160 | 
            +
                    unless ref
         | 
| 161 | 
            +
                      ref = project.frameworks_group.new_file(path, :developer_dir)
         | 
| 180 162 | 
             
                    end
         | 
| 163 | 
            +
             | 
| 164 | 
            +
                    target.frameworks_build_phase.add_file_reference(ref)
         | 
| 165 | 
            +
                    ref
         | 
| 181 166 | 
             
                  end
         | 
| 182 167 |  | 
| 183 168 | 
             
                  # @!group Private Helpers
         | 
| @@ -231,20 +216,36 @@ module Xcodeproj | |
| 231 216 | 
             
                  #
         | 
| 232 217 | 
             
                  # @return [Hash] The common build settings
         | 
| 233 218 | 
             
                  #
         | 
| 234 | 
            -
                  def self.common_build_settings(type, platform, deployment_target = nil)
         | 
| 235 | 
            -
                     | 
| 236 | 
            -
             | 
| 237 | 
            -
             | 
| 238 | 
            -
             | 
| 239 | 
            -
             | 
| 240 | 
            -
             | 
| 241 | 
            -
             | 
| 242 | 
            -
             | 
| 243 | 
            -
             | 
| 244 | 
            -
                         | 
| 219 | 
            +
                  def self.common_build_settings(type, platform, deployment_target = nil, target_product_type = nil)
         | 
| 220 | 
            +
                    if target_product_type == Constants::PRODUCT_TYPE_UTI[:bundle]
         | 
| 221 | 
            +
                      build_settings = {
         | 
| 222 | 
            +
                        'PRODUCT_NAME' => '$(TARGET_NAME)',
         | 
| 223 | 
            +
                        'WRAPPER_EXTENSION' => 'bundle',
         | 
| 224 | 
            +
                        'SKIP_INSTALL' => 'YES'
         | 
| 225 | 
            +
                      }
         | 
| 226 | 
            +
             | 
| 227 | 
            +
                      if platform == :osx
         | 
| 228 | 
            +
                        build_settings['COMBINE_HIDPI_IMAGES'] = 'YES'
         | 
| 229 | 
            +
                        build_settings['SDKROOT'] = 'macosx'
         | 
| 230 | 
            +
                      else
         | 
| 231 | 
            +
                        build_settings['SDKROOT'] = 'iphoneos'
         | 
| 232 | 
            +
                      end
         | 
| 233 | 
            +
                      build_settings
         | 
| 234 | 
            +
                    else
         | 
| 235 | 
            +
                      common_settings = Constants::COMMON_BUILD_SETTINGS
         | 
| 236 | 
            +
                      settings = common_settings[:all].dup
         | 
| 237 | 
            +
                      settings.merge!(common_settings[type])
         | 
| 238 | 
            +
                      settings.merge!(common_settings[platform])
         | 
| 239 | 
            +
                      settings.merge!(common_settings[[platform, type]])
         | 
| 240 | 
            +
                      if deployment_target
         | 
| 241 | 
            +
                        if platform == :ios
         | 
| 242 | 
            +
                          settings['IPHONEOS_DEPLOYMENT_TARGET'] = deployment_target
         | 
| 243 | 
            +
                        elsif platform == :osx
         | 
| 244 | 
            +
                          settings['MACOSX_DEPLOYMENT_TARGET'] = deployment_target
         | 
| 245 | 
            +
                        end
         | 
| 245 246 | 
             
                      end
         | 
| 247 | 
            +
                      settings
         | 
| 246 248 | 
             
                    end
         | 
| 247 | 
            -
                    settings
         | 
| 248 249 | 
             
                  end
         | 
| 249 250 |  | 
| 250 251 | 
             
                  #-----------------------------------------------------------------------#
         |