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.
- data/README.rdoc +7 -0
- data/Rakefile +12 -32
- data/lib/rake/builder.rb +219 -42
- data/lib/rake/builder/version.rb +7 -5
- data/lib/rake/local_config.rb +19 -16
- data/lib/rake/microsecond.rb +70 -0
- data/lib/rake/once_task.rb +36 -0
- data/lib/rake/path.rb +12 -2
- data/spec/c_project_spec.rb +12 -5
- data/spec/cpp_project_spec.rb +8 -6
- data/spec/dependencies_spec.rb +138 -16
- data/spec/generated_files_spec.rb +7 -5
- data/spec/libraries_spec.rb +7 -5
- data/spec/local_config_spec.rb +51 -3
- data/spec/logger_spec.rb +2 -1
- data/spec/microsecond_task_spec.rb +32 -0
- data/spec/objective_c_project_spec.rb +9 -3
- data/spec/paths_spec.rb +1 -1
- data/spec/spec_helper.rb +8 -8
- data/spec/target_spec.rb +2 -2
- metadata +145 -74
data/README.rdoc
CHANGED
@@ -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
|
2
|
-
require '
|
3
|
-
require '
|
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
|
-
|
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
|
-
|
15
|
-
t.
|
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
|
-
|
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
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
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
|
data/lib/rake/builder.rb
CHANGED
@@ -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
|
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
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
478
|
+
microsecond_directory @objects_path
|
302
479
|
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
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
|
-
|
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
|
-
|
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
|
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
|
-
|
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.
|
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
|
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
|
-
@
|
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.
|
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(
|
670
|
-
|
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
|
+
|