cocoapods 1.9.1 → 1.10.2

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 (54) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +292 -5
  3. data/README.md +2 -1
  4. data/lib/cocoapods/command/lib/lint.rb +12 -3
  5. data/lib/cocoapods/command/repo/push.rb +1 -1
  6. data/lib/cocoapods/command/repo/update.rb +11 -0
  7. data/lib/cocoapods/command/spec/lint.rb +12 -3
  8. data/lib/cocoapods/command.rb +12 -2
  9. data/lib/cocoapods/config.rb +17 -0
  10. data/lib/cocoapods/downloader/cache.rb +2 -2
  11. data/lib/cocoapods/gem_version.rb +1 -1
  12. data/lib/cocoapods/generator/app_target_helper.rb +10 -2
  13. data/lib/cocoapods/generator/copy_dsyms_script.rb +56 -0
  14. data/lib/cocoapods/generator/copy_resources_script.rb +2 -14
  15. data/lib/cocoapods/generator/copy_xcframework_script.rb +245 -0
  16. data/lib/cocoapods/generator/embed_frameworks_script.rb +125 -212
  17. data/lib/cocoapods/generator/script_phase_constants.rb +99 -0
  18. data/lib/cocoapods/installer/analyzer/target_inspection_result.rb +1 -1
  19. data/lib/cocoapods/installer/analyzer.rb +17 -8
  20. data/lib/cocoapods/installer/base_install_hooks_context.rb +135 -0
  21. data/lib/cocoapods/installer/installation_options.rb +5 -0
  22. data/lib/cocoapods/installer/pod_source_installer.rb +2 -1
  23. data/lib/cocoapods/installer/post_install_hooks_context.rb +1 -127
  24. data/lib/cocoapods/installer/post_integrate_hooks_context.rb +9 -0
  25. data/lib/cocoapods/installer/project_cache/project_metadata_cache.rb +4 -0
  26. data/lib/cocoapods/installer/sandbox_dir_cleaner.rb +2 -1
  27. data/lib/cocoapods/installer/user_project_integrator/target_integrator.rb +132 -111
  28. data/lib/cocoapods/installer/xcode/pods_project_generator/aggregate_target_installer.rb +13 -27
  29. data/lib/cocoapods/installer/xcode/pods_project_generator/app_host_installer.rb +5 -1
  30. data/lib/cocoapods/installer/xcode/pods_project_generator/file_references_installer.rb +2 -1
  31. data/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_dependency_installer.rb +8 -6
  32. data/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_installer.rb +187 -61
  33. data/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_integrator.rb +61 -30
  34. data/lib/cocoapods/installer/xcode/pods_project_generator/project_generator.rb +3 -2
  35. data/lib/cocoapods/installer/xcode/pods_project_generator/target_installation_result.rb +5 -7
  36. data/lib/cocoapods/installer/xcode/pods_project_generator.rb +45 -6
  37. data/lib/cocoapods/installer/xcode/pods_project_generator_result.rb +19 -0
  38. data/lib/cocoapods/installer/xcode/target_validator.rb +1 -1
  39. data/lib/cocoapods/installer.rb +70 -3
  40. data/lib/cocoapods/sandbox/file_accessor.rb +10 -1
  41. data/lib/cocoapods/sources_manager.rb +2 -1
  42. data/lib/cocoapods/target/aggregate_target.rb +35 -0
  43. data/lib/cocoapods/target/build_settings.rb +94 -18
  44. data/lib/cocoapods/target/pod_target.rb +85 -11
  45. data/lib/cocoapods/target.rb +44 -2
  46. data/lib/cocoapods/user_interface/error_report.rb +1 -1
  47. data/lib/cocoapods/user_interface/inspector_reporter.rb +3 -10
  48. data/lib/cocoapods/validator.rb +38 -12
  49. data/lib/cocoapods/xcode/framework_paths.rb +1 -1
  50. data/lib/cocoapods/xcode/xcframework/xcframework_slice.rb +91 -4
  51. data/lib/cocoapods/xcode/xcframework.rb +17 -4
  52. data/lib/cocoapods.rb +3 -1
  53. metadata +31 -53
  54. data/lib/cocoapods/generator/prepare_artifacts_script.rb +0 -257
@@ -1,3 +1,5 @@
1
+ require 'active_support/core_ext/array'
2
+ require 'active_support/core_ext/string/inflections'
1
3
  require 'cocoapods/xcode'
2
4
 
3
5
  module Pod
@@ -14,11 +16,15 @@ module Pod
14
16
  #
15
17
  attr_reader :umbrella_header_paths
16
18
 
19
+ # @return [PodTarget] @see TargetInstaller#target
20
+ #
21
+ attr_reader :target
22
+
17
23
  # Initialize a new instance
18
24
  #
19
25
  # @param [Sandbox] sandbox @see TargetInstaller#sandbox
20
26
  # @param [Pod::Project] project @see TargetInstaller#project
21
- # @param [Target] target @see TargetInstaller#target
27
+ # @param [PodTarget] target @see TargetInstaller#target
22
28
  # @param [Array<Pathname>] umbrella_header_paths @see #umbrella_header_paths
23
29
  #
24
30
  def initialize(sandbox, project, target, umbrella_header_paths = nil)
