cocoapods 1.5.3 → 1.6.0.beta.1

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.
Files changed (75) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +200 -0
  3. data/lib/cocoapods.rb +0 -1
  4. data/lib/cocoapods/command/init.rb +1 -1
  5. data/lib/cocoapods/command/install.rb +7 -0
  6. data/lib/cocoapods/command/lib/lint.rb +8 -1
  7. data/lib/cocoapods/command/outdated.rb +2 -7
  8. data/lib/cocoapods/command/repo/add.rb +1 -1
  9. data/lib/cocoapods/command/repo/list.rb +1 -1
  10. data/lib/cocoapods/command/repo/push.rb +17 -12
  11. data/lib/cocoapods/command/repo/remove.rb +1 -1
  12. data/lib/cocoapods/command/repo/update.rb +1 -1
  13. data/lib/cocoapods/command/setup.rb +1 -1
  14. data/lib/cocoapods/command/spec/create.rb +39 -39
  15. data/lib/cocoapods/command/spec/lint.rb +8 -1
  16. data/lib/cocoapods/config.rb +13 -2
  17. data/lib/cocoapods/downloader/cache.rb +1 -1
  18. data/lib/cocoapods/executable.rb +2 -2
  19. data/lib/cocoapods/external_sources.rb +7 -4
  20. data/lib/cocoapods/external_sources/abstract_external_source.rb +23 -13
  21. data/lib/cocoapods/gem_version.rb +1 -1
  22. data/lib/cocoapods/generator/acknowledgements/markdown.rb +6 -0
  23. data/lib/cocoapods/generator/acknowledgements/plist.rb +11 -0
  24. data/lib/cocoapods/generator/app_target_helper.rb +102 -16
  25. data/lib/cocoapods/generator/copy_resources_script.rb +6 -0
  26. data/lib/cocoapods/generator/dummy_source.rb +14 -5
  27. data/lib/cocoapods/generator/embed_frameworks_script.rb +13 -2
  28. data/lib/cocoapods/generator/header.rb +1 -1
  29. data/lib/cocoapods/generator/info_plist_file.rb +12 -4
  30. data/lib/cocoapods/generator/prefix_header.rb +2 -2
  31. data/lib/cocoapods/hooks_manager.rb +28 -17
  32. data/lib/cocoapods/installer.rb +103 -42
  33. data/lib/cocoapods/installer/analyzer.rb +362 -277
  34. data/lib/cocoapods/installer/analyzer/analysis_result.rb +52 -22
  35. data/lib/cocoapods/installer/analyzer/locking_dependency_analyzer.rb +9 -6
  36. data/lib/cocoapods/installer/analyzer/pod_variant.rb +4 -5
  37. data/lib/cocoapods/installer/analyzer/sandbox_analyzer.rb +3 -14
  38. data/lib/cocoapods/installer/analyzer/specs_state.rb +28 -4
  39. data/lib/cocoapods/installer/analyzer/target_inspection_result.rb +24 -16
  40. data/lib/cocoapods/installer/analyzer/target_inspector.rb +17 -11
  41. data/lib/cocoapods/installer/pod_source_installer.rb +31 -43
  42. data/lib/cocoapods/installer/post_install_hooks_context.rb +71 -46
  43. data/lib/cocoapods/installer/pre_install_hooks_context.rb +22 -13
  44. data/lib/cocoapods/installer/source_provider_hooks_context.rb +3 -1
  45. data/lib/cocoapods/installer/user_project_integrator.rb +0 -2
  46. data/lib/cocoapods/installer/user_project_integrator/target_integrator.rb +38 -28
  47. data/lib/cocoapods/installer/user_project_integrator/target_integrator/xcconfig_integrator.rb +44 -11
  48. data/lib/cocoapods/installer/xcode/pods_project_generator.rb +129 -119
  49. data/lib/cocoapods/installer/xcode/pods_project_generator/aggregate_target_installer.rb +25 -16
  50. data/lib/cocoapods/installer/xcode/pods_project_generator/app_host_installer.rb +95 -0
  51. data/lib/cocoapods/installer/xcode/pods_project_generator/file_references_installer.rb +12 -45
  52. data/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_installer.rb +277 -169
  53. data/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_integrator.rb +31 -24
  54. data/lib/cocoapods/installer/xcode/pods_project_generator/target_installation_result.rb +93 -0
  55. data/lib/cocoapods/installer/xcode/pods_project_generator/target_installer.rb +60 -69
  56. data/lib/cocoapods/installer/xcode/pods_project_generator/target_installer_helper.rb +72 -0
  57. data/lib/cocoapods/installer/xcode/target_validator.rb +15 -9
  58. data/lib/cocoapods/project.rb +14 -14
  59. data/lib/cocoapods/resolver.rb +38 -50
  60. data/lib/cocoapods/sandbox.rb +22 -38
  61. data/lib/cocoapods/sandbox/file_accessor.rb +11 -6
  62. data/lib/cocoapods/sandbox/headers_store.rb +9 -8
  63. data/lib/cocoapods/sandbox/path_list.rb +5 -8
  64. data/lib/cocoapods/sources_manager.rb +1 -1
  65. data/lib/cocoapods/target.rb +92 -37
  66. data/lib/cocoapods/target/aggregate_target.rb +140 -84
  67. data/lib/cocoapods/target/build_settings.rb +1076 -0
  68. data/lib/cocoapods/target/pod_target.rb +198 -294
  69. data/lib/cocoapods/user_interface.rb +5 -0
  70. data/lib/cocoapods/validator.rb +133 -41
  71. metadata +18 -18
  72. data/lib/cocoapods/generator/xcconfig.rb +0 -13
  73. data/lib/cocoapods/generator/xcconfig/aggregate_xcconfig.rb +0 -260
  74. data/lib/cocoapods/generator/xcconfig/pod_xcconfig.rb +0 -87
  75. data/lib/cocoapods/generator/xcconfig/xcconfig_helper.rb +0 -558
