rake-builder 0.0.12 → 0.0.13

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -23,6 +23,7 @@ spec = Gem::Specification.new do |s|
23
23
  s.homepage = 'http://github.com/joeyates/rake-builder'
24
24
  s.author = 'Joe Yates'
25
25
  s.email = 'joe.g.yates@gmail.com'
26
+ s.rubyforge_project = 'nowarning'
26
27
 
27
28
  s.files = ADMIN_FILES +
28
29
  SOURCE_FILES +
data/lib/compiler.rb ADDED
@@ -0,0 +1,84 @@
1
+
2
+ module Compiler
3
+
4
+ class Base
5
+ EXTRA_PATHS = [ '/opt/local/include' ]
6
+
7
+ def self.for( compiler )
8
+ COMPILERS[ compiler ].new
9
+ end
10
+
11
+ def initialize
12
+ @paths = {}
13
+ end
14
+
15
+ def include_paths( headers )
16
+ paths = []
17
+ headers.each do | header |
18
+ path = find_header( header )
19
+ raise "Can't find header '#{ header }' in any known include path" if path.nil?
20
+ paths << path
21
+ end
22
+ paths.uniq
23
+ end
24
+
25
+ private
26
+
27
+ def find_header( header )
28
+ EXTRA_PATHS.each do | path |
29
+ if File.exist?( "#{ path }/#{ header }" )
30
+ return path
31
+ end
32
+ end
33
+ nil
34
+ end
35
+
36
+ end
37
+
38
+ class GCC < Base
39
+
40
+ def self.framework_path( framework, qt_major )
41
+ "/Library/Frameworks/#{ framework }.framework/Versions/#{ qt_major }/Headers"
42
+ end
43
+
44
+ def default_include_paths( language )
45
+ return @paths[ language ] if @paths[ language ]
46
+
47
+ paths = []
48
+ # Below is the recommended(!) way of getting standard serach paths from GCC
49
+ output = `echo | gcc -v -x #{ language } -E - 2>&1 1>/dev/null`
50
+ collecting = false
51
+ output.each_line do | line |
52
+ case
53
+ when line =~ /#include <\.\.\.> search starts here:/
54
+ collecting = true
55
+ when line =~ /End of search list\./
56
+ collecting = false
57
+ when line =~ / \(framework directory\)/
58
+ # Skip frameworks
59
+ else
60
+ paths << line.strip if collecting
61
+ end
62
+ end
63
+
64
+ @paths[ language ] = paths
65
+ end
66
+
67
+ def missing_headers( include_paths, source_files )
68
+ include_path = include_paths.map { | path | "-I#{ path }" }.join( ' ' )
69
+ command = "makedepend -f- -- #{ include_path } -- #{ source_files.join( ' ' ) } 2>&1 1>/dev/null"
70
+ output = `#{ command }`
71
+ missing = []
72
+ output.each_line do | line |
73
+ match = line.match( /cannot find include file "([^"]*)"/m )
74
+ missing << match[ 1 ] if match
75
+ end
76
+
77
+ missing
78
+ end
79
+
80
+ end
81
+
82
+ COMPILERS = { :gcc => GCC }
83
+
84
+ end
@@ -8,10 +8,10 @@ module Rake
8
8
  # generate Info.plist
9
9
  # package task
10
10
 
11
+ attr_accessor :qt_version
11
12
  attr_accessor :frameworks
12
13
  attr_accessor :resource_files
13
- attr_accessor :qt_version
14
- attr_accessor :architecture
14
+ attr_accessor :ui_files
15
15
 
16
16
  def initialize( &block )
17
17
  super( &block )
@@ -25,11 +25,20 @@ module Rake
25
25
  super
26
26
  @programming_language = 'c++'
27
27
  @header_file_extension = 'h'
28
- @frameworks = [ 'QtGui', 'QtCore' ]
29
- @framework_paths = [ '/Library/Frameworks' ]
30
- @compilation_defines = '-DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED'
31
- @moc_defines = '-D__APPLE__ -D__GNUC__'
28
+ @frameworks = []
29
+ case
30
+ when RUBY_PLATFORM =~ /linux$/
31
+ @include_paths << '/usr/include/qt4'
32
+ @moc_defines = [ '-D__GNUC__' ]
33
+ when RUBY_PLATFORM =~ /darwin/i
34
+ @framework_paths = [ '/Library/Frameworks' ]
35
+ @moc_defines = [ '-D__APPLE__', '-D__GNUC__' ]
36
+ else
37
+ raise "Unrecognised platform"
38
+ end
39
+ @compilation_defines = [ '-DQT_GUI_LIB', '-DQT_CORE_LIB', '-DQT_SHARED' ]
32
40
  @resource_files = []
