cocoapods 0.39.0 → 1.0.0.beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +261 -12
  3. data/lib/cocoapods.rb +1 -0
  4. data/lib/cocoapods/command.rb +1 -0
  5. data/lib/cocoapods/command/env.rb +66 -0
  6. data/lib/cocoapods/command/init.rb +1 -1
  7. data/lib/cocoapods/command/lib.rb +1 -1
  8. data/lib/cocoapods/command/project.rb +0 -4
  9. data/lib/cocoapods/command/repo/lint.rb +7 -6
  10. data/lib/cocoapods/command/repo/push.rb +22 -1
  11. data/lib/cocoapods/command/setup.rb +0 -24
  12. data/lib/cocoapods/command/spec/create.rb +3 -1
  13. data/lib/cocoapods/command/spec/edit.rb +14 -21
  14. data/lib/cocoapods/command/spec/env_spec.rb +53 -0
  15. data/lib/cocoapods/command/spec/lint.rb +1 -1
  16. data/lib/cocoapods/config.rb +1 -34
  17. data/lib/cocoapods/downloader.rb +9 -4
  18. data/lib/cocoapods/external_sources.rb +0 -4
  19. data/lib/cocoapods/external_sources/abstract_external_source.rb +38 -11
  20. data/lib/cocoapods/external_sources/path_source.rb +2 -2
  21. data/lib/cocoapods/gem_version.rb +2 -2
  22. data/lib/cocoapods/generator/acknowledgements.rb +1 -1
  23. data/lib/cocoapods/generator/acknowledgements/plist.rb +1 -1
  24. data/lib/cocoapods/generator/copy_resources_script.rb +28 -21
  25. data/lib/cocoapods/generator/info_plist_file.rb +34 -8
  26. data/lib/cocoapods/generator/module_map.rb +3 -18
  27. data/lib/cocoapods/generator/xcconfig/aggregate_xcconfig.rb +22 -10
  28. data/lib/cocoapods/generator/xcconfig/pod_xcconfig.rb +2 -1
  29. data/lib/cocoapods/generator/xcconfig/xcconfig_helper.rb +2 -1
  30. data/lib/cocoapods/hooks_manager.rb +3 -11
  31. data/lib/cocoapods/installer.rb +45 -25
  32. data/lib/cocoapods/installer/analyzer.rb +53 -25
  33. data/lib/cocoapods/installer/analyzer/sandbox_analyzer.rb +2 -13
  34. data/lib/cocoapods/installer/analyzer/target_inspection_result.rb +4 -0
  35. data/lib/cocoapods/installer/analyzer/target_inspector.rb +22 -19
  36. data/lib/cocoapods/installer/file_references_installer.rb +53 -6
  37. data/lib/cocoapods/installer/installation_options.rb +156 -0
  38. data/lib/cocoapods/installer/migrator.rb +1 -56
  39. data/lib/cocoapods/installer/pod_source_installer.rb +10 -8
  40. data/lib/cocoapods/installer/podfile_validator.rb +42 -1
  41. data/lib/cocoapods/installer/post_install_hooks_context.rb +19 -2
  42. data/lib/cocoapods/installer/target_installer.rb +6 -2
  43. data/lib/cocoapods/installer/target_installer/aggregate_target_installer.rb +6 -5
  44. data/lib/cocoapods/installer/target_installer/pod_target_installer.rb +82 -14
  45. data/lib/cocoapods/installer/user_project_integrator.rb +37 -16
  46. data/lib/cocoapods/installer/user_project_integrator/target_integrator.rb +14 -136
  47. data/lib/cocoapods/installer/user_project_integrator/target_integrator/xcconfig_integrator.rb +15 -22
  48. data/lib/cocoapods/project.rb +109 -19
  49. data/lib/cocoapods/resolver.rb +17 -15
  50. data/lib/cocoapods/resolver/lazy_specification.rb +4 -0
  51. data/lib/cocoapods/sandbox.rb +0 -32
  52. data/lib/cocoapods/sandbox/headers_store.rb +2 -2
  53. data/lib/cocoapods/sandbox/podspec_finder.rb +1 -1
  54. data/lib/cocoapods/sources_manager.rb +181 -50
  55. data/lib/cocoapods/target/aggregate_target.rb +17 -11
  56. data/lib/cocoapods/target/pod_target.rb +31 -4
  57. data/lib/cocoapods/user_interface.rb +32 -3
  58. data/lib/cocoapods/user_interface/error_report.rb +46 -36
  59. data/lib/cocoapods/validator.rb +132 -43
  60. metadata +164 -79
