cocoapods 0.14.0 → 0.15.0

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 (37) hide show
  1. data/CHANGELOG.md +42 -9
  2. data/bin/pod +4 -0
  3. data/lib/cocoapods.rb +2 -2
  4. data/lib/cocoapods/command.rb +2 -25
  5. data/lib/cocoapods/command/install.rb +1 -2
  6. data/lib/cocoapods/command/linter.rb +24 -4
  7. data/lib/cocoapods/command/list.rb +16 -11
  8. data/lib/cocoapods/command/outdated.rb +2 -4
  9. data/lib/cocoapods/command/push.rb +10 -10
  10. data/lib/cocoapods/command/repo.rb +22 -20
  11. data/lib/cocoapods/command/search.rb +6 -4
  12. data/lib/cocoapods/command/setup.rb +15 -14
  13. data/lib/cocoapods/command/spec.rb +17 -14
  14. data/lib/cocoapods/command/update.rb +9 -1
  15. data/lib/cocoapods/config.rb +12 -4
  16. data/lib/cocoapods/dependency.rb +18 -15
  17. data/lib/cocoapods/downloader/git.rb +41 -28
  18. data/lib/cocoapods/downloader/http.rb +10 -3
  19. data/lib/cocoapods/downloader/mercurial.rb +6 -4
  20. data/lib/cocoapods/downloader/subversion.rb +6 -2
  21. data/lib/cocoapods/executable.rb +6 -6
  22. data/lib/cocoapods/generator/acknowledgements/markdown.rb +1 -0
  23. data/lib/cocoapods/installer.rb +73 -57
  24. data/lib/cocoapods/installer/target_installer.rb +15 -11
  25. data/lib/cocoapods/installer/user_project_integrator.rb +25 -16
  26. data/lib/cocoapods/local_pod.rb +34 -12
  27. data/lib/cocoapods/podfile.rb +15 -0
  28. data/lib/cocoapods/resolver.rb +33 -39
  29. data/lib/cocoapods/source.rb +172 -48
  30. data/lib/cocoapods/specification.rb +48 -32
  31. data/lib/cocoapods/specification/set.rb +102 -34
  32. data/lib/cocoapods/specification/statistics.rb +1 -1
  33. data/lib/cocoapods/user_interface.rb +215 -0
  34. data/lib/cocoapods/user_interface/ui_pod.rb +130 -0
  35. metadata +7 -7
  36. data/lib/cocoapods/command/presenter.rb +0 -61
  37. data/lib/cocoapods/command/presenter/cocoa_pod.rb +0 -118
@@ -8,11 +8,15 @@ module Pod
8
8
  end
9
9
 
10
10
  def download
11
- svn! %|export "#{reference_url}" "#{target_path}"|
11
+ UI.section(' > Exporting subversion repo', '', 3) do
12
+ svn! %|export "#{reference_url}" "#{target_path}"|
13
+ end
12
14
  end
13
15
 
14
16
  def download_head
15
- svn! %|export "#{trunk_url}" "#{target_path}"|
17
+ UI.section(' > Exporting subversion repo', '', 3) do
18
+ svn! %|export "#{trunk_url}" "#{target_path}"|
19
+ end
16
20
  end
17
21
 
18
22
  def reference_url
@@ -3,12 +3,14 @@ require 'open4'
3
3
  module Pod
4
4
  module Executable
5
5
  class Indenter < ::Array
6
+ include Config::Mixin
7
+
6
8
  attr_accessor :indent
7
9
  attr_accessor :io
8
10
 
9
- def initialize(io = nil, indent = ' ')
11
+ def initialize(io = nil)
10
12
  @io = io
11
- @indent = indent
13
+ @indent = ' ' * UI.indentation_level
12
14
  end
13
15
 
14
16
  def <<(value)
@@ -27,20 +29,19 @@ module Pod
27
29
  end
28
30
  full_command = "#{bin} #{command}"
29
31
  if Config.instance.verbose?
30
- puts " $ #{full_command}"
32
+ UI.message("$ #{full_command}")
31
33
  stdout, stderr = Indenter.new(STDOUT), Indenter.new(STDERR)
32
34
  else
33
35
  stdout, stderr = Indenter.new, Indenter.new
34
36
  end
35
37
  status = Open4.spawn(full_command, :stdout => stdout, :stderr => stderr, :status => true)
