cocoapods 1.6.2 → 1.7.0.beta.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (87) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +101 -7
  3. data/README.md +9 -9
  4. data/lib/cocoapods.rb +2 -0
  5. data/lib/cocoapods/command.rb +1 -1
  6. data/lib/cocoapods/command/init.rb +2 -12
  7. data/lib/cocoapods/command/install.rb +3 -0
  8. data/lib/cocoapods/command/lib/create.rb +1 -1
  9. data/lib/cocoapods/command/lib/lint.rb +5 -1
  10. data/lib/cocoapods/command/list.rb +3 -5
  11. data/lib/cocoapods/command/repo.rb +1 -0
  12. data/lib/cocoapods/command/repo/add.rb +4 -5
  13. data/lib/cocoapods/command/repo/add_cdn.rb +58 -0
  14. data/lib/cocoapods/command/repo/list.rb +5 -6
  15. data/lib/cocoapods/command/repo/push.rb +6 -5
  16. data/lib/cocoapods/command/spec/create.rb +12 -12
  17. data/lib/cocoapods/command/spec/lint.rb +1 -1
  18. data/lib/cocoapods/command/update.rb +3 -0
  19. data/lib/cocoapods/config.rb +1 -0
  20. data/lib/cocoapods/executable.rb +32 -7
  21. data/lib/cocoapods/gem_version.rb +1 -1
  22. data/lib/cocoapods/generator/app_target_helper.rb +1 -1
  23. data/lib/cocoapods/generator/embed_frameworks_script.rb +13 -0
  24. data/lib/cocoapods/generator/file_list.rb +39 -0
  25. data/lib/cocoapods/generator/module_map.rb +1 -1
  26. data/lib/cocoapods/installer.rb +188 -46
  27. data/lib/cocoapods/installer/analyzer.rb +64 -39
  28. data/lib/cocoapods/installer/analyzer/pod_variant.rb +14 -9
  29. data/lib/cocoapods/installer/analyzer/pod_variant_set.rb +11 -2
  30. data/lib/cocoapods/installer/installation_options.rb +70 -44
  31. data/lib/cocoapods/installer/pod_source_installer.rb +9 -4
  32. data/lib/cocoapods/installer/podfile_validator.rb +9 -0
  33. data/lib/cocoapods/installer/post_install_hooks_context.rb +5 -2
  34. data/lib/cocoapods/installer/project_cache/project_cache.rb +11 -0
  35. data/lib/cocoapods/installer/project_cache/project_cache_analysis_result.rb +53 -0
  36. data/lib/cocoapods/installer/project_cache/project_cache_analyzer.rb +156 -0
  37. data/lib/cocoapods/installer/project_cache/project_cache_version.rb +43 -0
  38. data/lib/cocoapods/installer/project_cache/project_installation_cache.rb +77 -0
  39. data/lib/cocoapods/installer/project_cache/project_metadata_cache.rb +63 -0
  40. data/lib/cocoapods/installer/project_cache/target_cache_key.rb +134 -0
  41. data/lib/cocoapods/installer/project_cache/target_metadata.rb +70 -0
  42. data/lib/cocoapods/installer/sandbox_dir_cleaner.rb +89 -0
  43. data/lib/cocoapods/installer/sandbox_header_paths_installer.rb +45 -0
  44. data/lib/cocoapods/installer/target_uuid_generator.rb +32 -0
  45. data/lib/cocoapods/installer/user_project_integrator.rb +8 -6
  46. data/lib/cocoapods/installer/user_project_integrator/target_integrator.rb +128 -63
  47. data/lib/cocoapods/installer/xcode.rb +3 -0
  48. data/lib/cocoapods/installer/xcode/multi_pods_project_generator.rb +72 -0
  49. data/lib/cocoapods/installer/xcode/pods_project_generator.rb +102 -218
  50. data/lib/cocoapods/installer/xcode/pods_project_generator/aggregate_target_dependency_installer.rb +75 -0
  51. data/lib/cocoapods/installer/xcode/pods_project_generator/aggregate_target_installer.rb +1 -1
  52. data/lib/cocoapods/installer/xcode/pods_project_generator/app_host_installer.rb +29 -17
  53. data/lib/cocoapods/installer/xcode/pods_project_generator/file_references_installer.rb +31 -65
  54. data/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_dependency_installer.rb +155 -0
  55. data/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_installer.rb +265 -110
  56. data/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_integrator.rb +70 -43
  57. data/lib/cocoapods/installer/xcode/pods_project_generator/pods_project_writer.rb +75 -0
  58. data/lib/cocoapods/installer/xcode/pods_project_generator/project_generator.rb +119 -0
  59. data/lib/cocoapods/installer/xcode/pods_project_generator/target_installation_result.rb +44 -7
  60. data/lib/cocoapods/installer/xcode/pods_project_generator/target_installer.rb +5 -7
  61. data/lib/cocoapods/installer/xcode/pods_project_generator/target_installer_helper.rb +32 -0
  62. data/lib/cocoapods/installer/xcode/pods_project_generator_result.rb +35 -0
  63. data/lib/cocoapods/installer/xcode/single_pods_project_generator.rb +38 -0
  64. data/lib/cocoapods/installer/xcode/target_validator.rb +32 -25
  65. data/lib/cocoapods/native_target_extension.rb +54 -0
  66. data/lib/cocoapods/open-uri.rb +1 -1
  67. data/lib/cocoapods/podfile.rb +13 -0
  68. data/lib/cocoapods/project.rb +88 -10
  69. data/lib/cocoapods/resolver.rb +11 -8
  70. data/lib/cocoapods/resolver/resolver_specification.rb +7 -7
  71. data/lib/cocoapods/sandbox.rb +38 -9
  72. data/lib/cocoapods/sandbox/file_accessor.rb +21 -0
  73. data/lib/cocoapods/sandbox/headers_store.rb +18 -3
  74. data/lib/cocoapods/sandbox/pod_dir_cleaner.rb +1 -14
  75. data/lib/cocoapods/sources_manager.rb +11 -3
  76. data/lib/cocoapods/target.rb +67 -7
  77. data/lib/cocoapods/target/aggregate_target.rb +70 -8
  78. data/lib/cocoapods/target/build_settings.rb +124 -65
  79. data/lib/cocoapods/target/build_type.rb +139 -0
  80. data/lib/cocoapods/target/framework_paths.rb +12 -7
  81. data/lib/cocoapods/target/pod_target.rb +322 -65
  82. data/lib/cocoapods/user_interface.rb +2 -2
  83. data/lib/cocoapods/user_interface/error_report.rb +3 -0
  84. data/lib/cocoapods/user_interface/inspector_reporter.rb +1 -1
  85. data/lib/cocoapods/validator.rb +74 -39
  86. data/lib/cocoapods/version_metadata.rb +7 -0
  87. metadata +30 -6
