cocoapods 1.9.1 → 1.10.2

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