@@ -17,6 +17,7 @@ module Pod
17
17
  @target_definition = target_definition
18
18
  @sandbox = sandbox
19
19
  @pod_targets = []
20
+ @search_paths_aggregate_targets = []
20
21
  @file_accessors = []
21
22
  @xcconfigs = {}
22
23
  end
@@ -54,13 +55,17 @@ module Pod
54
55
  #
55
56
  attr_accessor :client_root
56
57
 
57
- # @return [Pathname] the path of the user project that this target will
58
+ # @return [Xcodeproj::Project] the user project that this target will
58
59
  # integrate as identified by the analyzer.
59
60
  #
60
- # @note The project instance is not stored to prevent editing different
61
- # instances.
61
+ attr_accessor :user_project
62
+
63
+ # @return [Pathname] the path of the user project that this target will
64
+ # integrate as identified by the analyzer.
62
65
  #
63
- attr_accessor :user_project_path
66
+ def user_project_path
67
+ user_project.path if user_project
68
+ end
64
69
 
65
70
  # @return [Array<String>] the list of the UUIDs of the user targets that
66
71
  # will be integrated by this target as identified by the analyzer.
@@ -72,16 +77,12 @@ module Pod
72
77
 
73
78
  # List all user targets that will be integrated by this #target.
74
79
  #
75
- # @param [Xcodeproj::Project] project
76
- # The project to search for the user targets
77
- #
78
80
  # @return [Array<PBXNativeTarget>]
79
81
  #
80
- def user_targets(project = nil)
81
- return [] unless user_project_path
82
- project ||= Xcodeproj::Project.open(user_project_path)
82
+ def user_targets
83
+ return [] unless user_project
83
84
  user_target_uuids.map do |uuid|
84
- native_target = project.objects_by_uuid[uuid]
85
+ native_target = user_project.objects_by_uuid[uuid]
85
86
  unless native_target
86
87
  raise Informative, '[Bug] Unable to find the target with ' \
87
88
  "the `#{uuid}` UUID for the `#{self}` integration library"
@@ -103,6 +104,11 @@ module Pod
103
104
  #
104
105
  attr_accessor :pod_targets
105
106
 
107
+ # @return [Array<AggregateTarget>] The aggregate targets whose pods this
108
+ # target must be able to import, but will not directly link against.
109
+ #
110
+ attr_accessor :search_paths_aggregate_targets
111
+
106
112
  # @param [String] build_configuration The build configuration for which the
107
113
  # the pod targets should be returned.
108
114
  #
@@ -57,16 +57,23 @@ module Pod
57
57
  @dependent_targets = []
58
58
  end
59
59
 
60
+ # @param [Hash{Array => PodTarget}] cache
61
+ # the cached PodTarget for a previously scoped (specs, target_definition)
60
62
  # @return [Array<PodTarget>] a scoped copy for each target definition.
61
63
  #
62
- def scoped
64
+ def scoped(cache = {})
63
65
  target_definitions.map do |target_definition|
64
- PodTarget.new(specs, [target_definition], sandbox, true).tap do |target|
66
+ cache_key = [specs, target_definition]
67
+ if cache[cache_key]
68
+ cache[cache_key]
69
+ else
70
+ target = PodTarget.new(specs, [target_definition], sandbox, true)
65
71
  target.file_accessors = file_accessors
