rake-builder 0.0.8
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +5 -0
- data/COPYING +20 -0
- data/README.rdoc +105 -0
- data/Rakefile +60 -0
- data/examples/01_hello_world_cpp/Rakefile +13 -0
- data/examples/01_hello_world_cpp/main.cpp +7 -0
- data/examples/02_hello_world_c/Rakefile +8 -0
- data/examples/02_hello_world_c/main.c +7 -0
- data/examples/03_search_paths/Rakefile +10 -0
- data/examples/03_search_paths/include/main.h +7 -0
- data/examples/03_search_paths/src/main.cpp +17 -0
- data/examples/04_zlib/Rakefile +13 -0
- data/examples/04_zlib/include/main.h +7 -0
- data/examples/04_zlib/src/main.c +11 -0
- data/examples/05_tests/Rakefile +19 -0
- data/examples/05_tests/include/main.h +7 -0
- data/examples/05_tests/include/units.h +18 -0
- data/examples/05_tests/src/main.cpp +9 -0
- data/examples/05_tests/src/units.cpp +13 -0
- data/examples/05_tests/test/test_unit.cpp +12 -0
- data/examples/06_hello_world_objective_c/Rakefile +9 -0
- data/examples/06_hello_world_objective_c/main.m +7 -0
- data/examples/README.rdoc +33 -0
- data/lib/rake/builder.rb +447 -0
- data/spec/c_project/main.c +12 -0
- data/spec/c_project/main.h +6 -0
- data/spec/c_project_spec.rb +34 -0
- data/spec/cpp_project/main.cpp +12 -0
- data/spec/cpp_project/main.h +8 -0
- data/spec/cpp_project_spec.rb +186 -0
- data/spec/dependencies_spec.rb +103 -0
- data/spec/generated_files_spec.rb +72 -0
- data/spec/libraries_spec.rb +33 -0
- data/spec/logger_spec.rb +21 -0
- data/spec/paths_spec.rb +19 -0
- data/spec/spec_helper.rb +99 -0
- data/spec/target_spec.rb +44 -0
- metadata +142 -0
data/lib/rake/builder.rb
ADDED
@@ -0,0 +1,447 @@
|
|
1
|
+
require 'rubygems' if RUBY_VERSION < '1.9'
|
2
|
+
require 'logger'
|
3
|
+
require 'rake'
|
4
|
+
require 'rake/tasklib'
|
5
|
+
require 'rake/loaders/makefile'
|
6
|
+
|
7
|
+
module Rake
|
8
|
+
|
9
|
+
# A task whose behaviour depends on a FileTask
|
10
|
+
class FileTaskAlias < Task
|
11
|
+
|
12
|
+
attr_accessor :target
|
13
|
+
|
14
|
+
def self.define_task( name, target, &block )
|
15
|
+
alias_task = super( { name => [] }, &block )
|
16
|
+
alias_task.target = target
|
17
|
+
alias_task.prerequisites.unshift( target )
|
18
|
+
alias_task
|
19
|
+
end
|
20
|
+
|
21
|
+
def needed?
|
22
|
+
Rake::Task[ @target ].needed?
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
# Error indicating that the project failed to build.
|
28
|
+
class BuildFailureError < StandardError
|
29
|
+
end
|
30
|
+
|
31
|
+
class Builder < TaskLib
|
32
|
+
|
33
|
+
module VERSION #:nodoc:
|
34
|
+
MAJOR = 0
|
35
|
+
MINOR = 0
|
36
|
+
TINY = 8
|
37
|
+
|
38
|
+
STRING = [ MAJOR, MINOR, TINY ].join('.')
|
39
|
+
end
|
40
|
+
|
41
|
+
# Expand path to an absolute path relative to the supplied root
|
42
|
+
def self.expand_path_with_root( path, root )
|
43
|
+
if path =~ /^\//
|
44
|
+
File.expand_path( path )
|
45
|
+
else
|
46
|
+
File.expand_path( root + '/' + path )
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# Expand an array of paths to absolute paths relative to the supplied root
|
51
|
+
def self.expand_paths_with_root( paths, root )
|
52
|
+
paths.map{ |path| expand_path_with_root( path, root ) }
|
53
|
+
end
|
54
|
+
|
55
|
+
# The file to be built
|
56
|
+
attr_accessor :target
|
57
|
+
|
58
|
+
# The type of file to be built
|
59
|
+
# One of: :executable, :static_library, :shared_library
|
60
|
+
# If not set, this is deduced from the target.
|
61
|
+
attr_accessor :target_type
|
62
|
+
|
63
|
+
# The types of file that can be built
|
64
|
+
TARGET_TYPES = [ :executable, :static_library, :shared_library ]
|
65
|
+
|
66
|
+
# The programming language: 'c++' or 'c' (default 'c++')
|
67
|
+
# This also sets defaults for source_file_extension
|
68
|
+
attr_accessor :programming_language
|
69
|
+
|
70
|
+
# Programmaing languages that Rake::Builder can handle
|
71
|
+
KNOWN_LANGUAGES = {
|
72
|
+
'c' => {
|
73
|
+
:source_file_extension => 'c',
|
74
|
+
:compiler => 'gcc',
|
75
|
+
:linker => 'gcc'
|
76
|
+
},
|
77
|
+
'c++' => {
|
78
|
+
:source_file_extension => 'cpp',
|
79
|
+
:compiler => 'g++',
|
80
|
+
:linker => 'g++'
|
81
|
+
},
|
82
|
+
'objective-c' => {
|
83
|
+
:source_file_extension => 'm',
|
84
|
+
:compiler => 'gcc',
|
85
|
+
:linker => 'gcc'
|
86
|
+
},
|
87
|
+
}
|
88
|
+
|
89
|
+
# The compiler that will be used
|
90
|
+
attr_accessor :compiler
|
91
|
+
|
92
|
+
# The linker that will be used
|
93
|
+
attr_accessor :linker
|
94
|
+
|
95
|
+
# Extension of source files (default 'cpp' for C++ and 'c' fo C)
|
96
|
+
attr_accessor :source_file_extension
|
97
|
+
|
98
|
+
# Extension of header files (default 'h')
|
99
|
+
attr_accessor :header_file_extension
|
100
|
+
|
101
|
+
# The path of the Rakefile
|
102
|
+
# All paths are relative to this
|
103
|
+
attr_reader :rakefile_path
|
104
|
+
|
105
|
+
# The Rakefile
|
106
|
+
# The file is not necessarily called 'Rakefile'
|
107
|
+
# It is the file which calls to Rake::Builder.new
|
108
|
+
attr_reader :rakefile
|
109
|
+
|
110
|
+
# Directories containing project source files
|
111
|
+
attr_accessor :source_search_paths
|
112
|
+
|
113
|
+
# Directories containing project header files
|
114
|
+
attr_accessor :header_search_paths
|
115
|
+
|
116
|
+
# (Optional) namespace for tasks
|
117
|
+
attr_accessor :task_namespace
|
118
|
+
|
119
|
+
# Name of the default task
|
120
|
+
attr_accessor :default_task
|
121
|
+
|
122
|
+
# Tasks which the target file depends upon
|
123
|
+
attr_accessor :target_prerequisites
|
124
|
+
|
125
|
+
# Directory to be used for object files
|
126
|
+
attr_accessor :objects_path
|
127
|
+
|
128
|
+
# extra options to pass to the compiler
|
129
|
+
attr_accessor :compilation_options
|
130
|
+
|
131
|
+
# Additional include directories for compilation
|
132
|
+
attr_accessor :include_paths
|
133
|
+
|
134
|
+
# Additional library directories for linking
|
135
|
+
attr_accessor :library_paths
|
136
|
+
|
137
|
+
# Libraries to be linked
|
138
|
+
attr_accessor :library_dependencies
|
139
|
+
|
140
|
+
# The directory where 'rake install' will copy the target file
|
141
|
+
attr_accessor :install_path
|
142
|
+
|
143
|
+
# Name of the generated file containing source - header dependencies
|
144
|
+
attr_reader :makedepend_file
|
145
|
+
|
146
|
+
# Temporary files generated during compilation and linking
|
147
|
+
attr_accessor :generated_files
|
148
|
+
|
149
|
+
# Each instance has its own logger
|
150
|
+
attr_accessor :logger
|
151
|
+
|
152
|
+
def initialize( &block )
|
153
|
+
save_rakefile_info( caller[0] )
|
154
|
+
initialize_attributes
|
155
|
+
block.call( self )
|
156
|
+
configure
|
157
|
+
define_tasks
|
158
|
+
define_default
|
159
|
+
end
|
160
|
+
|
161
|
+
# Source files found in source_search_paths
|
162
|
+
def source_files
|
163
|
+
@source_fies ||= find_files( @source_search_paths, @source_file_extension )
|
164
|
+
end
|
165
|
+
|
166
|
+
# Header files found in header_search_paths
|
167
|
+
def header_files
|
168
|
+
@header_files ||= find_files( @header_search_paths, @header_file_extension )
|
169
|
+
end
|
170
|
+
|
171
|
+
private
|
172
|
+
|
173
|
+
def initialize_attributes
|
174
|
+
@logger = Logger.new( STDOUT )
|
175
|
+
@logger.level = Logger::UNKNOWN
|
176
|
+
@programming_language = 'c++'
|
177
|
+
@header_file_extension = 'h'
|
178
|
+
@objects_path = @rakefile_path.dup
|
179
|
+
@generated_files = []
|
180
|
+
@library_paths = []
|
181
|
+
@library_dependencies = []
|
182
|
+
@target_prerequisites = []
|
183
|
+
@source_search_paths = [ @rakefile_path.dup ]
|
184
|
+
@header_search_paths = [ @rakefile_path.dup ]
|
185
|
+
@target = 'a.out'
|
186
|
+
@generated_files = []
|
187
|
+
end
|
188
|
+
|
189
|
+
def configure
|
190
|
+
@programming_language.downcase!
|
191
|
+
raise "Don't know how to build '#{ @programming_language }' programs" if KNOWN_LANGUAGES[ @programming_language ].nil?
|
192
|
+
@compiler ||= KNOWN_LANGUAGES[ @programming_language ][ :compiler ]
|
193
|
+
@linker ||= KNOWN_LANGUAGES[ @programming_language ][ :linker ]
|
194
|
+
@source_file_extension ||= KNOWN_LANGUAGES[ @programming_language ][ :source_file_extension ]
|
195
|
+
|
196
|
+
@source_search_paths = Rake::Builder.expand_paths_with_root( @source_search_paths, @rakefile_path )
|
197
|
+
@header_search_paths = Rake::Builder.expand_paths_with_root( @header_search_paths, @rakefile_path )
|
198
|
+
@library_paths = Rake::Builder.expand_paths_with_root( @library_paths, @rakefile_path )
|
199
|
+
|
200
|
+
raise "The target name cannot be nil" if @target.nil?
|
201
|
+
raise "The target name cannot be an empty string" if @target == ''
|
202
|
+
@objects_path = Rake::Builder.expand_path_with_root( @objects_path, @rakefile_path )
|
203
|
+
@target = Rake::Builder.expand_path_with_root( @target, @objects_path )
|
204
|
+
@target_type ||= type( @target )
|
205
|
+
raise "Building #{ @target_type } targets is not supported" if ! TARGET_TYPES.include?( @target_type )
|
206
|
+
@install_path ||= default_install_path( @target_type )
|
207
|
+
|
208
|
+
@compilation_options ||= ''
|
209
|
+
@include_paths ||= @header_search_paths.dup
|
210
|
+
@include_paths = Rake::Builder.expand_paths_with_root( @include_paths, @rakefile_path )
|
211
|
+
@generated_files = Rake::Builder.expand_paths_with_root( @generated_files, @rakefile_path )
|
212
|
+
|
213
|
+
@default_task ||= :build
|
214
|
+
@target_prerequisites << @rakefile
|
215
|
+
|
216
|
+
@makedepend_file = @objects_path + '/.' + target_basename + '.depend.mf'
|
217
|
+
|
218
|
+
raise "No source files found" if source_files.length == 0
|
219
|
+
end
|
220
|
+
|
221
|
+
def define_tasks
|
222
|
+
if @task_namespace
|
223
|
+
namespace @task_namespace do
|
224
|
+
define
|
225
|
+
end
|
226
|
+
else
|
227
|
+
define
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
def define_default
|
232
|
+
name = scoped_task( @default_task )
|
233
|
+
desc "Equivalent to 'rake #{ name }'"
|
234
|
+
if @task_namespace
|
235
|
+
task @task_namespace => [ name ]
|
236
|
+
else
|
237
|
+
task :default => [ name ]
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
def define
|
242
|
+
if @target_type == :executable
|
243
|
+
desc "Run '#{ target_basename }'"
|
244
|
+
task :run => :build do
|
245
|
+
command = "cd #{ @rakefile_path } && #{ @target }"
|
246
|
+
puts shell( command, Logger::INFO )
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
desc "Compile and build '#{ target_basename }'"
|
251
|
+
FileTaskAlias.define_task( :build, @target )
|
252
|
+
|
253
|
+
desc "Build '#{ target_basename }'"
|
254
|
+
file @target => [ scoped_task( :compile ), @target_prerequisites ] do |t|
|
255
|
+
shell "rm -f #{ t.name }"
|
256
|
+
case @target_type
|
257
|
+
when :executable
|
258
|
+
shell "#{ @linker } #{ link_flags } -o #{ @target } #{ file_list( object_files ) }"
|
259
|
+
when :static_library
|
260
|
+
@logger.add( Logger::INFO, "Builing library '#{ t.name }'" )
|
261
|
+
shell "ar -cq #{ t.name } #{ file_list( object_files ) }"
|
262
|
+
when :shared_library
|
263
|
+
@logger.add( Logger::INFO, "Builing library '#{ t.name }'" )
|
264
|
+
shell "#{ @linker } -shared -o #{ t.name } #{ file_list( object_files ) } #{ link_flags }"
|
265
|
+
end
|
266
|
+
raise BuildFailureError if ! File.exist?( t.name )
|
267
|
+
end
|
268
|
+
|
269
|
+
desc "Compile all sources"
|
270
|
+
# Only import dependencies when we're compiling
|
271
|
+
# otherwise makedepend gets run on e.g. 'rake -T'
|
272
|
+
task :compile => [ @makedepend_file, scoped_task( :load_makedepend ), *object_files ]
|
273
|
+
|
274
|
+
source_files.each do |src|
|
275
|
+
object = object_path( src )
|
276
|
+
@generated_files << object
|
277
|
+
file object => [ src ] do |t|
|
278
|
+
@logger.add( Logger::INFO, "Compiling '#{ src }'" )
|
279
|
+
shell "#{ @compiler } #{ compiler_flags } -c -o #{ object } #{ src }"
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
file @makedepend_file => [ *project_files ] do
|
284
|
+
@logger.add( Logger::DEBUG, "Analysing dependencies" )
|
285
|
+
command = "makedepend -f- -- #{ include_path } -- #{ file_list( source_files ) } 2>/dev/null > #{ @makedepend_file }"
|
286
|
+
shell command
|
287
|
+
end
|
288
|
+
|
289
|
+
task :load_makedepend => @makedepend_file do |t|
|
290
|
+
object_to_source = source_files.inject( {} ) do |memo, source|
|
291
|
+
mapped_object = source.gsub( '.' + @source_file_extension, '.o' )
|
292
|
+
memo[ mapped_object ] = source
|
293
|
+
memo
|
294
|
+
end
|
295
|
+
File.open( @makedepend_file ).each_line do |line|
|
296
|
+
next if line !~ /:\s/
|
297
|
+
mapped_object_file = $`
|
298
|
+
header_file = $'.gsub( "\n", '' )
|
299
|
+
# Why does it work
|
300
|
+
# if I make the object (not the source) depend on the header
|
301
|
+
source_file = object_to_source[ mapped_object_file ]
|
302
|
+
object_file = object_path( source_file )
|
303
|
+
object_file_task = Rake.application[ object_file ]
|
304
|
+
object_file_task.enhance( [ header_file ] )
|
305
|
+
end
|
306
|
+
end
|
307
|
+
|
308
|
+
desc 'List generated files (which are remove with \'rake clean\')'
|
309
|
+
task :generated_files do
|
310
|
+
puts @generated_files.inspect
|
311
|
+
end
|
312
|
+
|
313
|
+
# Re-implement :clean locally for project and within namespace
|
314
|
+
# Standard :clean is a singleton
|
315
|
+
desc "Remove temporary files"
|
316
|
+
task :clean do
|
317
|
+
@generated_files.each do |file|
|
318
|
+
shell "rm -f #{ file }"
|
319
|
+
end
|
320
|
+
end
|
321
|
+
|
322
|
+
@generated_files << @target
|
323
|
+
@generated_files << @makedepend_file
|
324
|
+
|
325
|
+
desc "Install '#{ target_basename }' in '#{ @install_path }'"
|
326
|
+
task :install, [] => [ scoped_task( :build ) ] do
|
327
|
+
destination = File.join( @install_path, target_basename )
|
328
|
+
begin
|
329
|
+
shell "cp '#{ @target }' '#{ destination }'", Logger::INFO
|
330
|
+
rescue Errno::EACCES => e
|
331
|
+
raise "You do not have premission to install '#{ target_basename }' in '#{ @install_path }'\nTry\n $ sudo rake install"
|
332
|
+
end
|
333
|
+
end
|
334
|
+
|
335
|
+
desc "Uninstall '#{ target_basename }' from '#{ @install_path }'"
|
336
|
+
task :uninstall, [] => [] do
|
337
|
+
destination = File.join( @install_path, File.basename( @target ) )
|
338
|
+
if ! File.exist?( destination )
|
339
|
+
@logger.add( Logger::INFO, "The file '#{ destination }' does not exist" )
|
340
|
+
next
|
341
|
+
end
|
342
|
+
begin
|
343
|
+
shell "rm '#{ destination }'", Logger::INFO
|
344
|
+
rescue Errno::EACCES => e
|
345
|
+
raise "You do not have premission to uninstall '#{ destination }'\nTry\n $ sudo rake uninstall"
|
346
|
+
end
|
347
|
+
end
|
348
|
+
|
349
|
+
end
|
350
|
+
|
351
|
+
def scoped_task( task )
|
352
|
+
if @task_namespace
|
353
|
+
"#{ task_namespace }:#{ task }"
|
354
|
+
else
|
355
|
+
task
|
356
|
+
end
|
357
|
+
end
|
358
|
+
|
359
|
+
def type( target )
|
360
|
+
case target
|
361
|
+
when /\.a/
|
362
|
+
:static_library
|
363
|
+
when /\.so/
|
364
|
+
:shared_library
|
365
|
+
else
|
366
|
+
:executable
|
367
|
+
end
|
368
|
+
end
|
369
|
+
|
370
|
+
# Compiling and linking parameters
|
371
|
+
|
372
|
+
def include_path
|
373
|
+
@include_paths.map { |p| "-I#{ p }" }.join( " " )
|
374
|
+
end
|
375
|
+
|
376
|
+
def compiler_flags
|
377
|
+
include_path + ' ' + @compilation_options
|
378
|
+
end
|
379
|
+
|
380
|
+
def link_flags
|
381
|
+
[ library_paths_list, library_dependencies_list ].join( " " )
|
382
|
+
end
|
383
|
+
|
384
|
+
# Paths
|
385
|
+
|
386
|
+
def save_rakefile_info( caller )
|
387
|
+
@rakefile = caller.match(/^([^\:]+)/)[1]
|
388
|
+
@rakefile_path = File.expand_path( File.dirname( @rakefile ) )
|
389
|
+
end
|
390
|
+
|
391
|
+
def object_path( source_path_name )
|
392
|
+
o_name = File.basename( source_path_name ).gsub( '.' + @source_file_extension, '.o' )
|
393
|
+
Rake::Builder.expand_path_with_root( o_name, @objects_path )
|
394
|
+
end
|
395
|
+
|
396
|
+
def default_install_path( target_type )
|
397
|
+
case target_type
|
398
|
+
when :executable
|
399
|
+
'/usr/local/bin'
|
400
|
+
else
|
401
|
+
'/usr/local/lib'
|
402
|
+
end
|
403
|
+
end
|
404
|
+
|
405
|
+
def target_basename
|
406
|
+
File.basename( @target )
|
407
|
+
end
|
408
|
+
|
409
|
+
# Lists of files
|
410
|
+
|
411
|
+
def find_files( paths, extension )
|
412
|
+
files = paths.reduce( [] ) do |memo, path|
|
413
|
+
glob = ( path =~ /[\*\?]/ ) ? path : path + '/*.' + extension
|
414
|
+
memo + FileList[ glob ]
|
415
|
+
end
|
416
|
+
Rake::Builder.expand_paths_with_root( files, @rakefile_path )
|
417
|
+
end
|
418
|
+
|
419
|
+
# TODO: make this return a FileList, not a plain Array
|
420
|
+
def object_files
|
421
|
+
source_files.map { |file| object_path( file ) }
|
422
|
+
end
|
423
|
+
|
424
|
+
def project_files
|
425
|
+
source_files + header_files
|
426
|
+
end
|
427
|
+
|
428
|
+
def file_list( files )
|
429
|
+
files.join( " " )
|
430
|
+
end
|
431
|
+
|
432
|
+
def library_paths_list
|
433
|
+
@library_paths.map { |l| "-L#{ l }" }.join( " " )
|
434
|
+
end
|
435
|
+
|
436
|
+
def library_dependencies_list
|
437
|
+
@library_dependencies.map { |l| "-l#{ l }" }.join( " " )
|
438
|
+
end
|
439
|
+
|
440
|
+
def shell( command, log_level = Logger::ERROR )
|
441
|
+
@logger.add( log_level, command )
|
442
|
+
`#{ command }`
|
443
|
+
end
|
444
|
+
|
445
|
+
end
|
446
|
+
|
447
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper.rb'
|
2
|
+
|
3
|
+
describe 'when building a C project' do
|
4
|
+
|
5
|
+
include RakeBuilderHelper
|
6
|
+
|
7
|
+
before( :all ) do
|
8
|
+
@test_output_file = Rake::Builder.expand_path_with_root( 'rake-c-testfile.txt', SPEC_PATH )
|
9
|
+
end
|
10
|
+
|
11
|
+
before( :each ) do
|
12
|
+
Rake::Task.clear
|
13
|
+
@project = c_task( :executable )
|
14
|
+
@expected_generated = Rake::Builder.expand_paths_with_root( [ './main.o', @project.makedepend_file, @project.target ], SPEC_PATH )
|
15
|
+
`rm -f #{ @test_output_file }`
|
16
|
+
`rm -f #{ @project.target }`
|
17
|
+
end
|
18
|
+
|
19
|
+
after( :each ) do
|
20
|
+
Rake::Task[ 'clean' ].invoke
|
21
|
+
`rm -f #{ @test_output_file }`
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'builds the program with \'build\'' do
|
25
|
+
Rake::Task[ 'build' ].invoke
|
26
|
+
exist?( @project.target ).should be_true
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'runs the program with \'run\'' do
|
30
|
+
Rake::Task[ 'run' ].invoke
|
31
|
+
exist?( @test_output_file ).should be_true
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
@@ -0,0 +1,186 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper.rb'
|
2
|
+
|
3
|
+
describe 'when building an executable' do
|
4
|
+
|
5
|
+
include RakeBuilderHelper
|
6
|
+
|
7
|
+
before( :all ) do
|
8
|
+
@test_output_file = Rake::Builder.expand_path_with_root( 'rake-builder-testfile.txt', SPEC_PATH )
|
9
|
+
@expected_target = Rake::Builder.expand_path_with_root(
|
10
|
+
RakeBuilderHelper::TARGET[ :executable ],
|
11
|
+
SPEC_PATH
|
12
|
+
)
|
13
|
+
end
|
14
|
+
|
15
|
+
before( :each ) do
|
16
|
+
Rake::Task.clear
|
17
|
+
@project = cpp_task( :executable )
|
18
|
+
`rm -f #{ @test_output_file }`
|
19
|
+
`rm -f #{ @project.target }`
|
20
|
+
end
|
21
|
+
|
22
|
+
after( :each ) do
|
23
|
+
Rake::Task[ 'clean' ].invoke
|
24
|
+
`rm -f #{ @test_output_file }`
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'knows the target' do
|
28
|
+
@project.target.should == @expected_target
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'builds the target in the objects directory' do
|
32
|
+
File.dirname( @project.target ).should == @project.objects_path
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'knows the project type' do
|
36
|
+
@project.target_type.should == :executable
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'creates the correct tasks' do
|
40
|
+
expected_tasks = expected_tasks( [ @project.target ] )
|
41
|
+
missing_tasks = expected_tasks - task_names
|
42
|
+
missing_tasks.should == []
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'finds source files' do
|
46
|
+
expected_sources = Rake::Builder.expand_paths_with_root( [ 'cpp_project/main.cpp' ], SPEC_PATH )
|
47
|
+
@project.source_files.should == expected_sources
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'finds header files' do
|
51
|
+
expected_headers = Rake::Builder.expand_paths_with_root( [ 'cpp_project/main.h' ], SPEC_PATH )
|
52
|
+
@project.header_files.should == expected_headers
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'builds the program with \'build\'' do
|
56
|
+
Rake::Task[ 'build' ].invoke
|
57
|
+
exist?( @project.target ).should be_true
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'has a \'run\' task' do
|
61
|
+
Rake::Task[ 'run' ].should_not be_nil
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'builds the program with \'run\'' do
|
65
|
+
Rake::Task[ 'run' ].invoke
|
66
|
+
exist?( @project.target ).should be_true
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'runs the program with \'run\'' do
|
70
|
+
Rake::Task[ 'run' ].invoke
|
71
|
+
exist?( @test_output_file ).should be_true
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
describe 'when using namespaces' do
|
77
|
+
|
78
|
+
include RakeBuilderHelper
|
79
|
+
|
80
|
+
before( :each ) do
|
81
|
+
Rake::Task.clear
|
82
|
+
@project = cpp_task( :executable, 'my_namespace' )
|
83
|
+
end
|
84
|
+
|
85
|
+
after( :each ) do
|
86
|
+
Rake::Task[ 'my_namespace:clean' ].invoke
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'creates the correct tasks' do
|
90
|
+
expected_tasks = expected_tasks( [ @project.target ], 'my_namespace' )
|
91
|
+
missing_tasks = expected_tasks - task_names
|
92
|
+
missing_tasks.should == []
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
|
97
|
+
describe 'when building a static library' do
|
98
|
+
|
99
|
+
include RakeBuilderHelper
|
100
|
+
|
101
|
+
before( :each ) do
|
102
|
+
Rake::Task.clear
|
103
|
+
@project = cpp_task( :static_library )
|
104
|
+
`rm -f #{@project.target}`
|
105
|
+
end
|
106
|
+
|
107
|
+
after( :each ) do
|
108
|
+
Rake::Task[ 'clean' ].invoke
|
109
|
+
end
|
110
|
+
|
111
|
+
it 'knows the target type' do
|
112
|
+
@project.target_type.should == :static_library
|
113
|
+
end
|
114
|
+
|
115
|
+
it 'builds the library' do
|
116
|
+
Rake::Task[ 'build' ].invoke
|
117
|
+
exist?( @project.target ).should be_true
|
118
|
+
end
|
119
|
+
|
120
|
+
it 'hasn\'t got a \'run\' task' do
|
121
|
+
task_names.include?( 'run' ).should be_false
|
122
|
+
end
|
123
|
+
|
124
|
+
end
|
125
|
+
|
126
|
+
describe 'when building a shared library' do
|
127
|
+
|
128
|
+
include RakeBuilderHelper
|
129
|
+
|
130
|
+
before( :each ) do
|
131
|
+
Rake::Task.clear
|
132
|
+
@project = cpp_task( :shared_library )
|
133
|
+
`rm -f #{ @project.target }`
|
134
|
+
end
|
135
|
+
|
136
|
+
after( :each ) do
|
137
|
+
Rake::Task[ 'clean' ].invoke
|
138
|
+
end
|
139
|
+
|
140
|
+
it 'knows the target type' do
|
141
|
+
@project.target_type.should == :shared_library
|
142
|
+
end
|
143
|
+
|
144
|
+
it 'builds the library' do
|
145
|
+
Rake::Task[ 'build' ].invoke
|
146
|
+
exist?( @project.target ).should be_true
|
147
|
+
end
|
148
|
+
|
149
|
+
it 'hasn\'t got a \'run\' task' do
|
150
|
+
task_names.include?( 'run' ).should be_false
|
151
|
+
end
|
152
|
+
|
153
|
+
end
|
154
|
+
|
155
|
+
describe 'when installing' do
|
156
|
+
|
157
|
+
include RakeBuilderHelper
|
158
|
+
|
159
|
+
INSTALL_DIRECTORY = '/tmp/rake-builder-test-install'
|
160
|
+
|
161
|
+
before( :each ) do
|
162
|
+
Rake::Task.clear
|
163
|
+
`mkdir #{ INSTALL_DIRECTORY }`
|
164
|
+
@project = cpp_task( :executable ) do |builder|
|
165
|
+
builder.install_path = INSTALL_DIRECTORY
|
166
|
+
end
|
167
|
+
@installed_target = File.join( INSTALL_DIRECTORY, File.basename( @project.target ) )
|
168
|
+
end
|
169
|
+
|
170
|
+
after( :each ) do
|
171
|
+
`rm -rf #{ INSTALL_DIRECTORY }`
|
172
|
+
end
|
173
|
+
|
174
|
+
it 'should install the file' do
|
175
|
+
Rake::Task[ 'install' ].invoke
|
176
|
+
exist?( @installed_target ).should be_true
|
177
|
+
end
|
178
|
+
|
179
|
+
it 'should uninstall the file' do
|
180
|
+
Rake::Task[ 'install' ].invoke
|
181
|
+
exist?( @installed_target ).should be_true
|
182
|
+
Rake::Task[ 'uninstall' ].invoke
|
183
|
+
exist?( @installed_target ).should be_false
|
184
|
+
end
|
185
|
+
|
186
|
+
end
|