36
- # TODO not sure that we should be silent in case of a failure.
37
38
 
38
39
  output = stdout.join("\n") + stderr.join("\n") # TODO will this suffice?
39
40
  unless status.success?
40
41
  if should_raise
41
42
  raise Informative, "#{name} #{command}\n\n#{output}"
42
43
  else
43
- puts((Config.instance.verbose? ? ' ' : '') << "[!] Failed: #{full_command}".red) unless Config.instance.silent?
44
+ UI.message("[!] Failed: #{full_command}".red)
44
45
  end
45
46
  end
46
47
  output
@@ -54,7 +55,6 @@ module Pod
54
55
  send(base_method, command, true)
55
56
  end
56
57
 
57
-
58
58
  private name
59
59
  end
60
60
  end
@@ -28,6 +28,7 @@ module Pod
28
28
  licenses_string = "#{title_from_string(header_title, 1)}\n#{header_text}\n"
29
29
  @pods.each do |pod|
30
30
  if (license = string_for_pod(pod))
31
+ license = license.force_encoding("UTF-8") if license.respond_to?(:force_encoding)
31
32
  licenses_string += license
32
33
  end
33
34
  end
@@ -23,7 +23,7 @@ module Pod
23
23
  # Add all source files to the project grouped by pod
24
24
  pod.relative_source_files_by_spec.each do |spec, paths|
25
25
  parent_group = pod.local? ? @project.local_pods : @project.pods
26
- group = @project.add_spec_group(pod.name, parent_group)
26
+ group = @project.add_spec_group(spec.name, parent_group)
27
27
  paths.each do |path|
28
28
  group.files.new('path' => path.to_s)
29
29
  end
@@ -49,23 +49,21 @@ module Pod
49
49
  def install_dependencies!
50
50
  pods.sort_by { |pod| pod.top_specification.name.downcase }.each do |pod|
51
51
  should_install = @resolver.should_install?(pod.top_specification.name) || !pod.exists?
52
-
53
- unless config.silent?
54
- marker = config.verbose ? "\n-> ".green : ''
55
- puts marker << ( should_install ? "Installing #{pod}".green : "Using #{pod}" )
56
- end
57
-
58
52
  if should_install
59
- unless pod.downloaded?
60
- pod.implode
61
- download_pod(pod)
53
+ UI.section("Installing #{pod}".green, "-> ".green) do
54
+ unless pod.downloaded?
55
+ pod.implode
56
+ download_pod(pod)
57
+ end
58
+ # The docs need to be generated before cleaning because the
59
+ # documentation is created for all the subspecs.
60
+ generate_docs(pod)
61
+ # Here we clean pod's that just have been downloaded or have been
62
+ # pre-downloaded in AbstractExternalSource#specification_from_sandbox.
63
+ pod.clean! if config.clean?
62
64
  end
63
- # The docs need to be generated before cleaning because the
64
- # documentation is created for all the subspecs.
65
- generate_docs(pod)
66
- # Here we clean pod's that just have been downloaded or have been
67
- # pre-downloaded in AbstractExternalSource#specification_from_sandbox.
68
- pod.clean! if config.clean?
65
+ else
66
+ UI.section("Using #{pod}", "-> ".green)
69
67
  end
70
68
  end
71
69
  end
@@ -89,10 +87,10 @@ module Pod
89
87
  def generate_docs(pod)
90
88
  doc_generator = Generator::Documentation.new(pod)
91
89
  if ( config.generate_docs? && !doc_generator.already_installed? )
92
- puts "-> Installing documentation" if config.verbose?
90
+ UI.section " > Installing documentation"
93
91
  doc_generator.generate(config.doc_install?)
94
92
  else
95
- puts "-> Using existing documentation" if config.verbose?
93
+ UI.section " > Using existing documentation"
96
94
  end
97
95
  end
98
96
 
@@ -100,47 +98,65 @@ module Pod
100
98
  #
101
99
  def remove_deleted_dependencies!
102
100
  resolver.removed_pods.each do |pod_name|
103
- marker = config.verbose ? "\n-> ".red : ''
104
- path = sandbox.root + pod_name
105
- puts marker << "Removing #{pod_name}".red
106
- path.rmtree if path.exist?
101
+ UI.section("Removing #{pod_name}", "-> ".red) do
102
+ path = sandbox.root + pod_name
103
+ path.rmtree if path.exist?
104
+ end
107
105
  end
