cocoapods 1.5.2 → 1.6.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +365 -1
  3. data/bin/pod +1 -1
  4. data/lib/cocoapods/command/cache/clean.rb +1 -1
  5. data/lib/cocoapods/command/init.rb +4 -2
  6. data/lib/cocoapods/command/install.rb +7 -0
  7. data/lib/cocoapods/command/lib/lint.rb +8 -1
  8. data/lib/cocoapods/command/outdated.rb +4 -9
  9. data/lib/cocoapods/command/repo/add.rb +1 -1
  10. data/lib/cocoapods/command/repo/list.rb +1 -1
  11. data/lib/cocoapods/command/repo/push.rb +17 -12
  12. data/lib/cocoapods/command/repo/remove.rb +1 -1
  13. data/lib/cocoapods/command/repo/update.rb +1 -1
  14. data/lib/cocoapods/command/setup.rb +1 -1
  15. data/lib/cocoapods/command/spec/create.rb +39 -39
  16. data/lib/cocoapods/command/spec/lint.rb +8 -1
  17. data/lib/cocoapods/command.rb +3 -1
  18. data/lib/cocoapods/config.rb +13 -2
  19. data/lib/cocoapods/downloader/cache.rb +1 -1
  20. data/lib/cocoapods/executable.rb +3 -3
  21. data/lib/cocoapods/external_sources/abstract_external_source.rb +23 -13
  22. data/lib/cocoapods/external_sources.rb +7 -4
  23. data/lib/cocoapods/gem_version.rb +1 -1
  24. data/lib/cocoapods/generator/acknowledgements/markdown.rb +6 -0
  25. data/lib/cocoapods/generator/acknowledgements/plist.rb +13 -2
  26. data/lib/cocoapods/generator/app_target_helper.rb +141 -17
  27. data/lib/cocoapods/generator/copy_resources_script.rb +14 -3
  28. data/lib/cocoapods/generator/dummy_source.rb +14 -5
  29. data/lib/cocoapods/generator/embed_frameworks_script.rb +37 -20
  30. data/lib/cocoapods/generator/header.rb +1 -1
  31. data/lib/cocoapods/generator/info_plist_file.rb +12 -4
  32. data/lib/cocoapods/generator/prefix_header.rb +2 -2
  33. data/lib/cocoapods/hooks_manager.rb +28 -17
  34. data/lib/cocoapods/installer/analyzer/analysis_result.rb +52 -22
  35. data/lib/cocoapods/installer/analyzer/locking_dependency_analyzer.rb +14 -6
  36. data/lib/cocoapods/installer/analyzer/pod_variant.rb +4 -5
  37. data/lib/cocoapods/installer/analyzer/sandbox_analyzer.rb +3 -14
  38. data/lib/cocoapods/installer/analyzer/specs_state.rb +28 -4
  39. data/lib/cocoapods/installer/analyzer/target_inspection_result.rb +27 -14
  40. data/lib/cocoapods/installer/analyzer/target_inspector.rb +17 -11
  41. data/lib/cocoapods/installer/analyzer.rb +391 -284
  42. data/lib/cocoapods/installer/installation_options.rb +2 -0
  43. data/lib/cocoapods/installer/pod_source_installer.rb +31 -43
  44. data/lib/cocoapods/installer/post_install_hooks_context.rb +72 -47
  45. data/lib/cocoapods/installer/pre_install_hooks_context.rb +22 -13
  46. data/lib/cocoapods/installer/source_provider_hooks_context.rb +3 -1
  47. data/lib/cocoapods/installer/user_project_integrator/target_integrator/xcconfig_integrator.rb +44 -11
  48. data/lib/cocoapods/installer/user_project_integrator/target_integrator.rb +69 -29
  49. data/lib/cocoapods/installer/user_project_integrator.rb +6 -4
  50. data/lib/cocoapods/installer/xcode/pods_project_generator/aggregate_target_installer.rb +25 -16
  51. data/lib/cocoapods/installer/xcode/pods_project_generator/app_host_installer.rb +104 -0
  52. data/lib/cocoapods/installer/xcode/pods_project_generator/file_references_installer.rb +23 -50
  53. data/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_installer.rb +296 -177
  54. data/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_integrator.rb +51 -33
  55. data/lib/cocoapods/installer/xcode/pods_project_generator/target_installation_result.rb +93 -0
  56. data/lib/cocoapods/installer/xcode/pods_project_generator/target_installer.rb +62 -69
  57. data/lib/cocoapods/installer/xcode/pods_project_generator/target_installer_helper.rb +72 -0
  58. data/lib/cocoapods/installer/xcode/pods_project_generator.rb +130 -122
  59. data/lib/cocoapods/installer/xcode/target_validator.rb +15 -9
  60. data/lib/cocoapods/installer.rb +140 -63
  61. data/lib/cocoapods/project.rb +16 -14
  62. data/lib/cocoapods/resolver/resolver_specification.rb +41 -0
  63. data/lib/cocoapods/resolver.rb +79 -98
  64. data/lib/cocoapods/sandbox/file_accessor.rb +11 -6
  65. data/lib/cocoapods/sandbox/headers_store.rb +9 -8
  66. data/lib/cocoapods/sandbox/path_list.rb +5 -8
  67. data/lib/cocoapods/sandbox.rb +31 -43
  68. data/lib/cocoapods/sources_manager.rb +1 -1
  69. data/lib/cocoapods/target/aggregate_target.rb +143 -85
  70. data/lib/cocoapods/target/build_settings.rb +1124 -0
  71. data/lib/cocoapods/target/framework_paths.rb +36 -0
  72. data/lib/cocoapods/target/pod_target.rb +198 -295
  73. data/lib/cocoapods/target.rb +92 -37
  74. data/lib/cocoapods/user_interface.rb +5 -0
  75. data/lib/cocoapods/validator.rb +149 -44
  76. data/lib/cocoapods.rb +0 -1
  77. metadata +31 -23
  78. data/lib/cocoapods/generator/xcconfig/aggregate_xcconfig.rb +0 -260
  79. data/lib/cocoapods/generator/xcconfig/pod_xcconfig.rb +0 -87
  80. data/lib/cocoapods/generator/xcconfig/xcconfig_helper.rb +0 -558
  81. data/lib/cocoapods/generator/xcconfig.rb +0 -13
