cocoapods 0.37.2 → 0.38.0.beta.1

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