@@ -4,22 +4,36 @@ module Pod
4
4
  # the context of the installer.
5
5
  #
6
6
  class PostInstallHooksContext
7
- # @return [String] The path to the sandbox root (`Pods` directory).
7
+ # @return [Sandbox] The Sandbox for the project.
8
8
  #
9
- attr_accessor :sandbox_root
9
+ attr_reader :sandbox
10
10
 
11
- # @return [Project] The Pods Xcode project.
11
+ # @return [String] The path to the sandbox root (`Pods` directory).
12
12
  #
13
- attr_accessor :pods_project
13
+ attr_reader :sandbox_root
14
14
 
15
- # @return [Sandbox] The Sandbox for the project.
15
+ # @return [Xcodeproj::Project] The Pods Xcode project.
16
16
  #
17
- attr_accessor :sandbox
17
+ attr_reader :pods_project
18
18
 
19
19
  # @return [Array<UmbrellaTargetDescription>] The list of
20
20
  # the CocoaPods umbrella targets generated by the installer.
21
21
  #
22
- attr_accessor :umbrella_targets
22
+ attr_reader :umbrella_targets
23
+
24
+ # Initialize a new instance
25
+ #
26
+ # @param [Sandbox] sandbox see #sandbox
27
+ # @param [String] sandbox_root see #sandbox_root
28
+ # @param [Xcodeproj::Project] pods_project see #pods_project
29
+ # @param [Array<UmbrellaTargetDescription>] umbrella_targets see #umbrella_targets
30
+ #
31
+ def initialize(sandbox, sandbox_root, pods_project, umbrella_targets)
32
+ @sandbox = sandbox
33
+ @sandbox_root = sandbox_root
34
+ @pods_project = pods_project
35
+ @umbrella_targets = umbrella_targets
36
+ end
23
37
 
24
38
  # @return [PostInstallHooksContext] Convenience class generator method
25
39
  #
@@ -34,24 +48,17 @@ module Pod
34
48
  # static context.
35
49
  #
36
50
  def self.generate(sandbox, aggregate_targets)
37
- umbrella_targets_descriptions = []
38
- aggregate_targets.each do |umbrella|
39
- desc = UmbrellaTargetDescription.new
40
- desc.user_project = umbrella.user_project
41
- desc.user_targets = umbrella.user_targets
42
- desc.specs = umbrella.specs
43
- desc.platform_name = umbrella.platform.name
44
- desc.platform_deployment_target = umbrella.platform.deployment_target.to_s
45
- desc.cocoapods_target_label = umbrella.label
46
- umbrella_targets_descriptions << desc
51
+ umbrella_targets_descriptions = aggregate_targets.map do |umbrella|
52
+ user_project = umbrella.user_project
53
+ user_targets = umbrella.user_targets
54
+ specs = umbrella.specs
55
+ platform_name = umbrella.platform.name
56
+ platform_deployment_target = umbrella.platform.deployment_target.to_s
57
+ cocoapods_target_label = umbrella.label
58
+ UmbrellaTargetDescription.new(user_project, user_targets, specs, platform_name, platform_deployment_target, cocoapods_target_label)
47
59
  end
48
60
 
49
- result = new
50
- result.sandbox_root = sandbox.root.to_s
51
- result.pods_project = sandbox.project
52
- result.sandbox = sandbox
53
- result.umbrella_targets = umbrella_targets_descriptions
54
- result
61
+ new(sandbox, sandbox.root.to_s, sandbox.project, umbrella_targets_descriptions)
55
62
  end
56
63
 
57
64
  # Pure data class which describes and umbrella target.
@@ -60,7 +67,47 @@ module Pod
60
67
  # @return [Xcodeproj::Project] The user project into which this target
61
68
  # is integrated.
62
69
  #
63
- attr_accessor :user_project
70
+ attr_reader :user_project
71
+
72
+ # @return [Array<PBXNativeTarget>]
73
+ # The list of user targets integrated by this umbrella target.
74
+ #
75
+ attr_reader :user_targets
76
+
77
+ # @return [Array<Specification>] The list of the
78
+ # specifications of the target.
79
+ #
80
+ attr_reader :specs
81
+
82
+ # @return [Symbol] The platform (either `:ios`, `:watchos`, `:tvos`, or `:osx`).
83
+ #
84
+ attr_reader :platform_name
85
+
86
+ # @return [String] The deployment target.
87
+ #
88
+ attr_reader :platform_deployment_target
89
+
90
+ # @return [String] The label for the target.
91
+ #
92
+ attr_reader :cocoapods_target_label
93
+
94
+ # Initialize a new instance
95
+ #
96
+ # @param [Xcodeproj::Project] user_project see #user_project
97
+ # @param [Array<PBXNativeTarget>] user_targets see #user_targets
98
+ # @param [Array<Specification>] specs see #specs
99
+ # @param [Symbol] platform_name see #platform_name
100
+ # @param [String] platform_deployment_target see #platform_deployment_target
101
+ # @param [String] cocoapods_target_label see #cocoapods_target_label
102
+ #
103
+ def initialize(user_project, user_targets, specs, platform_name, platform_deployment_target, cocoapods_target_label)
104
+ @user_project = user_project
105
+ @user_targets = user_targets
106
+ @specs = specs
107
+ @platform_name = platform_name
108
+ @platform_deployment_target = platform_deployment_target
109
+ @cocoapods_target_label = cocoapods_target_label
110
+ end
64
111
 
65
112
  # @return [String] The path of the user project
66
113
  # integrated by this target.
@@ -69,11 +116,6 @@ module Pod
69
116
  user_project.path if user_project
70
117
  end
71
118
 