@@ -1,3 +1,5 @@
1
+ require 'cocoapods/target/build_settings'
2
+
1
3
  module Pod
2
4
  # Model class which describes a Pods target.
3
5
  #
@@ -7,6 +9,8 @@ module Pod
7
9
  #
8
10
  class Target
9
11
  DEFAULT_VERSION = '1.0.0'.freeze
12
+ DEFAULT_NAME = 'Default'.freeze
13
+ DEFAULT_BUILD_CONFIGURATIONS = { 'Release' => :release, 'Debug' => :debug }.freeze
10
14
 
11
15
  # @return [Sandbox] The sandbox where the Pods should be installed.
12
16
  #
@@ -15,13 +19,43 @@ module Pod
15
19
  # @return [Boolean] Whether the target needs to be implemented as a framework.
16
20
  # Computed by analyzer.
17
21
  #
18
- attr_accessor :host_requires_frameworks
22
+ attr_reader :host_requires_frameworks
19
23
  alias_method :host_requires_frameworks?, :host_requires_frameworks
20
24
 
25
+ # @return [Hash{String=>Symbol}] A hash representing the user build
26
+ # configurations where each key corresponds to the name of a
27
+ # configuration and its value to its type (`:debug` or `:release`).
28
+ #
29
+ attr_reader :user_build_configurations
30
+
31
+ # @return [Array<String>] The value for the ARCHS build setting.
32
+ #
33
+ attr_reader :archs
34
+
35
+ # @return [Platform] the platform of this target.
36
+ #
37
+ attr_reader :platform
38
+
39
+ # @return [BuildSettings] the build settings for this target.
40
+ #
41
+ attr_reader :build_settings
42
+
21
43
  # Initialize a new target
22
44
  #