@@ -17,7 +17,7 @@ module Pod
17
17
  attr_reader :sandbox
18
18
 
19
19
  # @return [Pod::Project]
20
- # The `Pods/Pods.xcodeproj` to install the target into.
20
+ # The project to install the target into.
21
21
  #
22
22
  attr_reader :project
23
23
 
@@ -91,11 +91,9 @@ module Pod
91
91
  settings['ARCHS'] = target.archs
92
92
  end
93
93
 
94
- if target.requires_frameworks?
95
- if target.static_framework?
96
- settings['MACH_O_TYPE'] = 'staticlib'
97
- end
98
- else
94
+ if target.build_as_static_framework?
95
+ settings['MACH_O_TYPE'] = 'staticlib'
96
+ elsif target.build_as_static_library?
99
97
  settings.merge!('OTHER_LDFLAGS' => '', 'OTHER_LIBTOOLFLAGS' => '')
100
98
  end
101
99
 
@@ -204,7 +202,7 @@ module Pod
204
202
  FileUtils.ln_sf(source, linked_path)
205
203
  end
206
204
 
207
- acl = target.requires_frameworks? ? 'Public' : 'Project'
205
+ acl = target.build_as_framework? ? 'Public' : 'Project'
208
206
  build_file.settings ||= {}
209
207
  build_file.settings['ATTRIBUTES'] = [acl]
210
208
  end
@@ -63,8 +63,40 @@ module Pod
63
63
  end
64
64
  end
65
65
 
