rake-builder 0.0.8
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/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
|