cocoapods 0.37.2 → 0.38.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 (56) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +136 -1
  3. data/lib/cocoapods.rb +0 -5
  4. data/lib/cocoapods/command.rb +3 -0
  5. data/lib/cocoapods/command/cache.rb +28 -0
  6. data/lib/cocoapods/command/cache/clean.rb +90 -0
  7. data/lib/cocoapods/command/cache/list.rb +69 -0
  8. data/lib/cocoapods/command/lib.rb +11 -4
  9. data/lib/cocoapods/command/list.rb +4 -4
  10. data/lib/cocoapods/command/outdated.rb +1 -10
  11. data/lib/cocoapods/command/project.rb +3 -2
  12. data/lib/cocoapods/command/spec.rb +0 -17
  13. data/lib/cocoapods/command/spec/cat.rb +1 -1
  14. data/lib/cocoapods/command/spec/create.rb +1 -0
  15. data/lib/cocoapods/command/spec/edit.rb +1 -1
  16. data/lib/cocoapods/command/spec/lint.rb +10 -4
  17. data/lib/cocoapods/config.rb +6 -0
  18. data/lib/cocoapods/downloader/cache.rb +48 -1
  19. data/lib/cocoapods/executable.rb +27 -6
  20. data/lib/cocoapods/gem_version.rb +1 -1
  21. data/lib/cocoapods/generator/copy_resources_script.rb +1 -0
  22. data/lib/cocoapods/generator/embed_frameworks_script.rb +23 -28
  23. data/lib/cocoapods/generator/header.rb +5 -1
  24. data/lib/cocoapods/generator/umbrella_header.rb +1 -1
  25. data/lib/cocoapods/generator/xcconfig/aggregate_xcconfig.rb +139 -33
  26. data/lib/cocoapods/generator/xcconfig/private_pod_xcconfig.rb +2 -2
  27. data/lib/cocoapods/generator/xcconfig/xcconfig_helper.rb +3 -3
  28. data/lib/cocoapods/installer.rb +64 -109
  29. data/lib/cocoapods/installer/analyzer.rb +167 -336
  30. data/lib/cocoapods/installer/analyzer/analysis_result.rb +46 -0
  31. data/lib/cocoapods/installer/analyzer/specs_state.rb +76 -0
  32. data/lib/cocoapods/installer/analyzer/target_inspection_result.rb +41 -0
  33. data/lib/cocoapods/installer/analyzer/target_inspector.rb +203 -0
  34. data/lib/cocoapods/installer/file_references_installer.rb +48 -13
  35. data/lib/cocoapods/installer/podfile_validator.rb +86 -0
  36. data/lib/cocoapods/installer/{hooks_context.rb → post_install_hooks_context.rb} +3 -3
  37. data/lib/cocoapods/installer/pre_install_hooks_context.rb +41 -0
  38. data/lib/cocoapods/installer/target_installer.rb +1 -7
  39. data/lib/cocoapods/installer/target_installer/aggregate_target_installer.rb +15 -17
  40. data/lib/cocoapods/installer/target_installer/pod_target_installer.rb +4 -4
  41. data/lib/cocoapods/installer/user_project_integrator/target_integrator.rb +16 -16
  42. data/lib/cocoapods/sandbox/file_accessor.rb +20 -2
  43. data/lib/cocoapods/sandbox/path_list.rb +15 -13
  44. data/lib/cocoapods/sandbox/podspec_finder.rb +1 -0
  45. data/lib/cocoapods/sources_manager.rb +2 -0
  46. data/lib/cocoapods/target.rb +7 -37
  47. data/lib/cocoapods/target/aggregate_target.rb +25 -1
  48. data/lib/cocoapods/target/pod_target.rb +106 -10
  49. data/lib/cocoapods/user_interface.rb +26 -0
  50. data/lib/cocoapods/user_interface/error_report.rb +6 -0
  51. data/lib/cocoapods/validator.rb +22 -0
  52. metadata +21 -16
  53. data/lib/cocoapods/generator/target_environment_header.rb +0 -171
  54. data/lib/cocoapods/hooks/installer_representation.rb +0 -133
  55. data/lib/cocoapods/hooks/library_representation.rb +0 -93
  56. data/lib/cocoapods/hooks/pod_representation.rb +0 -70