66
+ # Creates a prefix header file which imports `UIKit` or `Cocoa` according
67
+ # to the platform of the target. This file also include any prefix header
68
+ # content reported by the specification of the pods.
69
+ #
70
+ # @param [Pathname] path
71
+ # the path to generate the prefix header for.
72
+ #
73
+ # @param [Array<Sandbox::FileAccessor>] file_accessors
74
+ # the file accessors to use for this prefix header that point to a path of a prefix header.
75
+ #
76
+ # @param [Platform] platform
77
+ # the platform to use for this prefix header.
78
+ #
79
+ # @param [PBXNativeTarget] native_target
80
+ # the native target on which the prefix header should be configured for.
81
+ #
82
+ # @param [Pathname] project_directory
83
+ # the directory containing the project of the target
84
+ #
85
+ # @return [void]
86
+ #
87
+ def create_prefix_header(path, file_accessors, platform, native_target, project_directory)
88
+ generator = Generator::PrefixHeader.new(file_accessors, platform)
89
+ update_changed_file(generator, path)
90
+
91
+ relative_path = path.relative_path_from(project_directory).to_s
92
+ native_target.build_configurations.each do |c|
93
+ c.build_settings['GCC_PREFIX_HEADER'] = relative_path
94
+ end
95
+ end
96
+
66
97
  module_function :update_changed_file
67
98
  module_function :create_info_plist_file_with_sandbox
99
+ module_function :create_prefix_header
68
100
  end
69
101
  end
70
102
  end
@@ -0,0 +1,35 @@
1
+ module Pod
2
+ class Installer
3
+ class Xcode
4
+ class PodsProjectGenerator
5
+ # A simple container produced after a pod project generation is completed.
6
+ #
7
+ class PodsProjectGeneratorResult
8
+ # @return [Project] project
9
+ #
10
+ attr_reader :project
11
+
12
+ # @return [Hash{Project => Array<PodTargets>}] Project by pod targets map
13
+ #
14
+ attr_reader :projects_by_pod_targets
15
+
16
+ # @return [InstallationResults] target installation results
17
+ #
18
+ attr_reader :target_installation_results
19
+
20
+ # Initialize a new instance
21
+ #
22
+ # @param [Project] project @see #project
23
+ # @param [Hash{Project => Array<PodTargets>}] projects_by_pod_targets @see #projects_by_pod_targets
24
+ # @param [InstallationResults] target_installation_results @see #target_installation_results
25
+ #
26
+ def initialize(project, projects_by_pod_targets, target_installation_results)
27
+ @project = project
28
+ @projects_by_pod_targets = projects_by_pod_targets
29
+ @target_installation_results = target_installation_results
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,38 @@
1
+ module Pod
2
+ class Installer
3
+ class Xcode
4
+ # The {SinglePodsProjectGenerator} handles generation of the 'Pods/Pods.xcodeproj'
5
+ #
6
+ class SinglePodsProjectGenerator < PodsProjectGenerator
7
+ # Generates single `Pods/Pods.xcodeproj`.
8
+ #
9
+ # @return [PodsProjectGeneratorResult]
10
+ #
11
+ def generate!
12
+ project_path = sandbox.project_path
13
+ platforms = aggregate_targets.map(&:platform)
14
+ project_generator = ProjectGenerator.new(sandbox, project_path, pod_targets, build_configurations,
15
+ platforms, project_object_version, config.podfile_path)
16
+ project = project_generator.generate!
17
+ install_file_references(project, pod_targets)
18
+
19
+ pod_target_installation_results = install_all_pod_targets(project, pod_targets)
20
+ aggregate_target_installation_results = install_aggregate_targets(project, aggregate_targets)
21
+ target_installation_results = InstallationResults.new(pod_target_installation_results, aggregate_target_installation_results)
22
+
23
+ integrate_targets(target_installation_results.pod_target_installation_results)
24
+ wire_target_dependencies(target_installation_results)
25
+ PodsProjectGeneratorResult.new(project, {}, target_installation_results)
26
+ end
27
+
28
+ private
29
+
30
+ def install_all_pod_targets(project, pod_targets)
31
+ UI.message '- Installing Pod Targets' do
32
+ install_pod_targets(project, pod_targets)
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -47,11 +47,11 @@ module Pod
47
47
  file_accessors = pod_targets.flat_map(&:file_accessors)
48
48
 
49
49
  frameworks = file_accessors.flat_map(&:vendored_frameworks).uniq.map(&:basename)
