bake-toolkit 2.24.6 → 2.25.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.
- checksums.yaml +4 -4
- data/bin/bake-doc +11 -11
- data/bin/bake-format +2 -2
- data/bin/bakeclean +32 -32
- data/bin/bakeqac +77 -6
- data/documentation/_build/html/_images/eclipse.png +0 -0
- data/documentation/_build/html/_images/emacs.png +0 -0
- data/documentation/_build/html/_images/notepad.png +0 -0
- data/documentation/_build/html/_images/vim.png +0 -0
- data/documentation/_build/html/_images/visualstudio-pro.png +0 -0
- data/documentation/_build/html/_sources/changelog.txt +10 -0
- data/documentation/_build/html/_sources/ide/ide_integrations.txt +40 -8
- data/documentation/_build/html/_sources/index.txt +1 -1
- data/documentation/_build/html/_sources/tips_and_tricks/qac.txt +159 -152
- data/documentation/_build/html/_static/eclipse.png +0 -0
- data/documentation/_build/html/_static/emacs.png +0 -0
- data/documentation/_build/html/_static/notepad.png +0 -0
- data/documentation/_build/html/_static/syntax.html +8 -1
- data/documentation/_build/html/_static/vim.png +0 -0
- data/documentation/_build/html/_static/visualstudio-pro.png +0 -0
- data/documentation/_build/html/changelog.html +12 -0
- data/documentation/_build/html/ide/ide_integrations.html +22 -20
- data/documentation/_build/html/index.html +5 -4
- data/documentation/_build/html/searchindex.js +1 -1
- data/documentation/_build/html/syntax/project_meta_syntax.html +8 -1
- data/documentation/_build/html/tips_and_tricks/qac.html +10 -3
- data/lib/bake/cache.rb +16 -28
- data/lib/bake/config/loader.rb +14 -24
- data/lib/bake/model/metamodel.rb +311 -307
- data/lib/bake/model/metamodel_ext.rb +33 -27
- data/lib/bake/subst.rb +4 -4
- data/lib/bake/toolchain/clang.rb +43 -44
- data/lib/bake/toolchain/clang_analyze.rb +30 -31
- data/lib/bake/toolchain/diab.rb +52 -53
- data/lib/bake/toolchain/gcc.rb +1 -1
- data/lib/bake/toolchain/gcc_env.rb +54 -55
- data/lib/bake/toolchain/greenhills.rb +51 -52
- data/lib/bake/toolchain/keil.rb +54 -55
- data/lib/bake/toolchain/lint.rb +19 -20
- data/lib/bake/toolchain/msvc.rb +57 -58
- data/lib/bake/toolchain/provider.rb +6 -3
- data/lib/bake/toolchain/ti.rb +50 -49
- data/lib/bakeqac/options/options.rb +2 -2
- data/lib/blocks/block.rb +4 -0
- data/lib/blocks/compile.rb +36 -19
- data/lib/common/version.rb +1 -1
- data/lib/format/bake_format.rb +1 -1
- data/lib/tocxx.rb +576 -558
- metadata +26 -2
@@ -62,7 +62,7 @@ module Bake
|
|
62
62
|
puts " --acf <file> Set a specific analysis config file, otherwise $(QAC_HOME)/config/acf/default.acf will be used."
|
63
63
|
puts " --qaccctpatch If specified, some adaptions to cct are made. Might improve the result - no guarantee."
|
64
64
|
puts " --qacdata <dir> QAC writes data into this folder. Default is <working directory>/.qacdata."
|
65
|
-
puts " --qacstep admin|analyze|view Steps can be ORed. Per default
|
65
|
+
puts " --qacstep admin|analyze|view|report Steps can be ORed. Per default admin|analyze|view will be executed."
|
66
66
|
puts " --qacnofilter Output will be printed immediately and unfiltered. Per default filters are used to reduce noise."
|
67
67
|
puts " --qacrawformat Raw QAC output (with incomplete MISRA rules!)."
|
68
68
|
puts " --qacretry <seconds> If build or result step fail due to refused license, the step will be retried until timeout."
|
@@ -120,7 +120,7 @@ module Bake
|
|
120
120
|
|
121
121
|
if !@qacstep.nil?
|
122
122
|
@qacstep.split("|").each do |s|
|
123
|
-
if not ["admin", "analyze", "view"].include?s
|
123
|
+
if not ["admin", "analyze", "view", "report"].include?s
|
124
124
|
Bake.formatter.printError("Error: incorrect qacstep name.")
|
125
125
|
ExitHelper.exit(1)
|
126
126
|
end
|
data/lib/blocks/block.rb
CHANGED
data/lib/blocks/compile.rb
CHANGED
@@ -17,6 +17,7 @@ module Bake
|
|
17
17
|
super(block, config, referencedConfigs, tcs)
|
18
18
|
@objects = []
|
19
19
|
@object_files = {}
|
20
|
+
@system_includes = Set.new
|
20
21
|
|
21
22
|
calcFileTcs
|
22
23
|
calcIncludes
|
@@ -431,31 +432,41 @@ module Bake
|
|
431
432
|
Pathname.new(i).cleanpath
|
432
433
|
end
|
433
434
|
|
434
|
-
def
|
435
|
-
@
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
@include_list << mapInclude(inc, b)
|
435
|
+
def calcIncludesInternal(block)
|
436
|
+
@blocksRead << block
|
437
|
+
block.config.baseElement.each do |be|
|
438
|
+
if Metamodel::IncludeDir === be
|
439
|
+
if be.inherit == true || block == @block
|
440
|
+
mappedInc = mapInclude(be, block)
|
441
|
+
@include_list << mappedInc
|
442
|
+
@system_includes << mappedInc if be.system
|
443
443
|
end
|
444
|
-
|
444
|
+
elsif Metamodel::Dependency === be
|
445
|
+
childBlock = block.depToBlock[be.name + "," + be.config]
|
446
|
+
calcIncludesInternal(childBlock) if !@blocksRead.include?(childBlock)
|
447
|
+
end
|
445
448
|
end
|
449
|
+
end
|
450
|
+
|
451
|
+
def calcIncludes
|
452
|
+
|
453
|
+
@blocksRead = Set.new
|
454
|
+
@include_list = []
|
455
|
+
@system_includes = Set.new
|
456
|
+
calcIncludesInternal(@block) # includeDir and child dependencies with inherit: true
|
446
457
|
|
447
458
|
@block.getBlocks(:parents).each do |b|
|
448
459
|
if b.config.respond_to?("includeDir")
|
449
460
|
include_list_front = []
|
450
461
|
b.config.includeDir.each do |inc|
|
451
|
-
if inc.inject == "front"
|
452
|
-
|
453
|
-
|
454
|
-
@
|
455
|
-
elsif inc.infix == "
|
456
|
-
|
457
|
-
|
458
|
-
@
|
462
|
+
if inc.inject == "front" || inc.infix == "front"
|
463
|
+
mappedInc = mapInclude(inc, b)
|
464
|
+
include_list_front << mappedInc
|
465
|
+
@system_includes << mappedInc if inc.system
|
466
|
+
elsif inc.inject == "back" || inc.infix == "back"
|
467
|
+
mappedInc = mapInclude(inc, b)
|
468
|
+
@include_list << mappedInc
|
469
|
+
@system_includes << mappedInc if inc.system
|
459
470
|
end
|
460
471
|
end
|
461
472
|
@include_list = include_list_front + @include_list
|
@@ -466,7 +477,13 @@ module Bake
|
|
466
477
|
|
467
478
|
@include_array = {}
|
468
479
|
[:CPP, :C, :ASM].each do |type|
|
469
|
-
@include_array[type] = @include_list.map
|
480
|
+
@include_array[type] = @include_list.map do |k|
|
481
|
+
if @system_includes.include?(k)
|
482
|
+
"#{@tcs[:COMPILER][type][:SYSTEM_INCLUDE_PATH_FLAG]}#{k}"
|
483
|
+
else
|
484
|
+
"#{@tcs[:COMPILER][type][:INCLUDE_PATH_FLAG]}#{k}"
|
485
|
+
end
|
486
|
+
end
|
470
487
|
end
|
471
488
|
end
|
472
489
|
|
data/lib/common/version.rb
CHANGED
data/lib/format/bake_format.rb
CHANGED
data/lib/tocxx.rb
CHANGED
@@ -1,559 +1,577 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
|
4
|
-
require 'bake/model/metamodel_ext'
|
5
|
-
|
6
|
-
require 'bake/util'
|
7
|
-
require 'bake/cache'
|
8
|
-
require 'bake/subst'
|
9
|
-
require 'bake/mergeConfig'
|
10
|
-
|
11
|
-
require 'common/exit_helper'
|
12
|
-
require 'common/ide_interface'
|
13
|
-
require 'common/ext/file'
|
14
|
-
require 'bake/toolchain/provider'
|
15
|
-
require 'common/ext/stdout'
|
16
|
-
require 'common/utils'
|
17
|
-
require 'bake/toolchain/colorizing_formatter'
|
18
|
-
require 'bake/config/loader'
|
19
|
-
|
20
|
-
require 'blocks/block'
|
21
|
-
require 'blocks/commandLine'
|
22
|
-
require 'blocks/makefile'
|
23
|
-
require 'blocks/compile'
|
24
|
-
require 'blocks/convert'
|
25
|
-
require 'blocks/library'
|
26
|
-
require 'blocks/executable'
|
27
|
-
require 'blocks/lint'
|
28
|
-
require 'blocks/convert'
|
29
|
-
require 'blocks/docu'
|
30
|
-
|
31
|
-
require 'set'
|
32
|
-
require 'socket'
|
33
|
-
|
34
|
-
require 'blocks/showIncludes'
|
35
|
-
require 'common/abortException'
|
36
|
-
|
37
|
-
require 'adapt/config/loader'
|
38
|
-
|
39
|
-
module Bake
|
40
|
-
|
41
|
-
class SystemCommandFailed < Exception
|
42
|
-
end
|
43
|
-
|
44
|
-
class ToCxx
|
45
|
-
|
46
|
-
@@linkBlock = 0
|
47
|
-
|
48
|
-
def self.linkBlock
|
49
|
-
@@linkBlock = 1
|
50
|
-
end
|
51
|
-
|
52
|
-
def initialize
|
53
|
-
@configTcMap = {}
|
54
|
-
end
|
55
|
-
|
56
|
-
def createBaseTcsForConfig
|
57
|
-
@
|
58
|
-
configs.each do |config|
|
59
|
-
tcs = Utils.deep_copy(@defaultToolchain)
|
60
|
-
@configTcMap[config] = tcs
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
def createTcsForConfig
|
66
|
-
@
|
67
|
-
configs.each do |config|
|
68
|
-
integrateToolchain(@configTcMap[config], config.toolchain)
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
def substVars
|
74
|
-
Subst.itute(@mainConfig, Bake.options.main_project_name, true, @configTcMap[@mainConfig], @
|
75
|
-
@
|
76
|
-
configs.each do |config|
|
77
|
-
if config != @mainConfig
|
78
|
-
Subst.itute(config, projName, false, @configTcMap[config], @
|
79
|
-
end
|
80
|
-
end
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
def addSteps(block, blockSteps, configSteps)
|
87
|
-
Array(configSteps.step).each do |step|
|
88
|
-
if Bake::Metamodel::Makefile === step
|
89
|
-
blockSteps << Blocks::Makefile.new(step, @
|
90
|
-
elsif Bake::Metamodel::CommandLine === step
|
91
|
-
blockSteps << Blocks::CommandLine.new(step, @
|
92
|
-
end
|
93
|
-
end if configSteps
|
94
|
-
end
|
95
|
-
|
96
|
-
def addDependencies(block, config)
|
97
|
-
config.dependency.each do |dep|
|
98
|
-
@
|
99
|
-
if configRef.name == dep.config
|
100
|
-
block.dependencies << configRef.qname if not Bake.options.project# and not Bake.options.filename
|
101
|
-
blockRef = Blocks::ALL_BLOCKS[configRef.qname]
|
102
|
-
block.childs << blockRef
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
Blocks::
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
block.
|
165
|
-
block.
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
dblock = Blocks::ALL_BLOCKS[dqname]
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
block.
|
199
|
-
|
200
|
-
block.
|
201
|
-
|
202
|
-
block.
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
file.write "
|
221
|
-
|
222
|
-
file.write "
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
if
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
if
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
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
|
-
block
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
elsif
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
block.mainSteps <<
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
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
|
-
Blocks::ALL_BLOCKS
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
end
|
382
|
-
startBlocks.
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
taskType = "
|
406
|
-
elsif Bake.options.
|
407
|
-
taskType = "
|
408
|
-
elsif Bake.options.
|
409
|
-
|
410
|
-
elsif Bake.options.
|
411
|
-
taskType = "
|
412
|
-
elsif Bake.options.
|
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
|
-
|
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
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
|
4
|
+
require 'bake/model/metamodel_ext'
|
5
|
+
|
6
|
+
require 'bake/util'
|
7
|
+
require 'bake/cache'
|
8
|
+
require 'bake/subst'
|
9
|
+
require 'bake/mergeConfig'
|
10
|
+
|
11
|
+
require 'common/exit_helper'
|
12
|
+
require 'common/ide_interface'
|
13
|
+
require 'common/ext/file'
|
14
|
+
require 'bake/toolchain/provider'
|
15
|
+
require 'common/ext/stdout'
|
16
|
+
require 'common/utils'
|
17
|
+
require 'bake/toolchain/colorizing_formatter'
|
18
|
+
require 'bake/config/loader'
|
19
|
+
|
20
|
+
require 'blocks/block'
|
21
|
+
require 'blocks/commandLine'
|
22
|
+
require 'blocks/makefile'
|
23
|
+
require 'blocks/compile'
|
24
|
+
require 'blocks/convert'
|
25
|
+
require 'blocks/library'
|
26
|
+
require 'blocks/executable'
|
27
|
+
require 'blocks/lint'
|
28
|
+
require 'blocks/convert'
|
29
|
+
require 'blocks/docu'
|
30
|
+
|
31
|
+
require 'set'
|
32
|
+
require 'socket'
|
33
|
+
|
34
|
+
require 'blocks/showIncludes'
|
35
|
+
require 'common/abortException'
|
36
|
+
|
37
|
+
require 'adapt/config/loader'
|
38
|
+
|
39
|
+
module Bake
|
40
|
+
|
41
|
+
class SystemCommandFailed < Exception
|
42
|
+
end
|
43
|
+
|
44
|
+
class ToCxx
|
45
|
+
|
46
|
+
@@linkBlock = 0
|
47
|
+
|
48
|
+
def self.linkBlock
|
49
|
+
@@linkBlock = 1
|
50
|
+
end
|
51
|
+
|
52
|
+
def initialize
|
53
|
+
@configTcMap = {}
|
54
|
+
end
|
55
|
+
|
56
|
+
def createBaseTcsForConfig
|
57
|
+
@referencedConfigs.each do |projName, configs|
|
58
|
+
configs.each do |config|
|
59
|
+
tcs = Utils.deep_copy(@defaultToolchain)
|
60
|
+
@configTcMap[config] = tcs
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def createTcsForConfig
|
66
|
+
@referencedConfigs.each do |projName, configs|
|
67
|
+
configs.each do |config|
|
68
|
+
integrateToolchain(@configTcMap[config], config.toolchain)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def substVars
|
74
|
+
Subst.itute(@mainConfig, Bake.options.main_project_name, true, @configTcMap[@mainConfig], @referencedConfigs, @configTcMap)
|
75
|
+
@referencedConfigs.each do |projName, configs|
|
76
|
+
configs.each do |config|
|
77
|
+
if config != @mainConfig
|
78
|
+
Subst.itute(config, projName, false, @configTcMap[config], @referencedConfigs, @configTcMap)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
|
85
|
+
|
86
|
+
def addSteps(block, blockSteps, configSteps)
|
87
|
+
Array(configSteps.step).each do |step|
|
88
|
+
if Bake::Metamodel::Makefile === step
|
89
|
+
blockSteps << Blocks::Makefile.new(step, @referencedConfigs, block)
|
90
|
+
elsif Bake::Metamodel::CommandLine === step
|
91
|
+
blockSteps << Blocks::CommandLine.new(step, @referencedConfigs)
|
92
|
+
end
|
93
|
+
end if configSteps
|
94
|
+
end
|
95
|
+
|
96
|
+
def addDependencies(block, config)
|
97
|
+
config.dependency.each do |dep|
|
98
|
+
@referencedConfigs[dep.name].each do |configRef|
|
99
|
+
if configRef.name == dep.config
|
100
|
+
block.dependencies << configRef.qname if not Bake.options.project# and not Bake.options.filename
|
101
|
+
blockRef = Blocks::ALL_BLOCKS[configRef.qname]
|
102
|
+
block.childs << blockRef
|
103
|
+
block.depToBlock[dep.name + "," + dep.config] = blockRef
|
104
|
+
blockRef.parents << block
|
105
|
+
break
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def calcPrebuildBlocks
|
112
|
+
@referencedConfigs.each do |projName, configs|
|
113
|
+
configs.each do |config|
|
114
|
+
if config.prebuild
|
115
|
+
@prebuild ||= {}
|
116
|
+
config.prebuild.except.each do |except|
|
117
|
+
pName = projName
|
118
|
+
if not except.name.empty?
|
119
|
+
if not @referencedConfigs.keys.include? except.name
|
120
|
+
Bake.formatter.printWarning("Warning: prebuild project #{except.name} not found")
|
121
|
+
next
|
122
|
+
end
|
123
|
+
pName = except.name
|
124
|
+
end
|
125
|
+
if except.config != "" && !@referencedConfigs[pName].any? {|config| config.name == except.config}
|
126
|
+
Bake.formatter.printWarning("Warning: prebuild config #{except.config} of project #{pName} not found")
|
127
|
+
next
|
128
|
+
end
|
129
|
+
|
130
|
+
if not @prebuild.include?pName
|
131
|
+
@prebuild[pName] = [except.config]
|
132
|
+
else
|
133
|
+
@prebuild[pName] << except.config
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def makeBlocks
|
142
|
+
@referencedConfigs.each do |projName, configs|
|
143
|
+
configs.each do |config|
|
144
|
+
|
145
|
+
prebuild = !@prebuild.nil?
|
146
|
+
if @prebuild and @prebuild.has_key?projName
|
147
|
+
prebuild = false if (@prebuild[projName].include?"" or @prebuild[projName].include?config.name)
|
148
|
+
end
|
149
|
+
|
150
|
+
block = Blocks::Block.new(config, @referencedConfigs, prebuild)
|
151
|
+
Blocks::ALL_BLOCKS[config.qname] = block
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
def makeGraph
|
157
|
+
@referencedConfigs.each do |projName, configs|
|
158
|
+
configs.each do |config|
|
159
|
+
block = Blocks::ALL_BLOCKS[config.qname]
|
160
|
+
addDependencies(block, config)
|
161
|
+
end
|
162
|
+
end
|
163
|
+
Blocks::ALL_BLOCKS.each do |name,block|
|
164
|
+
block.dependencies.uniq!
|
165
|
+
block.childs.uniq!
|
166
|
+
block.parents.uniq!
|
167
|
+
end
|
168
|
+
|
169
|
+
|
170
|
+
# inject dependencies
|
171
|
+
num_interations = 0
|
172
|
+
begin
|
173
|
+
if (num_interations > 0) and Bake.options.debug and Bake.options.verbose >= 3
|
174
|
+
puts "Inject dependencies, iteration #{num_interations}:"
|
175
|
+
Blocks::ALL_BLOCKS.each do |name,block|
|
176
|
+
puts block.config.qname
|
177
|
+
block.dependencies.each { |d| puts "- #{d}" }
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
counter = 0
|
182
|
+
Blocks::ALL_BLOCKS.each do |name,block|
|
183
|
+
block.getBlocks(:parents).each do |b|
|
184
|
+
b.config.dependency.each do |d|
|
185
|
+
next if d.inject == ""
|
186
|
+
|
187
|
+
dqname = "#{d.name},#{d.config}"
|
188
|
+
dblock = Blocks::ALL_BLOCKS[dqname]
|
189
|
+
next if name == dqname
|
190
|
+
next if block.childs.include? dblock
|
191
|
+
counter += 1
|
192
|
+
newD = MergeConfig::cloneModelElement(d)
|
193
|
+
newD.setInject("")
|
194
|
+
ls = block.config.getBaseElement
|
195
|
+
dblock.parents << block
|
196
|
+
|
197
|
+
if d.inject == "front"
|
198
|
+
block.config.setBaseElement(ls.unshift(newD))
|
199
|
+
block.childs.unshift dblock
|
200
|
+
block.dependencies.unshift dqname if not Bake.options.project
|
201
|
+
else
|
202
|
+
block.config.setBaseElement(ls + [newD])
|
203
|
+
block.childs << dblock
|
204
|
+
block.dependencies << dqname if not Bake.options.project
|
205
|
+
end
|
206
|
+
block.depToBlock[d.name + "," + d.config] = dblock
|
207
|
+
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
211
|
+
num_interations += 1
|
212
|
+
end while counter > 0
|
213
|
+
end
|
214
|
+
|
215
|
+
def makeDot
|
216
|
+
|
217
|
+
File.open(Bake.options.dot, 'w') do |file|
|
218
|
+
puts "Creating #{Bake.options.dot}"
|
219
|
+
|
220
|
+
file.write "# Generated by bake\n"
|
221
|
+
file.write "# Example to show the graph: dot #{Bake.options.dot} -Tpng -o out.png\n"
|
222
|
+
file.write "# Example to reduce the graph: tred #{Bake.options.dot} | dot -Tpng -o out.png\n\n"
|
223
|
+
|
224
|
+
file.write "digraph \"#{Bake.options.main_project_name}_#{Bake.options.build_config}\" {\n\n"
|
225
|
+
|
226
|
+
file.write " concentrate = true\n\n"
|
227
|
+
|
228
|
+
onlyProjectName = nil
|
229
|
+
onlyConfigName = nil
|
230
|
+
if Bake.options.project
|
231
|
+
splitted = Bake.options.project.split(',')
|
232
|
+
onlyProjectName = splitted[0]
|
233
|
+
onlyConfigName = splitted[1] if splitted.length == 2
|
234
|
+
end
|
235
|
+
|
236
|
+
if onlyProjectName
|
237
|
+
if not @referencedConfigs.include? onlyProjectName
|
238
|
+
Bake.formatter.printError("Error: project #{onlyProjectName} not found")
|
239
|
+
ExitHelper.exit(1)
|
240
|
+
end
|
241
|
+
if onlyConfigName
|
242
|
+
if not @referencedConfigs[onlyProjectName].any? {|c| c.name == onlyConfigName}
|
243
|
+
Bake.formatter.printError("Error: project #{onlyProjectName} with config #{onlyConfigName} not found")
|
244
|
+
ExitHelper.exit(1)
|
245
|
+
end
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
foundProjs = {}
|
250
|
+
@referencedConfigs.each do |projName, configs|
|
251
|
+
configs.each do |config|
|
252
|
+
config.dependency.each do |d|
|
253
|
+
if onlyProjectName
|
254
|
+
next if config.parent.name != onlyProjectName && d.name != onlyProjectName
|
255
|
+
if onlyConfigName
|
256
|
+
leftSide = config.name == onlyConfigName && config.parent.name == onlyProjectName
|
257
|
+
rightSide = d.config == onlyConfigName && d.name == onlyProjectName
|
258
|
+
next if not leftSide and not rightSide
|
259
|
+
end
|
260
|
+
end
|
261
|
+
file.write " \"#{config.qname}\" -> \"#{d.name},#{d.config}\"\n"
|
262
|
+
|
263
|
+
foundProjs[config.parent.name] = [] if not foundProjs.include? config.parent.name
|
264
|
+
foundProjs[config.parent.name] << config.name if not foundProjs[config.parent.name].include? config.name
|
265
|
+
foundProjs[d.name] = [] if not foundProjs.include? d.name
|
266
|
+
foundProjs[d.name] << d.config if not foundProjs[config.parent.name].include? d.config
|
267
|
+
end
|
268
|
+
end
|
269
|
+
end
|
270
|
+
file.write "\n"
|
271
|
+
|
272
|
+
@referencedConfigs.each do |projName, configs|
|
273
|
+
next if Bake.options.project and not foundProjs.include?projName
|
274
|
+
file.write " subgraph \"cluster_#{projName}\" {\n"
|
275
|
+
file.write " label =\"#{projName}\"\n"
|
276
|
+
configs.each do |config|
|
277
|
+
next if Bake.options.project and not foundProjs[projName].include? config.name
|
278
|
+
file.write " \"#{projName},#{config.name}\" [label = \"#{config.name}\", style = filled, fillcolor = #{config.color}]\n"
|
279
|
+
end
|
280
|
+
file.write " }\n\n"
|
281
|
+
end
|
282
|
+
|
283
|
+
file.write "}\n"
|
284
|
+
end
|
285
|
+
|
286
|
+
ExitHelper.exit(0)
|
287
|
+
end
|
288
|
+
|
289
|
+
def convert2bb
|
290
|
+
@referencedConfigs.each do |projName, configs|
|
291
|
+
configs.each do |config|
|
292
|
+
block = Blocks::ALL_BLOCKS[config.qname]
|
293
|
+
|
294
|
+
addSteps(block, block.startupSteps, config.startupSteps)
|
295
|
+
addSteps(block, block.exitSteps, config.exitSteps)
|
296
|
+
|
297
|
+
if not Bake.options.prepro and not Bake.options.lint and not Bake.options.conversion_info and not Bake.options.docu and not Bake.options.filename and not Bake.options.analyze
|
298
|
+
addSteps(block, block.preSteps, config.preSteps)
|
299
|
+
addSteps(block, block.postSteps, config.postSteps)
|
300
|
+
end
|
301
|
+
|
302
|
+
if Bake.options.docu
|
303
|
+
block.mainSteps << Blocks::Docu.new(config, @configTcMap[config])
|
304
|
+
elsif Metamodel::CustomConfig === config
|
305
|
+
if not Bake.options.prepro and not Bake.options.lint and not Bake.options.conversion_info and not Bake.options.docu and not Bake.options.filename and not Bake.options.analyze
|
306
|
+
addSteps(block, block.mainSteps, config) if config.step
|
307
|
+
end
|
308
|
+
elsif Bake.options.conversion_info
|
309
|
+
block.mainSteps << Blocks::Convert.new(block, config, @referencedConfigs, @configTcMap[config])
|
310
|
+
elsif Bake.options.lint
|
311
|
+
block.mainSteps << Blocks::Lint.new(block, config, @referencedConfigs, @configTcMap[config])
|
312
|
+
else
|
313
|
+
compile = Blocks::Compile.new(block, config, @referencedConfigs, @configTcMap[config])
|
314
|
+
(Blocks::ALL_COMPILE_BLOCKS[projName] ||= []) << compile
|
315
|
+
block.mainSteps << compile
|
316
|
+
if not Bake.options.filename and not Bake.options.analyze
|
317
|
+
if Metamodel::LibraryConfig === config
|
318
|
+
block.mainSteps << Blocks::Library.new(block, config, @referencedConfigs, @configTcMap[config], compile)
|
319
|
+
else
|
320
|
+
block.mainSteps << Blocks::Executable.new(block, config, @referencedConfigs, @configTcMap[config], compile)
|
321
|
+
end
|
322
|
+
end
|
323
|
+
end
|
324
|
+
|
325
|
+
|
326
|
+
|
327
|
+
end
|
328
|
+
end
|
329
|
+
end
|
330
|
+
|
331
|
+
def callBlock(block, method)
|
332
|
+
begin
|
333
|
+
return block.send(method)
|
334
|
+
rescue AbortException
|
335
|
+
raise
|
336
|
+
rescue Exception => ex
|
337
|
+
if Bake.options.debug
|
338
|
+
puts ex.message
|
339
|
+
puts ex.backtrace
|
340
|
+
end
|
341
|
+
return false
|
342
|
+
end
|
343
|
+
end
|
344
|
+
|
345
|
+
def callBlocks(startBlocks, method, ignoreStopOnFirstError = false)
|
346
|
+
Blocks::ALL_BLOCKS.each {|name,block| block.visited = false; block.result = true; block.inDeps = false }
|
347
|
+
Blocks::Block.reset_block_counter
|
348
|
+
result = true
|
349
|
+
startBlocks.each do |block|
|
350
|
+
result = callBlock(block, method) && result
|
351
|
+
if not ignoreStopOnFirstError
|
352
|
+
return false if not result and Bake.options.stopOnFirstError
|
353
|
+
end
|
354
|
+
end
|
355
|
+
return result
|
356
|
+
end
|
357
|
+
|
358
|
+
def calcStartBlocks
|
359
|
+
startProjectName = nil
|
360
|
+
startConfigName = nil
|
361
|
+
if Bake.options.project
|
362
|
+
splitted = Bake.options.project.split(',')
|
363
|
+
startProjectName = splitted[0]
|
364
|
+
startConfigName = splitted[1] if splitted.length == 2
|
365
|
+
end
|
366
|
+
|
367
|
+
if startConfigName
|
368
|
+
blockName = startProjectName+","+startConfigName
|
369
|
+
if not Blocks::ALL_BLOCKS.include?(startProjectName+","+startConfigName)
|
370
|
+
Bake.formatter.printError("Error: project #{startProjectName} with config #{startConfigName} not found")
|
371
|
+
ExitHelper.exit(1)
|
372
|
+
end
|
373
|
+
startBlocks = [Blocks::ALL_BLOCKS[startProjectName+","+startConfigName]]
|
374
|
+
Blocks::Block.set_num_projects(1)
|
375
|
+
elsif startProjectName
|
376
|
+
startBlocks = []
|
377
|
+
Blocks::ALL_BLOCKS.each do |blockName, block|
|
378
|
+
if blockName.start_with?(startProjectName + ",")
|
379
|
+
startBlocks << block
|
380
|
+
end
|
381
|
+
end
|
382
|
+
if startBlocks.length == 0
|
383
|
+
Bake.formatter.printError("Error: project #{startProjectName} not found")
|
384
|
+
ExitHelper.exit(1)
|
385
|
+
end
|
386
|
+
startBlocks.reverse! # most probably the order of dependencies if any
|
387
|
+
Blocks::Block.set_num_projects(startBlocks.length)
|
388
|
+
else
|
389
|
+
startBlocks = [Blocks::ALL_BLOCKS[Bake.options.main_project_name+","+Bake.options.build_config]]
|
390
|
+
Blocks::Block.set_num_projects(Blocks::ALL_BLOCKS.length)
|
391
|
+
end
|
392
|
+
return startBlocks
|
393
|
+
end
|
394
|
+
|
395
|
+
def doit()
|
396
|
+
|
397
|
+
if Bake.options.show_includes or Bake.options.show_includes_and_defines
|
398
|
+
s = StringIO.new
|
399
|
+
tmp = Thread.current[:stdout]
|
400
|
+
Thread.current[:stdout] = s unless tmp
|
401
|
+
end
|
402
|
+
|
403
|
+
taskType = "Building"
|
404
|
+
if Bake.options.lint
|
405
|
+
taskType = "Linting"
|
406
|
+
elsif Bake.options.conversion_info
|
407
|
+
taskType = "Showing conversion infos"
|
408
|
+
elsif Bake.options.docu
|
409
|
+
taskType = "Generating documentation"
|
410
|
+
elsif Bake.options.prepro
|
411
|
+
taskType = "Preprocessing"
|
412
|
+
elsif Bake.options.linkOnly
|
413
|
+
taskType = "Linking"
|
414
|
+
elsif Bake.options.rebuild
|
415
|
+
taskType = "Rebuilding"
|
416
|
+
elsif Bake.options.clean
|
417
|
+
taskType = "Cleaning"
|
418
|
+
end
|
419
|
+
|
420
|
+
begin
|
421
|
+
|
422
|
+
if Bake.options.showConfigs
|
423
|
+
al = AdaptConfig.new
|
424
|
+
adaptConfigs = al.load()
|
425
|
+
Config.new.printConfigs(adaptConfigs)
|
426
|
+
else
|
427
|
+
cache = CacheAccess.new()
|
428
|
+
@referencedConfigs = cache.load_cache unless Bake.options.nocache
|
429
|
+
|
430
|
+
if @referencedConfigs.nil?
|
431
|
+
al = AdaptConfig.new
|
432
|
+
adaptConfigs = al.load()
|
433
|
+
|
434
|
+
@loadedConfig = Config.new
|
435
|
+
@referencedConfigs = @loadedConfig.load(adaptConfigs)
|
436
|
+
|
437
|
+
cache.write_cache(@referencedConfigs, adaptConfigs)
|
438
|
+
end
|
439
|
+
end
|
440
|
+
|
441
|
+
taskType = "Analyzing" if Bake.options.analyze
|
442
|
+
|
443
|
+
@mainConfig = @referencedConfigs[Bake.options.main_project_name].select { |c| c.name == Bake.options.build_config }.first
|
444
|
+
|
445
|
+
if Bake.options.lint
|
446
|
+
@defaultToolchain = Utils.deep_copy(Bake::Toolchain::Provider["Lint"])
|
447
|
+
else
|
448
|
+
basedOn = @mainConfig.defaultToolchain.basedOn
|
449
|
+
basedOnToolchain = Bake::Toolchain::Provider[basedOn]
|
450
|
+
if basedOnToolchain.nil?
|
451
|
+
Bake.formatter.printError("DefaultToolchain based on unknown compiler '#{basedOn}'", @mainConfig.defaultToolchain)
|
452
|
+
ExitHelper.exit(1)
|
453
|
+
end
|
454
|
+
|
455
|
+
# The flag "-FS" must only be set for VS2013 and above
|
456
|
+
ENV["MSVC_FORCE_SYNC_PDB_WRITES"] = ""
|
457
|
+
if basedOn == "MSVC"
|
458
|
+
begin
|
459
|
+
res = `cl.exe 2>&1`
|
460
|
+
raise Exception.new unless $?.success?
|
461
|
+
scan_res = res.scan(/ersion (\d+).(\d+).(\d+)/)
|
462
|
+
if scan_res.length > 0
|
463
|
+
ENV["MSVC_FORCE_SYNC_PDB_WRITES"] = "-FS" if scan_res[0][0].to_i >= 18 # 18 is the compiler major version in VS2013
|
464
|
+
else
|
465
|
+
Bake.formatter.printError("Could not read MSVC version")
|
466
|
+
ExitHelper.exit(1)
|
467
|
+
end
|
468
|
+
rescue SystemExit
|
469
|
+
raise
|
470
|
+
rescue Exception => e
|
471
|
+
Bake.formatter.printError("Could not detect MSVC compiler")
|
472
|
+
ExitHelper.exit(1)
|
473
|
+
end
|
474
|
+
end
|
475
|
+
|
476
|
+
@defaultToolchain = Utils.deep_copy(basedOnToolchain)
|
477
|
+
Bake.options.envToolchain = true if (basedOn.include?"_ENV")
|
478
|
+
end
|
479
|
+
integrateToolchain(@defaultToolchain, @mainConfig.defaultToolchain)
|
480
|
+
|
481
|
+
# todo: cleanup this hack
|
482
|
+
Bake.options.analyze = @defaultToolchain[:COMPILER][:CPP][:COMPILE_FLAGS].include?"analyze"
|
483
|
+
Bake.options.eclipseOrder = @mainConfig.defaultToolchain.eclipseOrder
|
484
|
+
|
485
|
+
createBaseTcsForConfig
|
486
|
+
substVars
|
487
|
+
createTcsForConfig
|
488
|
+
|
489
|
+
@@linkBlock = 0
|
490
|
+
|
491
|
+
@prebuild = nil
|
492
|
+
calcPrebuildBlocks if Bake.options.prebuild
|
493
|
+
|
494
|
+
makeBlocks
|
495
|
+
makeGraph
|
496
|
+
makeDot if Bake.options.dot
|
497
|
+
|
498
|
+
convert2bb
|
499
|
+
|
500
|
+
if Bake.options.show_includes
|
501
|
+
Thread.current[:stdout] = tmp
|
502
|
+
Blocks::Show.includes
|
503
|
+
end
|
504
|
+
|
505
|
+
if Bake.options.show_includes_and_defines
|
506
|
+
Thread.current[:stdout] = tmp
|
507
|
+
Blocks::Show.includesAndDefines(@mainConfig, @configTcMap[@mainConfig])
|
508
|
+
end
|
509
|
+
|
510
|
+
startBlocks = calcStartBlocks
|
511
|
+
|
512
|
+
Bake::IDEInterface.instance.set_build_info(@mainConfig.parent.name, @mainConfig.name, Blocks::ALL_BLOCKS.length)
|
513
|
+
|
514
|
+
ideAbort = false
|
515
|
+
begin
|
516
|
+
result = callBlocks(startBlocks, :startup, true)
|
517
|
+
if Bake.options.clean or Bake.options.rebuild
|
518
|
+
if not Bake.options.stopOnFirstError or result
|
519
|
+
result = callBlocks(startBlocks, :clean) && result
|
520
|
+
end
|
521
|
+
end
|
522
|
+
if Bake.options.rebuild or not Bake.options.clean
|
523
|
+
if not Bake.options.stopOnFirstError or result
|
524
|
+
result = callBlocks(startBlocks, :execute) && result
|
525
|
+
end
|
526
|
+
end
|
527
|
+
rescue AbortException
|
528
|
+
ideAbort = true
|
529
|
+
end
|
530
|
+
result = callBlocks(startBlocks, :exits, true) && result
|
531
|
+
|
532
|
+
if ideAbort
|
533
|
+
Bake.formatter.printError("\n#{taskType} aborted.")
|
534
|
+
ExitHelper.set_exit_code(1)
|
535
|
+
return
|
536
|
+
end
|
537
|
+
|
538
|
+
if Bake.options.cc2j_filename
|
539
|
+
require "json"
|
540
|
+
File.write(Bake.options.cc2j_filename, JSON.pretty_generate(Blocks::CC2J))
|
541
|
+
end
|
542
|
+
|
543
|
+
if result == false
|
544
|
+
Bake.formatter.printError("\n#{taskType} failed.")
|
545
|
+
ExitHelper.set_exit_code(1)
|
546
|
+
return
|
547
|
+
else
|
548
|
+
if Bake.options.linkOnly and @@linkBlock == 0
|
549
|
+
Bake.formatter.printSuccess("\nNothing to link.")
|
550
|
+
else
|
551
|
+
Bake.formatter.printSuccess("\n#{taskType} done.")
|
552
|
+
end
|
553
|
+
end
|
554
|
+
rescue SystemExit
|
555
|
+
Bake.formatter.printError("\n#{taskType} failed.") if ExitHelper.exit_code != 0
|
556
|
+
end
|
557
|
+
|
558
|
+
end
|
559
|
+
|
560
|
+
def connect()
|
561
|
+
if Bake.options.socket != 0
|
562
|
+
Bake::IDEInterface.instance.connect(Bake.options.socket)
|
563
|
+
end
|
564
|
+
end
|
565
|
+
|
566
|
+
def disconnect()
|
567
|
+
if Bake.options.socket != 0
|
568
|
+
Bake::IDEInterface.instance.disconnect()
|
569
|
+
end
|
570
|
+
end
|
571
|
+
|
572
|
+
end
|
573
|
+
end
|
574
|
+
|
575
|
+
trap("SIGINT") do
|
576
|
+
Bake::IDEInterface.instance.set_abort(1)
|
559
577
|
end
|