41
+ @ui_files = []
33
42
  end
34
43
 
35
44
  def configure
@@ -39,37 +48,83 @@ module Rake
39
48
  super
40
49
 
41
50
  @resource_files = Rake::Path.expand_all_with_root( @resource_files, @rakefile_path )
51
+ @ui_files = Rake::Path.expand_all_with_root( @ui_files, @rakefile_path )
42
52
  @compilation_options += [ '-pipe', '-g', '-gdwarf-2', '-Wall', '-W' ]
43
- @compilation_options.uniq!
44
- @architecture ||= 'i386'
45
- @compilation_options += [ architecture_option ]
46
-
47
- @frameworks.each do | framework |
48
- @include_paths << "/Library/Frameworks/#{ framework }.framework/Versions/#{ qt_major }/Headers"
49
- @include_paths << "/usr/include/#{ framework }"
50
- end
53
+ @include_paths << @objects_path # for UI headers
51
54
  end
52
55
 
53
56
  def define
54
57
  super
58
+ define_ui_tasks
55
59
  define_moc_tasks
56
60
  define_resource_tasks
57
61
  end
58
62
 
59
63
  def generated_files
60
- super + moc_files + qrc_files
64
+ super + moc_files + ui_headers + qrc_files
65
+ end
66
+
67
+ def generated_headers
68
+ super + ui_headers
61
69
  end
62
70
 
63
71
  def source_files
64
72
  ( super + moc_files + qrc_files ).uniq
65
73
  end
66
74
 
75
+ def header_files
76
+ ( super + ui_headers ).uniq
77
+ end
78
+
67
79
  def compiler_flags
68
- [ compilation_options.join( ' ' ), @compilation_defines, include_path, framework_path_list ].join( ' ' )
80
+ flags = compilation_options + @compilation_defines + [ include_path ]
81
+ if RUBY_PLATFORM =~ /darwin/i
82
+ flags += framework_paths
83
+ flags << architecture_option
84
+ end
85
+ flags.join( ' ' )
69
86
  end
70
87
 
71
88
  def link_flags
72
- [ '-headerpad_max_install_names', architecture_option, @linker_options, library_paths_list, library_dependencies_list, framework_path_list, framework_list ].join( " " )
89
+ flags = [ @linker_options, library_paths_list, library_dependencies_list ]
90
+ if RUBY_PLATFORM =~ /darwin/i
91
+ flags += [ '-headerpad_max_install_names', architecture_option ]
92
+ flags += framework_paths + framework_options
93
+ end
94
+ flags.join( ' ' )
95
+ end
96
+
97
+ # Exclude paths like QtFoo/Bar, but grab frameworks
98
+ def missing_headers
99
+ super
100
+ @missing_headers.reject! do | path |
101
+ m = path.match( /^(Qt\w+)\/(\w+?(?:\.h)?)$/ )
102
+ if m
103
+ framework = m[ 1 ]
104
+ @frameworks << framework
105
+ framework_path = Compiler::GCC.framework_path( framework, qt_major )
106
+ header_path = "#{ framework_path }/#{ m[ 2 ] }"
107
+ File.exist?( header_path )
108
+ else
109
+ false
110
+ end
111
+ end
112
+
113
+ @frameworks.each do | framework |
114
+ @include_paths << Compiler::GCC.framework_path( framework, qt_major )
115
+ @include_paths << "/usr/include/#{ framework }"
116
+ end
117
+
118
+ # Last chance: exclude headers of the form 'Aaaaaa' if found under frameworks
119
+ @missing_headers.reject! do | header |
120
+ @frameworks.any? do | framework |
121
+ framework_path = Compiler::GCC.framework_path( framework, qt_major )
122
+ header_path = "#{ framework_path }/#{ header }"
123
+ File.exist?( header_path )
124
+ end
125
+ end
126
+
127
+ @missing_headers
73
128
  end