@@ -42,6 +48,8 @@ module Pod
42
48
  # PBXAggregateTarget that will be used to wire up dependencies later.
43
49
  native_target = add_placeholder_target
44
50
  resource_bundle_targets = add_resources_bundle_targets(library_file_accessors).values.flatten
51
+ create_copy_dsyms_script
52
+ create_copy_xcframeworks_script unless target.xcframeworks.values.all?(&:empty?)
45
53
  create_xcconfig_file(native_target, resource_bundle_targets)
46
54
  return TargetInstallationResult.new(target, native_target, resource_bundle_targets)
47
55
  end
@@ -57,8 +65,10 @@ module Pod
57
65
  app_resource_bundle_targets = add_resources_bundle_targets(app_file_accessors)
58
66
 
59
67
  add_files_to_build_phases(native_target, test_native_targets, app_native_targets)
60
- validate_targets_contain_sources(test_native_targets + app_native_targets + [native_target])
61
- validate_xcframeworks_no_mixed_linkage
68
+ validate_targets_contain_sources(test_native_targets + app_native_targets.values + [native_target])
69
+ validate_xcframeworks
70
+
71
+ create_copy_xcframeworks_script unless target.xcframeworks.values.all?(&:empty?)
62
72
 
63
73
  create_xcconfig_file(native_target, resource_bundle_targets)
64
74
  create_test_xcconfig_files(test_native_targets, test_resource_bundle_targets)
@@ -120,12 +130,13 @@ module Pod
120
130
  target.app_specs.each do |app_spec|
121
131
  path = target.prefix_header_path_for_spec(app_spec)
122
132
  app_spec_consumer = app_spec.consumer(target.platform)
123
- app_native_target = app_native_target_from_spec(app_spec_consumer.spec, app_native_targets)
133
+ app_native_target = app_native_targets[app_spec_consumer.spec]
124
134
  create_prefix_header(path, app_file_accessors, target.platform, app_native_target, project_directory)
125
135
  add_file_to_support_group(path)
126
136
  end
127
137
  end
128
138
  create_dummy_source(native_target)
139
+ create_copy_dsyms_script
129
140
  clean_support_files_temp_dir