108
106
  end
109
107
 
110
108
  def install!
111
109
  @sandbox.prepare_for_install
110
+ UI.section "Resolving dependencies of #{UI.path @podfile.defined_in_file}" do
111
+ specs_by_target
112
+ end
112
113
 
113
- print_title "Resolving dependencies of: #{@podfile.defined_in_file}"
114
- specs_by_target
114
+ UI.section "Removing deleted dependencies" do
115
+ remove_deleted_dependencies!
116
+ end unless resolver.removed_pods.empty?
115
117
 
116
- print_title "Removing deleted dependencies" unless resolver.removed_pods.empty?
117
- remove_deleted_dependencies!
118
+ UI.section "Downloading dependencies" do
119
+ install_dependencies!
120
+ end
118
121
 
119
- print_title "Installing dependencies"
120
- install_dependencies!
122
+ UI.section "Generating support files" do
123
+ UI.message "- Running pre install hooks" do
124
+ run_pre_install_hooks
125
+ end
121
126
 
122
- print_title("Generating support files\n", false)
123
- target_installers.each do |target_installer|
124
- pods_for_target = pods_by_target[target_installer.target_definition]
125
- target_installer.install!(pods_for_target, @sandbox)
126
- acknowledgements_path = target_installer.target_definition.acknowledgements_path
127
- Generator::Acknowledgements.new(target_installer.target_definition,
128
- pods_for_target).save_as(acknowledgements_path)
129
- generate_dummy_source(target_installer)
130
- end
127
+ UI.message"- Generating project" do
128
+ project
129
+ end
130
+
131
+ UI.message"- Installing targets" do
132
+ generate_target_support_files
133
+ end
134
+
135
+ UI.message "- Running post install hooks" do
136
+ # Post install hooks run _before_ saving of project, so that they can alter it before saving.
137
+ run_post_install_hooks
138
+ end
131
139
 
132
- puts "- Running post install hooks" if config.verbose?
133
- # Post install hooks run _before_ saving of project, so that they can alter it before saving.
134
- run_post_install_hooks
140
+ UI.message "- Writing Xcode project file to #{UI.path @sandbox.project_path}" do
141
+ project.save_as(@sandbox.project_path)
142
+ end
135
143
 
136
- puts "- Writing Xcode project file to `#{@sandbox.project_path}'" if config.verbose?
137
- project.save_as(@sandbox.project_path)
144
+ UI.message "- Writing lockfile in #{UI.path config.project_lockfile}" do
145
+ @lockfile = Lockfile.generate(@podfile, specs_by_target.values.flatten)
146
+ @lockfile.write_to_disk(config.project_lockfile)
147
+ end
148
+ end
138
149
 
139
- puts "- Writing lockfile in `#{config.project_lockfile}'\n\n" if config.verbose?
140
- @lockfile = Lockfile.generate(@podfile, specs_by_target.values.flatten)
141
- @lockfile.write_to_disk(config.project_lockfile)
150
+ UserProjectIntegrator.new(@podfile).integrate! if config.integrate_targets?
151
+ end
142
152
 
143
- UserProjectIntegrator.new(@podfile).integrate! if config.integrate_targets?
153
+ def run_pre_install_hooks
154
+ pods_by_target.each do |target_definition, pods|
155
+ pods.each do |pod|
156
+ pod.top_specification.pre_install(pod, target_definition)
157
+ end
158
+ end
159
+ @podfile.pre_install!(self)
144
160
  end
145
161
 
146
162
  def run_post_install_hooks
@@ -151,10 +167,20 @@ module Pod
151
167
  spec.post_install(target_installer)
152
168
  end
153
169
  end
154
-
155
170
  @podfile.post_install!(self)
156
171
  end
157
172
 
173
+ def generate_target_support_files
174
+ target_installers.each do |target_installer|
175
+ pods_for_target = pods_by_target[target_installer.target_definition]
176
+ target_installer.install!(pods_for_target, @sandbox)
177
+ acknowledgements_path = target_installer.target_definition.acknowledgements_path
178
+ Generator::Acknowledgements.new(target_installer.target_definition,
179
+ pods_for_target).save_as(acknowledgements_path)
180
+ generate_dummy_source(target_installer)
181
+ end
182
+ end
183
+
158
184
  def generate_dummy_source(target_installer)