66
72
  target.user_build_configurations = user_build_configurations
67
73
  target.native_target = native_target
68
74
  target.archs = archs
69
- target.dependent_targets = dependent_targets.flat_map(&:scoped).select { |pt| pt.target_definitions == [target_definition] }
75
+ target.dependent_targets = dependent_targets.flat_map { |pt| pt.scoped(cache) }.select { |pt| pt.target_definitions == [target_definition] }
76
+ cache[cache_key] = target
70
77
  end
71
78
  end
72
79
  end
@@ -81,12 +88,32 @@ module Pod
81
88
  end
82
89
  end
83
90
 
91
+ # @note The deployment target for the pod target is the maximum of all
92
+ # the deployment targets for the current platform of the target
93
+ # (or the minimum required to support the current installation
94
+ # strategy, if higher).
95
+ #
84
96
  # @return [Platform] the platform for this target.
85
97
  #
86
98
  def platform
87
- @platform ||= target_definitions.first.platform
99
+ @platform ||= begin
100
+ platform_name = target_definitions.first.platform.name
101
+ default = Podfile::TargetDefinition::PLATFORM_DEFAULTS[platform_name]
102
+ deployment_target = specs.map do |spec|
103
+ Version.new(spec.deployment_target(platform_name) || default)
104
+ end.max
105
+ if platform_name == :ios && requires_frameworks?
106
+ minimum = Version.new('8.0')
107
+ deployment_target = [deployment_target, minimum].max
108
+ end
109
+ Platform.new(platform_name, deployment_target)
110
+ end
88
111
  end
89
112
 
113
+ # @visibility private
114
+ #
115
+ attr_writer :platform
116
+
90
117
  # @return [Podfile] The podfile which declares the dependency.
91
118
  #
92
119
  def podfile
@@ -20,6 +20,10 @@ module Pod
20
20
  attr_accessor :title_level
21
21
  attr_accessor :warnings
22
22
 
23
+ # @return [IO] IO object to which UI output will be directed.
24
+ #
25
+ attr_accessor :output_io
26
+
23
27
  # @return [Bool] Whether the wrapping of the strings to the width of the
24
28
  # terminal should be disabled.
25
29
  #
@@ -203,7 +207,7 @@ module Pod
203
207
  puts_indented "#{set.name} #{set.versions.first.version}"
204
208
  else
205
209
  pod = Specification::Set::Presenter.new(set)
206
- title = "\n-> #{pod.name} (#{pod.version})"
210
+ title = "-> #{pod.name} (#{pod.version})"
207
211
  if pod.spec.deprecated?
208
212
  title += " #{pod.deprecation_description}"
209
213
  colored_title = title.red
@@ -322,7 +326,12 @@ module Pod
322
326
  # The message to print.
323
327
  #
324
328
  def puts(message = '')
325
- STDOUT.puts(message) unless config.silent?
329
+ return if config.silent?
330
+ begin
331
+ (output_io || STDOUT).puts(message)
332
+ rescue Errno::EPIPE
333
+ exit 0
334
+ end
326
335
  end
327
336
 
328
337
  # prints a message followed by a new line unless config is silent.
@@ -331,7 +340,12 @@ module Pod
331
340
  # The message to print.
332
341
  #
333
342
  def print(message)
334
- STDOUT.print(message) unless config.silent?
343
+ return if config.silent?
344
+ begin
345
+ (output_io || STDOUT).print(message)
346
+ rescue Errno::EPIPE
347
+ exit 0
348
+ end
335
349
  end
336
350
 
337
351
  # gets input from $stdin
@@ -354,6 +368,21 @@ module Pod
354
368
  warnings << { :message => message, :actions => actions, :verbose_only => verbose_only }
355
369
  end
356
370
 