23
- def initialize
24
- @archs = []
45
+ # @param [Sandbox] sandbox @see #sandbox
46
+ # @param [Boolean] host_requires_frameworks @see #host_requires_frameworks
47
+ # @param [Hash{String=>Symbol}] user_build_configurations @see #user_build_configurations
48
+ # @param [Array<String>] archs @see #archs
49
+ # @param [Platform] platform @see #platform
50
+ #
51
+ def initialize(sandbox, host_requires_frameworks, user_build_configurations, archs, platform)
52
+ @sandbox = sandbox
53
+ @host_requires_frameworks = host_requires_frameworks
54
+ @user_build_configurations = user_build_configurations
55
+ @archs = archs
56
+ @platform = platform
57
+
58
+ @build_settings = create_build_settings
25
59
  end
26
60
 
27
61
  # @return [String] the name of the library.
@@ -30,6 +64,40 @@ module Pod
30
64
  label
31
65
  end
32
66
 
67
+ alias to_s name
68
+
69
+ # @return [String] the label for the target.
70
+ #
71
+ def label
72
+ DEFAULT_NAME
73
+ end
74
+
75
+ # @return [String] The version associated with this target
76
+ #
77
+ def version
78
+ DEFAULT_VERSION
79
+ end
80
+
81
+ # @return [Boolean] Whether the target uses Swift code
82
+ #
83
+ def uses_swift?
84
+ false
85
+ end
86
+
87
+ # @return [Boolean] Whether the target should build a static framework.
88
+ #
89
+ def static_framework?
90
+ false
91
+ end
92
+
93
+ # @return [String] the name to use for the source code module constructed
94
+ # for this target, and which will be used to import the module in
95
+ # implementation source files.
96
+ #
97
+ def product_module_name
98
+ c99ext_identifier(label)
99
+ end
100
+
33
101
  # @return [String] the name of the product.
34
102
  #
35
103
  def product_name
@@ -85,6 +153,8 @@ module Pod
85
153
 
86
154
  #-------------------------------------------------------------------------#
87
155
 
156
+ # @!group Framework support
157
+
88
158
  # @return [Boolean] whether the generated target needs to be implemented
89
159
  # as a framework
90
160
  #
@@ -92,33 +162,6 @@ module Pod
92
162
  host_requires_frameworks? || false
93
163
  end
94
164
 
95
- # @return [Boolean] Whether the target should build a static framework.
96
- #
97
- def static_framework?
98
- return if is_a?(Pod::AggregateTarget)
99
- return if specs.empty?
100
- specs.all? { |spec| spec.root.static_framework }
101
- end
102
-
103
- #-------------------------------------------------------------------------#
104
-
105
- # @!group Information storage
106
-
107
- # @return [Hash{String=>Symbol}] A hash representing the user build
108
- # configurations where each key corresponds to the name of a
109
- # configuration and its value to its type (`:debug` or `:release`).
110
- #
111
- attr_accessor :user_build_configurations
112
-
113
- # @return [PBXNativeTarget] the target generated in the Pods project for
114
- # this library.
115
- #
116
- attr_accessor :native_target
117
-
118
- # @return [Array<String>] The value for the ARCHS build setting.
119
- #
120
- attr_accessor :archs
121
-
122
165
  #-------------------------------------------------------------------------#
123
166
 
124
167
  # @!group Support files
@@ -153,10 +196,24 @@ module Pod
153
196
  module_map_path.parent + "#{label}-umbrella.h"
154
197
  end
155
198
 
199
+ def umbrella_header_path_to_write
200
+ module_map_path_to_write.parent + "#{label}-umbrella.h"
201
+ end
202
+
156
203
  # @return [Pathname] the absolute path of the LLVM module map file that
157
204
  # defines the module structure for the compiler.
158
205
  #
159
206
  def module_map_path
207
+ module_map_path_to_write
208
+ end
209
+
210
+ # @!private
211
+ #
212
+ # @return [Pathname] the absolute path of the module map file that
213
+ # CocoaPods writes. This can be different from `module_map_path`
214
+ # if the module map gets symlinked.
215
+ #
216
+ def module_map_path_to_write
160
217
  basename = "#{label}.modulemap"