50
- frameworks += pod_targets.select { |pt| pt.should_build? && pt.requires_frameworks? }.map(&:product_module_name).uniq
50
+ frameworks += pod_targets.select { |pt| pt.should_build? && pt.build_as_framework? }.map(&:product_module_name).uniq
51
51
  verify_no_duplicate_names(frameworks, aggregate_target.label, 'frameworks')
52
52
 
53
53
  libraries = file_accessors.flat_map(&:vendored_libraries).uniq.map(&:basename)
54
- libraries += pod_targets.select { |pt| pt.should_build? && !pt.requires_frameworks? }.map(&:product_name)
54
+ libraries += pod_targets.select { |pt| pt.should_build? && pt.build_as_library? }.map(&:product_name)
55
55
  verify_no_duplicate_names(libraries, aggregate_target.label, 'libraries')
56
56
  end
57
57
  end
@@ -68,24 +68,24 @@ module Pod
68
68
 
69
69
  def verify_no_static_framework_transitive_dependencies
70
70
  aggregate_targets.each do |aggregate_target|
71
- next unless aggregate_target.requires_frameworks?
72
-
73
- aggregate_target.user_build_configurations.keys.each do |config|
74
- dynamic_pod_targets = aggregate_target.pod_targets_for_build_configuration(config).reject(&:static_framework?)
71
+ aggregate_target.user_build_configurations.each_key do |config|
72
+ pod_targets = aggregate_target.pod_targets_for_build_configuration(config)
73
+ built_targets, unbuilt_targets = pod_targets.partition(&:should_build?)
74
+ dynamic_pod_targets = built_targets.select(&:build_as_dynamic?)
75
75
 
76
- dependencies = dynamic_pod_targets.select(&:should_build?).flat_map(&:dependencies)
77
- depended_upon_targets = dynamic_pod_targets.select { |t| dependencies.include?(t.pod_name) && !t.should_build? }
76
+ dependencies = dynamic_pod_targets.flat_map(&:dependencies)
77
+ depended_upon_targets = unbuilt_targets.select { |t| dependencies.include?(t.pod_name) }
78
78
 
79
79
  static_libs = depended_upon_targets.flat_map(&:file_accessors).flat_map(&:vendored_static_artifacts)
80
80
  unless static_libs.empty?
81
81
  raise Informative, "The '#{aggregate_target.label}' target has " \
82
- "transitive dependencies that include static binaries: (#{static_libs.to_sentence})"
82
+ "transitive dependencies that include statically linked binaries: (#{static_libs.to_sentence})"
83
83
  end
84
84
 
85
- static_framework_deps = dynamic_pod_targets.select(&:should_build?).flat_map(&:recursive_dependent_targets).select(&:static_framework?)
86
- unless static_framework_deps.empty?
85
+ static_deps = dynamic_pod_targets.flat_map(&:recursive_dependent_targets).select(&:build_as_static?).uniq
86
+ unless static_deps.empty?
87
87
  raise Informative, "The '#{aggregate_target.label}' target has " \
88
- "transitive dependencies that include static frameworks: (#{static_framework_deps.flat_map(&:name).to_sentence})"
88
+ "transitive dependencies that include statically linked binaries: (#{static_deps.flat_map(&:name).to_sentence})"
89
89
  end
90
90
  end
91
91
  end
@@ -96,18 +96,25 @@ module Pod
96
96
  "`#{target_definition.name}` (Swift #{target_definition.swift_version})"
97
97
  end
98
98
  swift_pod_targets = pod_targets.select(&:uses_swift?)
