cocoapods 1.7.5 → 1.8.0.beta.1

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