72
- # @return [Array<PBXNativeTarget>]
73
- # The list of user targets integrated by this umbrella target.
74
- #
75
- attr_accessor :user_targets
76
-
77
119
  # @return [Array<String>] The list of the UUIDs of the
78
120
  # user targets integrated by this umbrella
79
121
  # target. They can be used to find the
@@ -84,23 +126,6 @@ module Pod
84
126
  def user_target_uuids
85
127
  user_targets.map(&:uuid)
86
128
  end
87
-
88
- # @return [Array<Specification>] The list of the
89
- # specifications of the target.
90
- #
91
- attr_accessor :specs
92
-
93
- # @return [Symbol] The platform (either `:ios`, `:watchos`, `:tvos`, or `:osx`).
94
- #
95
- attr_accessor :platform_name
96
-
97
- # @return [String] The deployment target.
98
- #
99
- attr_accessor :platform_deployment_target
100
-
101
- # @return [String] The label for the target.
102
- #
103
- attr_accessor :cocoapods_target_label
104
129
  end
105
130
  end
106
131
  end
@@ -4,21 +4,35 @@ module Pod
4
4
  # the context of the installer before analysis has been completed.
5
5
  #
6
6
  class PreInstallHooksContext
7
- # @return [String] The path to the sandbox root (`Pods` directory).
8
- #
9
- attr_accessor :sandbox_root
10
-
11
7
  # @return [Podfile] The Podfile for the project.
12
8
  #
13
- attr_accessor :podfile
9
+ attr_reader :podfile
14
10
 
15
11
  # @return [Sandbox] The Sandbox for the project.
16
12
  #
17
- attr_accessor :sandbox
13
+ attr_reader :sandbox
14
+
15
+ # @return [String] The path to the sandbox root (`Pods` directory).
16
+ #
17
+ attr_reader :sandbox_root
18
18
 
19
19
  # @return [Lockfile] The Lockfile for the project.
20
20
  #
21
- attr_accessor :lockfile
21
+ attr_reader :lockfile
22
+
23
+ # Initialize a new instance
24
+ #
25
+ # @param [Sandbox] sandbox see #sandbox
26
+ # @param [String] sandbox_root see #sandbox_root
27
+ # @param [Podfile] podfile see #podfile
28
+ # @param [Lockfile] lockfile see #lockfile
29
+ #
30
+ def initialize(podfile, sandbox, sandbox_root, lockfile)
31
+ @podfile = podfile
32
+ @sandbox = sandbox
33
+ @sandbox_root = sandbox_root
34
+ @lockfile = lockfile
35
+ end
22
36
 
23
37
  # @param [Sandbox] sandbox see {#sandbox}
24
38
  #
@@ -30,12 +44,7 @@ module Pod
30
44
  # static context.
31
45
  #
32
46
  def self.generate(sandbox, podfile, lockfile)
33
- result = new
34
- result.podfile = podfile
35
- result.sandbox = sandbox
36
- result.sandbox_root = sandbox.root.to_s
37
- result.lockfile = lockfile
38
- result
47
+ new(podfile, sandbox, sandbox.root.to_s, lockfile)
39
48
  end
40
49
  end
41
50
  end
@@ -20,7 +20,9 @@ module Pod
20
20
  @sources = []
21
21
  end
22
22
 
23
- # @param [Source] Source object to be added to the installer
23
+ # @param [Source] source object to be added to the installer
24
+ #
25
+ # @return [void]
24
26
  #
25
27
  def add_source(source)
26
28
  unless source.nil?
@@ -44,8 +44,6 @@ module Pod
44
44
  # @param [Pathname] installation_root @see #installation_root
45
45
  # @param [Array<AggregateTarget>] targets @see #targets
46
46
  #
47
- # @todo Too many initialization arguments
48
- #
49
47
  def initialize(podfile, sandbox, installation_root, targets)
50
48
  @podfile = podfile
51
49
  @sandbox = sandbox
@@ -162,7 +162,7 @@ module Pod
162
162
  #
163
163
  def create_or_update_user_script_phases(script_phases, native_target)
164
164
  script_phase_names = script_phases.map { |k| k[:name] }
165
- # Delete script phases no longer present in the target definition.
165
+ # Delete script phases no longer present in the target.
166
166
  native_target_script_phases = native_target.shell_script_build_phases.select { |bp| !bp.name.nil? && bp.name.start_with?(USER_BUILD_PHASE_PREFIX) }
167
167
  native_target_script_phases.each do |script_phase|
168
168
  script_phase_name_without_prefix = script_phase.name.sub(USER_BUILD_PHASE_PREFIX, '')
@@ -171,16 +171,16 @@ module Pod
171
171
  end
172
172
  end
173
173
  # Create or update the ones that are expected to be.
174
- script_phases.each do |td_script_phase|
175
- name_with_prefix = USER_BUILD_PHASE_PREFIX + td_script_phase[:name]
174
+ script_phases.each do |script_phase|
175
+ name_with_prefix = USER_BUILD_PHASE_PREFIX + script_phase[:name]
176
176
  phase = TargetIntegrator.create_or_update_build_phase(native_target, name_with_prefix)
177
- phase.shell_script = td_script_phase[:script]
178
- phase.shell_path = td_script_phase[:shell_path] if td_script_phase.key?(:shell_path)
179
- phase.input_paths = td_script_phase[:input_files] if td_script_phase.key?(:input_files)
180
- phase.output_paths = td_script_phase[:output_files] if td_script_phase.key?(:output_files)
181
- phase.show_env_vars_in_log = td_script_phase[:show_env_vars_in_log] ? '1' : '0' if td_script_phase.key?(:show_env_vars_in_log)
177
+ phase.shell_script = script_phase[:script]
178
+ phase.shell_path = script_phase[:shell_path] if script_phase.key?(:shell_path)
179
+ phase.input_paths = script_phase[:input_files] if script_phase.key?(:input_files)
180
+ phase.output_paths = script_phase[:output_files] if script_phase.key?(:output_files)
181
+ phase.show_env_vars_in_log = script_phase[:show_env_vars_in_log] ? '1' : '0' if script_phase.key?(:show_env_vars_in_log)
182
182
 