99
- error_messages = swift_pod_targets.map do |pod_target|
100
- next unless pod_target.spec_swift_version.nil?
101
- swift_target_definitions = pod_target.target_definitions.reject { |target| target.swift_version.blank? }
102
- next if swift_target_definitions.uniq(&:swift_version).count == 1
103
- if swift_target_definitions.empty?
104
- "- `#{pod_target.name}` does not specify a Swift version and none of the targets " \
105
- "(#{pod_target.target_definitions.map { |td| "`#{td.name}`" }.to_sentence}) integrating it have the " \
106
- '`SWIFT_VERSION` attribute set. Please contact the author or set the `SWIFT_VERSION` attribute in at ' \
107
- 'least one of the targets that integrate this pod.'
108
- else
109
- target_errors = swift_target_definitions.map(&error_message_for_target_definition).to_sentence
110
- "- `#{pod_target.name}` is integrated by multiple targets that use a different Swift version: #{target_errors}."
99
+ error_messages = swift_pod_targets.map do |swift_pod_target|
100
+ # Legacy targets that do not specify Swift versions derive their Swift version from the target definitions
101
+ # they are integrated with. An error is displayed if the target definition Swift versions collide or none
102
+ # of target definitions specify the `SWIFT_VERSION` attribute.
103
+ if swift_pod_target.spec_swift_versions.empty?
104
+ swift_target_definitions = swift_pod_target.target_definitions.reject { |target| target.swift_version.blank? }
105
+ next if swift_target_definitions.uniq(&:swift_version).count == 1
106
+ if swift_target_definitions.empty?
107
+ "- `#{swift_pod_target.name}` does not specify a Swift version and none of the targets " \
108
+ "(#{swift_pod_target.target_definitions.map { |td| "`#{td.name}`" }.to_sentence}) integrating it have the " \
109
+ '`SWIFT_VERSION` attribute set. Please contact the author or set the `SWIFT_VERSION` attribute in at ' \
110
+ 'least one of the targets that integrate this pod.'
111
+ else
112
+ target_errors = swift_target_definitions.map(&error_message_for_target_definition).to_sentence
113
+ "- `#{swift_pod_target.name}` is integrated by multiple targets that use a different Swift version: #{target_errors}."
114
+ end
115
+ elsif swift_pod_target.swift_version.empty?
116
+ "- `#{swift_pod_target.name}` does not specify a Swift version (#{swift_pod_target.spec_swift_versions.map { |v| "`#{v}`" }.to_sentence}) " \
117
+ "that is satisfied by any of targets (#{swift_pod_target.target_definitions.map { |td| "`#{td.name}`" }.to_sentence}) integrating it."
111
118
  end
112
119
  end.compact
113
120
 
@@ -130,7 +137,7 @@ module Pod
130
137
  next if non_module_dependencies.empty?
131
138
 
132
139
  error_messages << "The Swift pod `#{pod_target.name}` depends upon #{non_module_dependencies.map { |d| "`#{d}`" }.to_sentence}, " \
133
- 'which do not define modules. ' \
140
+ "which #{non_module_dependencies.count == 1 ? 'does' : 'do'} not define modules. " \
134
141
  'To opt into those targets generating module maps '\
135
142
  '(which is necessary to import them from Swift when building as static libraries), ' \
136
143
  'you may set `use_modular_headers!` globally in your Podfile, '\
@@ -0,0 +1,54 @@
1
+ module Pod
2
+ class Project
3
+ # Adds a dependency on the given metadata cache.
4
+ #
5
+ # @param [AbstractTarget] target
6
+ # The parent target used to add a cached dependency.
7
+ #
8
+ # @param [MetadataCache] metadata
9
+ # The metadata holding all the required metadata to construct a target as a dependency.
10
+ #
11
+ # @return [void]
12
+ #
13
+ def self.add_cached_dependency(target, metadata)
14
+ return if dependency_for_cached_target?(target, metadata)
15
+ container_proxy = target.project.new(Xcodeproj::Project::PBXContainerItemProxy)
16
+
17
+ subproject_reference = target.project.reference_for_path(metadata.container_project_path)
18
+ raise ArgumentError, "add_dependency received target (#{target}) that belongs to a project that is not this project (#{self}) and is not a subproject of this project" unless subproject_reference
19
+ container_proxy.container_portal = subproject_reference.uuid
20
+
21
+ container_proxy.proxy_type = Xcodeproj::Constants::PROXY_TYPES[:native_target]
22
+ container_proxy.remote_global_id_string = metadata.native_target_uuid
23
+ container_proxy.remote_info = metadata.target_label
24
+
25
+ dependency = target.project.new(Xcodeproj::Project::PBXTargetDependency)
26
+ dependency.name = metadata.target_label
27
+ dependency.target_proxy = container_proxy
28
+
29
+ target.dependencies << dependency
30
+ end
31
+
32
+ # Checks whether this target has a dependency on the given target.
33
+ #
34
+ # @param [AbstractTarget] target
35
+ # The parent target used to add a cached dependency.
36
+ #
37
+ # @param [TargetMetadata] cached_target
38
+ # the target to search for.
39
+ #
40
+ # @return [Bool]
41
+ #
42
+ def self.dependency_for_cached_target?(target, cached_target)
43
+ target.dependencies.find do |dep|
44
+ if dep.target_proxy.remote?
45
+ subproject_reference = target.project.reference_for_path(cached_target.container_project_path)
46
+ uuid = subproject_reference.uuid if subproject_reference
47
+ dep.target_proxy.remote_global_id_string == cached_target.native_target_uuid && dep.target_proxy.container_portal == uuid
48
+ else
49
+ dep.target.uuid == cached_target.native_target_uuid
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -8,7 +8,7 @@ module OpenURI
8
8
  # Whether {#open} should follow a redirect.