74
129
 
75
130
  # QT-specific
@@ -78,18 +133,38 @@ module Rake
78
133
  @qt_version.match( /^(\d+)/ )[ 1 ]
79
134
  end
80
135
 
81
- def architecture_option
82
- "-arch #{ @architecture }"
136
+ def framework_paths
137
+ @framework_paths.map { |p| "-F#{ p }" }
138
+ end
139
+
140
+ def framework_options
141
+ @frameworks.map { |p| "-framework #{ p }" }
83
142
  end
84
143
 
85
- def framework_path_list
86
- @framework_paths.map { |p| "-F#{ p }" }.join( " " )
144
+ # UI
145
+ # /Developer/Tools/Qt/uic ../scanner_cpp/mainwindow.ui -o ui_mainwindow.h
146
+
147
+ def define_ui_tasks
148
+ @ui_files.each do | ui_file |
149
+ ui_header = ui_header_path( ui_file )
150
+ file ui_header => [ @objects_path, ui_file ] do |t|
151
+ command = "uic #{ ui_file } -o #{ ui_header }"
152
+ shell command
153
+ end
154
+ end
87
155
  end
88
156
 
89
- def framework_list
90
- @frameworks.map { |p| "-framework #{ p }" }.join( " " )
157
+ def ui_headers
158
+ @ui_files.collect do | ui_file |
159
+ ui_header_path( ui_file )
160
+ end
161
+ end
162
+
163
+ def ui_header_path( ui_file )
164
+ header_name = 'ui_' + File.basename( ui_file ).gsub( '.ui', '.h' )
165
+ Rake::Path.expand_with_root( header_name, @objects_path )
91
166
  end
92
-
167
+
93
168
  # MOC
94
169
 
95
170
  def define_moc_tasks
@@ -98,7 +173,10 @@ module Rake
98
173
  moc = moc_pathname( header_file )
99
174
 
100
175
  file moc => [ header_file ] do |t|
101
- command = "moc #{ @compilation_defines } #{ framework_path_list } #{ @moc_defines } #{ header_file } -o #{ moc }"
176
+ options = @compilation_defines
177
+ options += framework_paths if RUBY_PLATFORM =~ /darwin/i
178
+ options += @moc_defines
179
+ command = "moc #{ options.join( ' ' ) } #{ header_file } -o #{ moc }"
102
180
  shell command
103
181
  end
104
182
 
data/lib/rake/builder.rb CHANGED
@@ -5,6 +5,7 @@ require 'rake'
5
5
  require 'rake/tasklib'
6
6
  require 'rake/path'
7
7
  require 'rake/file_task_alias'
8
+ require 'compiler'
8
9
 
9
10
  module Rake
10
11
 
@@ -23,8 +24,8 @@ module Rake
23
24
  module VERSION #:nodoc:
24
25
  MAJOR = 0
25
26
  MINOR = 0
26
- TINY = 12
27
-
27
+ TINY = 13
28
+
28
29
  STRING = [ MAJOR, MINOR, TINY ].join('.')
29
30
  end
30
31
 
@@ -39,7 +40,10 @@ module Rake
39
40
  # The types of file that can be built
40
41
  TARGET_TYPES = [ :executable, :static_library, :shared_library ]
41
42
 
42
- # The programming language: 'c++' or 'c' (default 'c++')
43
+ # processor type: 'i386', 'x86_64', 'ppc' or 'ppc64'.
44
+ attr_accessor :architecture
45
+
46
+ # The programming language: 'c++', 'c' or 'objective-c' (default 'c++')
43
47
  # This also sets defaults for source_file_extension
44
48
  attr_accessor :programming_language
45
49
 
@@ -165,6 +169,8 @@ module Rake
165
169
  end
166
170
 
167
171
  def initialize_attributes
172
+ @architecture = 'i386'
173
+ @compiler_data = Compiler::Base.for( :gcc )
168
174
  @logger = Logger.new( STDOUT )
169
175
  @logger.level = Logger::UNKNOWN
170
176
  @logger.formatter = Formatter.new
@@ -179,9 +185,13 @@ module Rake
179
185
  @target = 'a.out'
180
186
  @generated_files = []
181
187
  @compilation_options = []
188
+ @include_paths = []
182
189
  end
183
190
 
184
191
  def configure
