bake-toolkit 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile.rb +3 -0
- data/bin/bake +86 -0
- data/bin/bakery +234 -0
- data/lib/alias/loader.rb +56 -0
- data/lib/alias/model/language.rb +22 -0
- data/lib/alias/model/metamodel.rb +29 -0
- data/lib/bake/cache.rb +142 -0
- data/lib/bake/loader.rb +92 -0
- data/lib/bake/model/language.rb +46 -0
- data/lib/bake/model/metamodel.rb +226 -0
- data/lib/bake/model/metamodel_ext.rb +15 -0
- data/lib/bake/options.rb +288 -0
- data/lib/bake/subst.rb +90 -0
- data/lib/bake/util.rb +98 -0
- data/lib/bake/version.rb +30 -0
- data/lib/bakery/loader.rb +57 -0
- data/lib/bakery/model/language.rb +22 -0
- data/lib/bakery/model/metamodel.rb +44 -0
- data/lib/bakery/options.rb +98 -0
- data/lib/option/parser.rb +66 -0
- data/lib/tocxx.rb +883 -0
- data/license.txt +64 -0
- metadata +109 -0
@@ -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
|
+
|