cocoapods 0.35.0 → 0.36.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 (45) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +185 -6
  3. data/README.md +1 -1
  4. data/lib/cocoapods.rb +4 -0
  5. data/lib/cocoapods/command.rb +2 -2
  6. data/lib/cocoapods/command/inter_process_communication.rb +1 -1
  7. data/lib/cocoapods/command/lib.rb +3 -0
  8. data/lib/cocoapods/command/list.rb +0 -35
  9. data/lib/cocoapods/command/search.rb +1 -2
  10. data/lib/cocoapods/command/spec.rb +6 -3
  11. data/lib/cocoapods/config.rb +1 -20
  12. data/lib/cocoapods/external_sources/abstract_external_source.rb +4 -0
  13. data/lib/cocoapods/gem_version.rb +1 -1
  14. data/lib/cocoapods/generator/embed_frameworks_script.rb +107 -0
  15. data/lib/cocoapods/generator/header.rb +13 -1
  16. data/lib/cocoapods/generator/info_plist_file.rb +84 -0
  17. data/lib/cocoapods/generator/module_map.rb +49 -0
  18. data/lib/cocoapods/generator/umbrella_header.rb +44 -0
  19. data/lib/cocoapods/generator/xcconfig/aggregate_xcconfig.rb +69 -23
  20. data/lib/cocoapods/generator/xcconfig/private_pod_xcconfig.rb +12 -0
  21. data/lib/cocoapods/generator/xcconfig/public_pod_xcconfig.rb +1 -9
  22. data/lib/cocoapods/generator/xcconfig/xcconfig_helper.rb +79 -1
  23. data/lib/cocoapods/hooks_manager.rb +75 -13
  24. data/lib/cocoapods/installer.rb +59 -2
  25. data/lib/cocoapods/installer/analyzer.rb +115 -38
  26. data/lib/cocoapods/installer/analyzer/locking_dependency_analyzer.rb +6 -1
  27. data/lib/cocoapods/installer/file_references_installer.rb +11 -5
  28. data/lib/cocoapods/installer/migrator.rb +9 -0
  29. data/lib/cocoapods/installer/target_installer.rb +89 -5
  30. data/lib/cocoapods/installer/target_installer/aggregate_target_installer.rb +49 -5
  31. data/lib/cocoapods/installer/target_installer/pod_target_installer.rb +57 -9
  32. data/lib/cocoapods/installer/user_project_integrator.rb +3 -2
  33. data/lib/cocoapods/installer/user_project_integrator/target_integrator.rb +67 -6
  34. data/lib/cocoapods/project.rb +18 -2
  35. data/lib/cocoapods/resolver.rb +2 -2
  36. data/lib/cocoapods/sandbox/file_accessor.rb +23 -3
  37. data/lib/cocoapods/sandbox/headers_store.rb +4 -0
  38. data/lib/cocoapods/sources_manager.rb +5 -1
  39. data/lib/cocoapods/target.rb +117 -1
  40. data/lib/cocoapods/target/aggregate_target.rb +46 -4
  41. data/lib/cocoapods/target/pod_target.rb +39 -1
  42. data/lib/cocoapods/user_interface.rb +16 -21
  43. data/lib/cocoapods/user_interface/error_report.rb +2 -2
  44. data/lib/cocoapods/validator.rb +68 -23
  45. metadata +23 -19
@@ -89,6 +89,7 @@ module Pod
89
89
  prepare
90
90
  resolve_dependencies
91
91
  download_dependencies
92
+ determine_dependency_product_types
92
93
  generate_pods_project
93
94
  integrate_user_project if config.integrate_targets?
94
95
  perform_post_install_actions
@@ -97,6 +98,7 @@ module Pod
97
98
  def prepare
98
99
  UI.message 'Preparing' do
99
100
  sandbox.prepare
101
+ ensure_plugins_are_installed!
100
102
  Migrator.migrate(sandbox)
101
103
  end
102
104
  end
@@ -310,6 +312,21 @@ module Pod
310
312
  @pod_installers.each(&:clean!)