@@ -8,15 +8,6 @@ module Pod
8
8
  spec repos, not those from local/external sources or `:head` versions.
9
9
  DESC
10
10
 
11
- def self.options
12
- [['--no-repo-update', 'Skip running `pod repo update` before install']].concat(super)
13
- end
14
-
15
- def initialize(argv)
16
- config.skip_repo_update = !argv.flag?('repo-update', !config.skip_repo_update)
17
- super
18
- end
19
-
20
11
  # Run the command
21
12
  #
22
13
  # @todo the command report new dependencies added to the Podfile as
@@ -98,7 +89,7 @@ module Pod
98
89
 
99
90
  def spec_sets
100
91
  @spec_sets ||= begin
101
- analyzer.send(:update_repositories_if_needed)
92
+ analyzer.send(:update_repositories) unless config.skip_repo_update?
102
93
  aggregate = Source::Aggregate.new(analyzer.sources.map(&:repo))
103
94
  installed_pods.map do |pod_name|
104
95
  aggregate.search(Dependency.new(pod_name))
@@ -134,8 +134,9 @@ module Pod
134
134
  verify_lockfile_exists!
135
135
 
136
136
  # Check if all given pods are installed
137
- missing_pods = @pods.select do |pod|
138
- !config.lockfile.pod_names.include?(pod)
137
+ lockfile_roots = config.lockfile.pod_names.map { |p| Specification.root_name(p) }
138
+ missing_pods = @pods.map { |p| Specification.root_name(p) }.select do |pod|
139
+ !lockfile_roots.include?(pod)
139
140
  end
140
141
 
141
142
  if missing_pods.length > 0
@@ -30,23 +30,6 @@ module Pod
30
30
  help! 'A valid regular expression is required.'
31
31
  end
32
32
 
33
- # @return [Fixnum] the index of the chosen array item
34
- #
35
- def choose_from_array(array, message)
36
- array.each_with_index do |item, index|
37
- UI.puts "#{ index + 1 }: #{ item }"
38
- end
39
-
40
- UI.puts message
41
-
42
- index = UI.gets.chomp.to_i - 1
43
- if index < 0 || index > array.count - 1
44
- raise Informative, "#{ index + 1 } is invalid [1-#{ array.count }]"
45
- else
46
- index
47
- end
48
- end
49
-
50
33
  # @param [String] spec
51
34
  # The name of the specification.
52
35
  #
@@ -37,7 +37,7 @@ module Pod
37
37
  query = @use_regex ? @query : Regexp.escape(@query)
38
38
  filepath = if @show_all
39
39
  specs = get_path_of_spec(query, @show_all).split(/\n/)
40
- index = choose_from_array(specs, "Which spec would you like to print [1-#{ specs.count }]? ")
40
+ index = UI.choose_from_array(specs, "Which spec would you like to print [1-#{ specs.count }]? ")
41
41
  specs[index]
42
42
  else
43
43
  get_path_of_spec(query)
@@ -177,6 +177,7 @@ Pod::Spec.new do |s|
177
177
  # When using multiple platforms
178
178
  # s.ios.deployment_target = "5.0"
179
179
  # s.osx.deployment_target = "10.7"
180
+ # s.watchos.deployment_target = "2.0"
180
181
 
181
182
 
182
183
  # ――― Source Location ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
@@ -38,7 +38,7 @@ module Pod
38
38
  if @show_all
39
39
  specs = get_path_of_spec(query, @show_all).split(/\n/)
40
40
  message = "Which spec would you like to edit [1-#{specs.count}]? "
