rake-builder 0.0.14 → 0.0.15

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.
@@ -15,6 +15,12 @@ Here is a typical example:
15
15
  builder.header_search_paths = [ 'include' ]
16
16
  end
17
17
 
18
+ = Dependencies
19
+
20
+ * makedepend
21
+ ** linux: package 'xutils-dev'
22
+ ** OS X: already installed
23
+
18
24
  = Installation
19
25
 
20
26
  $ sudo gem install rake-builder
@@ -57,6 +63,7 @@ The file should be a YAML structure, and must include a version.
57
63
 
58
64
  Currently, the following can be configured:
59
65
  * extra include paths: :include_paths
66
+ * extra compilation options (e.g. defines): :compilation_options
60
67
 
61
68
  === Example '.rake-builder'
62
69
 
data/Rakefile CHANGED
@@ -1,40 +1,20 @@
1
- require 'rubygems' if RUBY_VERSION < '1.9'
2
- require 'rake'
3
- require 'rake/rdoctask'
4
- require 'spec/rake/spectask'
5
- $:.unshift( File.dirname( __FILE__ ) + '/lib' )
6
- require 'rake/builder/version'
1
+ require "bundler/gem_tasks"
2
+ require 'rcov/rcovtask' if RUBY_VERSION < '1.9'
3
+ require 'rspec/core/rake_task'
7
4
 
8
- RDOC_FILES = FileList[ 'COPYING', 'README.rdoc' ] +
9
- FileList[ 'lib/**/*.rb' ] +
10
- FileList[ 'examples/README.rdoc' ] +
11
- FileList[ 'examples/**/Rakefile' ]
12
- RDOC_OPTS = [ '--quiet', '--main', 'README.rdoc', '--inline-source' ]
5
+ task :default => :spec
13
6
 
14
- Spec::Rake::SpecTask.new do |t|
15
- t.spec_files = FileList[ 'spec/**/*_spec.rb' ]
16
- t.spec_opts += [ '--color', '--format specdoc' ]
7
+ RSpec::Core::RakeTask.new do | t |
8
+ t.pattern = 'spec/**/*_spec.rb'
17
9
  end
18
10
 
19
- Spec::Rake::SpecTask.new( 'spec:rcov' ) do |t|
20
- t.spec_files = FileList[ 'spec/**/*_spec.rb' ]
21
- t.rcov = true
22
- t.rcov_opts = [ '--exclude spec' ]
23
- end
11
+ if RUBY_VERSION < '1.9'
24
12
 
25
- Rake::RDocTask.new do |rdoc|
26
- rdoc.rdoc_dir = 'html'
27
- rdoc.options += RDOC_OPTS
28
- rdoc.title = 'Rake for C/C++/Objective-C/Objective-C++ Projects'
29
- rdoc.rdoc_files.add RDOC_FILES
30
- end
13
+ RSpec::Core::RakeTask.new( 'spec:rcov' ) do |t|
14
+ t.pattern = 'spec/**/*_spec.rb'
15
+ t.rcov = true
16
+ t.rcov_opts = [ '--exclude', 'spec/,/gems/' ]
17
+ end
31
18
 
32
- desc "Build the gem"
33
- task :build do
34
- system "gem build rake-builder.gemspec"
35
19
  end
36
20
 
37
- desc "Publish gem version #{ Rake::Builder::VERSION::STRING }"
38
- task :release => :build do
39
- system "gem push rake-builder-#{ Rake::Builder::VERSION::STRING }.gem"
40
- end
@@ -1,12 +1,17 @@
1
1
  require 'rubygems' if RUBY_VERSION < '1.9'
2
+ require 'json'
2
3
  require 'logger'
3
4
  require 'rake'
4
5
  require 'rake/tasklib'
5
6
  require 'rake/path'
6
7
  require 'rake/local_config'
7
8
  require 'rake/file_task_alias'
9
+ require 'rake/microsecond'
10
+ require 'rake/once_task'
8
11
  require 'compiler'
9
12
 
13
+ include Rake::DSL
14
+
10
15
  module Rake
11
16
 