159
185
  class_name_identifier = target_installer.target_definition.label
160
186
  dummy_source = Generator::DummySource.new(class_name_identifier)
@@ -198,15 +224,5 @@ module Pod
198
224
  end
199
225
  result
200
226
  end
201
-
202
- private
203
-
204
- def print_title(title, only_verbose = true)
205
- if config.verbose?
206
- puts "\n" + title.yellow
207
- elsif !config.silent? && !only_verbose
208
- puts title
209
- end
210
- end
211
227
  end
212
228
  end
@@ -97,20 +97,24 @@ module Pod
97
97
  end
98
98
 
99
99
  def create_files(pods, sandbox)
100
- if @podfile.generate_bridge_support?
101
- bridge_support_metadata_path = sandbox.root + @target_definition.bridge_support_name
102
- puts "- Generating BridgeSupport metadata file at `#{bridge_support_metadata_path}'" if config.verbose?
100
+ bridge_support_metadata_path = sandbox.root + @target_definition.bridge_support_name
101
+ UI.message "- Generating BridgeSupport metadata file at #{UI.path bridge_support_metadata_path}" do
103
102
  bridge_support_generator_for(pods, sandbox).save_as(bridge_support_metadata_path)
104
103
  copy_resources_script_for(pods).resources << @target_definition.bridge_support_name
104
+ end if @podfile.generate_bridge_support?
105
+
106
+ UI.message "- Generating xcconfig file at #{UI.path(sandbox.root + @target_definition.xcconfig_name)}" do
107
+ xcconfig.save_as(sandbox.root + @target_definition.xcconfig_name)
108
+ @target_definition.xcconfig = xcconfig
109
+ end
110
+
111
+ UI.message "- Generating prefix header at #{UI.path(sandbox.root + @target_definition.prefix_header_name)}" do
112
+ save_prefix_header_as(sandbox.root + @target_definition.prefix_header_name, pods)
113
+ end
114
+
115
+ UI.message "- Generating copy resources script at #{UI.path(sandbox.root + @target_definition.copy_resources_script_name)}" do
116
+ copy_resources_script_for(pods).save_as(sandbox.root + @target_definition.copy_resources_script_name)
105
117
  end
106
- puts "- Generating xcconfig file at `#{sandbox.root + @target_definition.xcconfig_name}'" if config.verbose?
107
- xcconfig.save_as(sandbox.root + @target_definition.xcconfig_name)
108
- @target_definition.xcconfig = xcconfig
109
-
110
- puts "- Generating prefix header at `#{sandbox.root + @target_definition.prefix_header_name}'" if config.verbose?
111
- save_prefix_header_as(sandbox.root + @target_definition.prefix_header_name, pods)
112
- puts "- Generating copy resources script at `#{sandbox.root + @target_definition.copy_resources_script_name}'" if config.verbose?
113
- copy_resources_script_for(pods).save_as(sandbox.root + @target_definition.copy_resources_script_name)
114
118
  end
115
119
 
116
120
  private
@@ -51,7 +51,7 @@ module Pod
51
51
  workspace << project_path unless workspace.include?(project_path)
52
52
  end
53
53
  unless workspace_path.exist? || config.silent?
54
- puts "[!] From now on use `#{workspace_path.basename}'."
54
+ UI.notice "From now on use `#{workspace_path.basename}'."
55
55
  end
56
56
  workspace.save_as(workspace_path)
57
57
  end
@@ -69,20 +69,30 @@ module Pod
69
69
  "#<#{self.class} for target `#{@target_definition.label}'>"
70
70
  end
71
71
 
72
+ # Integrates the user project targets. Only the targets that do **not**
73
+ # already have the Pods library in their frameworks build phase are
74
+ # processed.
75
+ #
76
+ # @return [void]
77
+ #
72
78
  def integrate!
73
79
  return if targets.empty?
74
80
 
75
- unless Config.instance.silent?
76
- puts "-> Integrating `#{@target_definition.lib_name}' into #{'target'.pluralize(targets.size)} " \
77
- "`#{targets.map(&:name).to_sentence}' of Xcode project `#{user_project_path.basename}'.".green
81
+ UI.section("Integrating `#{@target_definition.lib_name}' into #{'target'.pluralize(targets.size)} " \
82
+ "`#{targets.map(&:name).to_sentence}' of Xcode project #{UI.path user_project_path}.") do
83
+ add_xcconfig_base_configuration
84
+ add_pods_library
85
+ add_copy_resources_script_phase
86
+ user_project.save_as(@target_definition.user_project.path)
78
87
  end
