bake-toolkit 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,66 @@
1
+ require 'cxxproject/utils/printer'
2
+ require 'cxxproject/utils/exit_helper'
3
+
4
+ module Cxxproject
5
+
6
+
7
+ class Option
8
+ attr_reader :param, :arg, :block
9
+ def initialize(param, arg, &f)
10
+ @param = param
11
+ @arg = arg # true / false
12
+ @block = f
13
+ f
14
+
15
+ end
16
+ end
17
+
18
+
19
+ class Parser
20
+
21
+ def initialize(argv)
22
+ @options = {}
23
+ @argv = argv
24
+ end
25
+
26
+ def add_option(opt)
27
+ @options[opt.param] = opt
28
+ end
29
+
30
+ def parse_internal(ignoreInvalid = true)
31
+ pos = 0
32
+ begin
33
+ while pos < @argv.length do
34
+ if not @options.include?@argv[pos]
35
+ if ignoreInvalid
36
+ pos = pos + 1
37
+ next
38
+ end
39
+ raise "Option #{@argv[pos]} unknown"
40
+ end
41
+ option = @options[@argv[pos]]
42
+ if option.arg
43
+ if pos+1 < @argv.length and @argv[pos+1][0] != "-"
44
+ option.block.call(@argv[pos+1])
45
+ pos = pos + 1
46
+ else
47
+ raise "Argument for option #{@argv[pos]} missing"
48
+ end
49
+ else
50
+ option.block.call()
51
+ end
52
+ pos = pos + 1
53
+ end
54
+ rescue SystemExit => e
55
+ raise
56
+ rescue Exception => e
57
+ Printer.printError e.message
58
+ ExitHelper.exit(1)
59
+ end
60
+
61
+ end
62
+
63
+ end
64
+
65
+
66
+ end
data/lib/tocxx.rb ADDED
@@ -0,0 +1,883 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ gem 'rake', '>= 0.7.3'
4
+
5
+ require 'rake'
6
+ require 'rake/clean'
7
+ require 'bake/loader'
8
+ require 'bake/model/metamodel_ext'
9
+ require 'bake/util'
10
+ require 'bake/cache'
11
+ require 'bake/subst'
12
+ require 'cxxproject/buildingblocks/module'
13
+ require 'cxxproject/buildingblocks/makefile'
14
+ require 'cxxproject/buildingblocks/executable'
15
+ require 'cxxproject/buildingblocks/source_library'
16
+ require 'cxxproject/buildingblocks/binary_library'
17
+ require 'cxxproject/buildingblocks/custom_building_block'
18
+ require 'cxxproject/buildingblocks/command_line'
19
+ require 'cxxproject/buildingblocks/single_source'
20
+ require 'cxxproject/utils/exit_helper'
21
+ require 'cxxproject/ide_interface'
22
+ require 'cxxproject/ext/file'
23
+ require 'cxxproject/toolchain/provider'
24
+ require 'cxxproject/ext/stdout'
25
+ require 'cxxproject/ext/rake'
26
+ require 'cxxproject/utils/utils'
27
+ require 'cxxproject/utils/printer'
28
+
29
+ require 'set'
30
+ require 'socket'
31
+
32
+ #require 'ruby-prof'
33
+
34
+ module Cxxproject
35
+
36
+ class ToCxx
37
+
38
+ def initialize(options)
39
+ @options = options
40
+
41
+ RakeFileUtils.verbose_flag = @options.verbose
42
+ end
43
+
44
+ def set_output_taskname(bb)
45
+ return if not bb.instance_of?ModuleBuildingBlock
46
+ outputTaskname = task "Print #{bb.get_task_name}" do
47
+ num = Rake.application.idei.get_number_of_projects
48
+ @numCurrent ||= 0
49
+ @numCurrent += 1
50
+
51
+ unless @options.printLess
52
+ Printer.printAdditionalInfo "**** Building #{@numCurrent} of #{num}: #{bb.name.gsub("Project ","")} (#{bb.config_name}) ****"
53
+ end
54
+
55
+ Rake.application.idei.set_build_info(bb.name.gsub("Project ",""), bb.config_name)
56
+ Rake.application.addEmptyLine = true if @options.verbose
57
+ end
58
+ outputTaskname.type = Rake::Task::UTIL
59
+ outputTaskname.transparent_timestamp = true
60
+ insertAt = 0
61
+ t = Rake.application[bb.last_content.get_task_name]
62
+ t.prerequisites.each do |p|
63
+ pname = String === p ? p : p.name
64
+ if pname.index("Project ") == 0
65
+ insertAt = insertAt + 1
66
+ else
67
+ break
68
+ end
69
+ end
70
+ t.prerequisites.insert(insertAt, outputTaskname)
71
+ end
72
+
73
+
74
+ def calc_needed_bbs(bbChildName, needed_bbs)
75
+ bbChild = ALL_BUILDING_BLOCKS[bbChildName]
76
+ isModule = (ModuleBuildingBlock === bbChild ? 1 : 0)
77
+ return 0 if needed_bbs.include?bbChild
78
+ needed_bbs << bbChild
79
+ bbChild.dependencies.each { |d| isModule += calc_needed_bbs(d, needed_bbs) }
80
+ return isModule
81
+ end
82
+
83
+ # PRE and POST CONDITIONS
84
+ def addSteps(steps, bbModule, projDir, globalFilterStr = nil)
85
+ if steps
86
+ array = (Metamodel::Step === steps ? [steps] : steps.step)
87
+ array.reverse.each do |m|
88
+
89
+ checkDefault = true
90
+ if m.filter != "" # explicit filter = 1. prio
91
+ next if @options.exclude_filter.include?m.filter
92
+ checkDefault = false if @options.include_filter.include?m.filter
93
+ end
94
+
95
+ if globalFilterStr != nil
96
+ if checkDefault == true # global filter = 2. prio
97
+ next if @options.exclude_filter.include?globalFilterStr
98
+ checkDefault = false if @options.include_filter.include?globalFilterStr
99
+ end
100
+ end
101
+
102
+ if checkDefault # default = 3. prio
103
+ next if m.default == "off"
104
+ end
105
+
106
+ if Cxxproject::Metamodel::Makefile === m
107
+ nameOfBB = m.name+"_"+m.target
108
+ bb = Makefile.new(m.name, m.target)
109
+ if m.pathTo != ""
110
+ pathHash = {}
111
+ m.pathTo.split(",").each do |p|
112
+ nameOfP = p.strip
113
+ dirOfP = nil
114
+ if not @project2config.include?nameOfP
115
+ @options.roots.each do |r|
116
+ absIncDir = r+"/"+nameOfP
117
+ if File.exists?(absIncDir)
118
+ dirOfP = absIncDir
119
+ break
120
+ end
121
+ end
122
+ else
123
+ dirOfP = @project2config[nameOfP].parent.get_project_dir
124
+ end
125
+ if dirOfP == nil
126
+ Printer.printError "Error: Project '#{nameOfP}' not found for makefile #{projDir}/#{m.name}"
127
+ ExitHelper.exit(1)
128
+ end
129
+ pathHash[nameOfP] = File.rel_from_to_project(File.dirname(projDir),File.dirname(dirOfP))
130
+ end
131
+ bb.set_path_to(pathHash)
132
+ bb.pre_step = true if globalFilterStr
133
+ end
134
+ bb.set_flags(m.flags)
135
+ @lib_elements[m.line_number] = [HasLibraries::LIB_WITH_PATH, m.lib] if m.lib != ""
136
+ elsif Cxxproject::Metamodel::CommandLine === m
137
+ nameOfBB = m.name
138
+ bb = CommandLine.new(nameOfBB)
139
+ bb.set_defined_in_file(m.file_name.to_s)
140
+ bb.set_defined_in_line(m.line_number)
141
+ bb.pre_step = true if globalFilterStr
142
+ else
143
+ next
144
+ end
145
+ bbModule.last_content.dependencies << bb.name
146
+ bbModule.contents << bb
147
+ bbModule.last_content = bb
148
+ end
149
+ end
150
+ end
151
+
152
+ def convPath(dir, config, exe = nil)
153
+ projName = config.parent.name
154
+ projDir = config.parent.get_project_dir
155
+
156
+ d = dir.respond_to?("name") ? dir.name : dir
157
+ inc = d.split("/")
158
+ if (inc[0] == projName)
159
+ res = inc[1..-1].join("/") # within self
160
+ res = "." if res == ""
161
+ elsif @project2config.include?(inc[0])
162
+ dirOther = @project2config[inc[0]].parent.get_project_dir
163
+ res = File.rel_from_to_project(projDir, dirOther)
164
+ postfix = inc[1..-1].join("/")
165
+ res = res + postfix if postfix != ""
166
+ else
167
+ if (inc[0] != "..")
168
+ return d if File.exists?(projDir + "/" + d) # e.g. "include"
169
+
170
+ # check if dir exists without Project.meta entry
171
+ @options.roots.each do |r|
172
+ absIncDir = r+"/"+d
173
+ if File.exists?(absIncDir)
174
+ res = File.rel_from_to_project(projDir,absIncDir)
175
+ if not res.nil?
176
+ return res
177
+ end
178
+ end
179
+ end
180
+ else
181
+ Printer.printInfo "Info: #{projName} uses \"..\" in path name #{d}"
182
+ end
183
+
184
+ res = d # relative from self as last resort
185
+ end
186
+ res
187
+ end
188
+
189
+ def loadProjMeta(loader, filename, configname)
190
+
191
+ @project_files << filename
192
+ f = loader.load(filename)
193
+
194
+ config = nil
195
+
196
+ if f.root_elements.length != 1 or not Metamodel::Project === f.root_elements[0]
197
+ Printer.printError "Error: '#{filename}' must have exactly one 'Project' element as root element"
198
+ ExitHelper.exit(1)
199
+ end
200
+
201
+ f.root_elements.each do |e|
202
+ x = e.getConfig
203
+ x.each do |y|
204
+ if y.name == configname
205
+ if config
206
+ Printer.printError "Error: Config '#{configname}' found more than once in '#{filename}'"
207
+ ExitHelper.exit(1)
208
+ end
209
+ config = y
210
+ else
211
+ e.removeGeneric("Config", y)
212
+ end
213
+ end
214
+ end
215
+ f.mark_changed
216
+ f.build_index
217
+
218
+ if not config
219
+ Printer.printError "Error: Config '#{configname}' not found in '#{filename}'"
220
+ ExitHelper.exit(1)
221
+ end
222
+
223
+ config
224
+ end
225
+
226
+ def load_meta
227
+
228
+ loader = Loader.new(@options)
229
+ @project_files = []
230
+
231
+ @project2config = {}
232
+
233
+ project2config_pending = {}
234
+ project2config_pending[@mainProjectName] = @options.build_config
235
+
236
+ while project2config_pending.length > 0
237
+
238
+ pname_toload = project2config_pending.keys[0]
239
+ cname_toload = project2config_pending[pname_toload]
240
+ project2config_pending.delete(pname_toload)
241
+
242
+
243
+ # check if file is in more than one root
244
+ pmeta_filenames = []
245
+ @options.roots.each do |r|
246
+ f = r + "/" + pname_toload + "/Project.meta"
247
+ if File.exists?(f)
248
+ pmeta_filenames << f
249
+ end
250
+ end
251
+
252
+ if pmeta_filenames.empty?
253
+ Printer.printError "Error: #{pname_toload}/Project.meta not found"
254
+ ExitHelper.exit(1)
255
+ end
256
+
257
+ if pmeta_filenames.length > 1
258
+ Printer.printWarning "Warning: #{pname_toload} exists more than once:"
259
+ chosen = " (chosen)"
260
+ pmeta_filenames.each do |f|
261
+ Printer.printWarning " #{f}#{chosen}"
262
+ chosen = ""
263
+ end
264
+ end
265
+
266
+
267
+ config = loadProjMeta(loader, pmeta_filenames[0], cname_toload)
268
+
269
+ @project2config[pname_toload] = config
270
+
271
+ project2configLocal = {}
272
+
273
+ if @project2config.length == 1
274
+ if config.defaultToolchain == nil
275
+ Printer.printError "Error: Main project configuration must contain DefaultToolchain"
276
+ ExitHelper.exit(1)
277
+ else
278
+ basedOnToolchain = Cxxproject::Toolchain::Provider[config.defaultToolchain.basedOn]
279
+ if basedOnToolchain == nil
280
+ Printer.printError "Error: DefaultToolchain based on unknown compiler '#{config.defaultToolchain.basedOn}'"
281
+ ExitHelper.exit(1)
282
+ end
283
+ @defaultToolchain = Utils.deep_copy(basedOnToolchain)
284
+ integrateToolchain(@defaultToolchain, config.defaultToolchain)
285
+
286
+ if @defaultToolchainCached
287
+ unless @defaultToolchain[:LINKER][:FLAGS] == @defaultToolchainCached[:LINKER][:FLAGS] and
288
+ @defaultToolchain[:LINKER][:LIB_PREFIX_FLAGS] == @defaultToolchainCached[:LINKER][:LIB_PREFIX_FLAGS] and
289
+ @defaultToolchain[:LINKER][:LIB_POSTFIX_FLAGS] == @defaultToolchainCached[:LINKER][:LIB_POSTFIX_FLAGS] and
290
+ @defaultToolchain[:ARCHIVER][:FLAGS] == @defaultToolchainCached[:ARCHIVER][:FLAGS] and
291
+ @defaultToolchain[:COMPILER][:CPP][:FLAGS] == @defaultToolchainCached[:COMPILER][:CPP][:FLAGS] and
292
+ @defaultToolchain[:COMPILER][:CPP][:DEFINES].join("") == @defaultToolchainCached[:COMPILER][:CPP][:DEFINES].join("") and
293
+ @defaultToolchain[:COMPILER][:C][:FLAGS] == @defaultToolchainCached[:COMPILER][:C][:FLAGS] and
294
+ @defaultToolchain[:COMPILER][:C][:DEFINES].join("") == @defaultToolchainCached[:COMPILER][:C][:DEFINES].join("") and
295
+ @defaultToolchain[:COMPILER][:ASM][:FLAGS] == @defaultToolchainCached[:COMPILER][:ASM][:FLAGS] and
296
+ @defaultToolchain[:COMPILER][:ASM][:DEFINES].join("") == @defaultToolchainCached[:COMPILER][:ASM][:DEFINES].join("")
297
+ @defaultToolchainTime = @mainMetaTime
298
+ end
299
+ end
300
+
301
+ end
302
+ end
303
+
304
+ config.dependency.each do |d|
305
+ pname = d.name
306
+ cname = d.config
307
+
308
+ # check that a project is not dependent twice
309
+ if project2configLocal.include?pname
310
+ Printer.printError "Error: More than one dependencies found to '#{pname}' in config '#{config.name}'"
311
+ ExitHelper.exit(1)
312
+ end
313
+ project2configLocal[pname] = cname
314
+
315
+ # check pending loads
316
+ inconsistentConfigs = nil
317
+ if @project2config.include?pname
318
+ inconsistentConfigs = @project2config[pname].name if @project2config[pname].name != cname
319
+ else
320
+ if project2config_pending.include?pname
321
+ if project2config_pending[pname] != cname
322
+ inconsistentConfigs = project2config_pending[pname]
323
+ end
324
+ else
325
+ project2config_pending[pname] = cname
326
+ end
327
+ end
328
+ if inconsistentConfigs
329
+ Printer.printError "Error: dependency to config '#{cname}' of project '#{pname}' found (line #{d.line_number}), but config #{inconsistentConfigs} was requested earlier"
330
+ ExitHelper.exit(1)
331
+ end
332
+ end
333
+ end
334
+
335
+ end
336
+
337
+
338
+ def substVars
339
+ @project2config.each do |projName, config|
340
+ Subst.itute(config, projName, @options)
341
+ end
342
+
343
+ @mainConfig = @project2config[@mainProjectName]
344
+
345
+ basedOnToolchain = Cxxproject::Toolchain::Provider[@mainConfig.defaultToolchain.basedOn]
346
+ @defaultToolchain = Utils.deep_copy(basedOnToolchain)
347
+ integrateToolchain(@defaultToolchain, @mainConfig.defaultToolchain)
348
+
349
+ end
350
+
351
+ def convert2bb
352
+
353
+ @project2config.each do |projName, config|
354
+
355
+ projDir = config.parent.get_project_dir
356
+ @lib_elements = {}
357
+
358
+ bbModule = ModuleBuildingBlock.new("Project "+projName)
359
+ bbModule.contents = []
360
+
361
+ addSteps(config.postSteps, bbModule, projDir, "POST") if not @options.linkOnly
362
+
363
+ # LIB, EXE
364
+ if Metamodel::LibraryConfig === config
365
+ bbModule.main_content = SourceLibrary.new(projName)
366
+ elsif Metamodel::ExecutableConfig === config
367
+ bbModule.main_content = Executable.new(projName)
368
+ if not config.artifactName.nil?
369
+ x = @options.build_config + "/" + config.artifactName.name
370
+ bbModule.main_content.set_executable_name(x)
371
+ end
372
+ bbModule.main_content.set_linker_script(config.linkerScript.name) unless config.linkerScript.nil?
373
+ else # CUSTOM
374
+ if config.step
375
+ if config.step.filter != ""
376
+ Printer.printError "Error: #{config.file_name}(#{config.step.line_number}): attribute filter not allowed here"
377
+ ExitHelper.exit(1)
378
+ end
379
+ if config.step.default != "on"
380
+ Printer.printError "Error: #{config.file_name}(#{config.step.line_number}): attribute default not allowed here"
381
+ ExitHelper.exit(1)
382
+ end
383
+ addSteps(config.step, bbModule, projDir)
384
+ end
385
+ bbModule.main_content = BinaryLibrary.new(projName, false)
386
+ end
387
+ bbModule.last_content.dependencies << bbModule.main_content.name
388
+ bbModule.last_content = bbModule.main_content
389
+ bbModule.contents << bbModule.main_content
390
+
391
+ # PRE CONDITIONS
392
+ addSteps(config.preSteps, bbModule, projDir, "PRE") if not @options.linkOnly
393
+
394
+
395
+ tcs = nil
396
+ if not Metamodel::CustomConfig === config
397
+ tcs = Utils.deep_copy(@defaultToolchain)
398
+ integrateToolchain(tcs, config.toolchain)
399
+ else
400
+ tcs = Utils.deep_copy(Cxxproject::Toolchain::Provider.default)
401
+ end
402
+
403
+
404
+ ([bbModule] + bbModule.contents).each do |c|
405
+ c.set_tcs(tcs)
406
+ if (@defaultToolchainTime <= File.mtime(config.file_name))
407
+ c.set_config_files([config.file_name])
408
+ else
409
+ xxx = file "ssss"
410
+ $defaultToolchainTime = @defaultToolchainTime
411
+ def xxx.timestamp
412
+ $defaultToolchainTime
413
+ end
414
+ def xxx.needed?
415
+ true
416
+ end
417
+ @defaultToolchainTime
418
+
419
+ c.set_config_files([config.file_name, "ssss"])
420
+ end
421
+ c.set_project_dir(projDir)
422
+
423
+ if projName == @mainProjectName
424
+ c.set_output_dir(@options.build_config)
425
+ else
426
+ c.set_output_dir(@options.build_config + "_" + @mainProjectName)
427
+ end
428
+ c.set_config_name(config.name)
429
+ end
430
+
431
+ if HasLibraries === bbModule.main_content
432
+ config.userLibrary.each do |l|
433
+ ln = l.lib
434
+ ls = nil
435
+ if l.lib.include?("/")
436
+ pos = l.lib.rindex("/")
437
+ ls = convPath(l.lib[0..pos-1], config)
438
+ ln = l.lib[pos+1..-1]
439
+ end
440
+ @lib_elements[l.line_number] = ls.nil? ? [] : [HasLibraries::SEARCH_PATH, ls]
441
+ @lib_elements[l.line_number].concat [HasLibraries::USERLIB, ln]
442
+ end
443
+
444
+ config.exLib.each do |exLib|
445
+ ln = exLib.name
446
+ ls = nil
447
+ if exLib.name.include?("/")
448
+ pos = exLib.name.rindex("/")
449
+ ls = convPath(exLib.name[0..pos-1], config)
450
+ ln = exLib.name[pos+1..-1]
451
+ end
452
+ if exLib.search
453
+ @lib_elements[exLib.line_number] = ls.nil? ? [] : [HasLibraries::SEARCH_PATH, ls]
454
+ @lib_elements[exLib.line_number].concat [HasLibraries::LIB, ln]
455
+ else
456
+ @lib_elements[exLib.line_number] = [HasLibraries::LIB_WITH_PATH, (ls.nil? ? ln : (ls + "/" + ln))]
457
+ end
458
+ end
459
+
460
+ config.exLibSearchPath.each do |exLibSP|
461
+ @lib_elements[exLibSP.line_number] = [HasLibraries::SEARCH_PATH, convPath(exLibSP, config)]
462
+ end
463
+ end
464
+
465
+ if HasSources === bbModule.main_content
466
+ srcs = config.files.map do |f|
467
+ f.name
468
+ end
469
+ ex_srcs = config.excludeFiles.map {|f| f.name}
470
+
471
+ bbModule.main_content.set_local_includes( config.includeDir.map do |dir|
472
+ convPath(dir, config)
473
+ end
474
+ )
475
+
476
+ bbModule.main_content.set_source_patterns(srcs)
477
+ bbModule.main_content.set_exclude_sources(ex_srcs)
478
+
479
+ tcsMapConverted = {}
480
+ srcs = config.files.each do |f|
481
+ if (f.define.length > 0 or f.flags.length > 0)
482
+ if f.name.include?"*"
483
+ Printer.printWarning "Warning: #{config.file_name}(#{f.line_number}): toolchain settings not allowed for file pattern #{f.name}"
484
+ err_res = ErrorDesc.new
485
+ err_res.file_name = config.file_name
486
+ err_res.line_number = f.line_number
487
+ err_res.severity = ErrorParser::SEVERITY_WARNING
488
+ err_res.message = "Toolchain settings not allowed for file patterns"
489
+ Rake.application.idei.set_errors([err_res])
490
+ else
491
+ tcsMapConverted[f.name] = integrateCompilerFile(Utils.deep_copy(tcs),f)
492
+ end
493
+ end
494
+ end
495
+ bbModule.main_content.set_tcs4source(tcsMapConverted)
496
+
497
+ end
498
+
499
+ # special exe stuff
500
+ if Metamodel::ExecutableConfig === config
501
+ if not config.mapFile.nil?
502
+ if config.mapFile.name == ""
503
+ exeName = bbModule.main_content.get_executable_name
504
+ mapfileName = exeName.chomp(File.extname(exeName)) + ".map"
505
+ else
506
+ mapfileName = config.mapFile.name
507
+ end
508
+
509
+ bbModule.main_content.set_mapfile(mapfileName)
510
+ end
511
+ end
512
+ bbModule.contents.each do |c|
513
+ if Cxxproject::CommandLine === c
514
+ cmdLine = convPath(c.get_command_line, config, bbModule.main_content)
515
+ if Cxxproject::OS.windows? # CommandLine "tool/abc.exe gaga" does not work --> / must be \\
516
+ maxPos = cmdLine.index(" ")
517
+ indexQuote = cmdLine.index("\"")
518
+ if indexQuote != nil and (maxPos == nil or indexQuote < maxPos)
519
+ maxPos = indexQuote
520
+ end
521
+ if maxPos != nil
522
+ cmdLine = cmdLine[0..maxPos-1].gsub("/","\\") + cmdLine[maxPos..-1]
523
+ end
524
+ end
525
+ c.set_command_line(cmdLine)
526
+ end
527
+ end
528
+
529
+ # DEPS
530
+ projDeps = config.dependency.map { |dd| "Project "+dd.name }
531
+ projDeps.concat(bbModule.main_content.dependencies)
532
+ bbModule.main_content.set_dependencies(projDeps)
533
+ config.dependency.each { |dd| @lib_elements[dd.line_number] = [HasLibraries::DEPENDENCY, dd.name] }
534
+
535
+
536
+ @lib_elements.sort.each do |x|
537
+ v = x[1]
538
+ elem = 0
539
+ while elem < v.length do
540
+ bbModule.main_content.add_lib_elements([v[elem..elem+1]])
541
+ elem = elem + 2
542
+ end
543
+ end
544
+
545
+ end
546
+
547
+ ALL_BUILDING_BLOCKS.each do |bbname,bb|
548
+ bb.complete_init
549
+ end
550
+
551
+ end
552
+
553
+ def showConfigNames()
554
+ loader = Loader.new(@options)
555
+
556
+ f = loader.load(@options.main_dir+"/Project.meta")
557
+
558
+ if f.root_elements.length != 1 or not Metamodel::Project === f.root_elements[0]
559
+ Printer.printError "Error: '#{filename}' must have exactly one 'Project' element as root element"
560
+ ExitHelper.exit(1)
561
+ end
562
+
563
+ validConfigs = []
564
+ f.root_elements[0].getConfig.each do |c|
565
+ validConfigs << c.name unless c.defaultToolchain.nil?
566
+ end
567
+ puts "Please specify a config name (with -b)!"
568
+ puts "Possible values are:"
569
+ if validConfigs.length > 0
570
+ validConfigs.each { |v| puts "* " + v }
571
+ else
572
+ puts " No main config found!"
573
+ end
574
+
575
+ ExitHelper.exit(0)
576
+ end
577
+
578
+ def doit()
579
+ parsingOk = false
580
+ ex = nil
581
+ begin
582
+ parsingOk = doit_internal
583
+ rescue Exception => e
584
+ ex = e
585
+ end
586
+ if not parsingOk and Rake.application.idei
587
+ Rake.application.idei.set_build_info(@mainProjectName, @options.build_config.nil? ? "Not set" : @options.build_config, 0)
588
+ err_res = ErrorDesc.new
589
+ err_res.file_name = @options.main_dir
590
+ err_res.line_number = 0
591
+ err_res.severity = ErrorParser::SEVERITY_ERROR
592
+ err_res.message = "Parsing configurations failed, see log output."
593
+ Rake.application.idei.set_errors([err_res])
594
+ end
595
+
596
+ raise ex if ex
597
+ parsingOk
598
+ end
599
+
600
+ def doit_internal()
601
+
602
+ @mainProjectName = File::basename(@options.main_dir)
603
+
604
+ if @options.build_config == ""
605
+ showConfigNames()
606
+ ExitHelper.exit(1)
607
+ end
608
+
609
+ @startupFilename = @options.filename
610
+
611
+ @mainMeta = @options.main_dir + "/Project.meta"
612
+
613
+ cache = CacheAccess.new(@mainMeta, @options.build_config, @options)
614
+
615
+ if File.exists? @mainMeta
616
+ @defaultToolchainTime = File.mtime(@mainMeta)
617
+ @mainMetaTime = @defaultToolchainTime
618
+ else
619
+ @defaultToolchainTime = Time.now
620
+ end
621
+
622
+ forceLoadMeta = @options.nocache
623
+
624
+ @defaultToolchainCached = nil
625
+
626
+ if not forceLoadMeta
627
+ @project2config = cache.load_cache
628
+ @defaultToolchainCached = cache.defaultToolchain
629
+ @defaultToolchainTime = cache.defaultToolchainTime unless cache.defaultToolchainTime.nil?
630
+ if @project2config.nil?
631
+ forceLoadMeta = true
632
+ else
633
+ @defaultToolchain = @defaultToolchainCached
634
+ end
635
+ end
636
+
637
+ if forceLoadMeta
638
+ load_meta
639
+ cache.write_cache(@project_files, @project2config, @defaultToolchain, @defaultToolchainTime)
640
+ end
641
+
642
+ substVars
643
+ convert2bb
644
+
645
+ #################################################
646
+
647
+ startBBName = "Project "+@options.project
648
+ startBB = ALL_BUILDING_BLOCKS[startBBName]
649
+ if startBB.nil?
650
+ Printer.printError "Error: Project #{@options.project} is not a dependency of #{@mainProjectName}"
651
+ ExitHelper.exit(1)
652
+ end
653
+
654
+
655
+ #################################################
656
+
657
+ if @options.single or @startupFilename
658
+ content_names = startBB.contents.map { |c| c.name }
659
+ startBB.main_content.set_helper_dependencies(startBB.main_content.dependencies.dup) if Executable === startBB.main_content
660
+ startBB.main_content.dependencies.delete_if { |d| not content_names.include?d}
661
+ end
662
+
663
+ if @startupFilename
664
+ startBB.contents.each do |c|
665
+ if SourceLibrary === c or Executable === c
666
+
667
+ # check that the file is REALLY included and glob if file does not exist and guess what file can be meant
668
+ Dir.chdir(startBB.project_dir) do
669
+
670
+ theFile = []
671
+ if not File.exists?(@startupFilename)
672
+ Dir.chdir(startBB.project_dir) do
673
+ theFile = Dir.glob("**/#{@startupFilename}")
674
+ end
675
+ if theFile.length == 0
676
+ Printer.printError "Error: #{@startupFilename} not found in project #{@options.project}"
677
+ ExitHelper.exit(1)
678
+ end
679
+ else
680
+ theFile << @startupFilename
681
+ end
682
+
683
+ exclude_files = []
684
+ c.exclude_sources.each do |e|
685
+ Dir.glob(e).each {|f| exclude_files << f}
686
+ end
687
+ theFile.delete_if { |f| exclude_files.any? {|e| e==f} }
688
+ if theFile.length == 0
689
+ Printer.printError "Error: #{@startupFilename} excluded in config #{@options.build_config} of project #{@options.project}"
690
+ ExitHelper.exit(1)
691
+ end
692
+
693
+ source_files = c.sources.dup
694
+ c.source_patterns.each do |p|
695
+ Dir.glob(p).each {|f| source_files << f}
696
+ end
697
+
698
+ theFile.delete_if { |f| source_files.all? {|e| e!=f} }
699
+ if theFile.length == 0
700
+ Printer.printError "Error: #{@startupFilename} is no source file in config #{@options.build_config} of project #{@options.project}"
701
+ ExitHelper.exit(1)
702
+ elsif theFile.length > 1
703
+ Printer.printError "Error: #{@startupFilename} is ambiguous in project #{@options.project}"
704
+ ExitHelper.exit(1)
705
+ else
706
+ @startupFilename = theFile[0]
707
+ end
708
+ end
709
+
710
+ c.set_sources([@startupFilename])
711
+ c.set_source_patterns([])
712
+ c.set_exclude_sources([])
713
+ c.extend(SingleSourceModule)
714
+ break
715
+ else
716
+ def c.needed?
717
+ false
718
+ end
719
+ end
720
+ end
721
+ end
722
+
723
+
724
+ Rake.application.check_unnecessary_includes = (@startupFilename == nil) if @options.check_uninc
725
+
726
+
727
+ #################################################
728
+
729
+
730
+ startBB.contents.each do |b|
731
+ if SourceLibrary === b or Executable === b or BinaryLibrary === b
732
+ @parseBB = b
733
+ end
734
+ end
735
+
736
+
737
+ @bbs = []
738
+ @num_modules = 1
739
+ if @options.single or @startupFilename
740
+ @bbs << startBB
741
+ @bbs.concat(startBB.contents)
742
+ else
743
+ @num_modules = calc_needed_bbs(startBBName, @bbs)
744
+ end
745
+
746
+ if @options.show_includes
747
+ @bbs.each do |bb|
748
+ if HasIncludes === bb
749
+ print bb.name
750
+ li = bb.local_includes
751
+ li.each { |i| print "##{i}" }
752
+ print "\n"
753
+ end
754
+ end
755
+ exit(0)
756
+ end
757
+
758
+ theExeBB = nil
759
+ @bbs.each do |bb|
760
+ res = bb.convert_to_rake()
761
+ theExeBB = res if Executable === bb
762
+ end
763
+
764
+ if @options.linkOnly
765
+ if theExeBB.nil?
766
+ Printer.printError "Error: no executable to link"
767
+ ExitHelper.exit(1)
768
+ else
769
+ theExeBB.prerequisites.delete_if {|p| Rake::Task::SOURCEMULTI == Rake.application[p].type}
770
+ end
771
+ end
772
+
773
+ @bbs.each do |bb|
774
+ set_output_taskname(bb)
775
+ end
776
+
777
+ if @startupFilename
778
+ runTaskName = @parseBB.get_task_name
779
+ else
780
+ runTaskName = startBB.get_task_name
781
+ end
782
+
783
+
784
+ @runTask = Rake.application[runTaskName]
785
+
786
+ if @startupFilename
787
+ @runTask.prerequisites.clear
788
+ end
789
+
790
+
791
+ #RubyProf.start
792
+ #result = RubyProf.stop
793
+ #printer = RubyProf::FlatPrinter.new(result)
794
+ #printer.print(STDOUT)
795
+
796
+
797
+ return true
798
+ end
799
+
800
+ def start()
801
+
802
+ if @options.clean
803
+ cleanTask = nil
804
+ if @startupFilename
805
+ Dir.chdir(@parseBB.project_dir) do
806
+
807
+ if File.is_absolute?(@startupFilename)
808
+ @startupFilename = File.rel_from_to_project(@parseBB.project_dir, @startupFilename, false)
809
+ end
810
+
811
+ of = @parseBB.get_object_file(@startupFilename)
812
+ object = File.expand_path(of)
813
+
814
+ FileUtils.rm object, :force => true
815
+ FileUtils.rm @parseBB.get_dep_file(object), :force => true
816
+ end
817
+ else
818
+ cleanTask = Rake.application["clean"]
819
+ cleanTask.invoke
820
+ end
821
+
822
+ if Rake.application.idei and Rake.application.idei.get_abort
823
+ Printer.printError "\nClean aborted."
824
+ return false
825
+ elsif cleanTask != nil and cleanTask.failure
826
+ Printer.printError "\nClean failed."
827
+ return false
828
+ elsif not @options.rebuild
829
+ Printer.printSuccess "\nClean done."
830
+ return true
831
+ end
832
+
833
+ end
834
+ Rake::application.idei.set_build_info(@parseBB.name, @parseBB.config_name, @num_modules)
835
+
836
+ @runTask.invoke
837
+
838
+ buildType = @options.rebuild ? "Rebuild" : "Build"
839
+
840
+ if Rake.application.idei and Rake.application.idei.get_abort
841
+ Printer.printError "\n#{buildType} aborted."
842
+ return false
843
+ elsif @runTask.failure
844
+ if Rake::application.preproFlags
845
+ Printer.printSuccess "\nPreprocessing done."
846
+ return true
847
+ else
848
+ Printer.printError "\n#{buildType} failed."
849
+ return false
850
+ end
851
+ else
852
+ text = ""
853
+ # this "fun part" shall not fail in any case!
854
+ begin
855
+ #if Time.now.year == 2012 and Time.now.month == 1
856
+ # text = " -- The munich software team wishes you a happy new year 2012!"
857
+ #end
858
+ rescue Exception
859
+ end
860
+ Printer.printSuccess("\n#{buildType} done." + text)
861
+ return true
862
+ end
863
+ end
864
+
865
+ def connect()
866
+ if @options.socket != 0
867
+ Rake.application.idei.connect(@options.socket)
868
+ end
869
+ end
870
+
871
+ def disconnect()
872
+ if @options.socket != 0
873
+ Rake.application.idei.disconnect()
874
+ end
875
+ end
876
+
877
+
878
+ end
879
+ end
880
+
881
+
882
+ # metamodel Files vs File vs Dir vs Make vs ... ? merge?
883
+