371
+ # Pipes all output inside given block to a pager.
372
+ #
373
+ # @yield Code block in which inputs to {#puts} and {#print} methods will be printed to the piper.
374
+ #
375
+ def with_pager
376
+ prev_handler = Signal.trap('INT', 'IGNORE')
377
+ IO.popen((ENV['PAGER'] || 'less -R'), 'w') do |io|
378
+ UI.output_io = io
379
+ yield
380
+ end
381
+ ensure
382
+ Signal.trap('INT', prev_handler)
383
+ UI.output_io = nil
384
+ end
385
+
357
386
  private
358
387
 
359
388
  # @!group Helpers
@@ -18,28 +18,9 @@ module Pod
18
18
  #{original_command}
19
19
  ```
20
20
 
21
- ### Report
22
-
23
- * What did you do?
24
-
25
- * What did you expect to happen?
26
-
27
- * What happened instead?
28
-
29
-
30
- ### Stack
31
-
32
- ```
33
- CocoaPods : #{Pod::VERSION}
34
- Ruby : #{RUBY_DESCRIPTION}
35
- RubyGems : #{Gem::VERSION}
36
- Host : #{host_information}
37
- Xcode : #{xcode_information}
38
- Git : #{git_information}
39
- Ruby lib dir : #{RbConfig::CONFIG['libdir']}
40
- Repositories : #{repo_information.join("\n ")}
41
- ```
21
+ #{report_instructions}
42
22
 
23
+ #{stack}
43
24
  ### Plugins
44
25
 
45
26
  ```
@@ -71,16 +52,41 @@ Don't forget to anonymize any private data!
71
52
  EOS
72
53
  end
73
54
 
74
- private
55
+ def report_instructions
56
+ <<-EOS
57
+ ### Report
75
58
 
76
- def `(other)
77
- super
78
- rescue Errno::ENOENT => e
79
- "Unable to find an executable (#{e})"
59
+ * What did you do?
60
+
61
+ * What did you expect to happen?
62
+
63
+ * What happened instead?
64
+ EOS
80
65
  end
81
66
 
82
- def pathless_exception_message(message)
83
- message.gsub(/- \(.*\):/, '-')
67
+ def stack
68
+ <<-EOS
69
+ ### Stack
70
+
71
+ ```
72
+ CocoaPods : #{Pod::VERSION}
73
+ Ruby : #{RUBY_DESCRIPTION}
74
+ RubyGems : #{Gem::VERSION}
75
+ Host : #{host_information}
76
+ Xcode : #{xcode_information}
77
+ Git : #{git_information}
78
+ Ruby lib dir : #{RbConfig::CONFIG['libdir']}
79
+ Repositories : #{repo_information.join("\n ")}
80
+ ```
81
+ EOS
82
+ end
83
+
84
+ def plugins_string
85
+ plugins = installed_plugins
86
+ max_name_length = plugins.keys.map(&:length).max
87
+ plugins.map do |name, version|
88
+ "#{name.ljust(max_name_length)} : #{version}"
89
+ end.sort.join("\n")
84
90
  end
85
91
 
86
92
  def markdown_podfile
@@ -95,6 +101,18 @@ EOS
95
101
  EOS
96
102
  end
97
103
 
104
+ private
105
+
106
+ def `(other)
107
+ super
108
+ rescue Errno::ENOENT => e
109
+ "Unable to find an executable (#{e})"
110
+ end
111
+
112
+ def pathless_exception_message(message)
113
+ message.gsub(/- \(.*\):/, '-')
114
+ end
115
+
98
116
  def error_from_podfile(error)
99
117
  if error.message =~ /Podfile:(\d*)/
100
118
  "\nIt appears to have originated from your Podfile at line #{Regexp.last_match[1]}.\n"
@@ -130,14 +148,6 @@ EOS
130
148
  reduce({}) { |hash, s| hash.tap { |h| h[s.name] = s.version.to_s } }
