cocoapods 1.7.5 → 1.8.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 (60) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +175 -11
  3. data/LICENSE +13 -8
  4. data/README.md +2 -1
  5. data/lib/cocoapods/command/init.rb +18 -16
  6. data/lib/cocoapods/command/install.rb +2 -1
  7. data/lib/cocoapods/command/lib/create.rb +1 -2
  8. data/lib/cocoapods/command/lib/lint.rb +12 -11
  9. data/lib/cocoapods/command/repo/add.rb +2 -2
  10. data/lib/cocoapods/command/repo/list.rb +7 -5
  11. data/lib/cocoapods/command/repo/push.rb +15 -12
  12. data/lib/cocoapods/command/setup.rb +2 -88
  13. data/lib/cocoapods/command/spec/lint.rb +10 -9
  14. data/lib/cocoapods/command/update.rb +5 -4
  15. data/lib/cocoapods/config.rb +9 -8
  16. data/lib/cocoapods/external_sources/path_source.rb +1 -1
  17. data/lib/cocoapods/gem_version.rb +1 -1
  18. data/lib/cocoapods/generator/embed_frameworks_script.rb +1 -1
  19. data/lib/cocoapods/generator/info_plist_file.rb +2 -2
  20. data/lib/cocoapods/installer.rb +32 -12
  21. data/lib/cocoapods/installer/analyzer.rb +132 -97
  22. data/lib/cocoapods/installer/analyzer/target_inspector.rb +6 -8
  23. data/lib/cocoapods/installer/installation_options.rb +4 -0
  24. data/lib/cocoapods/installer/pod_source_installer.rb +17 -1
  25. data/lib/cocoapods/installer/podfile_validator.rb +26 -6
  26. data/lib/cocoapods/installer/project_cache/project_cache_analyzer.rb +37 -27
  27. data/lib/cocoapods/installer/project_cache/project_cache_version.rb +1 -1
  28. data/lib/cocoapods/installer/project_cache/project_installation_cache.rb +3 -3
  29. data/lib/cocoapods/installer/project_cache/project_metadata_cache.rb +12 -6
  30. data/lib/cocoapods/installer/project_cache/target_cache_key.rb +32 -8
  31. data/lib/cocoapods/installer/project_cache/target_metadata.rb +6 -2
  32. data/lib/cocoapods/installer/sandbox_dir_cleaner.rb +12 -0
  33. data/lib/cocoapods/installer/user_project_integrator/target_integrator/xcconfig_integrator.rb +1 -1
  34. data/lib/cocoapods/installer/xcode/multi_pods_project_generator.rb +3 -1
  35. data/lib/cocoapods/installer/xcode/pods_project_generator/aggregate_target_dependency_installer.rb +2 -2
  36. data/lib/cocoapods/installer/xcode/pods_project_generator/app_host_installer.rb +18 -3
  37. data/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_dependency_installer.rb +53 -11
  38. data/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_installer.rb +92 -60
  39. data/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_integrator.rb +66 -50
  40. data/lib/cocoapods/installer/xcode/pods_project_generator/target_installation_result.rb +12 -0
  41. data/lib/cocoapods/installer/xcode/pods_project_generator/target_installer.rb +6 -2
  42. data/lib/cocoapods/installer/xcode/pods_project_generator/target_installer_helper.rb +2 -2
  43. data/lib/cocoapods/installer/xcode/target_validator.rb +30 -14
  44. data/lib/cocoapods/native_target_extension.rb +11 -5
  45. data/lib/cocoapods/open-uri.rb +1 -1
  46. data/lib/cocoapods/project.rb +13 -7
  47. data/lib/cocoapods/resolver.rb +63 -53
  48. data/lib/cocoapods/resolver/lazy_specification.rb +14 -5
  49. data/lib/cocoapods/sandbox.rb +35 -2
  50. data/lib/cocoapods/sandbox/pod_dir_cleaner.rb +3 -4
  51. data/lib/cocoapods/sources_manager.rb +72 -43
  52. data/lib/cocoapods/target.rb +7 -1
  53. data/lib/cocoapods/target/aggregate_target.rb +13 -8
  54. data/lib/cocoapods/target/build_settings.rb +33 -10
  55. data/lib/cocoapods/target/pod_target.rb +114 -30
  56. data/lib/cocoapods/user_interface/error_report.rb +9 -5
  57. data/lib/cocoapods/validator.rb +55 -11
  58. data/lib/cocoapods/version_metadata.rb +14 -1
  59. metadata +6 -7
  60. data/lib/cocoapods/command/spec/env_spec.rb +0 -53