41
- index = choose_from_array(specs, message)
41
+ index = UI.choose_from_array(specs, message)
42
42
  filepath = specs[index]
43
43
  else
44
44
  filepath = get_path_of_spec(query)
@@ -42,7 +42,7 @@ module Pod
42
42
 
43
43
  def run
44
44
  UI.puts
45
- invalid_count = 0
45
+ failure_reasons = []
46
46
  podspecs_to_lint.each do |podspec|
47
47
  validator = Validator.new(podspec, @source_urls)
48
48
  validator.quick = @quick
@@ -53,7 +53,7 @@ module Pod
53
53
  validator.only_subspec = @only_subspec
54
54
  validator.use_frameworks = @use_frameworks
55
55
  validator.validate
56
- invalid_count += 1 unless validator.validated?
56
+ failure_reasons << validator.failure_reason
57
57
 
58
58
  unless @clean
59
59
  UI.puts "Pods project available at `#{validator.validation_dir}/Pods/Pods.xcodeproj` for inspection."
@@ -63,11 +63,17 @@ module Pod
63
63
 
64
64
  count = podspecs_to_lint.count
65
65
  UI.puts "Analyzed #{count} #{'podspec'.pluralize(count)}.\n\n"
66
- if invalid_count == 0
66
+
67
+ failure_reasons.compact!
68
+ if failure_reasons.empty?
67
69
  lint_passed_message = count == 1 ? "#{podspecs_to_lint.first.basename} passed validation." : 'All the specs passed validation.'
68
70
  UI.puts lint_passed_message.green << "\n\n"
69
71
  else
70
- raise Informative, count == 1 ? 'The spec did not pass validation.' : "#{invalid_count} out of #{count} specs failed validation."
72
+ raise Informative, if count == 1
73
+ "The spec did not pass validation, due to #{failure_reasons.first}."
74
+ else
75
+ "#{invalid_count} out of #{count} specs failed validation."
76
+ end
71
77
  end
72
78
  podspecs_tmp_dir.rmtree if podspecs_tmp_dir.exist?
73
79
  end
@@ -19,6 +19,7 @@ module Pod
19
19
 
20
20
  :clean => true,
21
21
  :integrate_targets => true,
22
+ :deduplicate_targets => true,
22
23
  :lock_pod_source => true,
23
24
  :new_version_message => ENV['COCOAPODS_SKIP_UPDATE_MESSAGE'].nil?,
24
25
 
@@ -89,6 +90,11 @@ module Pod
89
90
  attr_accessor :integrate_targets
90
91
  alias_method :integrate_targets?, :integrate_targets
91
92
 
93
+ # @return [Bool] Whether CocoaPods should deduplicate pod targets.
94
+ #
95
+ attr_accessor :deduplicate_targets
96
+ alias_method :deduplicate_targets?, :deduplicate_targets
97
+
92
98
  # @return [Bool] Whether the installer should skip the repos update.
93
99
  #
94
100
  attr_accessor :skip_repo_update
@@ -19,7 +19,7 @@ module Pod
19
19
  #
20
20
  def initialize(root)
21
21
  @root = Pathname(root)
22
- @root.mkpath
22
+ ensure_matching_version
23
23
  end
24
24
 
25
25
  # Downloads the Pod from the given `request`
@@ -38,8 +38,54 @@ module Pod
38
38
  raise
39
39
  end
40
40
 