130
141
  TargetInstallationResult.new(target, native_target, resource_bundle_targets,
131
142
  test_native_targets, test_resource_bundle_targets, test_app_host_targets,
@@ -177,7 +188,7 @@ module Pod
177
188
  # @return [Boolean] Whether the target should build a pch file.
178
189
  #
179
190
  def skip_pch?(specs)
180
- specs.any? { |spec| spec.prefix_header_file.is_a?(FalseClass) }
191
+ specs.any? { |spec| spec.root.prefix_header_file.is_a?(FalseClass) }
181
192
  end
182
193
 
183
194
  # True if info.plist generation should be skipped
@@ -216,9 +227,30 @@ module Pod
216
227
  settings['SWIFT_VERSION'] = target.swift_version
217
228
  end
218
229
 
230
+ if info_plist_bundle_id
231
+ settings['PRODUCT_BUNDLE_IDENTIFIER'] = info_plist_bundle_id
232
+ end
233
+
219
234
  settings
220
235
  end
221
236
 
237
+ # @return [String] Bundle Identifier found in the custom Info.plist entries
238
+ #
239
+ def info_plist_bundle_id
240
+ return @plist_bundle_id if defined?(@plist_bundle_id)
241
+ unless target.info_plist_entries.nil?
242
+ @plist_bundle_id = target.info_plist_entries['CFBundleIdentifier']
243
+ unless @plist_bundle_id.nil?
244
+ message = "The `#{target.name}` target " \
245
+ "sets a Bundle Identifier of `#{@plist_bundle_id}` in it's info.plist file. " \
246
+ 'The Bundle Identifier should be set using pod_target_xcconfig: ' \
247
+ "s.pod_target_xcconfig = { 'PRODUCT_BUNDLE_IDENTIFIER': '#{@plist_bundle_id}' }`."
248
+ UI.warn message
249
+ end
250
+ @plist_bundle_id
251
+ end
252
+ end
253
+
222
254
  # Filters the given resource file references discarding empty paths which are
223
255
  # added by their parent directory. This will also include references to the parent [PBXVariantGroup]
224
256
  # for all resources underneath it.
@@ -285,7 +317,7 @@ module Pod
285
317
  when :test
286
318
  test_native_target_from_spec(consumer.spec, test_native_targets)
287
319
  when :app
288
- app_native_target_from_spec(consumer.spec, app_native_targets)
320
+ app_native_targets[consumer.spec]
289
321
  end
290
322
 
291
323
  headers = file_accessor.headers
@@ -322,6 +354,11 @@ module Pod
322
354
 
323
355
  filter_resource_file_references(file_accessor.resources.flatten) do |compile_phase_refs, resource_phase_refs|
324
356
  native_target.add_file_references(compile_phase_refs, nil)
357
+
358
+ if target.build_as_static_framework? && consumer.spec.library_specification?
359
+ resource_phase_refs = resource_phase_refs.select { |ref| Target.resource_extension_compilable?(File.extname(ref.path)) }
360
+ end
361
+
325
362
  native_target.add_resources(resource_phase_refs)
326
363
  end
327
364
  end
@@ -371,13 +408,16 @@ module Pod
371
408
  configuration.build_settings['CODE_SIGNING_ALLOWED'] = 'YES'
372
409
  end
373
410
  # For macOS we do not code sign the XCTest bundle because we do not code sign the frameworks either.
374
- configuration.build_settings['CODE_SIGN_IDENTITY'] = '' if target.platform == :osx
411
+ if target.platform == :osx
412
+ configuration.build_settings['CODE_SIGN_IDENTITY'] = ''
413
+ elsif target.platform == :ios
414
+ configuration.build_settings['CODE_SIGN_IDENTITY'] = 'iPhone Developer'
415
+ end
375
416
  end
376
417
 
377
418
  remove_pod_target_xcconfig_overrides_from_target(target.test_spec_build_settings_by_config[test_spec.name], test_native_target)
378
419
 
379
420
  # Test native targets also need frameworks and resources to be copied over to their xctest bundle.
380
- create_test_target_prepare_artifacts_script(test_spec)
381
421
  create_test_target_embed_frameworks_script(test_spec)
382
422
  create_test_target_copy_resources_script(test_spec)
383
423
 
@@ -411,10 +451,10 @@ module Pod
411
451
  # Adds the app targets for the library to the Pods project with the
412
452
  # appropriate build configurations.
413
453
  #
414
- # @return [Array<PBXNativeTarget>] the app native targets created.
454
+ # @return [Hash{Specification => PBXNativeTarget}] the app native targets created, keyed by their app spec
415
455
  #
416
456
  def add_app_targets
417
- target.app_specs.map do |app_spec|
457
+ target.app_specs.each_with_object({}) do |app_spec, hash|
418
458
  spec_consumer = app_spec.consumer(target.platform)
419
459
  spec_name = app_spec.parent.name
420
460
  subspec_name = target.subspec_label(app_spec)
@@ -473,7 +513,7 @@ module Pod
473
513
  create_app_target_copy_resources_script(app_spec)
474
514
  add_resources_to_target(resources, app_native_target)
475
515
 
476
- app_native_target
516
+ hash[app_spec] = app_native_target
477
517
  end
478
518
  end
479
519
 
@@ -649,33 +689,6 @@ module Pod
649
689
  end
650
690
  end
651
691
 
652
- # Creates a script that prepares artifacts for the test target.
653
- #
654
- # @param [Specification] test_spec
655
- # The test spec to create the script for.
656
- #
657
- # @return [void]
658
- #
659
- def create_test_target_prepare_artifacts_script(test_spec)
660
- path = target.prepare_artifacts_script_path_for_spec(test_spec)
661
- host_target_spec_names = target.app_host_dependent_targets_for_spec(test_spec).flat_map do |pt|
662
- pt.specs.map(&:name)
663
- end.uniq
664
- frameworks_by_config = target.user_build_configurations.each_with_object({}) do |(config_name, config), paths_by_config|
665
- paths_by_config[config_name] = target.dependent_targets_for_test_spec(test_spec, :configuration => config).flat_map do |pod_target|
666
- spec_paths_to_include = pod_target.library_specs.map(&:name)
667
- spec_paths_to_include -= host_target_spec_names
668
- spec_paths_to_include << test_spec.name if pod_target == target
669
- pod_target.xcframeworks.values_at(*spec_paths_to_include).flatten.compact.uniq
670
- end
671
- end
672
- unless frameworks_by_config.each_value.all?(&:empty?)
673
- generator = Generator::PrepareArtifactsScript.new(frameworks_by_config, target.sandbox.root, target.platform)
674
- update_changed_file(generator, path)
675
- add_file_to_support_group(path)
676
- end
677
- end
678
-
679
692
  # Creates a script that embeds the frameworks to the bundle of the test target.
680
693
  #
681
694
  # @param [Specification] test_spec
@@ -696,8 +709,16 @@ module Pod
696
709
  pod_target.framework_paths.values_at(*spec_paths_to_include).flatten.compact.uniq
697
710
  end
698
711
  end
699
- unless framework_paths_by_config.each_value.all?(&:empty?)
700
- generator = Generator::EmbedFrameworksScript.new(framework_paths_by_config)
712
+ xcframeworks_by_config = target.user_build_configurations.each_with_object({}) do |(config_name, config), paths_by_config|
713
+ paths_by_config[config_name] = target.dependent_targets_for_test_spec(test_spec, :configuration => config).flat_map do |pod_target|
714
+ spec_paths_to_include = pod_target.library_specs.map(&:name)
715
+ spec_paths_to_include -= host_target_spec_names
716
+ spec_paths_to_include << test_spec.name if pod_target == target
717
+ pod_target.xcframeworks.values_at(*spec_paths_to_include).flatten.compact.uniq
718
+ end
719
+ end
720
+ unless framework_paths_by_config.each_value.all?(&:empty?) && xcframeworks_by_config.each_value.all?(&:empty?)
721
+ generator = Generator::EmbedFrameworksScript.new(framework_paths_by_config, xcframeworks_by_config)
701
722
  update_changed_file(generator, path)
702
723
  add_file_to_support_group(path)
703
724
  end
@@ -705,8 +726,8 @@ module Pod
705
726
 
706
727
  # Generates the contents of the xcconfig file used for each app target type and saves it to disk.
707
728
  #
708
- # @param [Array<PBXNativeTarget>] app_native_targets
709
- # the app native target to link the xcconfig file into.
729
+ # @param [Hash{Specification => PBXNativeTarget}] app_native_targets
730
+ # the app native targets to link the xcconfig file into.
710
731
  #
711
732
  # @param [Hash{String=>Array<PBXNativeTarget>}] app_resource_bundle_targets
712
733
  # the additional app resource bundle targets to link the xcconfig file into.
@@ -716,7 +737,7 @@ module Pod
716
737
  def create_app_xcconfig_files(app_native_targets, app_resource_bundle_targets)
717
738
  target.app_specs.each do |app_spec|
718
739
  spec_consumer = app_spec.consumer(target.platform)
719
- app_native_target = app_native_target_from_spec(spec_consumer.spec, app_native_targets)
740
+ app_native_target = app_native_targets[spec_consumer.spec]
720
741
 
721
742
  target.user_config_names_by_config_type.each do |config, names|
722
743
  path = target.xcconfig_path("#{target.subspec_label(app_spec)}.#{config}")
@@ -765,20 +786,57 @@ module Pod
765
786
  def create_app_target_embed_frameworks_script(app_spec)
766
787
  path = target.embed_frameworks_script_path_for_spec(app_spec)
767
788
  framework_paths_by_config = target.user_build_configurations.each_with_object({}) do |(config_name, config), paths_by_config|
768
- pod_targets = target.dependent_targets_for_app_spec(app_spec, :configuration => config)
769
- paths_by_config[config_name] = pod_targets.flat_map do |pod_target|
789
+ paths_by_config[config_name] = target.dependent_targets_for_app_spec(app_spec, :configuration => config).flat_map do |pod_target|
770
790
  spec_paths_to_include = pod_target.library_specs.map(&:name)
771
791
  spec_paths_to_include << app_spec.name if pod_target == target
772
792
  pod_target.framework_paths.values_at(*spec_paths_to_include).flatten.compact.uniq
773
793
  end
774
794
  end
775
- unless framework_paths_by_config.each_value.all?(&:empty?)
776
- generator = Generator::EmbedFrameworksScript.new(framework_paths_by_config)
795
+ xcframeworks_by_config = target.user_build_configurations.each_with_object({}) do |(config_name, config), paths_by_config|
796
+ paths_by_config[config_name] = target.dependent_targets_for_app_spec(app_spec, :configuration => config).flat_map do |pod_target|
797
+ spec_paths_to_include = pod_target.library_specs.map(&:name)
798
+ spec_paths_to_include << app_spec.name if pod_target == target
799
+ pod_target.xcframeworks.values_at(*spec_paths_to_include).flatten.compact.uniq
800
+ end
801
+ end
802
+
803
+ unless framework_paths_by_config.each_value.all?(&:empty?) && xcframeworks_by_config.each_value.all?(&:empty?)
804
+ generator = Generator::EmbedFrameworksScript.new(framework_paths_by_config, xcframeworks_by_config)
777
805
  update_changed_file(generator, path)
778
806
  add_file_to_support_group(path)
779
807
  end
780
808
  end
781
809
 
810
+ # Creates a script that copies and strips vendored dSYMs and bcsymbolmaps.
811
+ #
812
+ # @return [void]
813
+ #
814
+ def create_copy_dsyms_script
815
+ dsym_paths = PodTargetInstaller.dsym_paths(target)
816
+ bcsymbolmap_paths = PodTargetInstaller.bcsymbolmap_paths(target)
817
+ path = target.copy_dsyms_script_path
818
+ unless dsym_paths.empty? && bcsymbolmap_paths.empty?
819
+ generator = Generator::CopydSYMsScript.new(dsym_paths, bcsymbolmap_paths)
820
+ update_changed_file(generator, path)
821
+ add_file_to_support_group(path)
822
+ end
823
+ end
824
+
825
+ # Creates a script that copies the appropriate xcframework slice to the build dir.
826
+ #
827
+ # @note We can't use Xcode default link libraries phase, because
828
+ # we need to ensure that we only copy the frameworks which are
829
+ # relevant for the current build configuration.
830
+ #
831
+ # @return [void]
832
+ #
833
+ def create_copy_xcframeworks_script
834
+ path = target.copy_xcframeworks_script_path
835
+ generator = Generator::CopyXCFrameworksScript.new(target.xcframeworks.values.flatten, sandbox.root, target.platform)
836
+ update_changed_file(generator, path)
837
+ add_file_to_support_group(path)
838
+ end
839
+
782
840
  # Manually add `libswiftSwiftOnoneSupport.dylib` as it seems there is an issue with tests that do not include it for Debug configurations.
783
841
  # Possibly related to Swift module optimization.
784
842
  #
@@ -792,7 +850,7 @@ module Pod
792
850
  end
793
851
 
794
852
  # Creates a build phase which links the versioned header folders
795
- # of the OS X into the framework bundle's root root directory.
853
+ # of the OS X framework into the framework bundle's root directory.
796
854
  # This is only necessary because the way how headers are copied
797
855
  # via custom copy file build phases in combination with
798
856
  # header_mappings_dir interferes with xcodebuild's expectations
@@ -804,11 +862,16 @@ module Pod
804
862
  # @return [void]
805
863
  #
806
864
  def create_build_phase_to_symlink_header_folders(native_target)
807
- return unless target.platform.name == :osx && any_header_mapping_dirs?
865
+ # This is required on iOS for Catalyst, which uses macOS framework layouts
866
+ return unless (target.platform.name == :osx || target.platform.name == :ios) && any_header_mapping_dirs?
808
867
 
809
868
  build_phase = native_target.new_shell_script_build_phase('Create Symlinks to Header Folders')
810
869
  build_phase.shell_script = <<-eos.strip_heredoc
811
870
  cd "$CONFIGURATION_BUILD_DIR/$WRAPPER_NAME" || exit 1
871
+ if [ ! -d Versions ]; then
872
+ # Not a versioned framework, so no need to do anything
873
+ exit 0
874
+ fi
812
875
 
813
876
  public_path="${PUBLIC_HEADERS_FOLDER_PATH\#\$CONTENTS_FOLDER_PATH/}"
814
877
  if [ ! -f "$public_path" ]; then
@@ -943,9 +1006,18 @@ module Pod
943
1006
  end
944
1007
 
945
1008
  def project_file_references_array(files, file_type)
1009
+ error_message_for_missing_reference = lambda do |sf, target|
1010
+ "Unable to find #{file_type} ref for `#{sf.basename}` for target `#{target.name}`."
1011
+ end
946
1012
  files.map do |sf|
947
- project.reference_for_path(sf).tap do |ref|
948
- raise Informative, "Unable to find #{file_type} ref for `#{sf.basename}` for target `#{target.name}`." unless ref
1013
+ begin
1014
+ project.reference_for_path(sf).tap do |ref|
1015
+ raise Informative, error_message_for_missing_reference.call(sf, target) unless ref
1016
+ end
1017
+ rescue Errno::ENOENT
1018
+ # Normalize the error for Ruby < 2.7. Ruby 2.7 can crash on a different call of real path compared
1019
+ # to older versions. This ensures that the error message is consistent.
1020
+ raise Informative, error_message_for_missing_reference.call(sf, target)
949
1021
  end
950
1022
  end
951
1023
  end
@@ -1011,13 +1083,6 @@ module Pod
1011
1083
  end
1012
1084
  end
1013
1085
 
1014
- def app_native_target_from_spec(spec, app_native_targets)
1015
- app_target_label = target.app_target_label(spec)
1016
- app_native_targets.find do |app_native_target|
1017
- app_native_target.name == app_target_label
1018
- end
1019
- end
1020
-
1021
1086
  # Adds a placeholder native target for the library to the Pods project with the
1022
1087
  # appropriate build configurations.
1023
1088
  #
@@ -1086,19 +1151,80 @@ module Pod
1086
1151
  end
1087
1152
  end
1088
1153
 
1089
- # Raises if a vendored xcframework contains frameworks of mixed linkage
1154
+ # Raises if a vendored xcframework contains frameworks of mixed linkage or mixed packaging
1090
1155
  #
1091
- def validate_xcframeworks_no_mixed_linkage
1156
+ def validate_xcframeworks
1092
1157
  target.xcframeworks.each_value do |xcframeworks|
1093
1158
  xcframeworks.each do |xcframework|
1094
- dynamic_slices, static_slices = xcframework.slices.partition { |slice| Pod::Xcode::LinkageAnalyzer.dynamic_binary?(slice.path) }
1159
+ if xcframework.slices.empty?
1160
+ raise Informative, "Unable to install vendored xcframework `#{xcframework.name}` for Pod `#{target.label}` because it does not contain any binaries."
1161
+ end
1162
+ if xcframework.build_type.dynamic_library?
1163
+ raise Informative, <<-MSG.strip_heredoc
1164
+ Unable to install vendored xcframework `#{xcframework.name}` for Pod `#{target.label}` because it contains dynamic libraries which are not supported.
1165
+ Use dynamic frameworks for dynamic linking instead.
1166
+ MSG
1167
+ end
1168
+ if xcframework.build_type.static_library?
1169
+ binary_names = xcframework.slices.map { |slice| File.basename(slice.binary_path, File.extname(slice.binary_path)) }.uniq
1170
+ if binary_names.size > 1
1171
+ raise Informative, <<-MSG.strip_heredoc
1172
+ Unable to install vendored xcframework `#{xcframework.name}` for Pod `#{target.label}` because it contains static libraries
1173
+ with differing binary names: #{binary_names.to_sentence}.
1174
+ MSG
1175
+ end
1176
+ end
1177
+ dynamic_slices, static_slices = xcframework.slices.partition(&:dynamic?)
1095
1178
  if !dynamic_slices.empty? && !static_slices.empty?
1096
1179
  raise Informative, "Unable to install vendored xcframework `#{xcframework.name}` for Pod `#{target.label}`, because it contains both static and dynamic frameworks."
1097
1180
  end
1181
+ library_slices, framework_slices = xcframework.slices.partition(&:library?)
1182
+ if !library_slices.empty? && !framework_slices.empty?
1183
+ raise Informative, "Unable to install vendored xcframework `#{xcframework.name}` for Pod `#{target.label}`, because it contains both libraries and frameworks."
1184
+ end
1098
1185
  end
1099
1186
  end
1100
1187
  end
1188
+
1101
1189
  #-----------------------------------------------------------------------#
1190
+
1191
+ class << self
1192
+ # @param [PodTarget] target the target to be installed
1193
+ #
1194
+ # @return [Array<String>] the dSYM paths for the given target
1195
+ #
1196
+ def dsym_paths(target)
1197
+ dsym_paths = target.framework_paths.values.flatten.reject { |fmwk_path| fmwk_path.dsym_path.nil? }.map(&:dsym_path)
1198
+ dsym_paths.concat(target.xcframeworks.values.flatten.flat_map { |xcframework| xcframework_dsyms(xcframework.path) })
1199
+ dsym_paths
1200
+ end
1201
+
1202
+ # @param [PodTarget] target the target to be installed
1203
+ #
1204
+ # @return [Array<String>] the bcsymbolmap paths for the given target
1205
+ #
1206
+ def bcsymbolmap_paths(target)
1207
+ target.framework_paths.values.flatten.reject do |fmwk_path|
1208
+ fmwk_path.bcsymbolmap_paths.nil?
1209
+ end.flat_map(&:bcsymbolmap_paths)
1210
+ end
1211
+
1212
+ # @param [Pathname] xcframework_path
1213
+ # the base path of the .xcframework bundle
1214
+ #
1215
+ # @return [Array<Pathname>] all found .dSYM paths
1216
+ #
1217
+ def xcframework_dsyms(xcframework_path)
1218
+ basename = File.basename(xcframework_path, '.xcframework')
1219
+ dsym_basename = basename + '.dSYMs'
1220
+ path = xcframework_path.dirname + dsym_basename
1221
+ if File.directory?(path)
1222
+ Dir.glob(path + '*.dSYM')
1223
+ else
1224
+ []
1225
+ end
1226
+ end
1227
+ end
1102
1228
  end
1103
1229
  end
1104
1230
  end
@@ -32,11 +32,12 @@ module Pod
32
32
  def integrate!
33
33
  UI.section(integration_message) do
34
34
  target_installation_result.non_library_specs_by_native_target.each do |native_target, spec|
35
- add_prepare_artifacts_script_phase(native_target, spec)
36
35
  add_embed_frameworks_script_phase(native_target, spec)
37
36
  add_copy_resources_script_phase(native_target, spec)
38
37
  UserProjectIntegrator::TargetIntegrator.create_or_update_user_script_phases(script_phases_for_specs(spec), native_target)
39
38
  end
39
+ add_copy_dsyms_script_phase(target_installation_result.native_target)
40
+ add_copy_xcframeworks_script_phase(target_installation_result.native_target)
40
41
  UserProjectIntegrator::TargetIntegrator.create_or_update_user_script_phases(script_phases_for_specs(target.library_specs), target_installation_result.native_target)
41
42
  end
42
43
  end
@@ -138,15 +139,12 @@ module Pod
138
139
  input_file_list_path = target.embed_frameworks_script_input_files_path_for_spec(spec)
139
140
  input_file_list_relative_path = "${PODS_ROOT}/#{input_file_list_path.relative_path_from(target.sandbox.root)}"
140
141
  input_paths_key = UserProjectIntegrator::TargetIntegrator::XCFileListConfigKey.new(input_file_list_path, input_file_list_relative_path)
141
- input_paths = input_paths_by_config[input_paths_key] = [script_path]
142
- framework_paths.each do |path|
143
- input_paths.concat(path.all_paths)
144
- end
142
+ input_paths_by_config[input_paths_key] = [script_path] + UserProjectIntegrator::TargetIntegrator.embed_frameworks_input_paths(framework_paths, [])
145
143
 
146
144
  output_file_list_path = target.embed_frameworks_script_output_files_path_for_spec(spec)
147
145
  output_file_list_relative_path = "${PODS_ROOT}/#{output_file_list_path.relative_path_from(target.sandbox.root)}"
148
146
  output_paths_key = UserProjectIntegrator::TargetIntegrator::XCFileListConfigKey.new(output_file_list_path, output_file_list_relative_path)
149
- output_paths_by_config[output_paths_key] = UserProjectIntegrator::TargetIntegrator.framework_output_paths(framework_paths)
147
+ output_paths_by_config[output_paths_key] = UserProjectIntegrator::TargetIntegrator.embed_frameworks_output_paths(framework_paths, [])
150
148
  end
151
149
 
152
150
  if framework_paths.empty?
@@ -162,34 +160,18 @@ module Pod
162
160
  # @param [PBXNativeTarget] native_target
163
161
  # the native target for which to add the prepare artifacts script
164
162
  #
165
- # @param [Pod::Specification] spec
166
- # the specification to integrate
167
- #
168
163
  # @return [void]
169
164
  #
170
- def add_prepare_artifacts_script_phase(native_target, spec)
171
- script_path = "${PODS_ROOT}/#{target.prepare_artifacts_script_path_for_spec(spec).relative_path_from(target.sandbox.root)}"
165
+ def add_copy_xcframeworks_script_phase(native_target)
166
+ script_path = "${PODS_ROOT}/#{target.copy_xcframeworks_script_path.relative_path_from(target.sandbox.root)}"
172
167
 
173
168
  input_paths_by_config = {}
174
169
  output_paths_by_config = {}
175
170
 
176
- dependent_targets = if spec.test_specification?
177
- target.dependent_targets_for_test_spec(spec)
178
- else
179
- target.dependent_targets_for_app_spec(spec)
180
- end
181
- host_target_spec_names = target.app_host_dependent_targets_for_spec(spec).flat_map do |pt|
182
- pt.specs.map(&:name)
183
- end.uniq
184
- xcframeworks = dependent_targets.flat_map do |dependent_target|
185
- spec_paths_to_include = dependent_target.library_specs.map(&:name)
186
- spec_paths_to_include -= host_target_spec_names
187
- spec_paths_to_include << spec.name if dependent_target == target
188
- dependent_target.xcframeworks.values_at(*spec_paths_to_include).flatten.compact
189
- end.uniq
171
+ xcframeworks = target.xcframeworks.values.flatten
190
172
 
191
173
  if use_input_output_paths? && !xcframeworks.empty?
192
- input_file_list_path = target.prepare_artifacts_script_input_files_path_for_spec(spec)
174
+ input_file_list_path = target.copy_xcframeworks_script_input_files_path
193
175
  input_file_list_relative_path = "${PODS_ROOT}/#{input_file_list_path.relative_path_from(target.sandbox.root)}"
194
176
  input_paths_key = UserProjectIntegrator::TargetIntegrator::XCFileListConfigKey.new(input_file_list_path, input_file_list_relative_path)
195
177
  input_paths = input_paths_by_config[input_paths_key] = [script_path]
@@ -197,20 +179,69 @@ module Pod
197
179
  framework_paths = xcframeworks.map { |xcf| "${PODS_ROOT}/#{xcf.path.relative_path_from(target.sandbox.root)}" }
198
180
  input_paths.concat framework_paths
199
181
 
200
- output_file_list_path = target.prepare_artifacts_script_output_files_path_for_spec(spec)
182
+ output_file_list_path = target.copy_xcframeworks_script_output_files_path
201
183
  output_file_list_relative_path = "${PODS_ROOT}/#{output_file_list_path.relative_path_from(target.sandbox.root)}"
202
184
  output_paths_key = UserProjectIntegrator::TargetIntegrator::XCFileListConfigKey.new(output_file_list_path, output_file_list_relative_path)
203
- output_paths_by_config[output_paths_key] = [UserProjectIntegrator::TargetIntegrator::ARTIFACT_LIST_FILE]
185
+ output_paths_by_config[output_paths_key] = xcframeworks.map do |xcf|
186
+ "#{Target::BuildSettings::XCFRAMEWORKS_BUILD_DIR_VARIABLE}/#{xcf.name}"
187
+ end
204
188
  end
205
189
 
206
190
  if xcframeworks.empty?
207
- UserProjectIntegrator::TargetIntegrator.remove_prepare_artifacts_script_phase_from_target(native_target)
191
+ UserProjectIntegrator::TargetIntegrator.remove_copy_xcframeworks_script_phase_from_target(native_target)
208
192
  else
209
- UserProjectIntegrator::TargetIntegrator.create_or_update_prepare_artifacts_script_phase_to_target(
193
+ UserProjectIntegrator::TargetIntegrator.create_or_update_copy_xcframeworks_script_phase_to_target(
210
194
  native_target, script_path, input_paths_by_config, output_paths_by_config)
211
195
  end
212
196
  end
213
197
 
198
+ # Adds a script phase that copies and strips dSYMs that are part of this target. Note this only deals with
199
+ # vendored dSYMs.
200
+ #
201
+ # @param [PBXNativeTarget] native_target
202
+ # the native target for which to add the the copy dSYM files build phase.
203
+ #
204
+ # @return [void]
205
+ #
206
+ def add_copy_dsyms_script_phase(native_target)
207
+ script_path = "${PODS_ROOT}/#{target.copy_dsyms_script_path.relative_path_from(target.sandbox.root)}"
208
+ dsym_paths = PodTargetInstaller.dsym_paths(target)
209
+ bcsymbolmap_paths = PodTargetInstaller.bcsymbolmap_paths(target)
210
+
211
+ if dsym_paths.empty? && bcsymbolmap_paths.empty?
212
+ script_phase = native_target.shell_script_build_phases.find do |bp|
213
+ bp.name && bp.name.end_with?(UserProjectIntegrator::TargetIntegrator::COPY_DSYM_FILES_PHASE_NAME)
214
+ end
215
+ native_target.build_phases.delete(script_phase) if script_phase.present?
216
+ return
217
+ end
218
+
219
+ phase_name = UserProjectIntegrator::TargetIntegrator::BUILD_PHASE_PREFIX + UserProjectIntegrator::TargetIntegrator::COPY_DSYM_FILES_PHASE_NAME
220
+ phase = UserProjectIntegrator::TargetIntegrator.create_or_update_shell_script_build_phase(native_target, phase_name)
221
+ phase.shell_script = %("#{script_path}"\n)
222
+
223
+ input_paths_by_config = {}
224
+ output_paths_by_config = {}
225
+ if use_input_output_paths?
226
+ input_file_list_path = target.copy_dsyms_script_input_files_path
227
+ input_file_list_relative_path = "${PODS_ROOT}/#{input_file_list_path.relative_path_from(target.sandbox.root)}"
228
+ input_paths_key = UserProjectIntegrator::TargetIntegrator::XCFileListConfigKey.new(input_file_list_path, input_file_list_relative_path)
229
+ input_paths = input_paths_by_config[input_paths_key] = []
230
+ input_paths.concat([dsym_paths, *bcsymbolmap_paths].flatten.compact)
231
+
232
+ output_file_list_path = target.copy_dsyms_script_output_files_path
233
+ output_file_list_relative_path = "${PODS_ROOT}/#{output_file_list_path.relative_path_from(target.sandbox.root)}"
234
+ output_paths_key = UserProjectIntegrator::TargetIntegrator::XCFileListConfigKey.new(output_file_list_path, output_file_list_relative_path)
235
+ output_paths = output_paths_by_config[output_paths_key] = []
236
+
237
+ dsym_output_paths = dsym_paths.map { |dsym_path| "${DWARF_DSYM_FOLDER_PATH}/#{File.basename(dsym_path)}" }
238
+ bcsymbolmap_output_paths = bcsymbolmap_paths.map { |bcsymbolmap_path| "${DWARF_DSYM_FOLDER_PATH}/#{File.basename(bcsymbolmap_path)}" }
239
+ output_paths.concat([dsym_output_paths, *bcsymbolmap_output_paths].flatten.compact)
240
+ end
241
+
242
+ UserProjectIntegrator::TargetIntegrator.set_input_output_paths(phase, input_paths_by_config, output_paths_by_config)
243
+ end
244
+
214
245
  # @return [String] the message that should be displayed for the target
215
246
  # integration.
216
247
  #
@@ -30,7 +30,7 @@ module Pod
30
30
  #
31
31
  attr_reader :platforms
32
32
 
33
- # @return [String] Object version for the Xcode project.
33
+ # @return [Integer] Object version for the Xcode project.
34
34
  #
35
35
  attr_reader :object_version
36
36
 
@@ -50,7 +50,7 @@ module Pod
50
50
  # @param [Array<PodTarget>] pod_targets @see #pod_targets
51
51
  # @param [Hash{String=>Symbol}] build_configurations @see #build_configurations
52
52
  # @param [Array<Platform>] platforms @see #platforms
53
- # @param [String] object_version @see #object_version
53
+ # @param [Integer] object_version @see #object_version
54
54
  # @param [String] podfile_path @see #podfile_path
55
55
  #
56
56
  def initialize(sandbox, path, pod_targets, build_configurations, platforms,
@@ -110,6 +110,7 @@ module Pod
110
110
  build_configuration.build_settings['TVOS_DEPLOYMENT_TARGET'] = tvos_deployment_target.to_s if tvos_deployment_target
111
111
  build_configuration.build_settings['STRIP_INSTALLED_PRODUCT'] = 'NO'
112
112
  build_configuration.build_settings['CLANG_ENABLE_OBJC_ARC'] = 'YES'
113
+ build_configuration.build_settings['CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED'] = 'YES'
113
114
  end
114
115
  end
115
116
  end
@@ -38,7 +38,7 @@ module Pod
38
38
  #
39
39
  attr_reader :test_app_host_targets
40
40
 
41
- # @return [Array<PBXNativeTarget>] app_native_targets
41
+ # @return [Hash{Specification => PBXNativeTarget}] app_native_targets
42
42
  # The app native targets that were produced for this target. Can be empty if there were no app
43
43
  # native targets created (e.g. no app specs present).
44
44
  #
@@ -58,12 +58,12 @@ module Pod
58
58
  # @param [Array<PBXNativeTarget>] test_native_targets @see #test_native_targets
59
59
  # @param [Hash{String=>Array<PBXNativeTarget>}] test_resource_bundle_targets @see #test_resource_bundle_targets
60
60
  # @param [Array<PBXNativeTarget>] test_app_host_targets @see #test_app_host_targets
61
- # @param [Array<PBXNativeTarget>] app_native_targets @see #app_native_targets
61
+ # @param [Hash{Specification => PBXNativeTarget}] app_native_targets @see #app_native_targets
62
62
  # @param [Hash{String=>Array<PBXNativeTarget>}] app_resource_bundle_targets @see #app_resource_bundle_targets
63
63
  #
64
64
  def initialize(target, native_target, resource_bundle_targets = [], test_native_targets = [],
65
65
  test_resource_bundle_targets = {}, test_app_host_targets = [],
66
- app_native_targets = [], app_resource_bundle_targets = {})
66
+ app_native_targets = {}, app_resource_bundle_targets = {})
67
67
  @target = target
68
68
  @native_target = native_target
69
69
  @resource_bundle_targets = resource_bundle_targets
@@ -115,7 +115,7 @@ module Pod
115
115
  # @return [PBXNativeTarget] the app host target with the given target label.
116
116
  #
117
117
  def app_host_target_labelled(label)
118
- app_native_targets.find do |app_native_target|
118
+ app_native_targets.values.find do |app_native_target|
119
119
  app_native_target.name == label
120
120
  end || test_app_host_targets.find do |app_native_target|
121
121
  app_native_target.name == label
@@ -131,9 +131,7 @@ module Pod
131
131
  end
132
132
 
133
133
  def app_native_target_from_spec(spec)
134
- app_native_targets.find do |app_native_target|
135
- app_native_target.name == target.app_target_label(spec)
136
- end
134
+ app_native_targets[spec]
137
135
  end
138
136
  end
139
137
  end