131
149
  end
132
150
 
133
- def plugins_string
134
- plugins = installed_plugins
135
- max_name_length = plugins.keys.map(&:length).max
136
- plugins.map do |name, version|
137
- "#{name.ljust(max_name_length)} : #{version}"
138
- end.sort.join("\n")
139
- end
140
-
141
151
  def repo_information
142
152
  SourcesManager.all.map do |source|
143
153
  next unless source.type == 'file system'
@@ -1,6 +1,8 @@
1
1
  require 'active_support/core_ext/array'
2
2
  require 'active_support/core_ext/string/inflections'
3
3
 
4
+ autoload :Fourflusher, 'fourflusher'
5
+
4
6
  module Pod
5
7
  # Validates a Specification.
6
8
  #
@@ -67,7 +69,8 @@ module Pod
67
69
  # Replace default spec with a subspec if asked for
68
70
  a_spec = spec
69
71
  if spec && @only_subspec
70
- a_spec = spec.subspec_by_name(@only_subspec)
72
+ subspec_name = @only_subspec.start_with?(spec.root.name) ? @only_subspec : "#{spec.root.name}/#{@only_subspec}"
73
+ a_spec = spec.subspec_by_name(subspec_name)
71
74
  @subspec_name = a_spec.name
72
75
  end
73
76
 
@@ -87,6 +90,11 @@ module Pod
87
90
  # @return [void]
88
91
  #
89
92
  def print_results
93
+ UI.puts results_message
94
+ end
95
+
96
+ def results_message
97
+ message = ''
90
98
  results.each do |result|
91
99
  if result.platforms == [:ios]
92
100
  platform_message = '[iOS] '
@@ -113,9 +121,9 @@ module Pod
113
121
  when :warning then type = 'WARN'
114
122
  when :note then type = 'NOTE'
115
123
  else raise "#{result.type}" end
116
- UI.puts " - #{type.ljust(5)} | #{platform_message}#{subspecs_message}#{result.attribute_name}: #{result.message}"
124
+ message << " - #{type.ljust(5)} | #{platform_message}#{subspecs_message}#{result.attribute_name}: #{result.message}\n"
117
125
  end
118
- UI.puts
126
+ message << "\n"
119
127
  end
120
128
 
121
129
  def failure_reason
@@ -133,8 +141,8 @@ module Pod
133
141
  reasons << reason
134
142
  end
135
143
  if results.all?(&:public_only)
136
- reasons << 'All results apply only to public specs, but you can use ' \
137
- '`--private` to ignore them if linting the specification for a private pod.'
144
+ reasons << 'all results apply only to public specs, but you can use ' \
145
+ '`--private` to ignore them if linting the specification for a private pod'
138
146
  end
139
147
  reasons.to_sentence
140
148
  end
@@ -251,24 +259,30 @@ module Pod
251
259
  validate_screenshots(spec)
252
260
  validate_social_media_url(spec)
253
261
  validate_documentation_url(spec)
254
- validate_docset_url(spec)
255
262
 
256
263
  valid = spec.available_platforms.send(fail_fast ? :all? : :each) do |platform|
257
264
  UI.message "\n\n#{spec} - Analyzing on #{platform} platform.".green.reversed
258
265
  @consumer = spec.consumer(platform)
259
266
  setup_validation_environment
260
- download_pod
261
- check_file_patterns
262
- install_pod
263
- validate_vendored_dynamic_frameworks
264
- build_pod
265
- tear_down_validation_environment
267
+ begin
268
+ create_app_project
269
+ download_pod
270
+ check_file_patterns
271
+ install_pod
272
+ add_app_project_import
273
+ validate_vendored_dynamic_frameworks
274
+ build_pod
275
+ ensure
276
+ tear_down_validation_environment
277
+ end
266
278
  validated?
267
279
  end
268
280
  return false if fail_fast && !valid