183
- execution_position = td_script_phase[:execution_position]
183
+ execution_position = script_phase[:execution_position]
184
184
  unless execution_position == :any
185
185
  compile_build_phase_index = native_target.build_phases.index do |bp|
186
186
  bp.is_a?(Xcodeproj::Project::Object::PBXSourcesBuildPhase)
@@ -321,18 +321,24 @@ module Pod
321
321
  # @return [void]
322
322
  #
323
323
  def add_copy_resources_script_phase
324
- native_targets.each do |native_target|
325
- script_path = target.copy_resources_script_relative_path
326
- resource_paths_by_config = target.resource_paths_by_config
327
- if resource_paths_by_config.values.all?(&:empty?)
324
+ unless target.includes_resources?
325
+ native_targets.each do |native_target|
328
326
  TargetIntegrator.remove_copy_resources_script_phase_from_target(native_target)
329
- else
330
- resource_paths_flattened = resource_paths_by_config.values.flatten.uniq
331
- input_paths = [target.copy_resources_script_relative_path, *resource_paths_flattened]
332
- output_paths = TargetIntegrator.resource_output_paths(resource_paths_flattened)
333
- TargetIntegrator.validate_input_output_path_limit(input_paths, output_paths)
334
- TargetIntegrator.create_or_update_copy_resources_script_phase_to_target(native_target, script_path, input_paths, output_paths)
335
327
  end
328
+ return
329
+ end
330
+
331
+ script_path = target.copy_resources_script_relative_path
332
+ resource_paths_by_config = target.resource_paths_by_config
333
+ resource_paths_flattened = resource_paths_by_config.values.flatten.uniq
334
+ input_paths = [target.copy_resources_script_relative_path, *resource_paths_flattened]
335
+ output_paths = TargetIntegrator.resource_output_paths(resource_paths_flattened)
336
+ TargetIntegrator.validate_input_output_path_limit(input_paths, output_paths)
337
+
338
+ native_targets.each do |native_target|
339
+ # Static library targets cannot include resources. Skip this phase from being added instead.
340
+ next if native_target.symbol_type == :static_library
341
+ TargetIntegrator.create_or_update_copy_resources_script_phase_to_target(native_target, script_path, input_paths, output_paths)
336
342
  end
337
343
  end
338
344
 
@@ -356,17 +362,21 @@ module Pod
356
362
  # @return [void]
357
363
  #
358
364
  def add_embed_frameworks_script_phase
359
- native_targets_to_embed_in.each do |native_target|
360
- script_path = target.embed_frameworks_script_relative_path
361
- framework_paths_by_config = target.framework_paths_by_config.values.flatten.uniq
362
- if framework_paths_by_config.all?(&:empty?)
365
+ unless target.includes_frameworks?
366
+ native_targets_to_embed_in.each do |native_target|
363
367
  TargetIntegrator.remove_embed_frameworks_script_phase_from_target(native_target)
364
- else
365
- input_paths = [target.embed_frameworks_script_relative_path, *framework_paths_by_config.map { |fw| [fw[:input_path], fw[:dsym_input_path]] }.flatten.compact]
366
- output_paths = framework_paths_by_config.map { |fw| [fw[:output_path], fw[:dsym_output_path]] }.flatten.compact.uniq
367
- TargetIntegrator.validate_input_output_path_limit(input_paths, output_paths)
368
- TargetIntegrator.create_or_update_embed_frameworks_script_phase_to_target(native_target, script_path, input_paths, output_paths)
369
368
  end
369
+ return
370
+ end
371
+
372
+ script_path = target.embed_frameworks_script_relative_path
373
+ framework_paths_by_config = target.framework_paths_by_config.values.flatten.uniq
374
+ input_paths = [target.embed_frameworks_script_relative_path, *framework_paths_by_config.map { |fw| [fw[:input_path], fw[:dsym_input_path]] }.flatten.compact]
375
+ output_paths = framework_paths_by_config.map { |fw| [fw[:output_path], fw[:dsym_output_path]] }.flatten.compact.uniq
376
+ TargetIntegrator.validate_input_output_path_limit(input_paths, output_paths)
377
+
378
+ native_targets_to_embed_in.each do |native_target|
379
+ TargetIntegrator.create_or_update_embed_frameworks_script_phase_to_target(native_target, script_path, input_paths, output_paths)
370
380
  end
371
381
  end
372
382
 
@@ -42,19 +42,14 @@ module Pod
42
42
  # The build configuration.
43
43
  #
44
44
  def self.set_target_xcconfig(pod_bundle, target, config)
45
- path = pod_bundle.xcconfig_relative_path(config.name)
46
- group = config.project['Pods'] || config.project.new_group('Pods')
47
- file_ref = group.files.find { |f| f.path == path }
48
- existing = config.base_configuration_reference
45
+ file_ref = create_xcconfig_ref(pod_bundle, config)
46
+ path = file_ref.path
49
47
 
50
- set_base_configuration_reference = ->() do
51
- file_ref ||= group.new_file(path)
52
- config.base_configuration_reference = file_ref
53
- end
48
+ existing = config.base_configuration_reference
54
49
 
55
50
  if existing && existing != file_ref
56
51
  if existing.real_path.to_path.start_with?(pod_bundle.sandbox.root.to_path << '/')
57
- set_base_configuration_reference.call
52
+ config.base_configuration_reference = file_ref
58
53
  elsif !xcconfig_includes_target_xcconfig?(config.base_configuration_reference, path)