41
+ # @return [Hash<String, Hash<Symbol, String>>]
42
+ # A hash whose keys are the pod name
43
+ # And values are a hash with the following keys:
44
+ # :spec_file : path to the spec file
45
+ # :name : name of the pod
46
+ # :version : pod version
47
+ # :release : boolean to tell if that's a release pod
48
+ # :slug : the slug path where the pod cache is located
49
+ #
50
+ def cache_descriptors_per_pod
51
+ specs_dir = root + 'Specs'
52
+ release_specs_dir = specs_dir + 'Release'
53
+ return {} unless specs_dir.exist?
54
+
55
+ spec_paths = specs_dir.find.select { |f| f.fnmatch('*.podspec.json') }
56
+ spec_paths.reduce({}) do |hash, spec_path|
57
+ spec = Specification.from_file(spec_path)
58
+ hash[spec.name] ||= []
59
+ is_release = spec_path.to_s.start_with?(release_specs_dir.to_s)
60
+ request = Downloader::Request.new(:spec => spec, :released => is_release)
61
+ hash[spec.name] << {
62
+ :spec_file => spec_path,
63
+ :name => spec.name,
64
+ :version => spec.version,
65
+ :release => is_release,
66
+ :slug => root + request.slug,
67
+ }
68
+ hash
69
+ end
70
+ end
71
+
41
72
  private
42
73
 
74
+ # Ensures the cache on disk was created with the same CocoaPods version as
75
+ # is currently running.
76
+ #
77
+ # @return [Void]
78
+ #
79
+ def ensure_matching_version
80
+ version_file = root + 'VERSION'
81
+ version = version_file.read.strip if version_file.file?
82
+
83
+ root.rmtree if version != Pod::VERSION && root.exist?
84
+ root.mkpath
85
+
86
+ version_file.open('w') { |f| f << Pod::VERSION }
87
+ end
88
+
43
89
  # @param [Request] request
44
90
  # the request to be downloaded.
45
91
  #
@@ -105,6 +151,7 @@ module Pod
105
151
  def uncached_pod(request)
106
152
  in_tmpdir do |target|
107
153
  result, podspecs = download(request, target)
154
+ result.location = nil
108
155
 
109
156
  podspecs.each do |name, spec|
110
157
  destination = path_for_pod(request, :name => name, :params => result.checkout_options)
@@ -64,7 +64,7 @@ module Pod
64
64
  end
65
65
 
66
66
  status = popen3(bin, command, stdout, stderr)
67
- output = stdout.join("\n") + stderr.join("\n")
67
+ output = stdout.join + stderr.join
68
68
  unless status.success?
69
69
  if raise_on_failure
70
70
  raise Informative, "#{full_command}\n\n#{output}"
@@ -80,19 +80,41 @@ module Pod
80
80
  def self.popen3(bin, command, stdout, stderr)
81
81
  require 'open3'
82
82
  Open3.popen3(bin, *command) do |i, o, e, t|
83
- Thread.new { while s = o.gets; stdout << s; end }
84
- Thread.new { while s = e.gets; stderr << s; end }
83
+ reader(o, stdout)
84
+ reader(e, stderr)
85
85
  i.close
86
+
86
87
  status = t.value
87
88
 
88
89
  o.flush
89
90
  e.flush
90
- sleep(0.1)
91
+ sleep(0.01)
91
92
 
92
93
  status
93
94
  end
94
95
  end
95
96
 
97
+ def self.reader(input, output)
98
+ Thread.new do
99
+ buf = ''
100
+ begin
101
+ loop do
102
+ buf << input.readpartial(4096)
103
+ loop do
104
+ string, separator, buf = buf.partition(/[\r\n]/)
105
+ if separator.empty?
106
+ buf = string
107
+ break
108
+ end
109
+ output << (string << separator)
110
+ end
111
+ end
112
+ rescue EOFError
113
+ output << (buf << $/) unless buf.empty?
114
+ end
115
+ end
116
+ end
117
+
96
118
  #-------------------------------------------------------------------------#
97
119
 
98
120
  # Helper class that allows to write to an {IO} instance taking into account
@@ -125,8 +147,7 @@ module Pod
125
147
  #
126
148
  def <<(value)
127
149
  super
128
- ensure
129
- @io << "#{ indent }#{ value }" if @io
150
+ io << "#{ indent }#{ value }" if io
130
151
  end
131
152
  end
132
153
  end
@@ -1,5 +1,5 @@
1
1
  module Pod
2
2
  # The version of the cocoapods command line tool.
3
3
  #