@@ -59,6 +59,10 @@ module Pod
59
59
  #
60
60
  attr_reader :installation_options
61
61
 
62
+ # @return [Source::Manager] the sources manager to use when resolving dependencies
63
+ #
64
+ attr_reader :sources_manager
65
+
62
66
  # Initialize a new instance
63
67
  #
64
68
  # @param [Sandbox] sandbox @see #sandbox
@@ -67,9 +71,10 @@ module Pod
67
71
  # @param [Array<Source>] plugin_sources @see #plugin_sources
68
72
  # @param [Boolean] has_dependencies @see #has_dependencies
69
73
  # @param [Hash, Boolean, nil] pods_to_update @see #pods_to_update
74
+ # @param [Source::Manager] sources_manager @see #sources_manager
70
75
  #
71
76
  def initialize(sandbox, podfile, lockfile = nil, plugin_sources = nil, has_dependencies = true,
72
- pods_to_update = false)
77
+ pods_to_update = false, sources_manager = Source::Manager.new(config.repos_dir))
73
78
  @sandbox = sandbox
74
79
  @podfile = podfile
75
80
  @lockfile = lockfile
@@ -78,6 +83,7 @@ module Pod
78
83
  @pods_to_update = pods_to_update
79
84
  @installation_options = podfile.installation_options
80
85
  @podfile_dependency_cache = PodfileDependencyCache.from_podfile(podfile)
86
+ @sources_manager = sources_manager
81
87
  @result = nil
82
88
  end
83
89
 
@@ -117,9 +123,8 @@ module Pod
117
123
  locked_dependencies = generate_version_locking_dependencies(podfile_state)
118
124
  resolver_specs_by_target = resolve_dependencies(locked_dependencies)
119
125
  validate_platforms(resolver_specs_by_target)
120
- specifications = generate_specifications(resolver_specs_by_target)
121
- targets = generate_aggregate_targets(resolver_specs_by_target, target_inspections)
122
- pod_targets = calculate_pod_targets(targets)
126
+ specifications = generate_specifications(resolver_specs_by_target)
127
+ aggregate_targets, pod_targets = generate_targets(resolver_specs_by_target, target_inspections)
123
128
  sandbox_state = generate_sandbox_state(specifications)
124
129
  specs_by_target = resolver_specs_by_target.each_with_object({}) do |rspecs_by_target, hash|
125
130
  hash[rspecs_by_target[0]] = rspecs_by_target[1].map(&:spec)
@@ -129,17 +134,17 @@ module Pod
129
134
  end]
130
135
  sources.each { |s| specs_by_source[s] ||= [] }
131
136
  @result = AnalysisResult.new(podfile_state, specs_by_target, specs_by_source, specifications, sandbox_state,
132
- targets, pod_targets, @podfile_dependency_cache)
137
+ aggregate_targets, pod_targets, @podfile_dependency_cache)
133
138
  end
134
139
 
135
140
  # Updates the git source repositories.
136
141
  #
137
142
  def update_repositories
138
143
  sources.each do |source|
139
- if source.git?
140
- config.sources_manager.update(source.name, true)
144
+ if source.updateable?
145
+ sources_manager.update(source.name, true)
141
146
  else
142
- UI.message "Skipping `#{source.name}` update because the repository is not a git source repository."
147
+ UI.message "Skipping `#{source.name}` update because the repository is not an updateable repository."
143
148
  end
144
149
  end
145
150
  @specs_updated = true
@@ -164,16 +169,19 @@ module Pod
164
169
  if all_dependencies_have_sources
165
170
  sources = dependency_sources
166
171
  elsif has_dependencies? && sources.empty? && plugin_sources.empty?
167
- sources = ['https://github.com/CocoaPods/Specs.git'] + dependency_sources
172
+ sources = [Pod::TrunkSource::TRUNK_REPO_URL] + dependency_sources
168
173
  else
169
174
  sources += dependency_sources
170
175
  end
171
176
 
172
177
  result = sources.uniq.map do |source_url|
