bake 0.1.0
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/CONCEPTS +2 -0
- data/MIT-LICENSE +21 -0
- data/README +38 -0
- data/REFERENCE +2 -0
- data/TUTORIAL +133 -0
- data/bin/bake +10 -0
- data/lib/bake.rb +155 -0
- data/lib/bake/common_scheme.rb +42 -0
- data/lib/bake/configuration.rb +154 -0
- data/lib/bake/context.rb +101 -0
- data/lib/bake/cpp_scheme.rb +460 -0
- data/lib/bake/project_loader.rb +111 -0
- data/lib/bake/qt_scheme.rb +62 -0
- data/lib/bake/scheme.rb +104 -0
- data/lib/bake/scheme_loader.rb +28 -0
- data/lib/bake/string_utils.rb +19 -0
- data/lib/bake/target.rb +115 -0
- data/lib/bake/toolset.rb +11 -0
- data/lib/bake_version.rb +5 -0
- data/test/bake_test.rb +5 -0
- data/test/configuration_test.rb +102 -0
- data/test/context_test.rb +94 -0
- data/test/scheme_test.rb +121 -0
- data/test/target_test.rb +93 -0
- metadata +76 -0
data/lib/bake/context.rb
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
require 'bake/string_utils.rb'
|
2
|
+
|
3
|
+
module Bake
|
4
|
+
class Context
|
5
|
+
def initialize(scheme_loader)
|
6
|
+
@scheme_loader = scheme_loader
|
7
|
+
@current = nil
|
8
|
+
end
|
9
|
+
|
10
|
+
def context_eval(target, str = nil, file = nil, &block)
|
11
|
+
old = @current
|
12
|
+
begin
|
13
|
+
@current = target
|
14
|
+
if str
|
15
|
+
instance_eval(str, file ? file : '')
|
16
|
+
else
|
17
|
+
instance_eval(&block)
|
18
|
+
end
|
19
|
+
ensure
|
20
|
+
@current = old
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def using(scheme_and_toolset)
|
25
|
+
scheme_name, toolset_name = scheme_and_toolset.to_s.split('.')
|
26
|
+
toolset_name = 'default' if !toolset_name
|
27
|
+
scheme = @scheme_loader.scheme(scheme_name)
|
28
|
+
raise "invalid scheme '#{scheme_name}'" if !scheme
|
29
|
+
scheme.toolset = toolset_name
|
30
|
+
end
|
31
|
+
|
32
|
+
def glob(*args)
|
33
|
+
has_options = args.last.respond_to?(:to_hash)
|
34
|
+
options = has_options ? args.pop.to_hash : {}
|
35
|
+
exclude = array_opt(options, :exclude)
|
36
|
+
files = []
|
37
|
+
args.each do |pat|
|
38
|
+
matches = Dir[pat]
|
39
|
+
matches.each do |file|
|
40
|
+
if !exclude.find { |exc| File.fnmatch(exc, file) }
|
41
|
+
files.push(file)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
if block_given?
|
46
|
+
for i in 0...files.size
|
47
|
+
yield(files[i])
|
48
|
+
end
|
49
|
+
end
|
50
|
+
return files
|
51
|
+
end
|
52
|
+
|
53
|
+
def macro(name, &block)
|
54
|
+
raise "no block given for macro '#{name}'" if !block
|
55
|
+
@current.opt(:macros => { :name => name, :block => block })
|
56
|
+
end
|
57
|
+
|
58
|
+
def method_missing(method, *args, &block)
|
59
|
+
@scheme_loader.schemes.each do |name, scheme|
|
60
|
+
if scheme.has_constructor?(method)
|
61
|
+
target = scheme.construct(method, @current, *args)
|
62
|
+
context_eval(target, &block) if block
|
63
|
+
return target
|
64
|
+
end
|
65
|
+
end
|
66
|
+
return object_method_missing(method, *args, &block) if !@current
|
67
|
+
macro = @current[:macros].find { |macro| macro[:name] == method }
|
68
|
+
if macro
|
69
|
+
return instance_exec(*args, ¯o[:block])
|
70
|
+
end
|
71
|
+
if @current.respond_to?(method)
|
72
|
+
return @current.send(method, *args, &block)
|
73
|
+
end
|
74
|
+
raise "undefined symbol '#{method}'"
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
def array_opt(options, name)
|
79
|
+
opt = options[name]
|
80
|
+
return [] if !opt
|
81
|
+
if opt.respond_to?(:to_ary)
|
82
|
+
opt = opt.to_ary
|
83
|
+
else
|
84
|
+
opt = [ opt ]
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
# took this implementation from http://tinyurl.com/gzrtn
|
89
|
+
def instance_exec(*args, &block)
|
90
|
+
mname = "__instance_exec_#{Thread.current.object_id.abs}"
|
91
|
+
class << self; self end.class_eval{ define_method(mname, &block) }
|
92
|
+
begin
|
93
|
+
ret = send(mname, *args)
|
94
|
+
ensure
|
95
|
+
class << self; self end.class_eval{ undef_method(mname) } rescue nil
|
96
|
+
end
|
97
|
+
ret
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
@@ -0,0 +1,460 @@
|
|
1
|
+
require 'bake/toolset'
|
2
|
+
require 'bake/target'
|
3
|
+
require 'fileutils'
|
4
|
+
require 'set'
|
5
|
+
|
6
|
+
class CppToolsetBase < Bake::Toolset
|
7
|
+
def build(target)
|
8
|
+
if stale?(target)
|
9
|
+
FileUtils.mkdir_p(target[:outdir])
|
10
|
+
if target.is_a?(Cpp::Object)
|
11
|
+
compile(target)
|
12
|
+
# refresh the .includes file
|
13
|
+
includes = target.includes
|
14
|
+
filename = "#{target[:outdir]}/#{target.src.basename}.includes"
|
15
|
+
File.open(filename, "w") do |file|
|
16
|
+
includes.each { |inc| file.puts(inc) }
|
17
|
+
end
|
18
|
+
elsif target.is_a?(Cpp::Library)
|
19
|
+
ar(target)
|
20
|
+
elsif target.is_a?(Cpp::Executable)
|
21
|
+
link(target)
|
22
|
+
elsif target.is_a?(Cpp::Runner)
|
23
|
+
run(target)
|
24
|
+
else
|
25
|
+
raise "unknown Cpp target of class '#{target.class}"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def stale?(target)
|
31
|
+
t = Time.now
|
32
|
+
output_files(target).each do |out|
|
33
|
+
return true if !File.exists?(out)
|
34
|
+
out_time = File.mtime(out)
|
35
|
+
t = out_time if out_time < t
|
36
|
+
end
|
37
|
+
if target.is_a?(Cpp::Object)
|
38
|
+
return true if File.mtime(target.src) > t
|
39
|
+
target.includes.each { |file| return true if File.mtime(file) > t }
|
40
|
+
elsif target.is_a?(Cpp::Runner)
|
41
|
+
return File.mtime(output_files(target.deps[0])[0]) > t
|
42
|
+
else
|
43
|
+
is_linked = target.is_a?(Cpp::Executable) ||
|
44
|
+
(target.is_a?(Cpp::Library) && target[:libtype] == 'dynamic')
|
45
|
+
target.children.each do |child|
|
46
|
+
output_files(child).each do |file|
|
47
|
+
return true if File.mtime(file) > t
|
48
|
+
end
|
49
|
+
end
|
50
|
+
target.deps.each do |dep|
|
51
|
+
if is_linked && dep.is_a?(Cpp::Library) &&
|
52
|
+
dep[:libtype] != 'dynamic'
|
53
|
+
output_files(dep).each do |file|
|
54
|
+
return true if File.mtime(file) > t
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
return false
|
60
|
+
end
|
61
|
+
|
62
|
+
def clean(target)
|
63
|
+
output_files(target).each { |file| FileUtils.rm_f(file) }
|
64
|
+
if target.is_a?(Cpp::Object)
|
65
|
+
filename = "#{target[:outdir]}/#{target.src.basename}.includes"
|
66
|
+
FileUtils.rm_f(filename)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def output_files(target)
|
71
|
+
out = output(target)
|
72
|
+
return [] if !out
|
73
|
+
return out.to_a if out.respond_to?(:to_a)
|
74
|
+
return [ out ]
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
class GccToolsetBase < CppToolsetBase
|
79
|
+
def output(target)
|
80
|
+
if target.is_a?(Cpp::Object)
|
81
|
+
return obj_fn(target)
|
82
|
+
elsif target.is_a?(Cpp::Library)
|
83
|
+
return lib_fn(target)
|
84
|
+
elsif target.is_a?(Cpp::Executable)
|
85
|
+
return exe_fn(target)
|
86
|
+
elsif target.is_a?(Cpp::Runner)
|
87
|
+
return runner_fn(target)
|
88
|
+
end
|
89
|
+
return nil
|
90
|
+
end
|
91
|
+
|
92
|
+
def compile(obj)
|
93
|
+
src = obj.src
|
94
|
+
output = obj_fn(obj)
|
95
|
+
flags = build_flags('-I', obj[:incdirs] + obj[:sysincdirs]) +
|
96
|
+
build_flags('-D', obj[:defines])
|
97
|
+
flags += obj[:cflags].join(' ')
|
98
|
+
flags += ' -fno-rtti' if !obj[:rtti?]
|
99
|
+
flags += ' -O3' if obj[:optimizations?]
|
100
|
+
flags += ' -g' if obj[:debug_symbols?]
|
101
|
+
sh("g++ -c -o #{output} #{flags} #{src}")
|
102
|
+
end
|
103
|
+
|
104
|
+
def ar(lib)
|
105
|
+
obj_str, lib_str, flags = process_inputs(lib)
|
106
|
+
|
107
|
+
output = lib_fn(lib)
|
108
|
+
if lib[:libtype] == 'dynamic'
|
109
|
+
sh("g++ #{flags} -shared -Wl,-soname,#{output} -o #{output} #{obj_str} #{lib_str}")
|
110
|
+
else
|
111
|
+
sh("ar rcs #{output} #{obj_str}")
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def link(exe)
|
116
|
+
obj_str, lib_str, flags = process_inputs(exe)
|
117
|
+
|
118
|
+
output = exe_fn(exe)
|
119
|
+
sh("g++ #{flags} -o #{output} #{obj_str} #{lib_str}")
|
120
|
+
end
|
121
|
+
|
122
|
+
def run(runner)
|
123
|
+
sh(exe_fn(runner.deps.first))
|
124
|
+
FileUtils.touch(runner_fn(runner))
|
125
|
+
end
|
126
|
+
|
127
|
+
private
|
128
|
+
def build_flags(flag, args)
|
129
|
+
return args.inject('') { |str, arg| str + "#{flag}#{arg} " }
|
130
|
+
end
|
131
|
+
|
132
|
+
def obj_fn(obj)
|
133
|
+
src = obj.src
|
134
|
+
basename = File.basename(src, File.extname(src)) + '.o'
|
135
|
+
return File.join(obj[:outdir], basename)
|
136
|
+
end
|
137
|
+
|
138
|
+
def lib_fn(lib)
|
139
|
+
if lib[:libtype] == 'dynamic'
|
140
|
+
return File.join(lib[:outdir], "#{lib.name}.so")
|
141
|
+
end
|
142
|
+
return File.join(lib[:outdir], "lib#{lib.name}.a")
|
143
|
+
end
|
144
|
+
|
145
|
+
def exe_fn(exe)
|
146
|
+
return File.join(exe[:outdir], exe.name)
|
147
|
+
end
|
148
|
+
|
149
|
+
def runner_fn(runner)
|
150
|
+
return "#{exe_fn(runner.deps.first)}.success"
|
151
|
+
end
|
152
|
+
|
153
|
+
def process_inputs(target)
|
154
|
+
output = output(target)
|
155
|
+
obj_str = ''
|
156
|
+
lib_str = ''
|
157
|
+
libdirs = []
|
158
|
+
(target.children + target.deps).each do |input|
|
159
|
+
if input.is_a?(Cpp::Object)
|
160
|
+
fn = obj_fn(input)
|
161
|
+
obj_str += fn + ' '
|
162
|
+
elsif input.is_a?(Cpp::SystemLibrary)
|
163
|
+
lib_str += '-l' + input.file + ' '
|
164
|
+
elsif input.is_a?(Cpp::Library)
|
165
|
+
fn = lib_fn(input)
|
166
|
+
if input[:libtype] == 'dynamic'
|
167
|
+
obj_str += fn + ' '
|
168
|
+
else
|
169
|
+
lib_str += '-l' + input.name + ' '
|
170
|
+
libdir = File.dirname(fn)
|
171
|
+
libdirs << libdir if !libdirs.include?(libdir)
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
libdirs.concat(target[:libdirs])
|
177
|
+
flags = build_flags('-L', libdirs)
|
178
|
+
|
179
|
+
return [ obj_str, lib_str, flags ]
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
module Cpp
|
184
|
+
class Darwin < GccToolsetBase
|
185
|
+
def ar(lib)
|
186
|
+
obj_str, lib_str, flags = process_inputs(lib)
|
187
|
+
|
188
|
+
output = lib_fn(lib)
|
189
|
+
if lib[:libtype] == 'dynamic'
|
190
|
+
sh("g++ #{flags} -dynamiclib -o #{output} #{obj_str} #{lib_str}")
|
191
|
+
else
|
192
|
+
sh("ar rcs #{output} #{obj_str}")
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
private
|
197
|
+
def lib_fn(lib)
|
198
|
+
if lib[:libtype] == 'dynamic'
|
199
|
+
return File.join(lib[:outdir], "#{lib.name}.dylib")
|
200
|
+
end
|
201
|
+
return File.join(lib[:outdir], "lib#{lib.name}.a")
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
class Gcc < GccToolsetBase
|
206
|
+
end
|
207
|
+
|
208
|
+
class Msvc6 < CppToolsetBase
|
209
|
+
def output(target)
|
210
|
+
if target.is_a?(Object)
|
211
|
+
return obj_fn(target)
|
212
|
+
elsif target.is_a?(Library)
|
213
|
+
return lib_fn(target)
|
214
|
+
elsif target.is_a?(Executable)
|
215
|
+
return exe_fn(target)
|
216
|
+
end
|
217
|
+
return nil
|
218
|
+
end
|
219
|
+
|
220
|
+
def compile(obj)
|
221
|
+
src = obj.src
|
222
|
+
output = obj_fn(obj)
|
223
|
+
flags = build_flags('/I', obj[:incdirs] + obj[:sysincdirs]) +
|
224
|
+
build_flags('/D', obj[:defines])
|
225
|
+
flags += obj[:cflags].join(' ')
|
226
|
+
flags += ' /MD'
|
227
|
+
flags += ' /EHsc' if obj[:exceptions?]
|
228
|
+
flags += ' /GR' if obj[:rtti?]
|
229
|
+
flags += obj[:optimizations?] ? ' /O2' : ' /Od'
|
230
|
+
flags += ' /Z7' if obj[:debug_symbols?]
|
231
|
+
sh("cl /nologo #{flags} /c /Fo#{output} /Tp#{src}")
|
232
|
+
end
|
233
|
+
|
234
|
+
def ar(lib)
|
235
|
+
obj_str, flags = process_inputs(lib)
|
236
|
+
|
237
|
+
output = lib_fn(lib)
|
238
|
+
if lib[:libtype] == 'dynamic'
|
239
|
+
flags += ' /debug' if lib[:debug_symbols?]
|
240
|
+
sh("link /nologo /dll #{flags} /out:#{output[1]} #{obj_str}")
|
241
|
+
else
|
242
|
+
sh("lib /nologo /out:#{output} #{obj_str}")
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
def link(exe)
|
247
|
+
obj_str, flags = process_inputs(exe)
|
248
|
+
|
249
|
+
output = exe_fn(exe)
|
250
|
+
flags += ' /debug' if exe[:debug_symbols?]
|
251
|
+
sh("link /nologo /subsystem:console #{flags} /out:#{output} #{obj_str}")
|
252
|
+
end
|
253
|
+
|
254
|
+
def run(runner)
|
255
|
+
sh(exe_fn(runner.deps.first))
|
256
|
+
FileUtils.touch(runner_fn(runner))
|
257
|
+
end
|
258
|
+
|
259
|
+
private
|
260
|
+
def build_flags(flag, args)
|
261
|
+
return args.inject('') { |str, arg| str + "#{flag}#{arg} " }
|
262
|
+
end
|
263
|
+
|
264
|
+
def obj_fn(obj)
|
265
|
+
src = obj.src
|
266
|
+
basename = File.basename(src, File.extname(src)) + '.obj'
|
267
|
+
return File.join(obj[:outdir], basename)
|
268
|
+
end
|
269
|
+
|
270
|
+
def lib_fn(lib)
|
271
|
+
if lib[:libtype] == 'dynamic'
|
272
|
+
return [File.join(lib[:outdir], "#{lib.name}.lib"),
|
273
|
+
File.join(lib[:outdir], "#{lib.name}.dll"),
|
274
|
+
File.join(lib[:outdir], "#{lib.name}.exp")]
|
275
|
+
end
|
276
|
+
return File.join(lib[:outdir], "#{lib.name}.lib")
|
277
|
+
end
|
278
|
+
|
279
|
+
def exe_fn(exe)
|
280
|
+
return File.join(exe[:outdir], exe.name + '.exe')
|
281
|
+
end
|
282
|
+
|
283
|
+
def runner_fn(runner)
|
284
|
+
return "#{exe_fn(runner.deps.first)}.success"
|
285
|
+
end
|
286
|
+
|
287
|
+
def process_inputs(target)
|
288
|
+
output = output(target)
|
289
|
+
obj_str = ''
|
290
|
+
libdirs = []
|
291
|
+
static_lib = target.is_a?(Library) && target[:libtype] == 'static'
|
292
|
+
(target.children + target.deps).each do |input|
|
293
|
+
if input.is_a?(Object)
|
294
|
+
fn = obj_fn(input)
|
295
|
+
obj_str += fn + ' '
|
296
|
+
elsif input.is_a?(SystemLibrary)
|
297
|
+
if !static_lib
|
298
|
+
obj_str += input.file + '.lib '
|
299
|
+
end
|
300
|
+
elsif input.is_a?(Library)
|
301
|
+
if !static_lib
|
302
|
+
if input[:libtype] == 'dynamic'
|
303
|
+
fn = lib_fn(input)[0]
|
304
|
+
else
|
305
|
+
fn = lib_fn(input)
|
306
|
+
end
|
307
|
+
libdir = File.dirname(fn)
|
308
|
+
libdirs << libdir if !libdirs.include?(libdir)
|
309
|
+
obj_str += File.basename(fn) + ' '
|
310
|
+
end
|
311
|
+
end
|
312
|
+
end
|
313
|
+
|
314
|
+
if !static_lib
|
315
|
+
target[:libs].each { |lib| obj_str += lib + '.lib ' }
|
316
|
+
end
|
317
|
+
libdirs.concat(target[:libdirs])
|
318
|
+
flags = build_flags('/LIBPATH:', libdirs)
|
319
|
+
|
320
|
+
return [ obj_str, flags ]
|
321
|
+
end
|
322
|
+
end
|
323
|
+
|
324
|
+
class Library < Bake::Target
|
325
|
+
ACCESSORS = :lib
|
326
|
+
|
327
|
+
def initialize(parent, name)
|
328
|
+
super(parent)
|
329
|
+
@name = name
|
330
|
+
default(:libtype => 'static')
|
331
|
+
default(:debug_symbols? => false)
|
332
|
+
end
|
333
|
+
|
334
|
+
def src(*args)
|
335
|
+
return args.flatten.collect { |file| Cpp::Object.new(self, file) }
|
336
|
+
end
|
337
|
+
end
|
338
|
+
|
339
|
+
class SystemLibrary < Bake::Target
|
340
|
+
ACCESSORS = :syslib
|
341
|
+
|
342
|
+
attr_reader :file
|
343
|
+
|
344
|
+
def initialize(parent, name, file)
|
345
|
+
super(parent)
|
346
|
+
@name = name
|
347
|
+
@file = file
|
348
|
+
opt(:built? => true)
|
349
|
+
end
|
350
|
+
end
|
351
|
+
|
352
|
+
class Executable < Bake::Target
|
353
|
+
ACCESSORS = :exe
|
354
|
+
|
355
|
+
def initialize(parent, name)
|
356
|
+
super(parent)
|
357
|
+
@name = name
|
358
|
+
default(:debug_symbols? => false)
|
359
|
+
end
|
360
|
+
|
361
|
+
def src(*args)
|
362
|
+
return args.flatten.collect { |file| Cpp::Object.new(self, file) }
|
363
|
+
end
|
364
|
+
end
|
365
|
+
|
366
|
+
class Source < Bake::Target
|
367
|
+
attr_reader :output
|
368
|
+
|
369
|
+
def initialize(parent, src)
|
370
|
+
super(parent)
|
371
|
+
@output = src
|
372
|
+
opt(:built? => true)
|
373
|
+
end
|
374
|
+
end
|
375
|
+
|
376
|
+
class Object < Bake::Target
|
377
|
+
ACCESSORS = :obj
|
378
|
+
|
379
|
+
def initialize(parent, src = nil)
|
380
|
+
super(parent)
|
381
|
+
return if !src
|
382
|
+
if src.instance_of?(String)
|
383
|
+
children << Source.new(self, src)
|
384
|
+
else
|
385
|
+
children << src
|
386
|
+
end
|
387
|
+
default(:exceptions? => true)
|
388
|
+
default(:rtti? => true)
|
389
|
+
default(:optimizations? => false)
|
390
|
+
default(:multithreaded? => true)
|
391
|
+
end
|
392
|
+
|
393
|
+
def src
|
394
|
+
return children.first.output
|
395
|
+
end
|
396
|
+
|
397
|
+
def includes(recalc = false)
|
398
|
+
incfile = "#{get(:outdir)}/#{src}.includes"
|
399
|
+
if !@includes || recalc
|
400
|
+
if File.exists?(incfile)
|
401
|
+
@includes = load_includes(incfile)
|
402
|
+
else
|
403
|
+
@includes = calc_includes(src, Set.new)
|
404
|
+
end
|
405
|
+
end
|
406
|
+
return @includes
|
407
|
+
end
|
408
|
+
|
409
|
+
private
|
410
|
+
def load_includes(incfile)
|
411
|
+
includes = Set.new
|
412
|
+
file = File.open(incfile)
|
413
|
+
while line = file.gets
|
414
|
+
line.chomp!
|
415
|
+
includes << line if !line.empty?
|
416
|
+
end
|
417
|
+
file.close
|
418
|
+
return includes
|
419
|
+
end
|
420
|
+
|
421
|
+
def calc_includes(filename, include_fns)
|
422
|
+
new_include_fns = Set.new
|
423
|
+
File.open(filename) do |file|
|
424
|
+
incdirs = get(:incdirs)
|
425
|
+
while line = file.gets
|
426
|
+
if line =~ /\s*#\s*include\s+("|<)([^"]+)("|>)/
|
427
|
+
inc = $2
|
428
|
+
incdirs.each do |include_dir|
|
429
|
+
fn = File.join(include_dir, inc)
|
430
|
+
break if include_fns.include?(fn)
|
431
|
+
if File.exists?(fn)
|
432
|
+
new_include_fns << fn
|
433
|
+
include_fns << fn
|
434
|
+
break
|
435
|
+
end
|
436
|
+
end
|
437
|
+
end
|
438
|
+
end
|
439
|
+
end
|
440
|
+
|
441
|
+
new_include_fns.each do |inc|
|
442
|
+
calc_includes(inc, include_fns)
|
443
|
+
end
|
444
|
+
return include_fns
|
445
|
+
end
|
446
|
+
end
|
447
|
+
|
448
|
+
class Runner < Bake::Target
|
449
|
+
ACCESSORS = :run
|
450
|
+
|
451
|
+
def initialize(parent, exe)
|
452
|
+
super(parent)
|
453
|
+
target = dep(exe)[0]
|
454
|
+
if !target.is_a?(Executable)
|
455
|
+
raise "target '#{target.name}' is not an executable"
|
456
|
+
end
|
457
|
+
end
|
458
|
+
end
|
459
|
+
end
|
460
|
+
|