79
-
80
- add_xcconfig_base_configuration
81
- add_pods_library
82
- add_copy_resources_script_phase
83
- user_project.save_as(@target_definition.user_project.path)
84
88
  end
85
89
 
90
+ # @return [Pathname] the path of the user project.
91
+ #
92
+ # @raises If the path doesn't exits.
93
+ #
94
+ # @raises If the project is implicit and there are multiple projects.
95
+ #
86
96
  def user_project_path
87
97
  if path = @target_definition.user_project.path
88
98
  unless path.exist?
@@ -96,6 +106,8 @@ module Pod
96
106
  end
97
107
  end
98
108
 
109
+ # @return [Xcodeproj::Project] Returns the project of the user.
110
+ #
99
111
  def user_project
100
112
  @user_project ||= Xcodeproj::Project.new(user_project_path)
101
113
  end
@@ -152,13 +164,10 @@ module Pod
152
164
  config.base_configuration = xcconfig
153
165
  end
154
166
 
155
- unless config.silent?
156
- config_build_names_by_overriden_key.each do |key, config_build_names|
157
- name = "#{target.attributes["name"]} [#{config_build_names.join(' - ')}]"
158
- puts "\n[!] The target `#{name}' overrides the `#{key}' build setting defined in `#{@target_definition.xcconfig_relative_path}'.".yellow
159
- puts " - Use the `$(inherited)' flag, or"
160
- puts " - Remove the build settings from the target."
161
- end
167
+ config_build_names_by_overriden_key.each do |key, config_build_names|
168
+ name = "#{target.attributes["name"]} [#{config_build_names.join(' - ')}]"
169
+ actions = [ "Use the `$(inherited)' flag, or", "Remove the build settings from the target." ]
170
+ UI.warn("The target `#{name}' overrides the `#{key}' build setting defined in `#{@target_definition.xcconfig_relative_path}'.", actions)
162
171
  end
163
172
  end
164
173
  end
@@ -187,6 +187,27 @@ module Pod
187
187
 
188
188
  # @!group Files
189
189
 
190
+ # @return [Pathname] Returns the relative path from the sandbox.
191
+ #
192
+ # @note If the two abosule paths don't share the same root directory an
193
+ # extra `../` is added to the result of {Pathname#relative_path_from}
194
+ #
195
+ # path = Pathname.new('/Users/dir')
196
+ # @sandbox
197
+ # #=> Pathname('/tmp/CocoaPods/Lint/Pods')
198
+ #
199
+ # p.relative_path_from(@sandbox
200
+ # #=> '../../../../Users/dir'
201
+ #
202
+ # relativize_from_sandbox(path)
203
+ # #=> '../../../../../Users/dir'
204
+ #
205
+ def relativize_from_sandbox(path)
206
+ result = path.relative_path_from(@sandbox.root)
207
+ result = Pathname.new('../') + result unless @sandbox.root.to_s.split('/')[1] == path.to_s.split('/')[1]
208
+ result
209
+ end
210
+
190
211
  # @return [Array<Pathname>] The paths of the source files.
191
212
  #
192
213
  def source_files
@@ -196,13 +217,13 @@ module Pod
196
217
  # @return [Array<Pathname>] The *relative* paths of the source files.
197
218
  #
198
219
  def relative_source_files
199
- source_files.map{ |p| p.relative_path_from(@sandbox.root) }
220
+ source_files.map{ |p| relativize_from_sandbox(p) }
200
221
  end
201
222
 
202
223
  def relative_source_files_by_spec
203
224
  result = {}
204
225
  source_files_by_spec.each do |spec, paths|
205
- result[spec] = paths.map{ |p| p.relative_path_from(@sandbox.root) }
226
+ result[spec] = paths.map{ |p| relativize_from_sandbox(p) }
206
227
  end
207
228
  result
208
229
  end
@@ -217,7 +238,7 @@ module Pod
217
238
  # {Specification}.
218
239
  #
219
240
  def source_files_by_spec
220
- options = {:glob => '*.{h,m,mm,c,cpp}'}
241
+ options = {:glob => '*.{h,hpp,m,mm,c,cpp}'}
221
242
  paths_by_spec(:source_files, options)