59
54
  unless existing_config_is_identical_to_pod_config?(existing.real_path, pod_bundle.xcconfig_path(config.name))
60
55
  UI.warn 'CocoaPods did not set the base configuration of your ' \
@@ -66,7 +61,7 @@ module Pod
66
61
  end
67
62
  end
68
63
  elsif config.base_configuration_reference.nil? || file_ref.nil?
69
- set_base_configuration_reference.call
64
+ config.base_configuration_reference = file_ref
70
65
  end
71
66
  end
72
67
 
@@ -97,7 +92,7 @@ module Pod
97
92
  ]
98
93
  message = "The `#{target.name} [#{config.name}]` " \
99
94
  "target overrides the `#{key}` build setting defined in " \
100
- "`#{pod_bundle.xcconfig_relative_path(config.name)}'. " \
95
+ "`#{pod_bundle.pod_bundle.xcconfig_relative_path(config.name)}'. " \
101
96
  'This can lead to problems with the CocoaPods installation'
102
97
  UI.warn(message, actions)
103
98
  end
@@ -139,6 +134,44 @@ module Pod
139
134
  def self.existing_config_is_identical_to_pod_config?(existing_config_path, pod_config_path)
140
135
  existing_config_path.file? && (!pod_config_path.file? || FileUtils.compare_file(existing_config_path, pod_config_path))
141
136
  end
137
+
138
+ # Creates a file reference to the xcconfig generated by
139
+ # CocoaPods (if needed).
140
+ # If the Pods group not exists, create the group and set
141
+ # the location to the `Pods` directory.
142
+ # If the file reference exists, the location is different
143
+ # with the xcconfig's path and the symlink target paths
144
+ # are different, we will update the location.
145
+ #
146
+ # @param [Target::AggregateTarget] pod_bundle
147
+ # The Pods bundle.
148
+ #
149
+ # @param [Xcodeproj::XCBuildConfiguration] config
150
+ # The build configuration.
151
+ #
152
+ # @return [PBXFileReference] the xcconfig reference.
153
+ #
154
+ def self.create_xcconfig_ref(pod_bundle, config)
155
+ # Xcode root group's path is absolute, we must get the relative path of the sandbox to the user project
156
+ group_path = pod_bundle.relative_pods_root_path
157
+ group = config.project['Pods'] || config.project.new_group('Pods', group_path)
158
+
159
+ # support user custom paths of Pods group and xcconfigs files.
160
+ group_path = Pathname.new(group.real_path)
161
+ xcconfig_path = Pathname.new(pod_bundle.xcconfig_path(config.name))
162
+ path = xcconfig_path.relative_path_from(group_path)
163
+
164
+ filename = path.basename.to_s
165
+ file_ref = group.files.find { |f| f.display_name == filename }
166
+ if file_ref && file_ref.path != path
167
+ file_ref_path = Pathname.new(file_ref.real_path)
168
+ if !file_ref_path.exist? || !xcconfig_path.exist? || file_ref_path.realpath != xcconfig_path.realpath
169
+ file_ref.path = path.to_s
170
+ end
171
+ end
172
+
173
+ file_ref || group.new_file(path.to_s)
174
+ end
142
175
  end
143
176
  end
144
177
  end
@@ -4,12 +4,18 @@ module Pod
4
4
  # The {PodsProjectGenerator} handles generation of the 'Pods/Pods.xcodeproj'
5
5
  #
6
6
  class PodsProjectGenerator
7
+ require 'cocoapods/installer/xcode/pods_project_generator/target_installer_helper'
7
8
  require 'cocoapods/installer/xcode/pods_project_generator/pod_target_integrator'
8
9
  require 'cocoapods/installer/xcode/pods_project_generator/target_installer'
10
+ require 'cocoapods/installer/xcode/pods_project_generator/target_installation_result'
9
11
  require 'cocoapods/installer/xcode/pods_project_generator/pod_target_installer'
10
12
  require 'cocoapods/installer/xcode/pods_project_generator/file_references_installer'
11
13
  require 'cocoapods/installer/xcode/pods_project_generator/aggregate_target_installer'
12
14
 
15
+ # @return [Sandbox] The sandbox where the Pods should be installed.
16
+ #
17
+ attr_reader :sandbox
18
+
13
19
  # @return [Pod::Project] the `Pods/Pods.xcodeproj` project.
14
20
  #
15
21
  attr_reader :project
@@ -20,10 +26,6 @@ module Pod
20
26
  #
21
27
  attr_reader :aggregate_targets
22
28
 
23
- # @return [Sandbox] The sandbox where the Pods should be installed.
24
- #
25
- attr_reader :sandbox
26
-
27
29
  # @return [Array<PodTarget>] The model representations of pod targets.
28
30
  #
29
31
  attr_reader :pod_targets
@@ -43,16 +45,16 @@ module Pod
43
45
 
44
46
  # Initialize a new instance
45
47
  #
46
- # @param [Array<AggregateTarget>] aggregate_targets @see aggregate_targets
47
- # @param [Sandbox] sandbox @see sandbox
48
- # @param [Array<PodTarget>] pod_targets @see pod_targets
49
- # @param [Analyzer] analysis_result @see analysis_result
50
- # @param [InstallationOptions] installation_options @see installation_options
51
- # @param [Config] config @see config
48
+ # @param [Sandbox] sandbox @see #sandbox
49
+ # @param [Array<AggregateTarget>] aggregate_targets @see #aggregate_targets
50
+ # @param [Array<PodTarget>] pod_targets @see #pod_targets
51
+ # @param [Analyzer] analysis_result @see #analysis_result
52
+ # @param [InstallationOptions] installation_options @see #installation_options
53
+ # @param [Config] config @see #config
52
54
  #
53
- def initialize(aggregate_targets, sandbox, pod_targets, analysis_result, installation_options, config)
54
- @aggregate_targets = aggregate_targets
55
+ def initialize(sandbox, aggregate_targets, pod_targets, analysis_result, installation_options, config)
55
56
  @sandbox = sandbox