4
- VERSION = '0.37.2' unless defined? Pod::VERSION
4
+ VERSION = '0.38.0.beta.1' unless defined? Pod::VERSION
5
5
  end
@@ -51,6 +51,7 @@ module Pod
51
51
  EXTERNAL_STRINGS_FILE_MIMINUM_DEPLOYMENT_TARGET = {
52
52
  :ios => Version.new('6.0'),
53
53
  :osx => Version.new('10.8'),
54
+ :watchos => Version.new('2.0'),
54
55
  }
55
56
 
56
57
  # @return [Bool] Whether the external strings file is supported by the
@@ -1,24 +1,15 @@
1
1
  module Pod
2
2
  module Generator
3
3
  class EmbedFrameworksScript
4
- # @return [TargetDefinition] The target definition, whose label will be
5
- # used to locate the target-specific build products.
6
- #
7
- attr_reader :target_definition
8
-
9
- # @return [Hash{String, Array{String}] Multiple lists of frameworks per
4
+ # @return [Hash{String => Array<String>}] Multiple lists of frameworks per
10
5
  # configuration.
11
6
  #
12
7
  attr_reader :frameworks_by_config
13
8
 
14
- # @param [TargetDefinition] target_definition
15
- # @see #target_definition
16
- #
17
- # @param [Hash{String, Array{String}] frameworks_by_config
9
+ # @param [Hash{String => Array<String>] frameworks_by_config
18
10
  # @see #frameworks_by_config
19
11
  #
20
- def initialize(target_definition, frameworks_by_config)
21
- @target_definition = target_definition
12
+ def initialize(frameworks_by_config)
22
13
  @frameworks_by_config = frameworks_by_config
23
14
  end
24
15
 
@@ -54,7 +45,12 @@ module Pod
54
45
 
55
46
  install_framework()
56
47
  {
57
- local source="${BUILT_PRODUCTS_DIR}/#{target_definition.label}/$1"
48
+ if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then
49
+ local source="${BUILT_PRODUCTS_DIR}/$1"
50
+ else
51
+ local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")"
52
+ fi
53
+
58
54
  local destination="${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
59
55
 
60
56
  if [ -L "${source}" ]; then
@@ -63,33 +59,32 @@ module Pod
63
59
  fi
64
60
 
65
61
  # use filter instead of exclude so missing patterns dont' throw errors
66
- echo "rsync -av --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers/\" --filter \"- PrivateHeaders/\" --filter \"- Modules/\" ${source} ${destination}"
67
- rsync -av --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers/" --filter "- PrivateHeaders/" --filter "- Modules/" "${source}" "${destination}"
62
+ echo "rsync -av --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" ${source} ${destination}"
63
+ rsync -av --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}"
64
+
68
65
  # Resign the code if required by the build settings to avoid unstable apps
69
- if [ "${CODE_SIGNING_REQUIRED}" == "YES" ]; then
70
- code_sign "${destination}/$1"
71
- fi
66
+ code_sign_if_enabled "${destination}/$(basename "$1")"
72
67
 
73
68
  # Embed linked Swift runtime libraries
74
69
  local basename
75
- basename=$(echo $1 | sed -E s/\\\\..+// && exit ${PIPESTATUS[0]})
70
+ basename=$(basename $1 | sed -E s/\\\\..+// && exit ${PIPESTATUS[0]})
76
71
  local swift_runtime_libs
77
- swift_runtime_libs=$(xcrun otool -LX "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/$1/${basename}" | grep --color=never @rpath/libswift | sed -E s/@rpath\\\\/\\(.+dylib\\).*/\\\\1/g | uniq -u && exit ${PIPESTATUS[0]})
72
+ swift_runtime_libs=$(xcrun otool -LX "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/${basename}.framework/${basename}" | grep --color=never @rpath/libswift | sed -E s/@rpath\\\\/\\(.+dylib\\).*/\\\\1/g | uniq -u && exit ${PIPESTATUS[0]})
78
73
  for lib in $swift_runtime_libs; do
79
74
  echo "rsync -auv \\"${SWIFT_STDLIB_PATH}/${lib}\\" \\"${destination}\\""
80
75
  rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}"
81
- if [ "${CODE_SIGNING_REQUIRED}" == "YES" ]; then
82
- code_sign "${destination}/${lib}"
83
- fi
76
+ code_sign_if_enabled "${destination}/${lib}"
84
77
  done
85
78
  }