311
313
  end
312
314
 
315
+ # Determines if the dependencies need to be built as dynamic frameworks or
316
+ # if they can be built as static libraries by checking for the Swift source
317
+ # presence. Therefore it is important that the file accessors of the
318
+ # #pod_targets are created.
319
+ #
320
+ # @return [void]
321
+ #
322
+ def determine_dependency_product_types
323
+ aggregate_targets.each do |aggregate_target|
324
+ aggregate_target.pod_targets.each do |pod_target|
325
+ pod_target.host_requires_frameworks = aggregate_target.requires_frameworks?
326
+ end
327
+ end
328
+ end
329
+
313
330
  # Performs any post-installation actions
314
331
  #
315
332
  # @return [void]
@@ -323,7 +340,23 @@ module Pod
323
340
  #
324
341
  def run_plugins_post_install_hooks
325
342
  context = HooksContext.generate(sandbox, aggregate_targets)
326
- HooksManager.run(:post_install, context)
343
+ HooksManager.run(:post_install, context, podfile.plugins)
344
+ end
345
+
346
+ # Ensures that all plugins specified in the {#podfile} are loaded.
347
+ #
348
+ # @return [void]
349
+ #
350
+ def ensure_plugins_are_installed!
351
+ require 'claide/command/plugin_manager'
352
+
353
+ loaded_plugins = Command::PluginManager.specifications.map(&:name)
354
+
355
+ podfile.plugins.keys.each do |plugin|
356
+ unless loaded_plugins.include? plugin
357
+ raise Informative, "Your Podfile requires that the plugin `#{plugin}` be installed. Please install it and try installation again."
358
+ end
359
+ end
327
360
  end
328
361
 
329
362
  # Prints a warning for any pods that are deprecated
@@ -418,16 +451,32 @@ module Pod
418
451
  pod_targets.sort_by(&:name).each do |pod_target|
419
452
  pod_target.file_accessors.each do |file_accessor|
420
453
  file_accessor.spec_consumer.frameworks.each do |framework|
421
- pod_target.native_target.add_system_framework(framework)
454
+ if pod_target.should_build?
455
+ pod_target.native_target.add_system_framework(framework)
456
+ end
422
457
  end
423
458
  end
424
459
  end
425
460
  end
426
461
  end
427
462
 
463
+ # Adds a target dependency for each pod spec to each aggregate target and
464
+ # links the pod targets among each other.
465
+ #
466
+ # @return [void]
467
+ #
428
468
  def set_target_dependencies
469
+ frameworks_group = pods_project.frameworks_group
429
470
  aggregate_targets.each do |aggregate_target|
430
471
  aggregate_target.pod_targets.each do |pod_target|
472
+ unless pod_target.should_build?
473
+ pod_target.resource_bundle_targets.each do |resource_bundle_target|
474
+ aggregate_target.native_target.add_dependency(resource_bundle_target)
475
+ end
476
+
477
+ next
478
+ end
479
+
431
480
  aggregate_target.native_target.add_dependency(pod_target.native_target)
432
481
  pod_target.dependencies.each do |dep|
433
482
 
@@ -437,7 +486,15 @@ module Pod
437
486
  unless pod_dependency_target
438
487
  puts "[BUG] DEP: #{dep}"
439
488
  end
489
+
490
+ next unless pod_dependency_target.should_build?
440
491
  pod_target.native_target.add_dependency(pod_dependency_target.native_target)
492
+
493
+ if pod_target.requires_frameworks?
494
+ product_ref = frameworks_group.files.find { |f| f.path == pod_dependency_target.product_name } ||
495
+ frameworks_group.new_product_ref_for_target(pod_dependency_target.product_basename, pod_dependency_target.product_type)
496
+ pod_target.native_target.frameworks_build_phase.add_file_reference(product_ref)
497
+ end
441
498
  end
442
499
  end
443
500
  end
@@ -180,47 +180,92 @@ module Pod
180
180
  def generate_targets
181
181
  targets = []
182
182
  result.specs_by_target.each do |target_definition, specs|