9
9
  #
10
10
  # Inspiration from: https://gist.github.com/1271420
11
- # Relevant issue: http://redmine.ruby-lang.org/issues/3719
11
+ # Relevant issue: https://bugs.ruby-lang.org/issues/3719
12
12
  # Source here: https://github.com/ruby/ruby/blob/trunk/lib/open-uri.rb
13
13
  #
14
14
  # This test is intended to forbid a redirection from http://... to
@@ -0,0 +1,13 @@
1
+ require 'cocoapods-core/podfile'
2
+
3
+ module Pod
4
+ class Podfile
5
+ autoload :InstallationOptions, 'cocoapods/installer/installation_options'
6
+
7
+ # @return [Pod::Installer::InstallationOptions] the installation options specified in the Podfile
8
+ #
9
+ def installation_options
10
+ @installation_options ||= Pod::Installer::InstallationOptions.from_podfile(self)
11
+ end
12
+ end
13
+ end
@@ -21,22 +21,39 @@ module Pod
21
21
  #
22
22
  attr_reader :development_pods
23
23
 
24
+ # @return [PBXGroup] The group for dependencies.
25
+ # Used by #generate_multiple_pod_projects installation option.
26
+ #
27
+ attr_reader :dependencies_group
28
+
29
+ # @return [Bool] Bool indicating if this project is a pod target subproject.
30
+ # Used by `generate_multiple_pod_projects` installation option.
31
+ #
32
+ attr_reader :pod_target_subproject
33
+ alias pod_target_subproject? pod_target_subproject
34
+
35
+ # @return [String] The basename of the project path without .xcodeproj extension.
36
+ #
37
+ attr_reader :project_name
38
+
24
39
  # Initialize a new instance
25
40
  #
26
- # @param [Pathname, String] path @see #path
27
- # @param [Bool] skip_initialization
28
- # Whether the project should be initialized from scratch.
29
- # @param [Int] object_version
30
- # Object version to use for serialization, defaults to Xcode 3.2 compatible.
41
+ # @param [Pathname, String] path @see Xcodeproj::Project#path
42
+ # @param [Bool] skip_initialization Whether the project should be initialized from scratch.
43
+ # @param [Int] object_version Object version to use for serialization, defaults to Xcode 3.2 compatible.
31
44
  #
32
45
  def initialize(path, skip_initialization = false,
33
- object_version = Xcodeproj::Constants::DEFAULT_OBJECT_VERSION)
46
+ object_version = Xcodeproj::Constants::DEFAULT_OBJECT_VERSION, pod_target_subproject: false)
47
+ @uuid_prefix = Digest('SHA256').hexdigest(File.basename(path)).upcase
34
48
  super(path, skip_initialization, object_version)
35
49
  @support_files_group = new_group('Targets Support Files')
36
50
  @refs_by_absolute_path = {}
37
51
  @variant_groups_by_path_and_name = {}
38
52
  @pods = new_group('Pods')
39
53
  @development_pods = new_group('Development Pods')
54
+ @dependencies_group = new_group('Dependencies')
55
+ @pod_target_subproject = pod_target_subproject
56
+ @project_name = Pathname(path).basename('.*')
40
57
  self.symroot = LEGACY_BUILD_ROOT
41
58
  end
42
59
 
@@ -52,7 +69,7 @@ module Pod
52
69
  #
53
70
  def generate_available_uuid_list(count = 100)
54
71
  start = @generated_uuids.size
55
- uniques = Array.new(count) { |i| format('%011X0', start + i) }
72
+ uniques = Array.new(count) { |i| format('%.4s%07X0', @uuid_prefix, start + i) }
56
73
  @generated_uuids += uniques