57
+ @aggregate_targets = aggregate_targets
56
58
  @pod_targets = pod_targets
57
59
  @analysis_result = analysis_result
58
60
  @installation_options = installation_options
@@ -62,9 +64,10 @@ module Pod
62
64
  def generate!
63
65
  prepare
64
66
  install_file_references
65
- install_libraries
66
- integrate_targets
67
- set_target_dependencies
67
+ @target_installation_results = install_targets
68
+ integrate_targets(@target_installation_results.pod_target_installation_results)
69
+ wire_target_dependencies(@target_installation_results)
70
+ @target_installation_results
68
71
  end
69
72
 
70
73
  def write
@@ -76,11 +79,19 @@ module Pod
76
79
  UI.message('- Generating deterministic UUIDs') { project.predictabilize_uuids }
77
80
  end
78
81
  library_product_types = [:framework, :dynamic_library, :static_library]
82
+
83
+ pod_target_installation_results = @target_installation_results.pod_target_installation_results
84
+ results_by_native_target = Hash[pod_target_installation_results.map do |_, result|
85
+ [result.native_target, result]
86
+ end]
79
87
  project.recreate_user_schemes(false) do |scheme, target|
88
+ next unless target.respond_to?(:symbol_type)
80
89
  next unless library_product_types.include? target.symbol_type
81
- pod_target = pod_targets.find { |pt| pt.native_target == target }
82
- next if pod_target.nil? || pod_target.test_native_targets.empty?
83
- pod_target.test_native_targets.each { |test_native_target| scheme.add_test_target(test_native_target) }
90
+ installation_result = results_by_native_target[target]
91
+ next unless installation_result
92
+ installation_result.test_native_targets.each do |test_native_target|
93
+ scheme.add_test_target(test_native_target)
94
+ end
84
95
  end
85
96
  project.save
86
97
  end
@@ -95,8 +106,8 @@ module Pod
95
106
  next unless share_scheme_for_development_pod?(pod_target.pod_name)
96
107
  Xcodeproj::XCScheme.share_scheme(project.path, pod_target.label)
97
108
  if pod_target.contains_test_specifications?
98
- pod_target.supported_test_types.each do |test_type|
99
- Xcodeproj::XCScheme.share_scheme(project.path, pod_target.test_target_label(test_type))
109
+ pod_target.test_specs.each do |test_spec|
110
+ Xcodeproj::XCScheme.share_scheme(project.path, pod_target.test_target_label(test_spec))
100
111
  end
101
112
  end
102
113
  end
@@ -104,6 +115,8 @@ module Pod
104
115
 
105
116
  private
106
117
 
118
+ InstallationResults = Struct.new(:pod_target_installation_results, :aggregate_target_installation_results)
119
+
107
120
  def create_project
108
121
  if object_version = aggregate_targets.map(&:user_project).compact.map { |p| p.object_version.to_i }.min
109
122
  Pod::Project.new(sandbox.project_path, false, object_version)
@@ -163,49 +176,59 @@ module Pod
163
176
  installer.install!
164
177
  end
165
178
 
166
- def install_libraries
179
+ def install_targets
167
180
  UI.message '- Installing targets' do
168
181
  umbrella_headers_by_dir = pod_targets.map do |pod_target|
169
182
  next unless pod_target.should_build? && pod_target.defines_module?
170
183
  pod_target.umbrella_header_path
171
184
  end.compact.group_by(&:dirname)
172
185
 
173
- pod_targets.sort_by(&:name).each do |pod_target|
174
- target_installer = PodTargetInstaller.new(sandbox, pod_target)
175
- target_installer.umbrella_headers_by_dir = umbrella_headers_by_dir
176
- target_installer.install!
177
- end
186
+ pod_target_installation_results = Hash[pod_targets.sort_by(&:name).map do |pod_target|
187
+ umbrella_headers_in_header_dir = umbrella_headers_by_dir[pod_target.module_map_path.dirname]
188
+ target_installer = PodTargetInstaller.new(sandbox, @project, pod_target, umbrella_headers_in_header_dir)
189
+ [pod_target.name, target_installer.install!]
190
+ end]
178
191
 
179
- aggregate_targets.sort_by(&:name).each do |target|
180
- target_installer = AggregateTargetInstaller.new(sandbox, target)
181
- target_installer.install!
192
+ # Hook up system framework dependencies for the pod targets that were just installed.
193
+ pod_target_installation_result_values = pod_target_installation_results.values.compact
194
+ unless pod_target_installation_result_values.empty?
195
+ add_system_framework_dependencies(pod_target_installation_result_values)
182
196
  end
183
197
 
184
- add_system_framework_dependencies
198
+ aggregate_target_installation_results = Hash[aggregate_targets.sort_by(&:name).map do |target|
199
+ target_installer = AggregateTargetInstaller.new(sandbox, @project, target)
200
+ [target.name, target_installer.install!]
201
+ end]
202
+
203
+ InstallationResults.new(pod_target_installation_results, aggregate_target_installation_results)
185
204
  end
186
205
  end
187
206
 
188
- def integrate_targets
189
- pod_targets_to_integrate = pod_targets.select { |pt| !pt.test_native_targets.empty? || pt.contains_script_phases? }
190
- unless pod_targets_to_integrate.empty?
207
+ def integrate_targets(pod_target_installation_results)
208
+ pod_installations_to_integrate = pod_target_installation_results.values.select do |pod_target_installation_result|
209
+ pod_target = pod_target_installation_result.target
210
+ !pod_target_installation_result.test_native_targets.empty? || pod_target.contains_script_phases?
211
+ end
212
+ unless pod_installations_to_integrate.empty?
191
213
  UI.message '- Integrating targets' do