183
- target = AggregateTarget.new(target_definition, sandbox)
184
- targets << target
185
-
186
- if config.integrate_targets?
187
- project_path = compute_user_project_path(target_definition)
188
- user_project = Xcodeproj::Project.open(project_path)
189
- native_targets = compute_user_project_targets(target_definition, user_project)
190
-
191
- target.user_project_path = project_path
192
- target.client_root = project_path.dirname
193
- target.user_target_uuids = native_targets.map(&:uuid)
194
- target.user_build_configurations = compute_user_build_configurations(target_definition, native_targets)
195
- target.archs = @archs_by_target_def[target_definition]
196
- else
197
- target.client_root = config.installation_root
198
- target.user_target_uuids = []
199
- target.user_build_configurations = target_definition.build_configurations || {}
200
- if target_definition.platform.name == :osx
201
- target.archs = '$(ARCHS_STANDARD_64_BIT)'
202
- end
183
+ targets << generate_target(target_definition, specs)
184
+ end
185
+ targets
186
+ end
187
+
188
+ # Setup the aggregate target for a single user target
189
+ #
190
+ # @param [TargetDefinition] target_definition
191
+ # the target definition for the user target.
192
+ #
193
+ # @param [Array<Specification>] specs
194
+ # the specifications that need to be installed grouped by the
195
+ # given target definition.
196
+ #
197
+ # @return [AggregateTarget]
198
+ #
199
+ def generate_target(target_definition, specs)
200
+ target = AggregateTarget.new(target_definition, sandbox)
201
+ target.host_requires_frameworks |= target_definition.uses_frameworks?
202
+
203
+ if config.integrate_targets?
204
+ project_path = compute_user_project_path(target_definition)
205
+ user_project = Xcodeproj::Project.open(project_path)
206
+ native_targets = compute_user_project_targets(target_definition, user_project)
207
+
208
+ target.user_project_path = project_path
209
+ target.client_root = project_path.dirname
210
+ target.user_target_uuids = native_targets.map(&:uuid)
211
+ target.user_build_configurations = compute_user_build_configurations(target_definition, native_targets)
212
+ target.archs = @archs_by_target_def[target_definition]
213
+ else
214
+ target.client_root = config.installation_root
215
+ target.user_target_uuids = []
216
+ target.user_build_configurations = target_definition.build_configurations || { 'Release' => :release, 'Debug' => :debug }
217
+ if target_definition.platform.name == :osx
218
+ target.archs = '$(ARCHS_STANDARD_64_BIT)'
203
219
  end
220
+ end
204
221
 
205
- grouped_specs = specs.map do |spec|
206
- specs.select { |s| s.root == spec.root }
207
- end.uniq
222
+ target.pod_targets = generate_pod_targets(target, specs)
208
223
 
209
- grouped_specs.each do |pod_specs|
210
- pod_target = PodTarget.new(pod_specs, target_definition, sandbox)
211
- if config.integrate_targets?
212
- pod_target.user_build_configurations = target.user_build_configurations
213
- pod_target.archs = @archs_by_target_def[target_definition]
214
- else
215
- pod_target.user_build_configurations = {}
216
- if target_definition.platform.name == :osx
217
- pod_target.archs = '$(ARCHS_STANDARD_64_BIT)'
218
- end
219
- end
220
- target.pod_targets << pod_target
224
+ target
225
+ end
226
+
227
+ # Setup the pod targets for an aggregate target. Group specs and subspecs
228
+ # by their root to create a {PodTarget} for each spec.
229
+ #
230
+ # @param [AggregateTarget] target
231
+ # the aggregate target
232
+ #
233
+ # @param [Array<Specification>] specs
234
+ # the specifications that need to be installed.
235
+ #
236
+ # @return [Array<PodTarget>]
237
+ #
238
+ def generate_pod_targets(target, specs)
239
+ grouped_specs = specs.group_by(&:root).values.uniq
240
+ grouped_specs.map do |pod_specs|
241
+ generate_pod_target(target, pod_specs)
242
+ end
243
+ end
244
+
245
+ # Create a target for each spec group and add it to the aggregate target
246
+ #
247
+ # @param [AggregateTarget] target
248
+ # the aggregate target
249
+ #
250
+ # @param [Array<Specification>] specs
251
+ # the specifications of an equal root.
252
+ #
253
+ # @return [PodTarget]
254
+ #
255
+ def generate_pod_target(target, pod_specs)
256
+ pod_target = PodTarget.new(pod_specs, target.target_definition, sandbox)
257
+
258
+ if config.integrate_targets?
259
+ pod_target.user_build_configurations = target.user_build_configurations
260
+ pod_target.archs = @archs_by_target_def[target.target_definition]
261
+ else
262
+ pod_target.user_build_configurations = {}
263
+ if target.platform.name == :osx
264
+ pod_target.archs = '$(ARCHS_STANDARD_64_BIT)'
221
265
  end