161
218
  support_files_dir + basename
162
219
  end
@@ -170,7 +227,7 @@ module Pod
170
227
  # @return [Pathname] the absolute path of the Info.plist file.
171
228
  #
172
229
  def info_plist_path
173
- support_files_dir + 'Info.plist'
230
+ support_files_dir + "#{label}-Info.plist"
174
231
  end
175
232
 
176
233
  # @return [Pathname] the path of the dummy source generated by CocoaPods
@@ -179,12 +236,6 @@ module Pod
179
236
  support_files_dir + "#{label}-dummy.m"
180
237
  end
181
238
 
182
- # @return [String] The version associated with this target
183
- #
184
- def version
185
- DEFAULT_VERSION
186
- end
187
-
188
239
  #-------------------------------------------------------------------------#
189
240
 
190
241
  private
@@ -202,5 +253,9 @@ module Pod
202
253
  def c99ext_identifier(name)
203
254
  name.gsub(/^([0-9])/, '_\1').gsub(/[^a-zA-Z0-9_]/, '_')
204
255
  end
256
+
257
+ def create_build_settings
258
+ BuildSettings.new(self)
259
+ end
205
260
  end
206
261
  end
@@ -62,6 +62,7 @@ module Pod
62
62
  self.indentation_level += relative_indentation
63
63
  self.title_level += 1
64
64
  yield if block_given?
65
+ ensure
65
66
  self.indentation_level -= relative_indentation
66
67
  self.title_level -= 1
67
68
  end
@@ -83,6 +84,7 @@ module Pod
83
84
  self.indentation_level += relative_indentation
84
85
  self.title_level += 1
85
86
  yield if block_given?
87
+ ensure
86
88
  self.indentation_level -= relative_indentation
87
89
  self.title_level -= 1
88
90
  end
@@ -114,6 +116,7 @@ module Pod
114
116
  self.indentation_level += relative_indentation
115
117
  self.title_level += 1
116
118
  yield if block_given?
119
+ ensure
117
120
  self.indentation_level -= relative_indentation
118
121
  self.title_level -= 1
119
122
  end
@@ -140,6 +143,7 @@ module Pod
140
143
 
141
144
  self.indentation_level += relative_indentation
142
145
  yield if block_given?
146
+ ensure
143
147
  self.indentation_level -= relative_indentation
144
148
  end
145
149
 
@@ -160,6 +164,7 @@ module Pod
160
164
  self.indentation_level += 2
161
165
  @treat_titles_as_messages = true
162
166
  yield if block_given?
167
+ ensure
163
168
  @treat_titles_as_messages = false
164
169
  self.indentation_level -= 2
165
170
  end
@@ -18,6 +18,10 @@ module Pod
18
18
  #
19
19
  DEFAULT_SWIFT_VERSION = '3.2'.freeze
20
20
 
21
+ # The valid platforms for linting
22
+ #
23
+ VALID_PLATFORMS = Platform.all.freeze
24
+
21
25
  # @return [Specification::Linter] the linter instance from CocoaPods
22
26
  # Core.
23
27
  #
@@ -31,13 +35,28 @@ module Pod
31
35
  # @param [Array<String>] source_urls
32
36
  # the Source URLs to use in creating a {Podfile}.
33
37
  #
34
- def initialize(spec_or_path, source_urls)
38
+ # @param. [Array<String>] platforms
39
+ # the platforms to lint.
40
+ #
41
+ def initialize(spec_or_path, source_urls, platforms = [])
35
42
  @linter = Specification::Linter.new(spec_or_path)
36
43
  @source_urls = if @linter.spec && @linter.spec.dependencies.empty? && @linter.spec.recursive_subspecs.all? { |s| s.dependencies.empty? }
37
44
  []
38
45
  else
39
46
  source_urls.map { |url| config.sources_manager.source_with_name_or_url(url) }.map(&:url)
40
47
  end