86
79
 
87
80
  # Signs a framework with the provided identity
88
- code_sign() {
89
- # Use the current code_sign_identitiy
90
- echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}"
91
- echo "/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} --preserve-metadata=identifier,entitlements $1"
92
- /usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} --preserve-metadata=identifier,entitlements "$1"
81
+ code_sign_if_enabled() {
82
+ if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then
83
+ # Use the current code_sign_identitiy
84
+ echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}"
85
+ echo "/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} --preserve-metadata=identifier,entitlements $1"
86
+ /usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} --preserve-metadata=identifier,entitlements "$1"
87
+ fi
93
88
  }
94
89
 
95
90
  eos
@@ -82,7 +82,11 @@ module Pod
82
82
  # @return [String]
83
83
  #
84
84
  def generate_platform_import_header
85
- "#import #{platform == :ios ? '<UIKit/UIKit.h>' : '<Cocoa/Cocoa.h>'}\n"
85
+ case platform.name
86
+ when :ios then "#import <UIKit/UIKit.h>\n"
87
+ when :osx then "#import <Cocoa/Cocoa.h>\n"
88
+ else "#import <Foundation/Foundation.h>\n"
89
+ end
86
90
  end
87
91
  end
88
92
  end
@@ -18,7 +18,7 @@ module Pod
18
18
  # @see target
19
19
  #
20
20
  def initialize(target)
21
- super(target.target_definition.platform)
21
+ super(target.platform)
22
22
  @target = target
23
23
  end
24
24
 
@@ -49,26 +49,62 @@ module Pod
49
49
  # @return [Xcodeproj::Config]
50
50
  #
51
51
  def generate
52
- pod_targets = target.pod_targets_for_build_configuration(@configuration_name)
53
52
  config = {
54
53
  'OTHER_LDFLAGS' => '$(inherited) ' + XCConfigHelper.default_ld_flags(target),
55
- 'OTHER_LIBTOOLFLAGS' => '$(OTHER_LDFLAGS)',
56
54
  'PODS_ROOT' => target.relative_pods_root,
57
55
  'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) COCOAPODS=1',
58
56
  }
57
+ @xcconfig = Xcodeproj::Config.new(config)
58
+
59
+ @xcconfig.merge!(merged_user_target_xcconfigs)
60
+
61
+ generate_settings_to_import_pod_targets
62
+
63
+ XCConfigHelper.add_target_specific_settings(target, @xcconfig)
64
+
65
+ generate_vendored_build_settings
66
+ generate_other_ld_flags
67
+
68
+ # TODO: Need to decide how we are going to ensure settings like these
69
+ # are always excluded from the user's project.
70
+ #
71
+ # See https://github.com/CocoaPods/CocoaPods/issues/1216
72
+ @xcconfig.attributes.delete('USE_HEADERMAP')
73
+
74
+ generate_ld_runpath_search_paths if target.requires_frameworks?
75
+
76
+ @xcconfig
77
+ end
78
+
79
+ #---------------------------------------------------------------------#
80
+
81
+ private
59
82
 
83
+ # Add build settings, which ensure that the pod targets can be imported
84
+ # from the integrating target by all sort of imports, which are:
85
+ # - `#import <…>`
86
+ # - `#import "…"`
87
+ # - `@import …;` / `import …`
88
+ #
89
+ def generate_settings_to_import_pod_targets
60
90
  if target.requires_frameworks?
61
91
  # Framework headers are automatically discoverable by `#import <…>`.