173
- config.sources_manager.find_or_create_source_with_url(source_url)
178
+ sources_manager.find_or_create_source_with_url(source_url)
174
179
  end
175
180
  unless plugin_sources.empty?
176
181
  result.insert(0, *plugin_sources)
182
+ plugin_sources.each do |source|
183
+ sources_manager.add_source(source)
184
+ end
177
185
  end
178
186
  result
179
187
  end
@@ -299,7 +307,7 @@ module Pod
299
307
  host_target_uuids = Set.new(aggregate_target.user_project.host_targets_for_embedded_target(embedded_user_target).map(&:uuid))
300
308
  !aggregate_user_target_uuids.intersection(host_target_uuids).empty?
301
309
  end
302
- embedded_aggregate_target.user_build_configurations.keys.each do |configuration_name|
310
+ embedded_aggregate_target.user_build_configurations.each_key do |configuration_name|
303
311
  pod_target_names = Set.new(aggregate_target.pod_targets_for_build_configuration(configuration_name).map(&:name))
304
312
  embedded_pod_targets = embedded_aggregate_target.pod_targets_for_build_configuration(configuration_name).select do |pod_target|
305
313
  if !pod_target_names.include?(pod_target.name) &&
@@ -326,11 +334,16 @@ module Pod
326
334
  #
327
335
  def analyze_host_targets_in_podfile(aggregate_targets, embedded_aggregate_targets)
328
336
  target_definitions_by_uuid = {}
337
+ cli_host_with_frameworks = []
338
+ cli_product_type = 'com.apple.product-type.tool'
329
339
  # Collect aggregate target definitions by uuid to later lookup host target
330
340
  # definitions and verify their compatiblity with their embedded targets
331
341
  aggregate_targets.each do |target|
332
- target.user_targets.map(&:uuid).each do |uuid|
333
- target_definitions_by_uuid[uuid] = target.target_definition
342
+ target.user_targets.each do |user_target|
343
+ target_definitions_by_uuid[user_target.uuid] = target.target_definition
344
+ if user_target.product_type == cli_product_type
345
+ cli_host_with_frameworks << user_target
346
+ end
334
347
  end
335
348
  end
336
349
  aggregate_target_user_projects = aggregate_targets.map(&:user_project)
@@ -338,9 +351,8 @@ module Pod
338
351
  host_uuid_to_embedded_target_definitions = {}
339
352
  # Search all of the known user projects for each embedded target's hosts
340
353
  embedded_aggregate_targets.each do |target|
341
- host_uuids = []
342
- aggregate_target_user_projects.product(target.user_targets).each do |user_project, user_target|
343
- host_uuids += user_project.host_targets_for_embedded_target(user_target).map(&:uuid)
354
+ host_uuids = aggregate_target_user_projects.product(target.user_targets).flat_map do |user_project, user_target|
355
+ user_project.host_targets_for_embedded_target(user_target).map(&:uuid)
344
356
  end
345
357
  # For each host, keep track of its embedded target definitions
346
358
  # to later verify each embedded target's compatiblity with its host,
@@ -356,6 +368,12 @@ module Pod
356
368
  end
357
369
  end
358
370
 
371
+ unless cli_host_with_frameworks.empty?
372
+ UI.warn "The Podfile contains command line tool target(s) (#{cli_host_with_frameworks.map(&:name).to_sentence}) which are attempting to integrate dynamic frameworks." \
373
+ "\n" \
374
+ 'This may not behave as expected, because command line tools are usually distributed as a single binary and cannot contain their own dynamic frameworks.'
375
+ end
376
+
359
377
  unless embedded_targets_missing_hosts.empty?
360
378
  embedded_targets_missing_hosts_product_types = Set.new embedded_targets_missing_hosts.flat_map(&:user_targets).map(&:symbol_type)
361
379
  target_names = embedded_targets_missing_hosts.map do |target|
@@ -404,13 +422,15 @@ module Pod
404
422
  # @param [Array<TargetInspection>] target_inspections
405
423
  # the user target inspections used to construct the aggregate and pod targets.
406
424
  #
407
- # @return [Array<AggregateTarget>] the list of aggregate targets generated.
425
+ # @return [(Array<AggregateTarget>, Array<PodTarget>)] the list of aggregate targets generated,
426
+ # and the list of pod targets generated.
408
427
  #