48
+
49
+ @platforms = platforms.map do |platform|
50
+ result = case platform.to_s.downcase
51
+ # Platform doesn't recognize 'macos' as being the same as 'osx' when initializing
52
+ when 'macos' then Platform.macos
53
+ else Platform.new(platform, nil)
54
+ end
55
+ unless valid_platform?(result)
56
+ raise Informative, "Unrecognized platform `#{platform}`. Valid platforms: #{VALID_PLATFORMS.join(', ')}"
57
+ end
58
+ result
59
+ end
41
60
  end
42
61
 
43
62
  #-------------------------------------------------------------------------#
@@ -55,6 +74,28 @@ module Pod
55
74
  @linter.file
56
75
  end
57
76
 
77
+ # Returns a list of platforms to lint for a given Specification
78
+ #
79
+ # @param [Specification] spec
80
+ # The specification to lint
81
+ #
82
+ # @return [Array<Platform>] platforms to lint for the given specification
83
+ #
84
+ def platforms_to_lint(spec)
85
+ return spec.available_platforms if @platforms.empty?
86
+
87
+ # Validate that the platforms specified are actually supported by the spec
88
+ results = @platforms.map do |platform|
89
+ matching_platform = spec.available_platforms.find { |p| p.name == platform.name }
90
+ unless matching_platform
91
+ raise Informative, "Platform `#{platform}` is not supported by specification `#{spec}`."
92
+ end
93
+ matching_platform
94
+ end.uniq
95
+
96
+ results
97
+ end
98
+
58
99
  # @return [Sandbox::FileAccessor] the file accessor for the spec.
59
100
  #
60
101
  attr_accessor :file_accessor
@@ -202,6 +243,10 @@ module Pod
202
243
  #
203
244
  attr_accessor :use_frameworks
204
245
 
246
+ # @return [Boolean] Whether modular headers should be used for the installation.
247
+ #
248
+ attr_accessor :use_modular_headers
249
+
205
250
  # @return [Boolean] Whether attributes that affect only public sources
206
251
  # Bool be skipped.
207
252
  #
@@ -309,7 +354,9 @@ module Pod
309
354
  validate_documentation_url(spec)
310
355
  validate_source_url(spec)
311
356
 
312
- valid = spec.available_platforms.send(fail_fast ? :all? : :each) do |platform|
357
+ platforms = platforms_to_lint(spec)
358
+
359
+ valid = platforms.send(fail_fast ? :all? : :each) do |platform|
313
360
  UI.message "\n\n#{spec} - Analyzing on #{platform} platform.".green.reversed
314
361
  @consumer = spec.consumer(platform)
315
362
  setup_validation_environment
@@ -464,7 +511,8 @@ module Pod
464
511
  end
465
512
 
466
513
  def download_pod
467
- podfile = podfile_from_spec(consumer.platform_name, deployment_target, use_frameworks, consumer.spec.test_specs.map(&:name))
514
+ test_spec_names = consumer.spec.test_specs.select { |ts| ts.supported_on_platform?(consumer.platform_name) }.map(&:name)
515
+ podfile = podfile_from_spec(consumer.platform_name, deployment_target, use_frameworks, test_spec_names, use_modular_headers)
468
516
  sandbox = Sandbox.new(config.sandbox_root)
469
517
  @installer = Installer.new(sandbox, podfile)
470
518
  @installer.use_default_plugins = false
@@ -475,7 +523,8 @@ module Pod
475
523
 
476
524
  def create_app_project
477
525
  app_project = Xcodeproj::Project.new(validation_dir + 'App.xcodeproj')
478
- Pod::Generator::AppTargetHelper.add_app_target(app_project, consumer.platform_name, deployment_target)
526
+ app_target = Pod::Generator::AppTargetHelper.add_app_target(app_project, consumer.platform_name, deployment_target)
527
+ Pod::Generator::AppTargetHelper.add_swift_version(app_target, swift_version)
479
528
  app_project.save
480
529
  app_project.recreate_user_schemes
481
530
  end
@@ -484,9 +533,9 @@ module Pod
484
533
  app_project = Xcodeproj::Project.open(validation_dir + 'App.xcodeproj')
485
534
  app_target = app_project.targets.first
486
535
  pod_target = @installer.pod_targets.find { |pt| pt.pod_name == spec.root.name }