62
- header_search_paths = pod_targets.map { |target| "$PODS_FRAMEWORK_BUILD_PATH/#{target.product_name}/Headers" }
92
+ header_search_paths = target.pod_targets.map do |target|
93
+ if target.scoped?
94
+ "$PODS_FRAMEWORK_BUILD_PATH/#{target.product_name}/Headers"
95
+ else
96
+ "$CONFIGURATION_BUILD_DIR/#{target.product_name}/Headers"
97
+ end
98
+ end
63
99
  build_settings = {
64
- 'PODS_FRAMEWORK_BUILD_PATH' => target.configuration_build_dir,
100
+ 'PODS_FRAMEWORK_BUILD_PATH' => target.scoped_configuration_build_dir,
65
101
  # Make headers discoverable by `import "…"`
66
102
  'OTHER_CFLAGS' => '$(inherited) ' + XCConfigHelper.quote(header_search_paths, '-iquote'),
67
103
  }
68
- if target.pod_targets.any?(&:should_build?)
104
+ if target.pod_targets.any? { |t| t.should_build? && t.scoped? }
69
105
  build_settings['FRAMEWORK_SEARCH_PATHS'] = '$(inherited) "$PODS_FRAMEWORK_BUILD_PATH"'
70
106
  end
71
- config.merge!(build_settings)
107
+ @xcconfig.merge!(build_settings)
72
108
  else
73
109
  # Make headers discoverable from $PODS_ROOT/Headers directory
74
110
  header_search_paths = target.sandbox.public_headers.search_paths(target.platform)
@@ -78,44 +114,50 @@ module Pod
78
114
  # by `#import <…>`
79
115
  'OTHER_CFLAGS' => '$(inherited) ' + XCConfigHelper.quote(header_search_paths, '-isystem'),
80
116
  }
81
- config.merge!(build_settings)
117
+ @xcconfig.merge!(build_settings)
82
118
  end
119
+ end
83
120
 
84
- @xcconfig = Xcodeproj::Config.new(config)
85
-
86
- XCConfigHelper.add_target_specific_settings(target, @xcconfig)
87
-
88
- pod_targets.each do |pod_target|
121
+ # Add custom build settings and required build settings to link to
122
+ # vendored libraries and frameworks.
123
+ #
124
+ # @note
125
+ # In case of generated pod targets, which require frameworks, the
126
+ # vendored frameworks and libraries are already linked statically
127
+ # into the framework binary and must not be linked again to the
128
+ # user target.
129
+ #
130
+ def generate_vendored_build_settings
131
+ target.pod_targets.each do |pod_target|
89
132
  unless pod_target.should_build? && pod_target.requires_frameworks?
90
- # In case of generated pod targets, which require frameworks, the
91
- # vendored frameworks and libraries are already linked statically
92
- # into the framework binary and must not be linked again to the
93
- # user target.
94
133
  XCConfigHelper.add_settings_for_file_accessors_of_target(pod_target, @xcconfig)
95
134
  end
135
+ end
136
+ end
96
137
 
97
- # Add pod target to list of frameworks / libraries that are
98
- # linked with the user’s project.
99
- if pod_target.should_build?
100
- if pod_target.requires_frameworks?
101
- @xcconfig.merge!('OTHER_LDFLAGS' => %(-framework "#{pod_target.product_basename}"))
102
- else
103
- @xcconfig.merge!('OTHER_LDFLAGS' => %(-l "#{pod_target.product_basename}"))
104
- end
138
+ # Add pod target to list of frameworks / libraries that are linked
139
+ # with the user’s project.
140
+ #
141
+ def generate_other_ld_flags
142
+ other_ld_flags = target.pod_targets.select(&:should_build?).map do |pod_target|
143
+ if pod_target.requires_frameworks?
144
+ %(-framework "#{pod_target.product_basename}")
145
+ else
146
+ %(-l "#{pod_target.product_basename}")
105
147
  end