409
- def generate_aggregate_targets(resolver_specs_by_target, target_inspections)
410
- resolver_specs_by_target = resolver_specs_by_target.reject { |td, _| td.abstract? }
428
+ def generate_targets(resolver_specs_by_target, target_inspections)
429
+ resolver_specs_by_target = resolver_specs_by_target.reject { |td, _| td.abstract? && !td.platform }
411
430
  pod_targets = generate_pod_targets(resolver_specs_by_target, target_inspections)
412
- aggregate_targets = resolver_specs_by_target.keys.map do |target_definition|
413
- generate_aggregate_target(target_definition, target_inspections, pod_targets, resolver_specs_by_target)
431
+ pod_targets_by_target_definition = group_pod_targets_by_target_definition(pod_targets, resolver_specs_by_target)
432
+ aggregate_targets = resolver_specs_by_target.keys.reject(&:abstract?).map do |target_definition|
433
+ generate_aggregate_target(target_definition, target_inspections, pod_targets_by_target_definition)
414
434
  end
415
435
  aggregate_targets.each do |target|
416
436
  search_paths_aggregate_targets = aggregate_targets.select do |aggregate_target|
@@ -438,7 +458,7 @@ module Pod
438
458
  aggregate_target.merge_embedded_pod_targets(embedded_pod_targets)
439
459
  end
440
460
  end
441
- aggregate_targets
461
+ [aggregate_targets, pod_targets]
442
462
  end
443
463
 
444
464
  # Setup the aggregate target for a single user target
@@ -449,18 +469,15 @@ module Pod
449
469
  # @param [Hash{TargetDefinition => TargetInspectionResult}] target_inspections
450
470
  # the user target inspections used to construct the aggregate and pod targets.
451
471
  #
452
- # @param [Array<PodTarget>] pod_targets
453
- # the pod targets, which were generated.
454
- #
455
- # @param [Hash{Podfile::TargetDefinition => Array<ResolvedSpecification>}] resolver_specs_by_target
456
- # the resolved specifications grouped by target.
472
+ # @param [Hash{Podfile::TargetDefinition => Array<PodTarget>}] pod_targets_by_target_definition
473
+ # the pod targets grouped by target.
457
474
  #
458
475
  # @return [AggregateTarget]
459
476
  #
460
- def generate_aggregate_target(target_definition, target_inspections, pod_targets, resolver_specs_by_target)
477
+ def generate_aggregate_target(target_definition, target_inspections, pod_targets_by_target_definition)
461
478
  if installation_options.integrate_targets?
462
479
  target_inspection = target_inspections[target_definition]
463
- raise "missing inspection: #{target_definition.name}" unless target_inspection
480
+ raise "missing inspection for #{target_definition.inspect}" unless target_inspection
464
481
  target_requires_64_bit = Analyzer.requires_64_bit_archs?(target_definition.platform, target_inspection.project.object_version)
465
482
  user_project = target_inspection.project
466
483
  client_root = target_inspection.client_root
@@ -477,8 +494,7 @@ module Pod
477
494
  end
478
495
  platform = target_definition.platform
479
496
  build_configurations = user_build_configurations.keys.concat(target_definition.all_whitelisted_configurations).uniq
480
- pod_targets_for_build_configuration = filter_pod_targets_for_target_definition(target_definition, pod_targets,
481
- resolver_specs_by_target,
497
+ pod_targets_for_build_configuration = filter_pod_targets_for_target_definition(target_definition, pod_targets_by_target_definition,
482
498
  build_configurations)
483
499
 
484
500
  build_type = target_definition.uses_frameworks? ? Target::BuildType.static_framework : Target::BuildType.static_library
@@ -487,21 +503,25 @@ module Pod
487
503
  pod_targets_for_build_configuration, :build_type => build_type)
488
504
  end
489
505
 
490
- # @return [Array<PodTarget>] The model representations of pod targets.
506
+ # Returns a filtered list of pod targets that should or should not be part of the target definition. Pod targets
507
+ # used by tests only are filtered.
508
+ #
509
+ # @return [Hash{TargetDefinition => Array<PodTarget>}]
491
510
  #