487
- Pod::Generator::AppTargetHelper.add_app_project_import(app_project, app_target, pod_target, consumer.platform_name, use_frameworks)
488
- Pod::Generator::AppTargetHelper.add_swift_version(app_target, swift_version)
536
+ Pod::Generator::AppTargetHelper.add_app_project_import(app_project, app_target, pod_target, consumer.platform_name)
489
537
  Pod::Generator::AppTargetHelper.add_xctest_search_paths(app_target) if @installer.pod_targets.any? { |pt| pt.spec_consumers.any? { |c| c.frameworks.include?('XCTest') } }
538
+ Pod::Generator::AppTargetHelper.add_empty_swift_file(app_project, app_target) if @installer.pod_targets.any?(&:uses_swift?)
490
539
  app_project.save
491
540
  Xcodeproj::XCScheme.share_scheme(app_project.path, 'App')
492
541
  # Share the pods xcscheme only if it exists. For pre-built vendored pods there is no xcscheme generated.
@@ -501,43 +550,33 @@ module Pod
501
550
  perform_post_install_actions).each { |m| @installer.send(m) }
502
551
 
503
552
  deployment_target = spec.subspec_by_name(subspec_name).deployment_target(consumer.platform_name)
504
- configure_pod_targets(@installer.aggregate_targets, deployment_target)
553
+ configure_pod_targets(@installer.aggregate_targets, @installer.target_installation_results, deployment_target)
505
554
  @installer.pods_project.save
506
555
  end
507
556
 
508
- def configure_pod_targets(targets, deployment_target)
509
- test_only_pod_targets = @installer.pod_targets - targets.flat_map(&:pod_targets)
510
- targets.each do |target|
511
- target.pod_targets.each do |pod_target|
512
- update_pod_target_build_settings(pod_target)
513
- if pod_target.uses_swift?
514
- pod_target.test_native_targets.each do |test_native_target|
515
- test_native_target.build_configuration_list.build_configurations.each do |build_configuration|
516
- build_configuration.build_settings['SWIFT_VERSION'] = swift_version
517
- end
557
+ def configure_pod_targets(targets, target_installation_results, deployment_target)
558
+ target_installation_results.first.values.each do |pod_target_installation_result|
559
+ pod_target = pod_target_installation_result.target
560
+ native_target = pod_target_installation_result.native_target
561
+ native_target.build_configuration_list.build_configurations.each do |build_configuration|
562
+ (build_configuration.build_settings['OTHER_CFLAGS'] ||= '$(inherited)') << ' -Wincomplete-umbrella'
563
+ build_configuration.build_settings['SWIFT_VERSION'] = (pod_target.swift_version || swift_version) if pod_target.uses_swift?
564
+ end
565
+ pod_target_installation_result.test_specs_by_native_target.each do |test_native_target, test_specs|
566
+ if pod_target.uses_swift_for_test_spec?(test_specs.first)
567
+ test_native_target.build_configuration_list.build_configurations.each do |build_configuration|
568
+ build_configuration.build_settings['SWIFT_VERSION'] = swift_version
518
569
  end
519
570
  end
520
571
  end
572
+ end
573
+ targets.each do |target|
521
574
  if target.pod_targets.any?(&:uses_swift?) && consumer.platform_name == :ios &&
522
575
  (deployment_target.nil? || Version.new(deployment_target).major < 8)
523
576
  uses_xctest = target.spec_consumers.any? { |c| (c.frameworks + c.weak_frameworks).include? 'XCTest' }
524
577
  error('swift', 'Swift support uses dynamic frameworks and is therefore only supported on iOS > 8.') unless uses_xctest
525
578
  end
526
579
  end
527
- # Wire up Swift version to pod targets used only by tests.
528
- test_only_pod_targets.each do |test_pod_target|
529
- update_pod_target_build_settings(test_pod_target)
530
- end
531
- end
532
-
533
- def update_pod_target_build_settings(pod_target)
534
- native_target = pod_target.native_target
535
- unless native_target.nil?
536
- native_target.build_configuration_list.build_configurations.each do |build_configuration|
537
- (build_configuration.build_settings['OTHER_CFLAGS'] ||= '$(inherited)') << ' -Wincomplete-umbrella'
538
- build_configuration.build_settings['SWIFT_VERSION'] = (pod_target.swift_version || swift_version) if pod_target.uses_swift?
539
- end
540
- end
541
580
  end