192
- pod_targets_to_integrate.each do |pod_target|
193
- PodTargetIntegrator.new(pod_target).integrate!
214
+ pod_installations_to_integrate.each do |pod_target_installation_result|
215
+ PodTargetIntegrator.new(pod_target_installation_result).integrate!
194
216
  end
195
217
  end
196
218
  end
197
219
  end
198
220
 
199
- def add_system_framework_dependencies
200
- # @TODO: Add Specs
201
- pod_targets.select(&:should_build?).sort_by(&:name).each do |pod_target|
202
- test_file_accessors, file_accessors = pod_target.file_accessors.partition { |fa| fa.spec.test_specification? }
203
- file_accessors.each do |file_accessor|
204
- add_system_frameworks_to_native_target(file_accessor, pod_target.native_target)
205
- end
206
- test_file_accessors.each do |test_file_accessor|
207
- native_target = pod_target.native_target_for_spec(test_file_accessor.spec)
208
- add_system_frameworks_to_native_target(test_file_accessor, native_target)
221
+ def add_system_framework_dependencies(pod_target_installation_results)
222
+ sorted_installation_results = pod_target_installation_results.sort_by do |pod_target_installation_result|
223
+ pod_target_installation_result.target.name
224
+ end
225
+ sorted_installation_results.each do |target_installation_result|
226
+ pod_target = target_installation_result.target
227
+ next unless pod_target.should_build?
228
+ next if !pod_target.requires_frameworks? || pod_target.static_framework?
229
+ pod_target.file_accessors.each do |file_accessor|
230
+ native_target = target_installation_result.native_target_for_spec(file_accessor.spec)
231
+ add_system_frameworks_to_native_target(native_target, file_accessor)
209
232
  end
210
233
  end
211
234
  end
@@ -213,53 +236,70 @@ module Pod
213
236
  # Adds a target dependency for each pod spec to each aggregate target and
214
237
  # links the pod targets among each other.
215
238
  #
239
+ # @param [Array[Hash{String=>TargetInstallationResult}]] target_installation_results
240
+ # the installation results that were produced when all targets were installed. This includes
241
+ # pod target installation results and aggregate target installation results.
242
+ #
216
243
  # @return [void]
217
244
  #
218
- def set_target_dependencies
245
+ def wire_target_dependencies(target_installation_results)
219
246
  frameworks_group = project.frameworks_group
220
- test_only_pod_targets = pod_targets.dup
221
- aggregate_targets.each do |aggregate_target|
247
+ pod_target_installation_results_hash = target_installation_results.pod_target_installation_results
248
+ aggregate_target_installation_results_hash = target_installation_results.aggregate_target_installation_results
249
+
250
+ # Wire up aggregate targets
251
+ aggregate_target_installation_results_hash.values.each do |aggregate_target_installation_result|
252
+ aggregate_target = aggregate_target_installation_result.target
253
+ aggregate_native_target = aggregate_target_installation_result.native_target
222
254
  is_app_extension = !(aggregate_target.user_targets.map(&:symbol_type) &
223
- [:app_extension, :watch_extension, :watch2_extension, :tv_extension, :messages_extension]).empty?
255
+ [:app_extension, :watch_extension, :watch2_extension, :tv_extension, :messages_extension]).empty?
224
256
  is_app_extension ||= aggregate_target.user_targets.any? { |ut| ut.common_resolved_build_setting('APPLICATION_EXTENSION_API_ONLY') == 'YES' }
225
-
257
+ configure_app_extension_api_only_to_native_target(aggregate_native_target) if is_app_extension
258
+ # Wire up dependencies that are part of inherit search paths for this aggregate target.
226
259
  aggregate_target.search_paths_aggregate_targets.each do |search_paths_target|
227
- aggregate_target.native_target.add_dependency(search_paths_target.native_target)
260
+ aggregate_native_target.add_dependency(aggregate_target_installation_results_hash[search_paths_target.name].native_target)
228
261
  end
229
-
262
+ # Wire up all pod target dependencies to aggregate target.
230
263
  aggregate_target.pod_targets.each do |pod_target|
231
- test_only_pod_targets.delete(pod_target)
232
- configure_app_extension_api_only_for_target(aggregate_target) if is_app_extension
233
-
234
- unless pod_target.should_build?
235
- add_resource_bundles_to_native_target(pod_target, aggregate_target.native_target)
236
- add_pod_target_test_dependencies(pod_target, frameworks_group)
237
- next
238
- end
239
-
240
- aggregate_target.native_target.add_dependency(pod_target.native_target)
241
- configure_app_extension_api_only_for_target(pod_target) if is_app_extension
264
+ pod_target_native_target = pod_target_installation_results_hash[pod_target.name].native_target
265
+ aggregate_native_target.add_dependency(pod_target_native_target)
266
+ configure_app_extension_api_only_to_native_target(pod_target_native_target) if is_app_extension
267
+ end
268
+ end
242
269
 
243
- add_dependent_targets_to_native_target(pod_target.dependent_targets,
244
- pod_target.native_target, is_app_extension,
245
- pod_target.requires_frameworks? && !pod_target.static_framework?,
246
- frameworks_group)
247
- unless pod_target.static_framework?
248
- add_pod_target_test_dependencies(pod_target, frameworks_group)
270
+ # Wire up pod targets
271
+ pod_target_installation_results_hash.values.each do |pod_target_installation_result|
272
+ pod_target = pod_target_installation_result.target
273
+ native_target = pod_target_installation_result.native_target
274
+ # First, wire up all resource bundles.
275
+ pod_target_installation_result.resource_bundle_targets.each do |resource_bundle_target|
276
+ native_target.add_dependency(resource_bundle_target)
277
+ if pod_target.requires_frameworks? && pod_target.should_build?
278
+ native_target.add_resources([resource_bundle_target.product_reference])
249
279
  end