12
17
  class Formatter < Logger::Formatter
@@ -17,14 +22,6 @@ module Rake
17
22
 
18
23
  class Builder < TaskLib
19
24
 
20
- module VERSION #:nodoc:
21
- MAJOR = 0
22
- MINOR = 0
23
- TINY = 13
24
-
25
- STRING = [ MAJOR, MINOR, TINY ].join('.')
26
- end
27
-
28
25
  class BuilderError < StandardError
29
26
  attr_accessor :namespace
30
27
 
@@ -154,12 +151,190 @@ module Rake
154
151
  # Name of the generated file containing source - header dependencies
155
152
  attr_reader :makedepend_file
156
153
 
154
+ # The file containing local settings such as include paths
155
+ attr_reader :local_config
156
+
157
157
  # Temporary files generated during compilation and linking
158
158
  attr_accessor :generated_files
159
159
 
160
160
  # Each instance has its own logger
161
161
  attr_accessor :logger
162
162
 
163
+ # All Rake::Builder instaces that get defined
164
+ # This allows us to create scripts for configure
165
+ @instances = []
166
+
167
+ def self.instances
168
+ @instances
169
+ end
170
+
171
+ def self.define_global
172
+ desc "Create input files for configure script creation"
173
+ task :autoconf, [:project_title, :version] => [] do | task, args |
174
+ project_title = args.project_title or raise "Please supply a project_title parameter"
175
+ version = decide_version( args.version )
176
+ if File.exist?( 'configure.ac' )
177
+ raise "The file 'configure.ac' already exists"
178
+ end
179
+ if File.exist?( 'Makefile.am' )
180
+ raise "The file 'Makefile.am' already exists"
181
+ end
182
+ create_configure_ac project_title, version
183
+ create_makefile_am
184
+ end
185
+
186
+ desc "A file containing the major.minor.revision version information"
187
+ file 'VERSION' do
188
+ raise <<-EOT
189
+ In order to create autoconf files, you need to create a file called VERSION in the root directory of the project.
190
+ The file should contain the version of the project, like this:
191
+ 1.2.3
192
+ EOT
193
+ end
194
+ end
195
+
196
+ def self.create_configure_ac( project_title, version )
197
+ source = Rake::Path.relative_path( instances[ 0 ].source_files[ 0 ], instances[ 0 ].rakefile_path )
198
+ File.open( 'configure.ac', 'w' ) do | f |
199
+ f.write <<EOT
200
+ AC_PREREQ(2.61)
201
+ AC_INIT(#{project_title}, #{ version })
202
+ AC_CONFIG_SRCDIR([#{ source }])
203
+ AC_CONFIG_HEADER([config.h])
204
+ AM_INIT_AUTOMAKE([#{project_title}], [#{ version }])
205
+
206
+ # Checks for programs.
207
+ AC_PROG_CXX
208
+ AC_PROG_CC
209
+ AC_PROG_RANLIB
210
+
211
+ # Checks for libraries.
212
+
213
+ # Checks for header files.
214
+
215
+ # Checks for typedefs, structures, and compiler characteristics.
216
+ AC_HEADER_STDBOOL
217
+ AC_C_CONST
218
+ AC_C_INLINE
219
+ AC_STRUCT_TM
220
+
221
+ # Checks for library functions.
222
+ AC_FUNC_LSTAT
223
+ AC_FUNC_LSTAT_FOLLOWS_SLASHED_SYMLINK
224
+ AC_FUNC_MEMCMP
225
+ AC_HEADER_STDC
226
+ AC_CHECK_FUNCS([memset strcasecmp])
227
+
228
+ AC_CONFIG_FILES([Makefile])
229
+
230
+ AC_OUTPUT
231
+ EOT
232
+ end
233
+ end
234
+
235
+ def self.create_makefile_am
236
+ libraries = []
237
+ binaries = []
238
+ instances.each do | instance |
239
+ entry = instance.makefile_am_entry
240
+ case entry[ :type ]
241
+ when :static_library, :shared_library
242
+ libraries << entry
243
+ else
244
+ binaries << entry
245
+ end
246
+ end
247
+
248
+ File.open( 'Makefile.am', 'w' ) do | f |
249
+ if libraries.size > 0
250
+ names = libraries.map { | lib | lib[ :name ] }.join( ' ' )
251
+ f.write "lib_LIBRARIES = #{ names }\n\n"
252
+ libraries.each do | lib |
253
+ f.write <<EOT
254
+ #{ lib[ :label ] }_SOURCES = #{ lib[ :sources ] }
255
+ #{ lib[ :label ] }_CPPFLAGS = #{ lib[ :compiler_flags ] }
256
+
257
+ EOT
258
+ end
259
+ end
260
+ if binaries.size > 0
261
+ names = binaries.map { | bin | bin[ :name ] }.join( ' ' )
262
+ f.write "bin_PROGRAMS = #{ names }\n\n"
263
+ binaries.each do | bin |
264
+ f.write <<EOT
265
+ #{ bin[ :label ] }_SOURCES = #{ bin[ :sources ] }
266
+ #{ bin[ :label ] }_CPPFLAGS = #{ bin[ :compiler_flags ] }
267
+
268
+ EOT
269
+ end
270
+ end
271
+
272
+ end
273
+ end
274
+
275
+ def makefile_am_entry
276
+ primary_name = Rake::Path.relative_path( target, rakefile_path, :initial_dot_slash => false )
277
+ sources = source_files.map{ | file | Rake::Path.relative_path( file, rakefile_path) }.join( ' ' )
278
+ sources_label = primary_name.gsub( %r(\.), '_' )
279
+
280
+ {
281
+ :type => @target_type,
282
+ :name => primary_name,
283
+ :label => sources_label,
284
+ :sources => sources,
285
+ :compiler_flags => compiler_flags
286
+ }
287
+ end
288
+
289
+ #########################################
290
+ # VERSION file
291
+
292
+ def self.decide_version( parameter_version )
293
+ acceptable_version_string = %r(^(\d+)\.(\d+)\.(\d+)$)
294
+ if parameter_version && parameter_version !~ acceptable_version_string
295
+ raise "The supplied version number '#{ parameter_version }' is badly formatted. It should consist of three numbers separated by ."
296
+ end
297
+ file_version = load_file_version
298
+ if file_version && file_version !~ acceptable_version_string
299
+ raise "Your VERSION file contains a version number '#{ parameter_version }' which is badly formatted. It should consist of three numbers separated by ."
300
+ end
301
+ case
302
+ when parameter_version.nil? && file_version.nil?
303
+ raise <<-EOT
304
+ This task requires a project version: major.minor.revision (e.g. 1.03.0567)
305
+ Please do one of the following:
306
+ - supply a version parameter: rake autoconf[project_name,version]
307
+ - create a VERSION file.
308
+ EOT
309
+ when file_version.nil?
310
+ save_file_version parameter_version
311
+ return parameter_version
312
+ when parameter_version.nil?
313
+ return file_version
314
+ when file_version != parameter_version
315
+ raise <<-EOT
316
+ The version parameter supplied is different to the value in the VERSION file
317
+ EOT
318
+ else
319
+ return file_version
320
+ end
321
+ end
322
+
323
+ def self.load_file_version
324
+ if File.exist?( 'VERSION' )
325
+ version = File.read( 'VERSION' )
326
+ version.strip!
327
+ else
328
+ nil
329
+ end
330
+ end
331
+
332
+ def self.save_file_version( version )
333
+ File.open( 'VERSION', 'w' ) { | f | f.write "#{ version }/n" }
334
+ end
335
+
336
+ self.define_global
337
+
163
338
  def initialize( &block )
164
339
  save_rakefile_info( block )
165
340
  initialize_attributes
@@ -167,22 +342,23 @@ module Rake
167
342
  configure
168
343
  define_tasks
169
344
  define_default
345
+ self.class.instances << self
170
346
  end
171
347
 
172
- private
173
-
174
348
  # Source files found in source_search_paths
175
349
  def source_files
176
- @source_files ||= find_files( @source_search_paths, @source_file_extension ).uniq
177
- @source_files
350
+ return @source_files if @source_files
351
+ @source_files = find_files( @source_search_paths, @source_file_extension ).uniq
178
352
  end
179
353
 
180
354
  # Header files found in header_search_paths
181
355
  def header_files
182
- @header_files ||= find_files( @header_search_paths, @header_file_extension ).uniq
183
- @header_files
356
+ return @header_files if @header_files
357
+ @header_files = find_files( @header_search_paths, @header_file_extension ).uniq
184
358
  end
185
359
 
360
+ private
361
+
186
362
  def initialize_attributes
187
363
  @architecture = 'i386'
188
364
  @compiler_data = Compiler::Base.for( :gcc )
@@ -220,7 +396,7 @@ module Rake
220
396
  raise BuilderError.new( "The target name cannot be nil", task_namespace ) if @target.nil?
221
397
  raise BuilderError.new( "The target name cannot be an empty string", task_namespace ) if @target == ''
222
398
  @objects_path = Rake::Path.expand_with_root( @objects_path, @rakefile_path )
223
- @target = @target
399
+ @target = File.expand_path( @target, @rakefile_path )
224
400
  @target_type ||= type( @target )
225
401
  raise BuilderError.new( "Building #{ @target_type } targets is not supported", task_namespace ) if ! TARGET_TYPES.include?( @target_type )
226
402
 
@@ -233,6 +409,7 @@ module Rake
233
409
 
234
410
  @default_task ||= :build
235
411
  @target_prerequisites << @rakefile
412
+ @local_config = Rake::Path.expand_with_root( '.rake-builder', @rakefile_path )
236
413
 
237
414
  @makedepend_file = @objects_path + '/.' + target_basename + '.depend.mf'
238
415
 
@@ -260,7 +437,7 @@ module Rake
260
437
  end
261
438
 
262
439
  def define
263
- task :environment do
440
+ once_task :environment do
264
441
  logger.level = Logger::DEBUG if ENV[ 'DEBUG' ]
265
442
  end
266
443
 
@@ -276,7 +453,7 @@ module Rake
276
453
  FileTaskAlias.define_task( :build, @target )
277
454
 
278
455
  desc "Build '#{ target_basename }'"
279
- file @target => [ scoped_task( :environment ),
456
+ microsecond_file @target => [ scoped_task( :environment ),
280
457
  scoped_task( :compile ),
281
458
  *@target_prerequisites ] do | t |
282
459
  shell "rm -f #{ t.name }"
@@ -289,7 +466,7 @@ module Rake
289
466
  desc "Compile all sources"
290
467
  # Only import dependencies when we're compiling
291
468
  # otherwise makedepend gets run on e.g. 'rake -T'
292
- task :compile => [ scoped_task( :environment ),
469
+ once_task :compile => [ scoped_task( :environment ),
293
470
  @makedepend_file,
294
471
  scoped_task( :load_makedepend ),
295
472
  *object_files ]
@@ -298,34 +475,35 @@ module Rake
298
475
  define_compile_task( src )
299
476
  end
300
477
 
301
- directory @objects_path
478
+ microsecond_directory @objects_path
302
479
 
303
- task :local_config do
304
- if ! File.exist?( local_config )
305
- @logger.add( Logger::DEBUG, "Creating file '#{ local_config }'" )
306
- added_includes = @compiler_data.include_paths( missing_headers )
307
- config = Rake::LocalConfig.new( local_config )
308
- config.include_paths = added_includes
309
- config.save
310
- end
480
+ file scoped_task( local_config ) do
481
+ @logger.add( Logger::DEBUG, "Creating file '#{ local_config }'" )
482
+ added_includes = @compiler_data.include_paths( missing_headers )
483
+ config = Rake::LocalConfig.new( local_config )
484
+ config.include_paths = added_includes
485
+ config.save
311
486
  end
312
487
 
313
- file @makedepend_file => [ scoped_task( :load_local_config ),
488
+ microsecond_file @makedepend_file => [ scoped_task( :load_local_config ),
314
489
  scoped_task( :missing_headers ),
315
490
  @objects_path,
316
491
  *project_files ] do
492
+ system('which makedepend >/dev/null')
493
+ raise 'makedepend not found' unless $?.success?
317
494
  @logger.add( Logger::DEBUG, "Analysing dependencies" )
318
495
  command = "makedepend -f- -- #{ include_path } -- #{ file_list( source_files ) } 2>/dev/null > #{ @makedepend_file }"
319
496
  shell command
320
497
  end
321
498
 
322
- task :load_local_config => scoped_task( :local_config ) do
499
+ once_task scoped_task( :load_local_config ) => scoped_task( local_config ) do
323
500
  config = LocalConfig.new( local_config )
324
501
  config.load
325
- @include_paths += Rake::Path.expand_all_with_root( config.include_paths, @rakefile_path )
502
+ @include_paths += Rake::Path.expand_all_with_root( config.include_paths, @rakefile_path )
503
+ @compilation_options += config.compilation_options
326
504
  end
327
505
 
328
- task :missing_headers => [ *generated_headers ] do
506
+ once_task scoped_task( :missing_headers ) => [ *generated_headers ] do
329
507
  missing_headers
330
508
  end
331
509
 
@@ -354,7 +532,7 @@ module Rake
354
532
 
355
533
  desc "List generated files (which are removed with 'rake #{ scoped_task( :clean ) }')"
356
534
  task :generated_files do
357
- puts generated_files.inspect
535
+ puts generated_files.to_json
358
536
  end
359
537
 
360
538
  # Re-implement :clean locally for project and within namespace
@@ -513,7 +691,8 @@ EOT
513
691
  # Compiling and linking parameters
514
692
 
515
693
  def include_path
516
- @include_paths.map { |p| "-I#{ p }" }.join( " " )
694
+ paths = @include_paths.map{ | file | Rake::Path.relative_path( file, rakefile_path) }
695
+ paths.map { |p| "-I#{ p }" }.join( ' ' )
517
696
  end
518
697
 
519
698
  def compiler_flags
@@ -534,11 +713,6 @@ EOT
534
713
 
535
714
  # Paths
536
715
 
537
- def local_config
538
- filename = '.rake-builder'
539
- Rake::Path.expand_with_root( filename, @rakefile_path )
540
- end
541
-
542
716
  def save_rakefile_info( block )
543
717
  if RUBY_VERSION < '1.9'
544
718
  # Hack the path from the block String representation
@@ -546,7 +720,8 @@ EOT
546
720
  else
547
721
  @rakefile = block.source_location[ 0 ]
548
722
  end
549
- @rakefile_path = File.expand_path( File.dirname( @rakefile ) )
723
+ @rakefile = File.expand_path( @rakefile )
724
+ @rakefile_path = File.dirname( @rakefile )
550
725
  end
551
726
 
552
727
  def object_path( source_path_name )
@@ -600,6 +775,7 @@ EOT
600
775
  def project_files
601
776
  source_files + header_files
602
777
  end
778
+ public :project_files
603
779
 
604
780
  def file_list( files, delimiter = ' ' )
605
781
  files.join( delimiter )
@@ -646,7 +822,7 @@ EOT
646
822
  FileList[ search ].each do | pathname |
647
823
  full_path = Rake::Path.expand_with_root( pathname, @rakefile_path )
648
824
  directory = File.dirname( full_path )
649
- relative = Rake::Path.subtract_prefix( non_glob_search, directory )
825
+ relative = Rake::Path.relative_path( directory, non_glob_search )
650
826
  memo << { :source_file => pathname, :relative_path => relative }
651
827
  end
652
828
  else
@@ -666,10 +842,11 @@ EOT
666
842
  end
667
843
 
668
844
  def shell( command, log_level = Logger::DEBUG )
669
- @logger.add( log_level, command )
670
- `#{ command }`
845
+ @logger.add(log_level, command)
846
+ system command, {:out => '/dev/null', :err => '/dev/null'}
671
847
  end
672
848
 
673
849
  end
674
850
 
675
851
  end
852
+