222
243
  end
223
244
 
@@ -230,7 +251,7 @@ module Pod
230
251
  # @return [Array<Pathname>] The *relative* paths of the source files.
231
252
  #
232
253
  def relative_header_files
233
- header_files.map{ |p| p.relative_path_from(@sandbox.root) }
254
+ header_files.map{ |p| relativize_from_sandbox(p) }
234
255
  end
235
256
 
236
257
  # @return [Hash{Specification => Array<Pathname>}] The paths of the header
@@ -239,7 +260,7 @@ module Pod
239
260
  def header_files_by_spec
240
261
  result = {}
241
262
  source_files_by_spec.each do |spec, paths|
242
- headers = paths.select { |f| f.extname == '.h' }
263
+ headers = paths.select { |f| f.extname == '.h' || f.extname == '.hpp' }
243
264
  result[spec] = headers unless headers.empty?
244
265
  end
245
266
  result
@@ -253,7 +274,7 @@ module Pod
253
274
  # header files (i.e. the build ones) are intended to be public.
254
275
  #
255
276
  def public_header_files_by_spec
256
- public_headers = paths_by_spec(:public_header_files, :glob => '*.h')
277
+ public_headers = paths_by_spec(:public_header_files, :glob => '*.{h,hpp}')
257
278
  build_headers = header_files_by_spec
258
279
 
259
280
  result = {}
@@ -276,7 +297,7 @@ module Pod
276
297
  # @return [Array<Pathname>] The *relative* paths of the resources.
277
298
  #
278
299
  def relative_resource_files
279
- resource_files.map{ |p| p.relative_path_from(@sandbox.root) }
300
+ resource_files.map{ |p| relativize_from_sandbox(p) }
280
301
  end
281
302
 
282
303
  # @return [Pathname] The absolute path of the prefix header file
@@ -356,7 +377,7 @@ module Pod
356
377
  if (public_h = public_headers[spec]) && !public_h.empty?
357
378
  result += public_h
358
379
  elsif (source_f = source_files[spec]) && !source_f.empty?
359
- build_h = source_f.select { |f| f.extname == '.h' }
380
+ build_h = source_f.select { |f| f.extname == '.h' || f.extname == '.hpp' }
360
381
  result += build_h unless build_h.empty?
361
382
  end
362
383
  end
@@ -390,7 +411,7 @@ module Pod
390
411
  source_files_by_spec.each do | spec, files |
391
412
  compiler_flags = spec.compiler_flags.strip
392
413
  files.each do |file|
393
- file = file.relative_path_from(@sandbox.root)
414
+ file = relativize_from_sandbox(file)
394
415
  desc = Xcodeproj::Project::PBXNativeTarget::SourceFileDescription.new(file, compiler_flags, nil)
395
416
  result << desc
396
417
  end
@@ -410,7 +431,7 @@ module Pod
410
431
  # (the files the need to compiled) of the pod.
411
432
  #
412
433
  def implementation_files
413
- relative_source_files.select { |f| f.extname != '.h' }
434
+ relative_source_files.reject { |f| f.extname == '.h' || f.extname == '.hpp' }
414
435
  end
415
436
 
416
437
  # @return [Pathname] The path of the pod relative from the sandbox.
@@ -432,9 +453,10 @@ module Pod
432
453
  mappings = {}
433
454
  files_by_spec.each do |spec, paths|
434
455
  paths = paths - headers_excluded_from_search_paths
456
+ dir = spec.header_dir ? (headers_sandbox + spec.header_dir) : headers_sandbox
435
457
  paths.each do |from|
436
458
  from_relative = from.relative_path_from(root)
437
- to = headers_sandbox + (spec.header_dir) + spec.copy_header_mapping(from_relative)
459
+ to = dir + spec.copy_header_mapping(from_relative)
438
460
  (mappings[to.dirname] ||= []) << from
439
461
  end
440
462
  end
@@ -452,7 +474,7 @@ module Pod
452
474
  # included in the linker search paths.
453
475
  #
454
476
  def headers_excluded_from_search_paths
455
- options = { :glob => '*.h' }
477
+ options = { :glob => '*.{h,hpp}' }
456
478
  paths = paths_by_spec(:exclude_header_search_paths, options)
457
479
  paths.values.compact.uniq
458
480
  end