222
266
  end
223
- targets
267
+
268
+ pod_target
224
269
  end
225
270
 
226
271
  # Generates dependencies that require the specific version of the Pods
@@ -331,6 +376,8 @@ module Pod
331
376
  pods_to_fetch = result.podfile_state.added + result.podfile_state.changed
332
377
  if update_mode == :selected
333
378
  pods_to_fetch += update[:pods]
379
+ elsif update_mode == :all
380
+ pods_to_fetch += result.podfile_state.unchanged + result.podfile_state.deleted
334
381
  end
335
382
  pods_to_fetch
336
383
  end
@@ -462,9 +509,8 @@ module Pod
462
509
  raise Informative, 'Unable to find the Xcode project ' \
463
510
  "`#{path}` for the target `#{target_definition.label}`."
464
511
  end
465
-
466
512
  else
467
- xcodeprojs = Pathname.glob(config.installation_root + '*.xcodeproj')
513
+ xcodeprojs = config.installation_root.children.select { |e| e.fnmatch('*.xcodeproj') }
468
514
  if xcodeprojs.size == 1
469
515
  path = xcodeprojs.first
470
516
  else
@@ -514,6 +560,37 @@ module Pod
514
560
  end
515
561
  end
516
562
 
563
+ # Checks if any of the targets for the {TargetDefinition} computed before
564
+ # by #compute_user_project_targets require to be build as a framework due
565
+ # the presence of Swift source code in any of the source build phases.
566
+ #
567
+ # @param [TargetDefinition] target_definition
568
+ # the target definition
569
+ #
570
+ # @param [Array<PBXNativeTarget>] native_targets
571
+ # the targets which are checked for presence of Swift source code
572
+ #
573
+ # @return [Boolean] Whether the user project targets to integrate into
574
+ # uses Swift
575
+ #
576
+ def compute_user_project_targets_require_framework(target_definition, native_targets)
577
+ file_predicate = nil
578
+ file_predicate = proc do |file_ref|
579
+ if file_ref.respond_to?(:last_known_file_type)
580
+ file_ref.last_known_file_type == 'sourcecode.swift'
581
+ elsif file_ref.respond_to?(:files)
582
+ file_ref.files.any?(&file_predicate)
583
+ else
584
+ false
585
+ end
586
+ end
587
+ target_definition.platform.supports_dynamic_frameworks? || native_targets.any? do |target|
588
+ target.source_build_phase.files.any? do |build_file|
589
+ file_predicate.call(build_file.file_ref)
590
+ end
591
+ end
592
+ end
593
+
517
594
  # @return [Hash{String=>Symbol}] A hash representing the user build
518
595
  # configurations where each key corresponds to the name of a
519
596
  # configuration and its value to its type (`:debug` or `:release`).
@@ -32,8 +32,13 @@ module Pod
32
32
  add_to_dependency_graph(pod, [], dependency_graph)
33
33
  end
34
34
 
35
+ pods_to_update = pods_to_update.flat_map do |u|
36
+ root_name = Specification.root_name(u)
37
+ dependency_graph.vertices.keys.select { |n| Specification.root_name(n) == root_name }
38
+ end
39
+
35
40
  pods_to_update.each do |u|