542
581
 
543
582
  def validate_vendored_dynamic_frameworks
@@ -597,10 +636,14 @@ module Pod
597
636
  UI.message "\nTesting with `xcodebuild`.\n".yellow do
598
637
  pod_target = @installer.pod_targets.find { |pt| pt.pod_name == spec.root.name }
599
638
  consumer.spec.test_specs.each do |test_spec|
600
- scheme = pod_target.native_target_for_spec(test_spec)
601
- output = xcodebuild('test', scheme, 'Debug')
602
- parsed_output = parse_xcodebuild_output(output)
603
- translate_output_to_linter_messages(parsed_output)
639
+ if !test_spec.supported_on_platform?(consumer.platform_name)
640
+ UI.warn "Skipping test spec `#{test_spec.name}` on platform `#{consumer.platform_name}` since it is not supported.\n".yellow
641
+ else
642
+ scheme = @installer.target_installation_results.first[pod_target.name].native_target_for_spec(test_spec)
643
+ output = xcodebuild('test', scheme, 'Debug')
644
+ parsed_output = parse_xcodebuild_output(output)
645
+ translate_output_to_linter_messages(parsed_output)
646
+ end
604
647
  end
605
648
  end
606
649
  end
@@ -624,10 +667,8 @@ module Pod
624
667
  FILE_PATTERNS.each do |attr_name|
625
668
  if respond_to?("_validate_#{attr_name}", true)
626
669
  send("_validate_#{attr_name}")
627
- end
628
-
629
- if !file_accessor.spec_consumer.send(attr_name).empty? && file_accessor.send(attr_name).empty?
630
- error('file patterns', "The `#{attr_name}` pattern did not match any file.")
670
+ else
671
+ validate_nonempty_patterns(attr_name, :error)
631
672
  end
632
673
  end
633
674
 
@@ -638,12 +679,26 @@ module Pod
638
679
  end
639
680
  end
640
681
 
682
+ # Validates that the file patterns in `attr_name` match at least 1 file.
683
+ #
684
+ # @param [String,Symbol] attr_name the name of the attribute to check (ex. :public_header_files)
685
+ #
686
+ # @param [String,Symbol] message_type the type of message to send if the patterns are empty (ex. :error)
687
+ #
688
+ def validate_nonempty_patterns(attr_name, message_type)
689
+ return unless !file_accessor.spec_consumer.send(attr_name).empty? && file_accessor.send(attr_name).empty?
690
+
691
+ add_result(message_type, 'file patterns', "The `#{attr_name}` pattern did not match any file.")
692
+ end
693
+
641
694
  def _validate_private_header_files
642
695
  _validate_header_files(:private_header_files)
696
+ validate_nonempty_patterns(:private_header_files, :warning)
643
697
  end
644
698
 
645
699
  def _validate_public_header_files
646
700
  _validate_header_files(:public_header_files)
701
+ validate_nonempty_patterns(:public_header_files, :warning)
647
702
  end
648
703
 
649
704
  def _validate_license
@@ -801,27 +856,30 @@ module Pod
801
856
  # @note The generated podfile takes into account whether the linter is
802
857
  # in local mode.
803
858
  #
804
- def podfile_from_spec(platform_name, deployment_target, use_frameworks = true, test_spec_names = [])
859
+ def podfile_from_spec(platform_name, deployment_target, use_frameworks = true, test_spec_names = [], use_modular_headers = false)
805
860
  name = subspec_name || spec.name
806
861
  podspec = file.realpath
807
862
  local = local?
808
863
  urls = source_urls
809
864
  Pod::Podfile.new do
810
865
  install! 'cocoapods', :deterministic_uuids => false
866
+ # By default inhibit warnings for all pods, except the one being validated.
867
+ inhibit_all_warnings!
811
868
  urls.each { |u| source(u) }
