bake-toolkit 2.24.0 → 2.24.1
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.
- checksums.yaml +4 -4
- data/documentation/_build/html/_sources/changelog.txt +527 -521
- data/documentation/_build/html/_sources/index.txt +33 -33
- data/documentation/_build/html/_static/syntax.html +1 -1
- data/documentation/_build/html/changelog.html +9 -1
- data/documentation/_build/html/index.html +4 -4
- data/documentation/_build/html/searchindex.js +1 -1
- data/documentation/_build/html/syntax/project_meta_syntax.html +2 -2
- data/documentation/_build/html/syntax/syntax.html +1 -1
- data/lib/bake/libElement.rb +177 -176
- data/lib/bake/toolchain/gcc.rb +59 -55
- data/lib/bakeqac/options/options.rb +19 -7
- data/lib/blocks/block.rb +333 -323
- data/lib/blocks/compile.rb +520 -530
- data/lib/common/version.rb +1 -1
- metadata +2 -2
data/lib/blocks/compile.rb
CHANGED
@@ -1,531 +1,521 @@
|
|
1
|
-
require 'blocks/blockBase'
|
2
|
-
require 'multithread/job'
|
3
|
-
require 'common/process'
|
4
|
-
require 'common/utils'
|
5
|
-
require 'bake/toolchain/colorizing_formatter'
|
6
|
-
require 'bake/config/loader'
|
7
|
-
|
8
|
-
module Bake
|
9
|
-
|
10
|
-
module Blocks
|
11
|
-
|
12
|
-
class Compile < BlockBase
|
13
|
-
|
14
|
-
attr_reader :objects, :include_list
|
15
|
-
|
16
|
-
def initialize(block, config, referencedConfigs, tcs)
|
17
|
-
super(block, config, referencedConfigs, tcs)
|
18
|
-
@objects = []
|
19
|
-
@object_files = {}
|
20
|
-
|
21
|
-
calcFileTcs
|
22
|
-
calcIncludes
|
23
|
-
calcDefines # not for files with changed tcs
|
24
|
-
calcFlags # not for files with changed tcs
|
25
|
-
end
|
26
|
-
|
27
|
-
def get_object_file(source)
|
28
|
-
|
29
|
-
# until now all OBJECT_FILE_ENDING are equal in all three types
|
30
|
-
adaptedSource = source.chomp(File.extname(source)).gsub(/\.\./, "##") + (Bake.options.prepro ? ".i" : @tcs[:COMPILER][:CPP][:OBJECT_FILE_ENDING])
|
31
|
-
return adaptedSource if File.is_absolute?source
|
32
|
-
File.join([@output_dir, adaptedSource])
|
33
|
-
end
|
34
|
-
|
35
|
-
def ignore?(type)
|
36
|
-
Bake.options.linkOnly or (Bake.options.prepro and type == :ASM)
|
37
|
-
end
|
38
|
-
|
39
|
-
def needed?(source, object, type, dep_filename_conv)
|
40
|
-
return "because analyzer toolchain is configured" if Bake.options.analyze
|
41
|
-
return "because prepro was specified and source is no assembler file" if Bake.options.prepro
|
42
|
-
|
43
|
-
return "because object does not exist" if not File.exist?(object)
|
44
|
-
oTime = File.mtime(object)
|
45
|
-
|
46
|
-
return "because source is newer than object" if oTime < File.mtime(source)
|
47
|
-
|
48
|
-
if type != :ASM
|
49
|
-
return "because dependency file does not exist" if not File.exist?(dep_filename_conv)
|
50
|
-
|
51
|
-
begin
|
52
|
-
File.readlines(dep_filename_conv).map{|line| line.strip}.each do |dep|
|
53
|
-
if not File.exist?(dep)
|
54
|
-
# we need a hack here. with some windows configurations the compiler prints unix paths
|
55
|
-
# into the dep file which cannot be found easily. this will be true for system includes,
|
56
|
-
# e.g. /usr/lib/...xy.h
|
57
|
-
if (Bake::Utils::OS.windows? and dep.start_with?"/") or
|
58
|
-
(not Bake::Utils::OS.windows? and dep.length > 1 and dep[1] == ":")
|
59
|
-
puts "Dependency header file #{dep} ignored!" if Bake.options.debug
|
60
|
-
else
|
61
|
-
return "because dependent header #{dep} does not exist"
|
62
|
-
end
|
63
|
-
else
|
64
|
-
return "because dependent header #{dep} is newer than object" if oTime < File.mtime(dep)
|
65
|
-
end
|
66
|
-
end
|
67
|
-
rescue Exception => ex
|
68
|
-
if Bake.options.debug
|
69
|
-
puts "While reading #{dep_filename_conv}:"
|
70
|
-
puts ex.message
|
71
|
-
puts ex.backtrace
|
72
|
-
end
|
73
|
-
return "because dependency file could not be loaded"
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
false
|
78
|
-
end
|
79
|
-
|
80
|
-
def calcCmdlineFile(object)
|
81
|
-
object[0..-3] + ".cmdline"
|
82
|
-
end
|
83
|
-
|
84
|
-
def calcDepFile(object, type)
|
85
|
-
dep_filename = nil
|
86
|
-
if type != :ASM
|
87
|
-
dep_filename = object[0..-3] + ".d"
|
88
|
-
end
|
89
|
-
dep_filename
|
90
|
-
end
|
91
|
-
|
92
|
-
def calcDepFileConv(dep_filename)
|
93
|
-
dep_filename + ".bake"
|
94
|
-
end
|
95
|
-
|
96
|
-
def get_source_type(source)
|
97
|
-
ex = File.extname(source)
|
98
|
-
[:CPP, :C, :ASM].each do |t|
|
99
|
-
return t if @tcs[:COMPILER][t][:SOURCE_FILE_ENDINGS].include?(ex)
|
100
|
-
end
|
101
|
-
nil
|
102
|
-
end
|
103
|
-
|
104
|
-
def compileFile(source)
|
105
|
-
type = get_source_type(source)
|
106
|
-
return if type.nil?
|
107
|
-
|
108
|
-
object = @object_files[source]
|
109
|
-
|
110
|
-
dep_filename = calcDepFile(object, type)
|
111
|
-
dep_filename_conv = calcDepFileConv(dep_filename) if type != :ASM
|
112
|
-
|
113
|
-
cmdLineCheck = false
|
114
|
-
cmdLineFile = calcCmdlineFile(object)
|
115
|
-
|
116
|
-
return if ignore?(type)
|
117
|
-
reason = needed?(source, object, type, dep_filename_conv)
|
118
|
-
if not reason
|
119
|
-
cmdLineCheck = true
|
120
|
-
reason = config_changed?(cmdLineFile)
|
121
|
-
end
|
122
|
-
|
123
|
-
if @fileTcs.include?(source)
|
124
|
-
compiler = @fileTcs[source][:COMPILER][type]
|
125
|
-
defines = getDefines(compiler)
|
126
|
-
flags = getFlags(compiler)
|
127
|
-
else
|
128
|
-
compiler = @tcs[:COMPILER][type]
|
129
|
-
defines = @define_array[type]
|
130
|
-
flags = @flag_array[type]
|
131
|
-
end
|
132
|
-
includes = @include_array[type]
|
133
|
-
|
134
|
-
if Bake.options.prepro and compiler[:PREPRO_FLAGS] == ""
|
135
|
-
Bake.formatter.printError("Error: No preprocessor option available for " + source)
|
136
|
-
raise SystemCommandFailed.new
|
137
|
-
end
|
138
|
-
|
139
|
-
cmd = Utils.flagSplit(compiler[:COMMAND], false)
|
140
|
-
cmd += compiler[:COMPILE_FLAGS].split(" ")
|
141
|
-
|
142
|
-
if dep_filename
|
143
|
-
cmd += @tcs[:COMPILER][type][:DEP_FLAGS].split(" ")
|
144
|
-
if @tcs[:COMPILER][type][:DEP_FLAGS_FILENAME]
|
145
|
-
if @tcs[:COMPILER][type][:DEP_FLAGS_SPACE]
|
146
|
-
cmd << dep_filename
|
147
|
-
else
|
148
|
-
if dep_filename.include?" "
|
149
|
-
cmd[cmd.length-1] << "\"" + dep_filename + "\""
|
150
|
-
else
|
151
|
-
cmd[cmd.length-1] << dep_filename
|
152
|
-
end
|
153
|
-
|
154
|
-
end
|
155
|
-
end
|
156
|
-
end
|
157
|
-
|
158
|
-
cmd += compiler[:PREPRO_FLAGS].split(" ") if Bake.options.prepro
|
159
|
-
cmd += flags
|
160
|
-
cmd += includes
|
161
|
-
cmd += defines
|
162
|
-
|
163
|
-
offlag = compiler[:OBJECT_FILE_FLAG]
|
164
|
-
offlag = compiler[:PREPRO_FILE_FLAG] if compiler[:PREPRO_FILE_FLAG] and Bake.options.prepro
|
165
|
-
|
166
|
-
if compiler[:OBJ_FLAG_SPACE]
|
167
|
-
cmd << offlag
|
168
|
-
cmd << object
|
169
|
-
else
|
170
|
-
if object.include?" "
|
171
|
-
cmd << offlag + "\"" + object + "\""
|
172
|
-
else
|
173
|
-
cmd << offlag + object
|
174
|
-
end
|
175
|
-
end
|
176
|
-
cmd << source
|
177
|
-
|
178
|
-
if Bake.options.cc2j_filename
|
179
|
-
cmdJson = cmd.is_a?(Array) ? cmd.join(' ') : cmd
|
180
|
-
Blocks::CC2J << { :directory => @projectDir, :command => cmdJson, :file => source }
|
181
|
-
end
|
182
|
-
|
183
|
-
if not (cmdLineCheck and BlockBase.isCmdLineEqual?(cmd, cmdLineFile))
|
184
|
-
BlockBase.prepareOutput(object)
|
185
|
-
BlockBase.writeCmdLineFile(cmd, cmdLineFile)
|
186
|
-
success, consoleOutput = ProcessHelper.run(cmd, false, false)
|
187
|
-
|
188
|
-
outputType = Bake.options.analyze ? "Analyzing" : (Bake.options.prepro ? "Preprocessing" : "Compiling")
|
189
|
-
incList = process_result(cmd, consoleOutput, compiler[:ERROR_PARSER], "#{outputType} #{source}", reason, success)
|
190
|
-
|
191
|
-
if type != :ASM and not Bake.options.analyze and not Bake.options.prepro
|
192
|
-
incList = Compile.read_depfile(dep_filename, @projectDir, @tcs[:COMPILER][:DEP_FILE_SINGLE_LINE]) if incList.nil?
|
193
|
-
Compile.write_depfile(incList, dep_filename_conv)
|
194
|
-
end
|
195
|
-
check_config_file
|
196
|
-
end
|
197
|
-
|
198
|
-
Bake::Bundle.instance.addSource(source, @include_list, dep_filename_conv) if isMainProject?
|
199
|
-
|
200
|
-
end
|
201
|
-
|
202
|
-
def self.read_depfile(dep_filename, projDir, singleLine)
|
203
|
-
deps = []
|
204
|
-
begin
|
205
|
-
if singleLine
|
206
|
-
File.readlines(dep_filename).each do |line|
|
207
|
-
splitted = line.split(": ")
|
208
|
-
deps << splitted[1].gsub(/[\\]/,'/') if splitted.length > 1
|
209
|
-
end
|
210
|
-
else
|
211
|
-
deps_string = File.read(dep_filename)
|
212
|
-
deps_string = deps_string.gsub(/\\\n/,'')
|
213
|
-
dep_splitted = deps_string.split(/([^\\]) /).each_slice(2).map(&:join)[2..-1]
|
214
|
-
deps = dep_splitted.map { |d| d.gsub(/[\\] /,' ').gsub(/[\\]/,'/').strip }.delete_if {|d| d == "" }
|
215
|
-
end
|
216
|
-
rescue Exception => ex1
|
217
|
-
Bake.formatter.printWarning("Could not read '#{dep_filename}'", projDir)
|
218
|
-
puts ex1.message if Bake.options.debug
|
219
|
-
return nil
|
220
|
-
end
|
221
|
-
deps
|
222
|
-
end
|
223
|
-
|
224
|
-
# todo: move to toolchain util file
|
225
|
-
def self.write_depfile(deps, dep_filename_conv)
|
226
|
-
if deps
|
227
|
-
begin
|
228
|
-
File.open(dep_filename_conv, 'wb') do |f|
|
229
|
-
deps.each do |dep|
|
230
|
-
f.puts(dep)
|
231
|
-
end
|
232
|
-
end
|
233
|
-
rescue Exception
|
234
|
-
Bake.formatter.printWarning("Could not write '#{dep_filename_conv}'", projDir)
|
235
|
-
return nil
|
236
|
-
end
|
237
|
-
end
|
238
|
-
end
|
239
|
-
|
240
|
-
def mutex
|
241
|
-
@mutex ||= Mutex.new
|
242
|
-
end
|
243
|
-
|
244
|
-
def execute
|
245
|
-
Dir.chdir(@projectDir) do
|
246
|
-
|
247
|
-
calcSources
|
248
|
-
calcObjects
|
249
|
-
|
250
|
-
@
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
if
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
[:
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
def
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
end
|
522
|
-
|
523
|
-
def tcs4source(source)
|
524
|
-
@fileTcs[source] || @tcs
|
525
|
-
end
|
526
|
-
|
527
|
-
|
528
|
-
end
|
529
|
-
|
530
|
-
end
|
1
|
+
require 'blocks/blockBase'
|
2
|
+
require 'multithread/job'
|
3
|
+
require 'common/process'
|
4
|
+
require 'common/utils'
|
5
|
+
require 'bake/toolchain/colorizing_formatter'
|
6
|
+
require 'bake/config/loader'
|
7
|
+
|
8
|
+
module Bake
|
9
|
+
|
10
|
+
module Blocks
|
11
|
+
|
12
|
+
class Compile < BlockBase
|
13
|
+
|
14
|
+
attr_reader :objects, :include_list
|
15
|
+
|
16
|
+
def initialize(block, config, referencedConfigs, tcs)
|
17
|
+
super(block, config, referencedConfigs, tcs)
|
18
|
+
@objects = []
|
19
|
+
@object_files = {}
|
20
|
+
|
21
|
+
calcFileTcs
|
22
|
+
calcIncludes
|
23
|
+
calcDefines # not for files with changed tcs
|
24
|
+
calcFlags # not for files with changed tcs
|
25
|
+
end
|
26
|
+
|
27
|
+
def get_object_file(source)
|
28
|
+
|
29
|
+
# until now all OBJECT_FILE_ENDING are equal in all three types
|
30
|
+
adaptedSource = source.chomp(File.extname(source)).gsub(/\.\./, "##") + (Bake.options.prepro ? ".i" : @tcs[:COMPILER][:CPP][:OBJECT_FILE_ENDING])
|
31
|
+
return adaptedSource if File.is_absolute?source
|
32
|
+
File.join([@output_dir, adaptedSource])
|
33
|
+
end
|
34
|
+
|
35
|
+
def ignore?(type)
|
36
|
+
Bake.options.linkOnly or (Bake.options.prepro and type == :ASM)
|
37
|
+
end
|
38
|
+
|
39
|
+
def needed?(source, object, type, dep_filename_conv)
|
40
|
+
return "because analyzer toolchain is configured" if Bake.options.analyze
|
41
|
+
return "because prepro was specified and source is no assembler file" if Bake.options.prepro
|
42
|
+
|
43
|
+
return "because object does not exist" if not File.exist?(object)
|
44
|
+
oTime = File.mtime(object)
|
45
|
+
|
46
|
+
return "because source is newer than object" if oTime < File.mtime(source)
|
47
|
+
|
48
|
+
if type != :ASM
|
49
|
+
return "because dependency file does not exist" if not File.exist?(dep_filename_conv)
|
50
|
+
|
51
|
+
begin
|
52
|
+
File.readlines(dep_filename_conv).map{|line| line.strip}.each do |dep|
|
53
|
+
if not File.exist?(dep)
|
54
|
+
# we need a hack here. with some windows configurations the compiler prints unix paths
|
55
|
+
# into the dep file which cannot be found easily. this will be true for system includes,
|
56
|
+
# e.g. /usr/lib/...xy.h
|
57
|
+
if (Bake::Utils::OS.windows? and dep.start_with?"/") or
|
58
|
+
(not Bake::Utils::OS.windows? and dep.length > 1 and dep[1] == ":")
|
59
|
+
puts "Dependency header file #{dep} ignored!" if Bake.options.debug
|
60
|
+
else
|
61
|
+
return "because dependent header #{dep} does not exist"
|
62
|
+
end
|
63
|
+
else
|
64
|
+
return "because dependent header #{dep} is newer than object" if oTime < File.mtime(dep)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
rescue Exception => ex
|
68
|
+
if Bake.options.debug
|
69
|
+
puts "While reading #{dep_filename_conv}:"
|
70
|
+
puts ex.message
|
71
|
+
puts ex.backtrace
|
72
|
+
end
|
73
|
+
return "because dependency file could not be loaded"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
false
|
78
|
+
end
|
79
|
+
|
80
|
+
def calcCmdlineFile(object)
|
81
|
+
object[0..-3] + ".cmdline"
|
82
|
+
end
|
83
|
+
|
84
|
+
def calcDepFile(object, type)
|
85
|
+
dep_filename = nil
|
86
|
+
if type != :ASM
|
87
|
+
dep_filename = object[0..-3] + ".d"
|
88
|
+
end
|
89
|
+
dep_filename
|
90
|
+
end
|
91
|
+
|
92
|
+
def calcDepFileConv(dep_filename)
|
93
|
+
dep_filename + ".bake"
|
94
|
+
end
|
95
|
+
|
96
|
+
def get_source_type(source)
|
97
|
+
ex = File.extname(source)
|
98
|
+
[:CPP, :C, :ASM].each do |t|
|
99
|
+
return t if @tcs[:COMPILER][t][:SOURCE_FILE_ENDINGS].include?(ex)
|
100
|
+
end
|
101
|
+
nil
|
102
|
+
end
|
103
|
+
|
104
|
+
def compileFile(source)
|
105
|
+
type = get_source_type(source)
|
106
|
+
return if type.nil?
|
107
|
+
|
108
|
+
object = @object_files[source]
|
109
|
+
|
110
|
+
dep_filename = calcDepFile(object, type)
|
111
|
+
dep_filename_conv = calcDepFileConv(dep_filename) if type != :ASM
|
112
|
+
|
113
|
+
cmdLineCheck = false
|
114
|
+
cmdLineFile = calcCmdlineFile(object)
|
115
|
+
|
116
|
+
return if ignore?(type)
|
117
|
+
reason = needed?(source, object, type, dep_filename_conv)
|
118
|
+
if not reason
|
119
|
+
cmdLineCheck = true
|
120
|
+
reason = config_changed?(cmdLineFile)
|
121
|
+
end
|
122
|
+
|
123
|
+
if @fileTcs.include?(source)
|
124
|
+
compiler = @fileTcs[source][:COMPILER][type]
|
125
|
+
defines = getDefines(compiler)
|
126
|
+
flags = getFlags(compiler)
|
127
|
+
else
|
128
|
+
compiler = @tcs[:COMPILER][type]
|
129
|
+
defines = @define_array[type]
|
130
|
+
flags = @flag_array[type]
|
131
|
+
end
|
132
|
+
includes = @include_array[type]
|
133
|
+
|
134
|
+
if Bake.options.prepro and compiler[:PREPRO_FLAGS] == ""
|
135
|
+
Bake.formatter.printError("Error: No preprocessor option available for " + source)
|
136
|
+
raise SystemCommandFailed.new
|
137
|
+
end
|
138
|
+
|
139
|
+
cmd = Utils.flagSplit(compiler[:COMMAND], false)
|
140
|
+
cmd += compiler[:COMPILE_FLAGS].split(" ")
|
141
|
+
|
142
|
+
if dep_filename
|
143
|
+
cmd += @tcs[:COMPILER][type][:DEP_FLAGS].split(" ")
|
144
|
+
if @tcs[:COMPILER][type][:DEP_FLAGS_FILENAME]
|
145
|
+
if @tcs[:COMPILER][type][:DEP_FLAGS_SPACE]
|
146
|
+
cmd << dep_filename
|
147
|
+
else
|
148
|
+
if dep_filename.include?" "
|
149
|
+
cmd[cmd.length-1] << "\"" + dep_filename + "\""
|
150
|
+
else
|
151
|
+
cmd[cmd.length-1] << dep_filename
|
152
|
+
end
|
153
|
+
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
cmd += compiler[:PREPRO_FLAGS].split(" ") if Bake.options.prepro
|
159
|
+
cmd += flags
|
160
|
+
cmd += includes
|
161
|
+
cmd += defines
|
162
|
+
|
163
|
+
offlag = compiler[:OBJECT_FILE_FLAG]
|
164
|
+
offlag = compiler[:PREPRO_FILE_FLAG] if compiler[:PREPRO_FILE_FLAG] and Bake.options.prepro
|
165
|
+
|
166
|
+
if compiler[:OBJ_FLAG_SPACE]
|
167
|
+
cmd << offlag
|
168
|
+
cmd << object
|
169
|
+
else
|
170
|
+
if object.include?" "
|
171
|
+
cmd << offlag + "\"" + object + "\""
|
172
|
+
else
|
173
|
+
cmd << offlag + object
|
174
|
+
end
|
175
|
+
end
|
176
|
+
cmd << source
|
177
|
+
|
178
|
+
if Bake.options.cc2j_filename
|
179
|
+
cmdJson = cmd.is_a?(Array) ? cmd.join(' ') : cmd
|
180
|
+
Blocks::CC2J << { :directory => @projectDir, :command => cmdJson, :file => source }
|
181
|
+
end
|
182
|
+
|
183
|
+
if not (cmdLineCheck and BlockBase.isCmdLineEqual?(cmd, cmdLineFile))
|
184
|
+
BlockBase.prepareOutput(object)
|
185
|
+
BlockBase.writeCmdLineFile(cmd, cmdLineFile)
|
186
|
+
success, consoleOutput = ProcessHelper.run(cmd, false, false)
|
187
|
+
|
188
|
+
outputType = Bake.options.analyze ? "Analyzing" : (Bake.options.prepro ? "Preprocessing" : "Compiling")
|
189
|
+
incList = process_result(cmd, consoleOutput, compiler[:ERROR_PARSER], "#{outputType} #{source}", reason, success)
|
190
|
+
|
191
|
+
if type != :ASM and not Bake.options.analyze and not Bake.options.prepro
|
192
|
+
incList = Compile.read_depfile(dep_filename, @projectDir, @tcs[:COMPILER][:DEP_FILE_SINGLE_LINE]) if incList.nil?
|
193
|
+
Compile.write_depfile(incList, dep_filename_conv)
|
194
|
+
end
|
195
|
+
check_config_file
|
196
|
+
end
|
197
|
+
|
198
|
+
Bake::Bundle.instance.addSource(source, @include_list, dep_filename_conv) if isMainProject?
|
199
|
+
|
200
|
+
end
|
201
|
+
|
202
|
+
def self.read_depfile(dep_filename, projDir, singleLine)
|
203
|
+
deps = []
|
204
|
+
begin
|
205
|
+
if singleLine
|
206
|
+
File.readlines(dep_filename).each do |line|
|
207
|
+
splitted = line.split(": ")
|
208
|
+
deps << splitted[1].gsub(/[\\]/,'/') if splitted.length > 1
|
209
|
+
end
|
210
|
+
else
|
211
|
+
deps_string = File.read(dep_filename)
|
212
|
+
deps_string = deps_string.gsub(/\\\n/,'')
|
213
|
+
dep_splitted = deps_string.split(/([^\\]) /).each_slice(2).map(&:join)[2..-1]
|
214
|
+
deps = dep_splitted.map { |d| d.gsub(/[\\] /,' ').gsub(/[\\]/,'/').strip }.delete_if {|d| d == "" }
|
215
|
+
end
|
216
|
+
rescue Exception => ex1
|
217
|
+
Bake.formatter.printWarning("Could not read '#{dep_filename}'", projDir)
|
218
|
+
puts ex1.message if Bake.options.debug
|
219
|
+
return nil
|
220
|
+
end
|
221
|
+
deps
|
222
|
+
end
|
223
|
+
|
224
|
+
# todo: move to toolchain util file
|
225
|
+
def self.write_depfile(deps, dep_filename_conv)
|
226
|
+
if deps
|
227
|
+
begin
|
228
|
+
File.open(dep_filename_conv, 'wb') do |f|
|
229
|
+
deps.each do |dep|
|
230
|
+
f.puts(dep)
|
231
|
+
end
|
232
|
+
end
|
233
|
+
rescue Exception
|
234
|
+
Bake.formatter.printWarning("Could not write '#{dep_filename_conv}'", projDir)
|
235
|
+
return nil
|
236
|
+
end
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
def mutex
|
241
|
+
@mutex ||= Mutex.new
|
242
|
+
end
|
243
|
+
|
244
|
+
def execute
|
245
|
+
Dir.chdir(@projectDir) do
|
246
|
+
|
247
|
+
calcSources
|
248
|
+
calcObjects
|
249
|
+
|
250
|
+
@error_strings = {}
|
251
|
+
|
252
|
+
compileJobs = Multithread::Jobs.new(@source_files) do |jobs|
|
253
|
+
while source = jobs.get_next_or_nil do
|
254
|
+
|
255
|
+
if (jobs.failed and Bake.options.stopOnFirstError) or Bake::IDEInterface.instance.get_abort
|
256
|
+
break
|
257
|
+
end
|
258
|
+
|
259
|
+
s = StringIO.new
|
260
|
+
tmp = Thread.current[:stdout]
|
261
|
+
Thread.current[:stdout] = s unless tmp
|
262
|
+
|
263
|
+
result = false
|
264
|
+
begin
|
265
|
+
compileFile(source)
|
266
|
+
result = true
|
267
|
+
rescue Bake::SystemCommandFailed => scf # normal compilation error
|
268
|
+
rescue SystemExit => exSys
|
269
|
+
rescue Exception => ex1
|
270
|
+
if not Bake::IDEInterface.instance.get_abort
|
271
|
+
Bake.formatter.printError("Error: #{ex1.message}")
|
272
|
+
puts ex1.backtrace if Bake.options.debug
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
276
|
+
jobs.set_failed if not result
|
277
|
+
|
278
|
+
Thread.current[:stdout] = tmp
|
279
|
+
|
280
|
+
mutex.synchronize do
|
281
|
+
if s.string.length > 0
|
282
|
+
if Bake.options.stopOnFirstError and not result
|
283
|
+
@error_strings[source] = s.string
|
284
|
+
else
|
285
|
+
puts s.string
|
286
|
+
end
|
287
|
+
end
|
288
|
+
end
|
289
|
+
|
290
|
+
end
|
291
|
+
end
|
292
|
+
compileJobs.join
|
293
|
+
|
294
|
+
# can only happen in case of bail_on_first_error.
|
295
|
+
# if not sorted, it may be confusing when builing more than once and the order of the error appearances changes from build to build
|
296
|
+
# (it is not deterministic which file compilation finishes first)
|
297
|
+
@error_strings.sort.each {|es| puts es[1]}
|
298
|
+
|
299
|
+
raise SystemCommandFailed.new if compileJobs.failed
|
300
|
+
|
301
|
+
|
302
|
+
end
|
303
|
+
return true
|
304
|
+
end
|
305
|
+
|
306
|
+
def clean
|
307
|
+
if Bake.options.filename or Bake.options.analyze
|
308
|
+
Dir.chdir(@projectDir) do
|
309
|
+
calcSources(true)
|
310
|
+
@source_files.each do |source|
|
311
|
+
|
312
|
+
type = get_source_type(source)
|
313
|
+
next if type.nil?
|
314
|
+
object = get_object_file(source)
|
315
|
+
if File.exist?object
|
316
|
+
puts "Deleting file #{object}" if Bake.options.verbose >= 2
|
317
|
+
FileUtils.rm_rf(object)
|
318
|
+
end
|
319
|
+
if not Bake.options.analyze
|
320
|
+
dep_filename = calcDepFile(object, type)
|
321
|
+
if dep_filename and File.exist?dep_filename
|
322
|
+
puts "Deleting file #{dep_filename}" if Bake.options.verbose >= 2
|
323
|
+
FileUtils.rm_rf(dep_filename)
|
324
|
+
end
|
325
|
+
cmdLineFile = calcCmdlineFile(object)
|
326
|
+
if File.exist?cmdLineFile
|
327
|
+
puts "Deleting file #{cmdLineFile}" if Bake.options.verbose >= 2
|
328
|
+
FileUtils.rm_rf(cmdLineFile)
|
329
|
+
end
|
330
|
+
end
|
331
|
+
end
|
332
|
+
end
|
333
|
+
end
|
334
|
+
return true
|
335
|
+
end
|
336
|
+
|
337
|
+
def calcObjects
|
338
|
+
@source_files.each do |source|
|
339
|
+
type = get_source_type(source)
|
340
|
+
if not type.nil?
|
341
|
+
object = get_object_file(source)
|
342
|
+
if @objects.include?object
|
343
|
+
@object_files.each do |k,v|
|
344
|
+
if (v == object) # will be found exactly once
|
345
|
+
Bake.formatter.printError("Source files '#{k}' and '#{source}' would result in the same object file", source)
|
346
|
+
raise SystemCommandFailed.new
|
347
|
+
end
|
348
|
+
end
|
349
|
+
end
|
350
|
+
@object_files[source] = object
|
351
|
+
@objects << object
|
352
|
+
end
|
353
|
+
end
|
354
|
+
end
|
355
|
+
|
356
|
+
def calcSources(cleaning = false, keep = false)
|
357
|
+
return @source_files if @source_files and not @source_files.empty?
|
358
|
+
Dir.chdir(@projectDir) do
|
359
|
+
@source_files = []
|
360
|
+
|
361
|
+
exclude_files = Set.new
|
362
|
+
@config.excludeFiles.each do |p|
|
363
|
+
Dir.glob(p.name).each {|f| exclude_files << f}
|
364
|
+
end
|
365
|
+
|
366
|
+
source_files = Set.new
|
367
|
+
@config.files.each do |sources|
|
368
|
+
p = sources.name
|
369
|
+
res = Dir.glob(p).sort
|
370
|
+
if res.length == 0 and cleaning == false
|
371
|
+
if not p.include?"*" and not p.include?"?"
|
372
|
+
Bake.formatter.printError("Source file '#{p}' not found", sources)
|
373
|
+
raise SystemCommandFailed.new
|
374
|
+
elsif Bake.options.verbose >= 1
|
375
|
+
Bake.formatter.printInfo("Source file pattern '#{p}' does not match to any file", sources)
|
376
|
+
end
|
377
|
+
end
|
378
|
+
res.each do |f|
|
379
|
+
next if exclude_files.include?(f)
|
380
|
+
next if source_files.include?(f)
|
381
|
+
source_files << f
|
382
|
+
@source_files << f
|
383
|
+
end
|
384
|
+
end
|
385
|
+
|
386
|
+
if Bake.options.filename
|
387
|
+
@source_files.keep_if do |source|
|
388
|
+
source.include?Bake.options.filename
|
389
|
+
end
|
390
|
+
if @source_files.length == 0 and cleaning == false
|
391
|
+
Bake.formatter.printInfo("#{Bake.options.filename} does not match to any source", @config)
|
392
|
+
end
|
393
|
+
end
|
394
|
+
|
395
|
+
if Bake.options.eclipseOrder # directories reverse order, files in directories in alphabetical order
|
396
|
+
dirs = []
|
397
|
+
filemap = {}
|
398
|
+
@source_files.sort.reverse.each do |o|
|
399
|
+
d = File.dirname(o)
|
400
|
+
if filemap.include?(d)
|
401
|
+
filemap[d] << o
|
402
|
+
else
|
403
|
+
filemap[d] = [o]
|
404
|
+
dirs << d
|
405
|
+
end
|
406
|
+
end
|
407
|
+
@source_files = []
|
408
|
+
dirs.each do |d|
|
409
|
+
filemap[d].reverse.each do |f|
|
410
|
+
@source_files << f
|
411
|
+
end
|
412
|
+
end
|
413
|
+
end
|
414
|
+
end
|
415
|
+
@source_files
|
416
|
+
end
|
417
|
+
|
418
|
+
def mapInclude(inc, orgBlock)
|
419
|
+
|
420
|
+
if inc.name == "___ROOTS___"
|
421
|
+
return Bake.options.roots.map { |r| File.rel_from_to_project(@projectDir,r,false) }
|
422
|
+
end
|
423
|
+
|
424
|
+
i = orgBlock.convPath(inc,nil,true)
|
425
|
+
if orgBlock != @block
|
426
|
+
if not File.is_absolute?(i)
|
427
|
+
i = File.rel_from_to_project(@projectDir,orgBlock.config.parent.get_project_dir) + i
|
428
|
+
end
|
429
|
+
end
|
430
|
+
|
431
|
+
Pathname.new(i).cleanpath
|
432
|
+
end
|
433
|
+
|
434
|
+
def calcIncludes
|
435
|
+
@include_list = @config.includeDir.uniq.map do |dir|
|
436
|
+
mapInclude(dir, @block)
|
437
|
+
end
|
438
|
+
|
439
|
+
@block.getBlocks(:childs).each do |b|
|
440
|
+
b.config.includeDir.each do |inc|
|
441
|
+
if inc.inherit == true
|
442
|
+
@include_list << mapInclude(inc, b)
|
443
|
+
end
|
444
|
+
end if b.config.respond_to?("includeDir")
|
445
|
+
end
|
446
|
+
|
447
|
+
@block.getBlocks(:parents).each do |b|
|
448
|
+
if b.config.respond_to?("includeDir")
|
449
|
+
include_list_front = []
|
450
|
+
b.config.includeDir.each do |inc|
|
451
|
+
if inc.inject == "front"
|
452
|
+
include_list_front << mapInclude(inc, b)
|
453
|
+
elsif inc.inject == "back"
|
454
|
+
@include_list << mapInclude(inc, b)
|
455
|
+
elsif inc.infix == "front"
|
456
|
+
include_list_front << mapInclude(inc, b)
|
457
|
+
elsif inc.infix == "back"
|
458
|
+
@include_list << mapInclude(inc, b)
|
459
|
+
end
|
460
|
+
end
|
461
|
+
@include_list = include_list_front + @include_list
|
462
|
+
end
|
463
|
+
end
|
464
|
+
|
465
|
+
@include_list = @include_list.flatten.uniq
|
466
|
+
|
467
|
+
@include_array = {}
|
468
|
+
[:CPP, :C, :ASM].each do |type|
|
469
|
+
@include_array[type] = @include_list.map {|k| "#{@tcs[:COMPILER][type][:INCLUDE_PATH_FLAG]}#{k}"}
|
470
|
+
end
|
471
|
+
end
|
472
|
+
|
473
|
+
def getDefines(compiler)
|
474
|
+
compiler[:DEFINES].map {|k| "#{compiler[:DEFINE_FLAG]}#{k}"}
|
475
|
+
end
|
476
|
+
|
477
|
+
def getFlags(compiler)
|
478
|
+
Bake::Utils::flagSplit(compiler[:FLAGS],true)
|
479
|
+
end
|
480
|
+
|
481
|
+
def calcDefines
|
482
|
+
@define_array = {}
|
483
|
+
[:CPP, :C, :ASM].each do |type|
|
484
|
+
@define_array[type] = getDefines(@tcs[:COMPILER][type])
|
485
|
+
end
|
486
|
+
end
|
487
|
+
def calcFlags
|
488
|
+
@flag_array = {}
|
489
|
+
[:CPP, :C, :ASM].each do |type|
|
490
|
+
@flag_array[type] = getFlags(@tcs[:COMPILER][type])
|
491
|
+
end
|
492
|
+
end
|
493
|
+
|
494
|
+
def calcFileTcs
|
495
|
+
@fileTcs = {}
|
496
|
+
@config.files.each do |f|
|
497
|
+
if (f.define.length > 0 or f.flags.length > 0)
|
498
|
+
if f.name.include?"*"
|
499
|
+
Bake.formatter.printWarning("Toolchain settings not allowed for file pattern #{f.name}", f)
|
500
|
+
err_res = ErrorDesc.new
|
501
|
+
err_res.file_name = @config.file_name
|
502
|
+
err_res.line_number = f.line_number
|
503
|
+
err_res.severity = ErrorParser::SEVERITY_WARNING
|
504
|
+
err_res.message = "Toolchain settings not allowed for file patterns"
|
505
|
+
Bake::IDEInterface.instance.set_errors([err_res])
|
506
|
+
else
|
507
|
+
@fileTcs[f.name] = integrateCompilerFile(Utils.deep_copy(@tcs),f)
|
508
|
+
end
|
509
|
+
end
|
510
|
+
end
|
511
|
+
end
|
512
|
+
|
513
|
+
def tcs4source(source)
|
514
|
+
@fileTcs[source] || @tcs
|
515
|
+
end
|
516
|
+
|
517
|
+
|
518
|
+
end
|
519
|
+
|
520
|
+
end
|
531
521
|
end
|