36
- dependency_graph.detach_vertex_named(u) if dependency_graph.vertex_named(u)
41
+ dependency_graph.detach_vertex_named(u)
37
42
  end
38
43
  end
39
44
 
@@ -67,7 +67,7 @@ module Pod
67
67
  #
68
68
  def add_source_files_references
69
69
  UI.message '- Adding source files to Pods project' do
70
- add_file_accessors_paths_to_pods_group(:source_files)
70
+ add_file_accessors_paths_to_pods_group(:source_files, nil, true)
71
71
  end
72
72
  end
73
73
 
@@ -100,8 +100,8 @@ module Pod
100
100
  #
101
101
  def add_resources
102
102
  UI.message '- Adding resources to Pods project' do
103
- add_file_accessors_paths_to_pods_group(:resources, :resources)
104
- add_file_accessors_paths_to_pods_group(:resource_bundle_files, :resources)
103
+ add_file_accessors_paths_to_pods_group(:resources, :resources, true)
104
+ add_file_accessors_paths_to_pods_group(:resource_bundle_files, :resources, true)
105
105
  end
106
106
  end
107
107
 
@@ -152,14 +152,20 @@ module Pod
152
152
  # @param [Symbol] group_key
153
153
  # The key of the group of the Pods project.
154
154
  #
155
+ # @param [Bool] reflect_file_system_structure_for_development
156
+ # Wether organizing the a local pod's files in subgroups inside
157
+ # the pod's group is allowed.
158
+ #
155
159
  # @return [void]
156
160
  #
157
- def add_file_accessors_paths_to_pods_group(file_accessor_key, group_key = nil)
161
+ def add_file_accessors_paths_to_pods_group(file_accessor_key, group_key = nil, reflect_file_system_structure_for_development = false)
158
162
  file_accessors.each do |file_accessor|
163
+ pod_name = file_accessor.spec.name
164
+ local = sandbox.local?(pod_name)
159
165
  paths = file_accessor.send(file_accessor_key)
160
166
  paths.each do |path|
161
167
  group = pods_project.group_for_spec(file_accessor.spec.name, group_key)
162
- pods_project.add_file_reference(path, group)
168
+ pods_project.add_file_reference(path, group, local && reflect_file_system_structure_for_development)
163
169
  end
164
170
  end
165
171
  end
@@ -13,6 +13,7 @@ module Pod
13
13
  def migrate(sandbox)
14
14
  if sandbox.manifest
15
15
  migrate_to_0_34(sandbox) if installation_minor?('0.34', sandbox)
16
+ migrate_to_0_36(sandbox) if installation_minor?('0.36', sandbox)
16
17
  end
17
18
  end
18
19
 
@@ -46,6 +47,14 @@ module Pod
46
47
  delete(Pathname(File.join(ENV['HOME'], 'Library/Caches/CocoaPods/Git')))
47
48
  end
48
49
 
50
+ # Migrates from CocoaPods versions prior to 0.36.
51
+ #
52
+ def migrate_to_0_36(sandbox)
53
+ UI.message('Migrating to CocoaPods 0.36') do
54
+ move(sandbox.root + 'Headers/Build', sandbox.root + 'Headers/Private')
55
+ end
56
+ end
57
+
49
58
  # @!group Private helpers
50
59
 
51
60
  def installation_minor?(target_version, sandbox)
@@ -36,25 +36,47 @@ module Pod
36
36
  # @return [void]
37
37
  #
38
38
  def add_target
39
+ product_type = target.product_type
39
40
  name = target.label
40
41
  platform = target.platform.name
41
42
  deployment_target = target.platform.deployment_target.to_s
42
- @native_target = project.new_target(:static_library, name, platform, deployment_target)
43
+ @native_target = project.new_target(product_type, name, platform, deployment_target)
44
+
45
+ product_name = target.product_name
46
+ product = @native_target.product_reference
47
+ product.name = product_name
48
+ product.path = product_name
43
49
 
