cocoapods 1.5.3 → 1.6.0.beta.1

Sign up to get free protection for your applications and to get access to all the features.
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