492
- def calculate_pod_targets(aggregate_targets)
493
- aggregate_target_pod_targets = aggregate_targets.flat_map(&:pod_targets).uniq
494
- test_dependent_targets = aggregate_target_pod_targets.flat_map do |pod_target|
495
- pod_target.test_specs.flat_map do |test_spec|
496
- pod_target.recursive_test_dependent_targets(test_spec)
511
+ def group_pod_targets_by_target_definition(pod_targets, resolver_specs_by_target)
512
+ pod_targets_by_target_definition = Hash.new { |h, td| h[td] = [] }
513
+ pod_targets.each do |pod_target|
514
+ pod_target.target_definitions.each do |td|
515
+ pod_targets_by_target_definition[td] << pod_target
497
516
  end
498
517
  end
499
- app_dependent_targets = aggregate_target_pod_targets.flat_map do |pod_target|
500
- pod_target.app_specs.flat_map do |app_spec|
501
- pod_target.recursive_app_dependent_targets(app_spec)
502
- end
518
+ resolver_specs_by_target.each do |td, resolver_specs|
519
+ specs_by_pod_name = resolver_specs.group_by { |s| s.root.name }
520
+ specs_by_pod_name.reject! { |_, specs| specs.all?(&:used_by_non_library_targets_only?) }
521
+ pod_targets_by_target_definition[td].keep_if { |pod_target| specs_by_pod_name.key?(pod_target.pod_name) }
503
522
  end
504
- (aggregate_target_pod_targets + test_dependent_targets + app_dependent_targets).uniq
523
+
524
+ pod_targets_by_target_definition
505
525
  end
506
526
 
507
527
  # Returns a filtered list of pod targets that should or should not be part of the target definition. Pod targets
@@ -510,11 +530,8 @@ module Pod
510
530
  # @param [TargetDefinition] target_definition
511
531
  # the target definition to use as the base for filtering
512
532
  #
513
- # @param [Array<PodTarget>] pod_targets
514
- # the array of pod targets to check against
515
- #
516
- # @param [Hash{Podfile::TargetDefinition => Array<ResolvedSpecification>}] resolver_specs_by_target
517
- # the resolved specifications grouped by target.
533
+ # @param [Hash{Podfile::TargetDefinition => Array<PodTarget>}] pod_targets_by_target_definition
534
+ # the pod targets grouped by target.
518
535
  #
519
536
  # @param [Array<String>] build_configurations
520
537
  # The list of all build configurations the targets will be built for.
@@ -522,16 +539,11 @@ module Pod
522
539
  # @return [Hash<String => Array<PodTarget>>]
523
540
  # the filtered list of pod targets, grouped by build configuration.
524
541
  #
525
- def filter_pod_targets_for_target_definition(target_definition, pod_targets, resolver_specs_by_target, build_configurations)
542
+ def filter_pod_targets_for_target_definition(target_definition, pod_targets_by_target_definition, build_configurations)
526
543
  pod_targets_by_build_config = Hash.new([].freeze)
527
544
  build_configurations.each { |config| pod_targets_by_build_config[config] = [] }
528
545
 
529
- pod_targets.each do |pod_target|
530
- next unless pod_target.target_definitions.include?(target_definition)
531
- next unless resolver_specs_by_target[target_definition].any? do |resolver_spec|
532
- !resolver_spec.used_by_non_library_targets_only? && pod_target.specs.include?(resolver_spec.spec)
533
- end
534
-
546
+ pod_targets_by_target_definition[target_definition].each do |pod_target|
535
547
  pod_name = pod_target.pod_name
536
548
 
537
549
  dependencies = @podfile_dependency_cache.target_definition_dependencies(target_definition).select do |dependency|
@@ -593,33 +605,17 @@ module Pod
593
605
  end
594
606
 
595
607
  pod_targets = distinct_targets.flat_map do |_root, target_definitions_by_variant|
608
+ target_definitions_by_variant.each_value do |target_definitions|
609
+ target_definitions.reject!(&:abstract?) unless target_definitions.all?(&:abstract?)
610
+ end
596
611
  suffixes = PodVariantSet.new(target_definitions_by_variant.keys).scope_suffixes
597
612
  target_definitions_by_variant.map do |variant, target_definitions|
598
613
  generate_pod_target(target_definitions, target_inspections, variant.specs + variant.test_specs + variant.app_specs, :build_type => variant.build_type, :scope_suffix => suffixes[variant])