250
280
  end
251
- end
252
- # Wire up remaining pod targets used only by tests and are not used by any aggregate target.
253
- test_only_pod_targets.each do |pod_target|
254
- unless pod_target.should_build?
255
- add_pod_target_test_dependencies(pod_target, frameworks_group)
256
- next
281
+ # Wire up all dependencies to this pod target, if any.
282
+ dependent_targets = pod_target.dependent_targets
283
+ dependent_targets.each do |dependent_target|
284
+ native_target.add_dependency(pod_target_installation_results_hash[dependent_target.name].native_target)
285
+ add_framework_file_reference_to_native_target(native_target, pod_target, dependent_target, frameworks_group)
257
286
  end
258
- unless pod_target.static_framework?
259
- add_dependent_targets_to_native_target(pod_target.dependent_targets,
260
- pod_target.native_target, false,
261
- pod_target.requires_frameworks?, frameworks_group)
262
- add_pod_target_test_dependencies(pod_target, frameworks_group)
287
+ # Wire up test native targets.
288
+ unless pod_target_installation_result.test_native_targets.empty?
289
+ pod_target_installation_result.test_specs_by_native_target.each do |test_native_target, test_specs|
290
+ test_dependent_targets = test_specs.flat_map { |s| pod_target.test_dependent_targets_by_spec_name[s.name] }.compact.unshift(pod_target).uniq
291
+ test_dependent_targets.each do |test_dependent_target|
292
+ dependency_installation_result = pod_target_installation_results_hash[test_dependent_target.name]
293
+ resource_bundle_native_targets = dependency_installation_result.test_resource_bundle_targets[test_specs.first.name]
294
+ unless resource_bundle_native_targets.nil?
295
+ resource_bundle_native_targets.each do |test_resource_bundle_target|
296
+ test_native_target.add_dependency(test_resource_bundle_target)
297
+ end
298
+ end
299
+ test_native_target.add_dependency(dependency_installation_result.native_target)
300
+ add_framework_file_reference_to_native_target(test_native_target, pod_target, test_dependent_target, frameworks_group)
301
+ end
302
+ end
263
303
  end
264
304
  end
265
305
  end
@@ -295,55 +335,25 @@ module Pod
295
335
 
296
336
  # @! group Private Helpers
297
337
 
298
- private
299
-
300
- def add_pod_target_test_dependencies(pod_target, frameworks_group)
301
- test_dependent_targets = pod_target.all_dependent_targets
302
- pod_target.test_specs_by_native_target.each do |test_native_target, test_specs|
303
- test_dependent_targets.reject(&:should_build?).each do |test_dependent_target|
304
- add_resource_bundles_to_native_target(test_dependent_target, test_native_target)
305
- end
306
- add_dependent_targets_to_native_target(test_dependent_targets, test_native_target, false, pod_target.requires_frameworks?, frameworks_group)
307
- test_spec_consumers = test_specs.map { |test_spec| test_spec.consumer(pod_target.platform) }
308
- if test_spec_consumers.any?(&:requires_app_host?)
309
- app_host_target = project.targets.find { |t| t.name == pod_target.app_host_label(test_specs.first.test_type) }
310
- test_native_target.add_dependency(app_host_target)
311
- end
312
- end
313
- end
314
-
315
- def add_dependent_targets_to_native_target(dependent_targets, native_target, is_app_extension, requires_frameworks, frameworks_group)
316
- dependent_targets.each do |pod_dependency_target|
317
- next unless pod_dependency_target.should_build?
318
- native_target.add_dependency(pod_dependency_target.native_target)
319
- configure_app_extension_api_only_for_target(pod_dependency_target) if is_app_extension
320
-
321
- if requires_frameworks
322
- product_ref = frameworks_group.files.find { |f| f.path == pod_dependency_target.product_name } ||
323
- frameworks_group.new_product_ref_for_target(pod_dependency_target.product_basename, pod_dependency_target.product_type)
324
- native_target.frameworks_build_phase.add_file_reference(product_ref, true)
325
- end
326
- end
327
- end
328
-
329
- def add_system_frameworks_to_native_target(file_accessor, native_target)
338
+ def add_system_frameworks_to_native_target(native_target, file_accessor)
330
339
  file_accessor.spec_consumer.frameworks.each do |framework|
331
340
  native_target.add_system_framework(framework)
332
341
  end
333
342
  end
334
343
 
335
- def add_resource_bundles_to_native_target(dependent_target, native_target)
336
- resource_bundle_targets = dependent_target.resource_bundle_targets + dependent_target.test_resource_bundle_targets
337
- resource_bundle_targets.each do |resource_bundle_target|
338
- native_target.add_dependency(resource_bundle_target)
344
+ def add_framework_file_reference_to_native_target(native_target, pod_target, dependent_target, frameworks_group)
345
+ if pod_target.should_build? && pod_target.requires_frameworks? && !pod_target.static_framework? && dependent_target.should_build?
346
+ product_ref = frameworks_group.files.find { |f| f.path == dependent_target.product_name } ||
347
+ frameworks_group.new_product_ref_for_target(dependent_target.product_basename, dependent_target.product_type)
348
+ native_target.frameworks_build_phase.add_file_reference(product_ref, true)
339
349
  end
340
350
  end
341
351
 
342
352
  # Sets the APPLICATION_EXTENSION_API_ONLY build setting to YES for all
343
- # configurations of the given target
353
+ # configurations of the given native target.
344
354
  #
345
- def configure_app_extension_api_only_for_target(target)
346
- target.native_target.build_configurations.each do |config|
355
+ def configure_app_extension_api_only_to_native_target(native_target)
356
+ native_target.build_configurations.each do |config|
347
357
  config.build_settings['APPLICATION_EXTENSION_API_ONLY'] = 'YES'
348
358
  end
349
359
  end