57
74
  @available_uuids += uniques
58
75
  end
@@ -101,7 +118,12 @@ module Pod
101
118
  def add_pod_group(pod_name, path, development = false, absolute = false)
102
119
  raise '[BUG]' if pod_group(pod_name)
103
120
 
104
- parent_group = development ? development_pods : pods
121
+ parent_group =
122
+ if pod_target_subproject
123
+ main_group
124
+ else
125
+ development ? development_pods : pods
126
+ end
105
127
  source_tree = absolute ? :absolute : :group
106
128
 
107
129
  group = parent_group.new_group(pod_name, path, source_tree)
@@ -111,7 +133,11 @@ module Pod
111
133
  # @return [Array<PBXGroup>] Returns all the group of the Pods.
112
134
  #
113
135
  def pod_groups
114
- pods.children.objects + development_pods.children.objects
136
+ if pod_target_subproject
137
+ main_group.children.objects
138
+ else
139
+ pods.children.objects + development_pods.children.objects
140
+ end
115
141
  end
116
142
 
117
143
  # Returns the group for the Pod with the given name.
@@ -212,6 +238,37 @@ module Pod
212
238
  @refs_by_absolute_path[file_path_name.to_s] = ref
213
239
  end
214
240
 
241
+ # @!group File references
242
+ #-------------------------------------------------------------------------#
243
+
244
+ # Adds a file reference for a project as a child of the given group.
245
+ #
246
+ # @param [Project] project
247
+ # The project to add as a subproject reference.
248
+ #
249
+ # @param [PBXGroup] group
250
+ # The group for the new subproject reference.
251
+ #
252
+ # @return [PBXFileReference] The new file reference.
253
+ #
254
+ def add_subproject_reference(project, group)
255
+ new_subproject_file_reference(project.path, group)
256
+ end
257
+
258
+ # Adds a file reference for a cached project as a child of the given group.
259
+ #
260
+ # @param [MetadataCache] metadata
261
+ # The metadata holding the required properties to create a subproject reference.
262
+ #
263
+ # @param [PBXGroup] group
264
+ # The group for the new subproject reference.
265
+ #
266
+ # @return [PBXFileReference] The new file reference.
267
+ #
268
+ def add_cached_subproject_reference(metadata, group)
269
+ new_subproject_file_reference(metadata.container_project_path, group)
270
+ end
271
+
215
272
  # Returns the file reference for the given absolute path.
216
273
  #
217
274
  # @param [#to_s] absolute_path
@@ -383,7 +440,7 @@ module Pod
383
440
  # Returns the name to be used for a the variant group for a file at a given path.
384
441
  # The path must be localized (within an *.lproj directory).
385
442
  #
386
- # @param [Pathname] The localized path to get a variant group name for.
443
+ # @param [Pathname] path The localized path to get a variant group name for.
387
444
  #
388
445
  # @return [String] The variant group name.
389
446
  #
@@ -411,6 +468,27 @@ module Pod
411
468
  path.basename.to_s
412
469
  end
413
470
 
471
+ def new_subproject_file_reference(project_path, group)
472
+ if ref = reference_for_path(project_path)
473
+ return ref
474
+ end
475
+
476
+ # We call into the private function `FileReferencesFactory.new_file_reference` instead of `FileReferencesFactory.new_reference`
477
+ # because it delegates into `FileReferencesFactory.new_subproject` which has the extra behavior of opening the Project which
478
+ # is an expensive operation for large projects.
479
+ #
480
+ ref = Xcodeproj::Project::FileReferencesFactory.send(:new_file_reference, group, project_path, :group)
481
+ ref.name = Pathname(project_path).basename('.*').to_s
482
+ ref.include_in_index = nil
483
+
484
+ attribute = PBXProject.references_by_keys_attributes.find { |attrb| attrb.name == :project_references }
485
+ project_reference = ObjectDictionary.new(attribute, group.project.root_object)
486
+ project_reference[:project_ref] = ref
487
+ root_object.project_references << project_reference
488
+ refs_by_absolute_path[project_path.to_s] = ref
489
+ ref
490
+ end
491
+
414
492
  #-------------------------------------------------------------------------#
415
493
  end
416
494
  end