599
614
  end
600
615
  end
601
616
 
602
- pod_targets_by_name = pod_targets.group_by(&:pod_name).each_with_object({}) do |(name, values), hash|
603
- # Sort the target by the number of activated subspecs, so that
604
- # we prefer a minimal target as transitive dependency.
605
- hash[name] = values.sort_by { |pt| pt.specs.count }
606
- end
607
617
  all_specs = resolver_specs_by_target.values.flatten.map(&:spec).uniq.group_by(&:name)
608
- pod_targets.each do |target|
609
- dependencies = dependencies_for_specs(target.library_specs.to_set, target.platform, all_specs.dup).group_by(&:root)
610
- target.dependent_targets = filter_dependencies(dependencies, pod_targets_by_name, target)
611
- target.test_dependent_targets_by_spec_name = target.test_specs.each_with_object({}) do |test_spec, hash|
612
- test_dependencies = dependencies_for_specs([test_spec], target.platform, all_specs).group_by(&:root)
613
- test_dependencies.delete_if { |k| dependencies.key? k }
614
- hash[test_spec.name] = filter_dependencies(test_dependencies, pod_targets_by_name, target)
615
- end
616
-
617
- target.app_dependent_targets_by_spec_name = target.app_specs.each_with_object({}) do |app_spec, hash|
618
- app_dependencies = dependencies_for_specs([app_spec], target.platform, all_specs).group_by(&:root)
619
- app_dependencies.delete_if { |k| dependencies.key? k }
620
- hash[app_spec.name] = filter_dependencies(app_dependencies, pod_targets_by_name, target)
621
- end
622
- end
618
+ compute_pod_target_dependencies(pod_targets, all_specs)
623
619
  else
624
620
  dedupe_cache = {}
625
621
  resolver_specs_by_target.flat_map do |target_definition, specs|
@@ -629,21 +625,48 @@ module Pod
629
625
  generate_pod_target([target_definition], target_inspections, pod_specs.map(&:spec), :build_type => target_type).scoped(dedupe_cache)
630
626
  end
631
627
 
632
- pod_targets.each do |target|
633
- all_specs = specs.map(&:spec).group_by(&:name)
634
- dependencies = dependencies_for_specs(target.library_specs.to_set, target.platform, all_specs.dup).group_by(&:root)
635
- target.dependent_targets = pod_targets.reject { |t| dependencies[t.root_spec].nil? }
636
- target.test_dependent_targets_by_spec_name = target.test_specs.each_with_object({}) do |test_spec, hash|
637
- test_dependencies = dependencies_for_specs(target.test_specs.to_set, target.platform, all_specs.dup).group_by(&:root)
638
- test_dependencies.delete_if { |k| dependencies.key? k }
639
- hash[test_spec.name] = pod_targets.reject { |t| test_dependencies[t.root_spec].nil? }
640
- end
641
- target.app_dependent_targets_by_spec_name = target.app_specs.each_with_object({}) do |app_spec, hash|
642
- app_dependencies = dependencies_for_specs(target.app_specs.to_set, target.platform, all_specs.dup).group_by(&:root)
643
- app_dependencies.delete_if { |k| dependencies.key? k }
644
- hash[app_spec.name] = pod_targets.reject { |t| app_dependencies[t.root_spec].nil? }
645
- end
646
- end
628
+ compute_pod_target_dependencies(pod_targets, specs.map(&:spec).group_by(&:name))
629
+ end
630
+ end
631
+ end
632
+
633
+ # Compute the dependencies for the set of pod targets.
634
+ #
635
+ # @param [Array<PodTarget>] pod_targets
636
+ # pod targets.
637
+ #
638
+ # @param [Hash{String => Array<Specification>}] all_specs
639
+ # specifications grouped by name.
640
+ #
641
+ # @return [Array<PodTarget>]
642
+ #
643
+ def compute_pod_target_dependencies(pod_targets, all_specs)
644
+ pod_targets_by_name = pod_targets.group_by(&:pod_name).each_with_object({}) do |(name, values), hash|
645
+ # Sort the target by the number of activated subspecs, so that
646
+ # we prefer a minimal target as transitive dependency.
647
+ hash[name] = values.sort_by { |pt| pt.specs.count }
648
+ end
649
+
650
+ pod_targets.each do |target|
651
+ dependencies = dependencies_for_specs(target.library_specs.to_set, target.platform, all_specs).group_by(&:root)
652
+ target.dependent_targets = filter_dependencies(dependencies, pod_targets_by_name, target)
653
+ target.test_dependent_targets_by_spec_name = target.test_specs.each_with_object({}) do |test_spec, hash|
654
+ test_dependencies = dependencies_for_specs([test_spec], target.platform, all_specs).group_by(&:root)
655
+ test_dependencies.delete_if { |k, _| dependencies.key? k }
656
+ hash[test_spec.name] = filter_dependencies(test_dependencies, pod_targets_by_name, target)
657
+ end
658
+
659
+ target.app_dependent_targets_by_spec_name = target.app_specs.each_with_object({}) do |app_spec, hash|
660
+ app_dependencies = dependencies_for_specs([app_spec], target.platform, all_specs).group_by(&:root)
661
+ app_dependencies.delete_if { |k, _| dependencies.key? k }
662
+ hash[app_spec.name] = filter_dependencies(app_dependencies, pod_targets_by_name, target)
663
+ end
664
+
665
+ target.test_app_hosts_by_spec_name = target.test_specs.each_with_object({}) do |test_spec, hash|
666
+ next unless app_host_name = test_spec.consumer(target.platform).app_host_name
667
+ app_host_spec = pod_targets_by_name[Specification.root_name(app_host_name)].flat_map(&:app_specs).find { |pt| pt.name == app_host_name }
668
+ app_host_dependencies = { app_host_spec.root => [app_host_spec] }
669
+ hash[test_spec.name] = [app_host_spec, filter_dependencies(app_host_dependencies, pod_targets_by_name, target).first]
647
670
  end
