cocoapods 0.14.0 → 0.15.0

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