192
+ @compilation_options += [ architecture_option ] if RUBY_PLATFORM =~ /apple/i
193
+ @compilation_options.uniq!
194
+
185
195
  @programming_language.downcase!
186
196
  raise "Don't know how to build '#{ @programming_language }' programs" if KNOWN_LANGUAGES[ @programming_language ].nil?
187
197
  @compiler ||= KNOWN_LANGUAGES[ @programming_language ][ :compiler ]
@@ -201,7 +211,8 @@ module Rake
201
211
  @install_path ||= default_install_path( @target_type )
202
212
 
203
213
  @linker_options ||= ''
204
- @include_paths ||= @header_search_paths.dup
214
+ @include_paths += []
215
+ @include_paths = Rake::Path.expand_all_with_root( @include_paths.uniq, @rakefile_path )
205
216
  @generated_files = Rake::Path.expand_all_with_root( @generated_files, @rakefile_path )
206
217
 
207
218
  @default_task ||= :build
@@ -209,32 +220,9 @@ module Rake
209
220
 
210
221
  @makedepend_file = @objects_path + '/.' + target_basename + '.depend.mf'
211
222
 
212
- load_local_config
213
-
214
- @include_paths = Rake::Path.expand_all_with_root( @include_paths, @rakefile_path )
215
-
216
223
  raise "No source files found" if source_files.length == 0
217
224
  end
218
225
 
219
- def local_config
220
- filename = '.rake-builder'
221
- filename += '.' + @task_namespace.to_s if @task_namespace
222
- Rake::Path.expand_with_root( filename, @rakefile_path )
223
- end
224
-
225
- def load_local_config
226
- return if ! File.exist?( local_config )
227
-
228
- config = YAML.load_file( local_config )
229
-
230
- version = config[ :rake_builder ][ :config_file ][ :version ]
231
- raise "Config file version missing" if version.nil?
232
-
233
- @include_paths += config[ :include_paths ] if config[ :include_paths ]
234
- rescue => e
235
- raise "#{__FILE__}:#{__LINE__}: Failed to load local config file '#{ local_config }': #{ e.message }"
236
- end
237
-
238
226
  def define_tasks
239
227
  if @task_namespace
240
228
  namespace @task_namespace do
@@ -287,12 +275,38 @@ module Rake
287
275
 
288
276
  directory @objects_path
289
277
 
290
- file @makedepend_file => [ @objects_path, *project_files ] do
278
+ file local_config => scoped_task( :missing_headers ) do
279
+ added_includes = @compiler_data.include_paths( missing_headers )
280
+ config = { :rake_builder => { :config_file => { :version=> '1.0' } },
281
+ :include_paths => added_includes }
282
+ File.open( local_config, 'w' ) do | file |
283
+ file.write config.to_yaml
284
+ end
285
+ end
286
+
287
+ file @makedepend_file => [ scoped_task( :load_local_config ),
288
+ scoped_task( :missing_headers ),
289
+ @objects_path,
290
+ *project_files ] do
291
291
  @logger.add( Logger::DEBUG, "Analysing dependencies" )
292
292
  command = "makedepend -f- -- #{ include_path } -- #{ file_list( source_files ) } 2>/dev/null > #{ @makedepend_file }"
293
293
  shell command
294
294
  end
295
295
 
296
+ task :load_local_config => local_config do
297
+ config = YAML.load_file( local_config )
298
+
299
+ version = config[ :rake_builder ][ :config_file ][ :version ]
300
+ raise "Config file version missing" if version.nil?
301
+
302
+ config[ :include_paths ] ||= []
303
+ @include_paths += Rake::Path.expand_all_with_root( config[ :include_paths ], @rakefile_path )
304
+ end
305
+
306
+ task :missing_headers => [ *generated_headers ] do
307
+ missing_headers
308
+ end
309
+
296
310
  # Reimplemented mkdepend file loading to make objects depend on
297
311
  # sources with the correct paths:
298
312
  # the standard rake mkdepend loader doesn't do what we want,
@@ -355,6 +369,10 @@ module Rake
355
369
  end
356
370
  end
357
371
 
372
+ def generated_headers
373
+ []
374
+ end
375
+
358
376
  def scoped_task( task )
359
377
  if @task_namespace
360
378
  "#{ task_namespace }:#{ task }"