648
671
  end
649
672
  end
@@ -683,6 +706,13 @@ module Pod
683
706
  specs.each do |s|
684
707
  s.dependencies(platform).each do |dep|
685
708
  all_specs[dep.name].each do |spec|
709
+ if spec.non_library_specification?
710
+ if s.test_specification? && spec.name == s.consumer(platform).app_host_name && spec.app_specification?
711
+ # This needs to be handled separately, since we _don't_ want to treat this as a "normal" dependency
712
+ next
713
+ end
714
+ raise Informative, "#{s} depends upon `#{spec}`, which is a `#{spec.spec_type}` spec."
715
+ end
686
716
  dependent_specs << spec
687
717
  end
688
718
  end
@@ -708,10 +738,10 @@ module Pod
708
738
  # @return [PodTarget]
709
739
  #
710
740
  def generate_pod_target(target_definitions, target_inspections, specs, scope_suffix: nil, build_type: nil)
711
- object_version = target_inspections.values.map { |ti| ti.project.object_version }.min
741
+ target_inspections = target_inspections.select { |t, _| target_definitions.include?(t) }.values
742
+ object_version = target_inspections.map { |ti| ti.project.object_version }.min
712
743
  target_requires_64_bit = target_definitions.all? { |td| Analyzer.requires_64_bit_archs?(td.platform, object_version) }
713
- if installation_options.integrate_targets?
714
- target_inspections = target_inspections.select { |t, _| target_definitions.include?(t) }.values
744
+ if !target_inspections.empty?
715
745
  user_build_configurations = target_inspections.map(&:build_configurations).reduce({}, &:merge)
716
746
  archs = if target_requires_64_bit
717
747
  ['$(ARCHS_STANDARD_64_BIT)']
@@ -719,7 +749,7 @@ module Pod
719
749
  target_inspections.flat_map(&:archs).compact.uniq.sort
720
750
  end
721
751
  else
722
- user_build_configurations = {}
752
+ user_build_configurations = Target::DEFAULT_BUILD_CONFIGURATIONS
723
753
  archs = target_requires_64_bit ? ['$(ARCHS_STANDARD_64_BIT)'] : []
724
754
  end
725
755
  host_requires_frameworks = target_definitions.any?(&:uses_frameworks?)
@@ -748,7 +778,11 @@ module Pod
748
778
  end
749
779
  end
750
780
 