269
281
  perform_extensive_subspec_analysis(spec) unless @no_subspecs
270
282
  rescue => e
271
- error('unknown', "Encountered an unknown error (#{e}) during validation.")
283
+ message = e.to_s
284
+ message << "\n" << e.backtrace.join("\n") << "\n" if config.verbose?
285
+ error('unknown', "Encountered an unknown error (#{message}) during validation.")
272
286
  false
273
287
  end
274
288
 
@@ -329,21 +343,13 @@ module Pod
329
343
  validate_url(spec.documentation_url) if spec.documentation_url
330
344
  end
331
345
 
332
- # Performs validations related to the `docset_url` attribute.
333
- #
334
- def validate_docset_url(spec)
335
- validate_url(spec.docset_url) if spec.docset_url
336
- end
337
-
338
346
  def setup_validation_environment
339
347
  validation_dir.rmtree if validation_dir.exist?
340
348
  validation_dir.mkpath
341
349
  @original_config = Config.instance.clone
342
- config.installation_root = validation_dir
343
- config.sandbox_root = validation_dir + 'Pods'
344
- config.silent = !config.verbose
345
- config.integrate_targets = false
346
- config.skip_repo_update = true
350
+ config.installation_root = validation_dir
351
+ config.silent = !config.verbose
352
+ config.skip_repo_update = true
347
353
  end
348
354
 
349
355
  def tear_down_validation_environment
@@ -351,8 +357,16 @@ module Pod
351
357
  Config.instance = @original_config
352
358
  end
353
359
 
354
- def download_pod
360
+ def deployment_target
355
361
  deployment_target = spec.subspec_by_name(subspec_name).deployment_target(consumer.platform_name)
362
+ if consumer.platform_name == :ios && use_frameworks
363
+ minimum = Version.new('8.0')
364
+ deployment_target = [Version.new(deployment_target), minimum].max.to_s
365
+ end
366
+ deployment_target
367
+ end
368
+
369
+ def download_pod
356
370
  podfile = podfile_from_spec(consumer.platform_name, deployment_target, use_frameworks)
357
371
  sandbox = Sandbox.new(config.sandbox_root)
358
372
  @installer = Installer.new(sandbox, podfile)
@@ -361,23 +375,79 @@ module Pod
361
375
  @file_accessor = @installer.pod_targets.flat_map(&:file_accessors).find { |fa| fa.spec.name == consumer.spec.name }
362
376
  end
363
377
 
378
+ def create_app_project
379
+ app_project = Xcodeproj::Project.new(validation_dir + 'App.xcodeproj')
380
+ app_project.new_target(:application, 'App', consumer.platform_name, deployment_target)
381
+ app_project.save
382
+ app_project.recreate_user_schemes
383
+ Xcodeproj::XCScheme.share_scheme(app_project.path, 'App')
384
+ end
385
+
386
+ def add_app_project_import
387
+ app_project = Xcodeproj::Project.open(validation_dir + 'App.xcodeproj')
388
+ pod_target = @installer.pod_targets.find { |pt| pt.pod_name == spec.root.name }
389
+
390
+ source_file = write_app_import_source_file(pod_target)
391
+ source_file_ref = app_project.new_group('App', 'App').new_file(source_file)
392
+ app_project.targets.first.add_file_references([source_file_ref])
393
+ app_project.save
394
+ end
395
+
396
+ def write_app_import_source_file(pod_target)
397
+ language = pod_target.uses_swift? ? :swift : :objc
398
+
399
+ if language == :swift
400
+ source_file = validation_dir.+('App/main.swift')
401
+ source_file.parent.mkpath
402
+ import_statement = use_frameworks ? "import #{pod_target.product_module_name}\n" : ''
403
+ source_file.open('w') { |f| f << import_statement }
404
+ else
405
+ source_file = validation_dir.+('App/main.m')
406
+ source_file.parent.mkpath
407
+ import_statement = if use_frameworks
408
+ "@import #{pod_target.product_module_name};\n"
409
+ else
410
+ header_name = "#{pod_target.product_module_name}/#{pod_target.product_module_name}.h"
411
+ if pod_target.sandbox.public_headers.root.+(header_name).file?
412
+ "#import <#{header_name}>\n"
413
+ else
414
+ ''
415
+ end
416
+ end
417
+ source_file.open('w') do |f|
418
+ f << "@import Foundation;\n"
419
+ f << "@import UIKit;\n" if consumer.platform_name == :ios || consumer.platform_name == :tvos
420
+ f << "@import Cocoa;\n" if consumer.platform_name == :osx
421
+ f << "#{import_statement}int main() {}\n"
422
+ end
423
+ end
424
+ source_file
425
+ end
426
+
364
427
  # It creates a podfile in memory and builds a library containing the pod