44
50
  target.user_build_configurations.each do |bc_name, type|
45
51
  configuration = @native_target.add_build_configuration(bc_name, type)
46
52
  end
47
53
 
48
- settings = { 'OTHER_LDFLAGS' => '', 'OTHER_LIBTOOLFLAGS' => '' }
54
+ @native_target.build_configurations.each do |configuration|
55
+ configuration.build_settings.merge!(custom_build_settings)
56
+ end
57
+
58
+ target.native_target = @native_target
59
+ end
60
+
61
+ # Returns the customized build settings which are overridden in the build
62
+ # settings of the user target.
63
+ #
64
+ # @return [Hash{String => String}]
65
+ #
66
+ def custom_build_settings
67
+ settings = {}
68
+
49
69
  if target.archs
50
70
  settings['ARCHS'] = target.archs
51
71
  end
52
72
 
53
- @native_target.build_configurations.each do |configuration|
54
- configuration.build_settings.merge!(settings)
73
+ if target.requires_frameworks?
74
+ settings['PRODUCT_NAME'] = target.product_module_name
75
+ else
76
+ settings.merge!('OTHER_LDFLAGS' => '', 'OTHER_LIBTOOLFLAGS' => '')
55
77
  end
56
78
 
57
- target.native_target = @native_target
79
+ settings
58
80
  end
59
81
 
60
82
  # Creates the directory where to store the support files of the target.
@@ -63,6 +85,68 @@ module Pod
63
85
  target.support_files_dir.mkdir
64
86
  end
65
87
 
88
+ # Creates the Info.plist file which sets public framework attributes
89
+ #
90
+ # @return [void]
91
+ #
92
+ def create_info_plist_file
93
+ path = target.info_plist_path
94
+ UI.message "- Generating Info.plist file at #{UI.path(path)}" do
95
+ generator = Generator::InfoPlistFile.new(target)
96
+ generator.save_as(path)
97
+ add_file_to_support_group(path)
98
+
99
+ native_target.build_configurations.each do |c|
100
+ relative_path = path.relative_path_from(sandbox.root)
101
+ c.build_settings['INFOPLIST_FILE'] = relative_path.to_s
102
+ end
103
+ end
104
+ end
105
+
106
+ # Creates the module map file which ensures that the umbrella header is
107
+ # recognized with a customized path
108
+ #
109
+ # @return [void]
110
+ #
111
+ def create_module_map
112
+ path = target.module_map_path
113
+ UI.message "- Generating module map file at #{UI.path(path)}" do
114
+ generator = Generator::ModuleMap.new(target)
115
+ generator.save_as(path)
116
+ add_file_to_support_group(path)
117
+
118
+ native_target.build_configurations.each do |c|
119
+ relative_path = path.relative_path_from(sandbox.root)
120
+ c.build_settings['MODULEMAP_FILE'] = relative_path.to_s
121
+ end
122
+ end
123
+ end
124
+
125
+ # Generates a header which ensures that all header files are exported
126
+ # in the module map
127
+ #
128
+ # @yield_param [Generator::UmbrellaHeader]
129
+ # yielded once to configure the imports
130
+ #
131
+ def create_umbrella_header
132
+ path = target.umbrella_header_path
133
+ UI.message "- Generating umbrella header at #{UI.path(path)}" do
134
+ generator = Generator::UmbrellaHeader.new(target)
135
+ yield generator if block_given?
136
+ generator.save_as(path)
137
+
138
+ # Add the file to the support group and the native target,
139
+ # so it will been added to the header build phase
140
+ file_ref = add_file_to_support_group(path)
141
+ native_target.add_file_references([file_ref])
142
+
143
+ # Make the umbrella header public
144
+ build_file = native_target.headers_build_phase.build_file(file_ref)
145
+ build_file.settings ||= {}
146
+ build_file.settings['ATTRIBUTES'] = ['Public']
147
+ end
148
+ end
149
+
66
150
  # Generates a dummy source file for each target so libraries that contain
67
151
  # only categories build.
68
152
  #