751
- # Calculates and returns the platform to use for the given list of specs and target definitions.
781
+ # Calculates and returns the platform to use for the given list specs and target definitions.
782
+ #
783
+ # @note The platform is only determined by all library specs and ignores non library ones. Subspecs are always
784
+ # integrated in the same target as the root spec therefore the max deployment target is always returned
785
+ # across the specs passed.
752
786
  #
753
787
  # @param [Array<Specification>] specs
754
788
  # the specs to inspect and calculate the platform for.
@@ -762,10 +796,11 @@ module Pod
762
796
  # @return [Platform]
763
797
  #
764
798
  def determine_platform(specs, target_definitions, host_requires_frameworks)
799
+ library_specs = specs.select(&:library_specification?)
765
800
  platform_name = target_definitions.first.platform.name
766
801
  default = Podfile::TargetDefinition::PLATFORM_DEFAULTS[platform_name]
767
- deployment_target = specs.map do |spec|
768
- Version.new(spec.deployment_target(platform_name) || default)
802
+ deployment_target = library_specs.map do |library_spec|
803
+ Version.new(library_spec.deployment_target(platform_name) || default)
769
804
  end.max
770
805
  if platform_name == :ios && host_requires_frameworks
771
806
  minimum = Version.new('8.0')
@@ -935,7 +970,7 @@ module Pod
935
970
 
936
971
  resolver_specs_by_target = nil
937
972
  UI.section "Resolving dependencies of #{UI.path(podfile.defined_in_file) || 'Podfile'}" do
938
- resolver = Pod::Resolver.new(sandbox, podfile, locked_dependencies, sources, @specs_updated)
973
+ resolver = Pod::Resolver.new(sandbox, podfile, locked_dependencies, sources, @specs_updated, :sources_manager => sources_manager)
939
974
  resolver_specs_by_target = resolver.resolve
940
975
  resolver_specs_by_target.values.flatten(1).map(&:spec).each(&:validate_cocoapods_version)
941
976
  end
@@ -105,7 +105,7 @@ module Pod
105
105
  target = native_targets.find { |t| t.name == target_definition.name.to_s }
106
106
  unless target
107
107
  found = native_targets.map { |t| "`#{t.name}`" }.to_sentence
108
- raise Informative, "Unable to find a target named `#{target_definition.name}`, did find #{found}."
108
+ raise Informative, "Unable to find a target named `#{target_definition.name}` in project `#{Pathname(user_project.path).basename}`, did find #{found}."
109
109
  end
110
110
  [target]
111
111
  end
@@ -156,7 +156,7 @@ module Pod
156
156
  "Unable to determine the platform for the `#{target_definition.name}` target."
157
157
  end
158
158
 
159
- UI.warn "Automatically assigning platform `#{name}` with version `#{deployment_target}` " \
159
+ UI.warn "Automatically assigning platform `#{Platform.string_name(name)}` with version `#{deployment_target}` " \
160
160
  "on target `#{target_definition.name}` because no platform was specified. " \
161
161
  "Please specify a platform for this target in your Podfile. See `#{PLATFORM_INFO_URL}`."
162
162
 
@@ -218,14 +218,12 @@ module Pod
218
218
  #
219
219
  def compute_swift_version_from_targets(targets)
220
220
  versions_to_targets = targets.inject({}) do |memo, target|
221
- # User project may have an xcconfig that specifies the `SWIFT_VERSION`. We first check if that is true and
222
- # that the xcconfig file actually exists. After the first integration the xcconfig set is most probably
221
+ # User project may have an xcconfig that specifies the `SWIFT_VERSION`.
222
+ # Xcodeproj handles that xcconfig either not being set or the file not being present on disk.
223
+ # After the first integration the xcconfig set is most probably
223
224
  # the one that was generated from CocoaPods. See https://github.com/CocoaPods/CocoaPods/issues/7731 for
224
225
  # more details.
225
- resolve_against_xcconfig = target.build_configuration_list.build_configurations.all? do |bc|
226
- !bc.base_configuration_reference.nil? && File.exist?(bc.base_configuration_reference.real_path)
227
- end
228
- versions = target.resolved_build_setting('SWIFT_VERSION', resolve_against_xcconfig).values
226
+ versions = target.resolved_build_setting('SWIFT_VERSION', true).values
229
227
  versions.each do |version|
230
228
  memo[version] = [] if memo[version].nil?
231
229
  memo[version] << target.name unless memo[version].include? target.name