365
428
  # for all available platforms with xcodebuild.
366
429
  #
367
430
  def install_pod
368
431
  %i(determine_dependency_product_types verify_no_duplicate_framework_names
369
432
  verify_no_static_framework_transitive_dependencies
370
- verify_framework_usage generate_pods_project
433
+ verify_framework_usage generate_pods_project integrate_user_project
371
434
  perform_post_install_actions).each { |m| @installer.send(m) }
372
435
 
373
436
  deployment_target = spec.subspec_by_name(subspec_name).deployment_target(consumer.platform_name)
374
437
  @installer.aggregate_targets.each do |target|
438
+ target.pod_targets.each do |pod_target|
439
+ next unless native_target = pod_target.native_target
440
+ native_target.build_configuration_list.build_configurations.each do |build_configuration|
441
+ (build_configuration.build_settings['OTHER_CFLAGS'] ||= '$(inherited)') << ' -Wincomplete-umbrella'
442
+ end
443
+ end
375
444
  if target.pod_targets.any?(&:uses_swift?) && consumer.platform_name == :ios &&
376
445
  (deployment_target.nil? || Version.new(deployment_target).major < 8)
377
446
  uses_xctest = target.spec_consumers.any? { |c| (c.frameworks + c.weak_frameworks).include? 'XCTest' }
378
447
  error('swift', 'Swift support uses dynamic frameworks and is therefore only supported on iOS > 8.') unless uses_xctest
379
448
  end
380
449
  end
450
+ @installer.pods_project.save
381
451
  end
382
452
 
383
453
  def validate_vendored_dynamic_frameworks
@@ -406,7 +476,7 @@ module Pod
406
476
  UI.warn "Skipping compilation with `xcodebuild' because it can't be found.\n".yellow
407
477
  else
408
478
  UI.message "\nBuilding with xcodebuild.\n".yellow do
409
- output = Dir.chdir(config.sandbox_root) { xcodebuild }
479
+ output = xcodebuild
410
480
  UI.puts output
411
481
  parsed_output = parse_xcodebuild_output(output)
412
482
  parsed_output.each do |message|
@@ -454,6 +524,7 @@ module Pod
454
524
  end
455
525
  end
456
526
 
527
+ _validate_header_mappings_dir
457
528
  if consumer.spec.root?
458
529
  _validate_license
459
530
  _validate_module_map
@@ -491,12 +562,26 @@ module Pod
491
562
  def _validate_header_files(attr_name)
492
563
  non_header_files = file_accessor.send(attr_name).
493
564
  select { |f| !Sandbox::FileAccessor::HEADER_EXTENSIONS.include?(f.extname) }.
494
- map { |f| f.relative_path_from file_accessor.root }
565
+ map { |f| f.relative_path_from(file_accessor.root) }
495
566
  unless non_header_files.empty?
496
567
  error(attr_name, "The pattern matches non-header files (#{non_header_files.join(', ')}).")
497
568
  end
498
569
  end
499
570
 