812
869
  target 'App' do
813
870
  use_frameworks!(use_frameworks)
871
+ use_modular_headers! if use_modular_headers
814
872
  platform(platform_name, deployment_target)
815
873
  if local
816
- pod name, :path => podspec.dirname.to_s
874
+ pod name, :path => podspec.dirname.to_s, :inhibit_warnings => false
817
875
  else
818
- pod name, :podspec => podspec.to_s
876
+ pod name, :podspec => podspec.to_s, :inhibit_warnings => false
819
877
  end
820
878
  test_spec_names.each do |test_spec_name|
821
879
  if local
822
- pod test_spec_name, :path => podspec.dirname.to_s
880
+ pod test_spec_name, :path => podspec.dirname.to_s, :inhibit_warnings => false
823
881
  else
824
- pod test_spec_name, :podspec => podspec.to_s
882
+ pod test_spec_name, :podspec => podspec.to_s, :inhibit_warnings => false
825
883
  end
826
884
  end
827
885
  end
@@ -863,6 +921,14 @@ module Pod
863
921
  when :ios
864
922
  command += %w(CODE_SIGN_IDENTITY=- -sdk iphonesimulator)
865
923
  command += Fourflusher::SimControl.new.destination(:oldest, 'iOS', deployment_target)
924
+ xcconfig = consumer.pod_target_xcconfig
925
+ if xcconfig
926
+ archs = xcconfig['VALID_ARCHS']
927
+ if archs && (archs.include? 'armv7') && !(archs.include? 'i386') && (archs.include? 'x86_64')
928
+ # Prevent Xcodebuild from testing the non-existent i386 simulator if armv7 is specified without i386
929
+ command += %w(ARCHS=x86_64)
930
+ end
931
+ end
866
932
  when :watchos
867
933
  command += %w(CODE_SIGN_IDENTITY=- -sdk watchsimulator)
868
934
  command += Fourflusher::SimControl.new.destination(:oldest, 'watchOS', deployment_target)
@@ -889,6 +955,45 @@ module Pod
889
955
  Executable.execute_command('xcodebuild', command, raise_on_failure)
890
956
  end
891
957
 
958
+ # Whether the platform with the specified name is valid
959
+ #
960
+ # @param [Platform] platform
961
+ # The platform to check
962
+ #
963
+ # @return [Bool] True if the platform is valid
964
+ #
965
+ def valid_platform?(platform)
966
+ VALID_PLATFORMS.any? { |p| p.name == platform.name }
967
+ end
968
+
969
+ # Whether the platform is supported by the specification
970
+ #
971
+ # @param [Platform] platform
972
+ # The platform to check
973
+ #
974
+ # @param [Specification] specification
975
+ # The specification which must support the provided platform
976
+ #
977
+ # @return [Bool] Whether the platform is supported by the specification
978
+ #
979
+ def supported_platform?(platform, spec)
980
+ available_platforms = spec.available_platforms
981
+
982
+ available_platforms.any? { |p| p.name == platform.name }
983
+ end
984
+
985
+ # Whether the provided name matches the platform
986
+ #
987
+ # @param [Platform] platform
988
+ # The platform
989
+ #
990
+ # @param [String] name
991
+ # The name to check against the provided platform
992
+ #
993
+ def platform_name_match?(platform, name)
994
+ [platform.name, platform.string_name].any? { |n| n.casecmp(name) == 0 }
995
+ end
996
+
892
997
  #-------------------------------------------------------------------------#
893
998
  end
894
999
  end
data/lib/cocoapods.rb CHANGED
@@ -66,7 +66,6 @@ module Pod
66
66
  autoload :ModuleMap, 'cocoapods/generator/module_map'
67
67
  autoload :PrefixHeader, 'cocoapods/generator/prefix_header'
68
68
  autoload :UmbrellaHeader, 'cocoapods/generator/umbrella_header'
69
- autoload :XCConfig, 'cocoapods/generator/xcconfig'
70
69
  autoload :AppTargetHelper, 'cocoapods/generator/app_target_helper'
71
70
  end
72
71