106
148
  end
107
149
 
108
- # TODO: Need to decide how we are going to ensure settings like these
109
- # are always excluded from the user's project.
110
- #
111
- # See https://github.com/CocoaPods/CocoaPods/issues/1216
112
- @xcconfig.attributes.delete('USE_HEADERMAP')
113
-
114
- generate_ld_runpath_search_paths if target.requires_frameworks?
115
-
116
- @xcconfig
150
+ @xcconfig.merge!('OTHER_LDFLAGS' => other_ld_flags.join(' '))
117
151
  end
118
152
 
153
+ # Ensure to add the default linker run path search paths as they could
154
+ # be not present due to being historically absent in the project or
155
+ # target template or just being removed by being superficial when
156
+ # linking third-party dependencies exclusively statically. This is not
157
+ # something a project needs specifically for the integration with
158
+ # CocoaPods, but makes sure that it is self-contained for the given
159
+ # constraints.
160
+ #
119
161
  def generate_ld_runpath_search_paths
120
162
  ld_runpath_search_paths = ['$(inherited)']
121
163
  if target.platform.symbolic_name == :osx
@@ -135,6 +177,70 @@ module Pod
135
177
  @xcconfig.merge!('LD_RUNPATH_SEARCH_PATHS' => ld_runpath_search_paths.join(' '))
136
178
  end
137
179
 
180
+ private
181
+
182
+ #---------------------------------------------------------------------#
183
+
184
+ # !@group Private Helpers
185
+
186
+ # Returns the {PodTarget}s which are active for the current
187
+ # configuration name.
188
+ #
189
+ # @return [Array<PodTarget>]
190
+ #
191
+ def pod_targets
192
+ target.pod_targets_for_build_configuration(@configuration_name)
193
+ end
194
+
195
+ # Returns the +user_target_xcconfig+ for all pod targets grouped by keys
196
+ #
197
+ # @return [Hash{String,Hash{Target,String}]
198
+ #
199
+ def user_target_xcconfig_values_by_target_by_key
200
+ pod_targets.each_with_object({}) do |target, hash|
201
+ target.spec_consumers.each do |spec_consumer|
202
+ spec_consumer.user_target_xcconfig.each do |k, v|
203
+ (hash[k] ||= {})[target] = v
204
+ end
205
+ end
206
+ end
207
+ end
208
+
209
+ # Merges the +user_target_xcconfig+ for all pod targets into the
210
+ # #xcconfig and warns on conflicting definitions.
211
+ #
212
+ # @return [Hash{String, String}]
213
+ #
214
+ def merged_user_target_xcconfigs
215
+ settings = user_target_xcconfig_values_by_target_by_key
216
+ settings.each_with_object({}) do |(key, values_by_target), xcconfig|
217
+ uniq_values = values_by_target.values.uniq
218
+ values_are_bools = uniq_values.all? { |v| v =~ /(yes|no)/i }
219
+ if values_are_bools
220
+ # Boolean build settings
221
+ if uniq_values.count > 1
222
+ UI.warn 'Can\'t merge user_target_xcconfig for pod targets: ' \
223
+ "#{values_by_target.keys.map(&:label)}. Boolean build "\
224
+ "setting #{key} has different values."
225
+ else
226
+ xcconfig[key] = uniq_values.first
227
+ end
228
+ elsif key =~ /S$/
229
+ # Plural build settings
230
+ xcconfig[key] = uniq_values.join(' ')
231
+ else
232
+ # Singular build settings
233
+ if uniq_values.count > 1
234
+ UI.warn 'Can\'t merge user_target_xcconfig for pod targets: ' \
235
+ "#{values_by_target.keys.map(&:label)}. Singular build "\
236
+ "setting #{key} has different values."
237
+ else
238
+ xcconfig[key] = uniq_values.first
239
+ end
240
+ end
241
+ end
242
+ end
243
+
138
244
  #---------------------------------------------------------------------#
139
245
  end
140
246
  end