571
+ def _validate_header_mappings_dir
572
+ return unless header_mappings_dir = file_accessor.spec_consumer.header_mappings_dir
573
+ absolute_mappings_dir = file_accessor.root + header_mappings_dir
574
+ unless absolute_mappings_dir.directory?
575
+ error('header_mappings_dir', "The header_mappings_dir (`#{header_mappings_dir}`) is not a directory.")
576
+ end
577
+ non_mapped_headers = file_accessor.headers.
578
+ reject { |h| h.to_path.start_with?(absolute_mappings_dir.to_path) }.
579
+ map { |f| f.relative_path_from(file_accessor.root) }
580
+ unless non_mapped_headers.empty?
581
+ error('header_mappings_dir', "There are header files outside of the header_mappings_dir (#{non_mapped_headers.join(', ')}).")
582
+ end
583
+ end
584
+
500
585
  #-------------------------------------------------------------------------#
501
586
 
502
587
  private
@@ -572,13 +657,16 @@ module Pod
572
657
  local = local?
573
658
  urls = source_urls
574
659
  Pod::Podfile.new do
660
+ install! 'cocoapods', :deterministic_uuids => false
575
661
  urls.each { |u| source(u) }
576
- use_frameworks!(use_frameworks)
577
- platform(platform_name, deployment_target)
578
- if local
579
- pod name, :path => podspec.dirname.to_s
580
- else
581
- pod name, :podspec => podspec.to_s
662
+ target 'App' do
663
+ use_frameworks!(use_frameworks)
664
+ platform(platform_name, deployment_target)
665
+ if local
666
+ pod name, :path => podspec.dirname.to_s
667
+ else
668
+ pod name, :podspec => podspec.to_s
669
+ end
582
670
  end
583
671
  end
584
672
  end
@@ -610,18 +698,20 @@ module Pod
610
698
  # returns its output (both STDOUT and STDERR).
611
699
  #
612
700
  def xcodebuild
613
- command = 'xcodebuild clean build -target Pods'
614
-
701
+ command = %w(clean build -workspace App.xcworkspace -scheme App -configuration Release)
615
702
  case consumer.platform_name
616
703
  when :ios
617
- command << ' CODE_SIGN_IDENTITY=- -sdk iphonesimulator'
704
+ command += %w(CODE_SIGN_IDENTITY=- -sdk iphonesimulator)
705
+ command += Fourflusher::SimControl.new.destination('iPhone 4s', deployment_target)
618
706
  when :watchos
619
- command << ' CODE_SIGN_IDENTITY=- -sdk watchsimulator'
707
+ command += %w(CODE_SIGN_IDENTITY=- -sdk watchsimulator)
708
+ command += Fourflusher::SimControl.new.destination('Apple Watch - 38mm', deployment_target)
620
709
  when :tvos
621
- command << ' CODE_SIGN_IDENTITY=- -sdk appletvsimulator'
710
+ command += %w(CODE_SIGN_IDENTITY=- -sdk appletvsimulator)
711
+ command += Fourflusher::SimControl.new.destination('Apple TV 1080p', deployment_target)
622
712
  end
623
713
 
624
- output, status = _xcodebuild "#{command} 2>&1"
714
+ output, status = Dir.chdir(validation_dir) { _xcodebuild(command) }
625
715
 
626
716
  unless status.success?
627
717
  message = 'Returned an unsuccessful exit code.'
@@ -638,9 +728,8 @@ module Pod
638
728
  # resulting status.
639
729
  #
640
730
  def _xcodebuild(command)
641
- UI.puts command if config.verbose
642
- output = `#{command}`
643
- [output, $?]
731
+ UI.puts 'xcodebuild ' << command.join(' ') if config.verbose
732
+ Executable.capture_command('xcodebuild', command, :capture => :merge)
644
733
  end
645
734
 
646
735
  #-------------------------------------------------------------------------#