@@ -368,7 +386,8 @@ module Rake
368
386
  @generated_files << object
369
387
  file object => [ source ] do |t|
370
388
  @logger.add( Logger::INFO, "Compiling '#{ source }'" )
371
- shell "#{ @compiler } -c #{ compiler_flags } -o #{ object } #{ source }"
389
+ command = "#{ @compiler } -c #{ compiler_flags } -o #{ object } #{ source }"
390
+ shell command
372
391
  end
373
392
  end
374
393
 
@@ -395,6 +414,15 @@ module Rake
395
414
  end
396
415
  end
397
416
 
417
+ # Discovery
418
+
419
+ def missing_headers
420
+ return @missing_headers if @missing_headers
421
+ default_includes = @compiler_data.default_include_paths( @programming_language )
422
+ all_includes = default_includes + @include_paths
423
+ @missing_headers = @compiler_data.missing_headers( all_includes, source_files )
424
+ end
425
+
398
426
  # Compiling and linking parameters
399
427
 
400
428
  def include_path
@@ -402,21 +430,34 @@ module Rake
402
430
  end
403
431
 
404
432
  def compiler_flags
405
- include_path + ' ' + compilation_options.join( " " )
433
+ flags = include_path + ' ' + compilation_options.join( ' ' )
434
+ flags << ' ' << architecture_option if RUBY_PLATFORM =~ /darwin/i
435
+ flags
436
+ end
437
+
438
+ def architecture_option
439
+ "-arch #{ @architecture }"
406
440
  end
407
441
 
408
442
  def link_flags
409
- [ @linker_options, library_paths_list, library_dependencies_list ].join( " " )
443
+ flags = [ @linker_options, architecture_option, library_paths_list, library_dependencies_list ]
444
+ flags << architecture_option if RUBY_PLATFORM =~ /darwin/i
445
+ flags.join( " " )
410
446
  end
411
447
 
412
448
  # Paths
413
449
 
450
+ def local_config
451
+ filename = '.rake-builder'
452
+ Rake::Path.expand_with_root( filename, @rakefile_path )
453
+ end
454
+
414
455
  def save_rakefile_info( block )
415
456
  if RUBY_VERSION < '1.9'
416
457
  # Hack the path from the block String representation
417
458
  @rakefile = block.to_s.match( /@([^\:]+):/ )[ 1 ]
418
459
  else
419
- @rakefile = block.source_location
460
+ @rakefile = block.source_location[ 0 ]
420
461
  end
421
462
  @rakefile_path = File.expand_path( File.dirname( @rakefile ) )
422
463
  end
@@ -455,8 +496,8 @@ module Rake
455
496
  source_files + header_files
456
497
  end
457
498
 
458
- def file_list( files )
459
- files.join( " " )
499
+ def file_list( files, delimiter = ' ' )
500
+ files.join( delimiter )
460
501
  end
461
502
 
462
503
  def library_paths_list
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rake-builder
3
3
  version: !ruby/object:Gem::Version
4
- hash: 7
4
+ hash: 5
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 12
10
- version: 0.0.12
9
+ - 13
10
+ version: 0.0.13
11
11
  platform: ruby
12
12
  authors:
13
13
  - Joe Yates
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-12-30 00:00:00 +01:00
18
+ date: 2011-02-20 00:00:00 +00:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -43,6 +43,7 @@ extensions: []
43
43
  extra_rdoc_files:
44
44
  - COPYING
45
45
  - README.rdoc
46
+ - lib/compiler.rb
46
47
  - lib/rake/builder/qt_builder.rb
47
48
  - lib/rake/builder.rb
48
49
  - lib/rake/file_task_alias.rb
@@ -59,6 +60,7 @@ files:
59
60
  - COPYING
60
61
  - Rakefile
61
62
  - README.rdoc
63
+ - lib/compiler.rb
62
64
  - lib/rake/builder/qt_builder.rb
63
65
  - lib/rake/builder.rb
64
66
  - lib/rake/file_task_alias.rb
@@ -131,7 +133,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
131
133
  version: "0"
132
134
  requirements: []
133
135
 
134
- rubyforge_project:
136
+ rubyforge_project: nowarning
135
137
  rubygems_version: 1.3.7
136
138
  signing_key:
137
139
  specification_version: 3