Class: Bake::Subst

Inherits:
Object
  • Object
show all
Defined in:
lib/bake/subst.rb

Class Method Summary collapse

Class Method Details

.empty(elem, var, mandatory, str) ⇒ Object



48
49
50
51
52
53
54
55
56
57
58
# File 'lib/bake/subst.rb', line 48

def self.empty(elem, var, mandatory, str)
  if mandatory
    Bake.formatter.printError("Variable '$(#{var})' cannot be substituted, because #{str}", elem ? elem : @@config)
    ExitHelper.exit(1)
  else
    if Bake.options.verbose > 0
      msg = "Substitute variable '$(#{var})' with empty string, because #{str}"
      Bake.formatter.printInfo(msg, elem ? elem : @@config)
    end
  end
end

.itute(config, projName, isMainProj, toolchain, referencedConfigs, configTcMap) ⇒ Object



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
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
151
152
153
154
155
156
157
# File 'lib/bake/subst.rb', line 60

def self.itute(config, projName, isMainProj, toolchain, referencedConfigs, configTcMap)
  @@lazy = true
  @@config = config
  @@toolchain = toolchain
  @@referencedConfigs = referencedConfigs
  @@configTcMap = configTcMap
  if isMainProj
    @@toolchainName = config.defaultToolchain.basedOn
    @@outputDirUnresolved = []
  end

  @@configName = config.name
  @@projDir = config.parent.get_project_dir
  @@projName = projName
  @@unresolvedVars = []
  @@configFilename = config.file_name

  @@artifactName = ""
  if Metamodel::ExecutableConfig === config || Metamodel::LibraryConfig === config
    if not config.artifactName.nil?
      @@artifactName = config.artifactName.name
    else
      if Metamodel::ExecutableConfig === config
        @@artifactName = projName+Bake::Toolchain.outputEnding(toolchain)
      elsif Metamodel::LibraryConfig === config
        @@artifactName = "lib#{projName}.a"
      end
    end
  end

  if isMainProj
    @@userVarMap = {}
  else
    @@userVarMap = @@userVarMapMain.clone
  end

  config.set.each do |s|

    if (s.value != "" and s.cmd != "")
      Bake.formatter.printError("value and cmd attributes must be used exclusively", s)
      ExitHelper.exit(1)
    end

    if (s.value != "") or (s.cmd == "")
      setName = substString(s.name, s)
      if (setName.empty?)
        Bake.formatter.printWarning("Name of variable must not be empty - variable will be ignored", s)
      else
        @@userVarMap[s.name] = substString(s.value, s)
        if s.env
          ENV[s.name] = @@userVarMap[s.name]
          config.setEnvVar(s.name, @@userVarMap[s.name])
        end
      end
    else
      cmd_result = false
      consoleOutput = ""
      cmd = [substString(s.cmd, s)]
      begin
        Dir.chdir(@@projDir) do
          cmd_result, consoleOutput = ProcessHelper.run(cmd)
          @@userVarMap[s.name] = consoleOutput.chomp
          if s.env
            ENV[s.name] = @@userVarMap[s.name]
            config.setEnvVar(s.name, @@userVarMap[s.name])
          end
        end
      rescue Exception=>e
        consoleOutput = e.message
      end
      if (cmd_result == false)
        puts consoleOutput
        Bake.formatter.printError("Command not successful: #{cmd.join(" ")}", s)
        ExitHelper.exit(1)
      end
    end

  end

  @@userVarMapMain = @@userVarMap.clone if isMainProj

  unresolvedVarsWithoutOutputDir = []
  10.times do
    @@unresolvedVars = []
    subst(config)
    substToolchain(toolchain)
    unresolvedVarsWithoutOutputDir = (@@unresolvedVars - @@outputDirUnresolved)
    break if unresolvedVarsWithoutOutputDir.empty?
  end
  if (unresolvedVarsWithoutOutputDir.length > 0)
    unresolvedVarsWithoutOutputDir.each do |elem|
      Bake.formatter.printError("Could not resolve variable", elem)
    end
    ExitHelper.exit(1)
  end


end

.lazyPathsObject

this is done lazy because usually there is no need to calculate that



8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/bake/subst.rb', line 8

def self.lazyPaths
  return unless @@lazy

  cppCmd = @@toolchain[:COMPILER][:CPP][:COMMAND]
  cCmd = @@toolchain[:COMPILER][:C][:COMMAND]
  asmCmd = @@toolchain[:COMPILER][:ASM][:COMMAND]
  archiverCmd = @@toolchain[:ARCHIVER][:COMMAND]
  linkerCmd = @@toolchain[:LINKER][:COMMAND]

  if @@config.toolchain
    linkerCmd = @@config.toolchain.linker.command if @@config.toolchain.linker and @@config.toolchain.linker.command != ""
    archiverCmd = @@config.toolchain.archiver.command if @@config.toolchain.linker and @@config.toolchain.archiver.command != ""
    @@config.toolchain.compiler.each do |c|
      if c.command != ""
        if c.ctype == :CPP
          cppCmd = c.command
        elsif c.ctype == :C
          cCmd = c.command
        elsif c.ctype == :ASM
          asmCmd = c.command
        end
      end
    end
  end

  @@cppExe      = File.which(cppCmd)
  @@cExe        = File.which(cCmd)
  @@asmExe      = File.which(asmCmd)
  @@archiverExe = File.which(archiverCmd)
  @@linkerExe   = File.which(linkerCmd)

  @@lazy = false
end

.resolveOutputDirObject



42
43
44
45
46
# File 'lib/bake/subst.rb', line 42

def self.resolveOutputDir()
  @@outputDirUnresolved.each do |elem|
    subst(elem) if elem
 end
end

.subst(elem) ⇒ Object



384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
# File 'lib/bake/subst.rb', line 384

def self.subst(elem)
  elem.class.ecore.eAllAttributes_derived.each do |a|
    next if a.name == "file_name" or a.name == "line_number"
    return if Metamodel::Set === elem.class
    return if Metamodel::DefaultToolchain === elem
    return if Metamodel::Toolchain === elem.class
    next if a.eType.name != "EString"
    value = elem.getGeneric(a.name)
    if value.kind_of?(Array)
      substArr = value.map { |s| substString(s, elem, a.name) }
      elem.setGeneric(a.name, substArr)
    else
      substStr = substString(value, elem, a.name)
      elem.setGeneric(a.name, substStr)
    end
  end

  childsRefs = elem.class.ecore.eAllReferences.select{|r| r.containment}
  childsRefs.each do |c|
    elem.getGenericAsArray(c.name).each { |child| subst(child) }
  end
end

.substString(str, elem = nil, attrName = nil) ⇒ Object



159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
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
300
301
302
303
304
305
306
307
308
309
310
311
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
# File 'lib/bake/subst.rb', line 159

def self.substString(str, elem=nil, attrName=nil)
  substStr = ""
  posSubst = 0
  while (true)
    posStart = str.index("$(", posSubst)
    break if posStart.nil?
    posEnd = str.index(")", posStart)
    if posEnd.nil?
      Bake.formatter.printError("'$(' found but no ')'", elem)
      ExitHelper.exit(1)
    end
    posStartSub = str.index("$(", posStart+1)
    if (not posStartSub.nil? and posStartSub < posEnd) # = nested vars

      newStr = str[0,posStartSub] + substString(str[posStartSub..posEnd],elem)
      if (str.length + 1 > posEnd)
        str = newStr + str[posEnd+1..-1]
      else
        str = newStr
      end
      next
    end

    substStr << str[posSubst..posStart-1] if posStart>0

    var = str[posStart+2..posEnd-1].strip
    mandatory = false

    splittedVar = var.split(",").map { |v| v.strip() }
    splittedVar.each_with_index do |s,i|
      if s.end_with?("!")
        mandatory = true
        splittedVar[i] = s[0..-2]
      end
    end
    var = splittedVar.join(", ")

    if Bake.options.vars.has_key?(var)
      substStr << Bake.options.vars[var]
    elsif @@userVarMap.has_key?(var)
      substStr << @@userVarMap[var]
    elsif var == "MainConfigName"
      substStr << Bake.options.build_config
    elsif var == "MainProjectName"
      substStr << Bake.options.main_project_name
    elsif var == "MainProjectDir"
      substStr << Bake.options.main_dir
    elsif var == "WorkingDir"
      substStr << Bake.options.working_dir
    elsif var == "ConfigName"
     substStr << @@configName
    elsif var == "ToolchainName" and defined?@@toolchainName
     substStr << @@toolchainName
#        elsif var == "PathToMainProject"

#          substStr << File.rel_from_to_project(@@config.parent.get_project_dir, Bake.options.main_dir, false)

#        elsif var == "PathToMainProjectSanitized"

#          path = File.rel_from_to_project(@@config.parent.get_project_dir, Bake.options.main_dir, false).gsub(/\.\./,"__").gsub(/:/,"")

#          path = path[1..-1] if path.start_with?("/")

#          substStr << path

#        elsif var == "UidNoMainConfigName"

#          substStr << CRC32.calc(File.rel_from_to_project(@@config.parent.get_project_dir, Bake.options.main_dir, false))

    elsif var == "Uid"
      substStr << CRC32.calc(File.rel_from_to_project(@@config.parent.get_project_dir, Bake.options.main_dir, false) + "," + Bake.options.build_config)
    elsif var == "ProjectName"
      substStr << @@projName
    elsif var == "FilterArguments" or (splittedVar.length == 2 and splittedVar[0] == "FilterArguments")
      if (var == "FilterArguments")
        # default = nothing

      else
        args = Bake.options.include_filter_args[splittedVar[1]]
        substStr << args if args
      end
    elsif var == "OriginalDir"
      org = File.dirname(elem.org_file_name)
      if (org == @@projDir)
        substStr << @@projDir
      else
        substStr << File.rel_from_to_project(@@projDir,File.dirname(elem.org_file_name),false)
      end
    elsif var == "ProjectDir" or (splittedVar.length == 2 and splittedVar[0] == "ProjectDir")
      if (var == "ProjectDir")
        substStr << @@projDir
      else
        out_proj_name = splittedVar[1]
        if @@referencedConfigs.has_key?out_proj_name
          configs = @@referencedConfigs[out_proj_name]
          config = configs.first
          substStr << File.rel_from_to_project(@@projDir,config.get_project_dir,false)
        else
          empty(elem, var, mandatory, "project #{out_proj_name} not found")
        end
      end
    elsif var == "OutputDir" or (splittedVar.length == 3 and splittedVar[0] == "OutputDir")
      if (var == "OutputDir")
        if (!elem.nil?)
          config = elem.getConfig
          out_proj_name = config.parent.name
          out_conf_name = config.name
        else
          out_proj_name = @@projName
          out_conf_name = @@configName
        end
      else
        out_proj_name = splittedVar[1]
        out_conf_name = splittedVar[2]
      end
      if @@referencedConfigs.has_key?out_proj_name
        configs = @@referencedConfigs[out_proj_name]
        config = configs.select {|c| c.name == out_conf_name }.first
        if config

          if config.toolchain && config.toolchain.outputDir && config.toolchain.outputDir != ""
            out_dir = config.toolchain.outputDir
          else
            out_dir = @@configTcMap[config][:OUTPUT_DIR]
          end
          if config.toolchain && config.toolchain.outputDirPostfix && config.toolchain.outputDirPostfix != ""
            out_dir_postfix = config.toolchain.outputDirPostfix
          else
            out_dir_postfix = @@configTcMap[config][:OUTPUT_DIR_POSTFIX]
          end

          if not out_dir
            qacPart = Bake.options.qac ? (".qac" + Bake.options.buildDirDelimiter) : ""
            if out_proj_name == Bake.options.main_project_name and out_conf_name == Bake.options.build_config
              out_dir = "build" + Bake.options.buildDirDelimiter + qacPart + Bake.options.build_config
            else
              out_dir = "build" + Bake.options.buildDirDelimiter + qacPart + out_conf_name + "_" + Bake.options.main_project_name + "_" + Bake.options.build_config
            end
          end
          out_dir += out_dir_postfix if out_dir_postfix

          if (out_dir.include?"$(")
            if !elem
              Bake.formatter.printError("Variable OutputDir not used correctly in this config", @@config)
              ExitHelper.exit(1)
            end
            substStr << str[posStart..posEnd]
            @@outputDirUnresolved << elem
          else
            out_dir = substString(out_dir, elem)
            if File.is_absolute?(out_dir)
              substStr << out_dir
            else
              if (elem.nil?)
                projDir = @@projDir
              else
                projDir = elem.get_project_dir
              end
              substStr << Pathname.new(File.rel_from_to_project(projDir,config.get_project_dir,true)  + out_dir).cleanpath.to_s
            end
          end
        else
          empty(elem, var, mandatory, "config #{out_conf_name} not found for project #{out_proj_name}")
        end
      else
        empty(elem, var, mandatory, "project #{out_proj_name} not found")
      end
    elsif splittedVar.length > 1 and splittedVar[0] == "OutputDir"
      empty(elem, var, mandatory, "syntax of complex variable OutputDir is not $(OutputDir,<project name>,<config name>)")
    elsif var == "Time"
      substStr << Time.now.to_s
    elsif var == "Hostname"
      substStr << Socket.gethostname
    elsif var == "QacActive"
      substStr << (Bake.options.qac ? "yes" : "no")
    elsif var == "ArtifactName"
      substStr << @@artifactName
    elsif var == "ArtifactNameBase"
      substStr << @@artifactName.chomp(File.extname(@@artifactName))
    elsif var == "CPPPath"
      self.lazyPaths
      substStr << @@cppExe
    elsif var == "CPath"
      self.lazyPaths
      substStr << @@cExe
    elsif var == "ASMPath"
      self.lazyPaths
      substStr << @@asmExe
    elsif var == "ArchiverPath"
      self.lazyPaths
      substStr << @@archiverExe
    elsif var == "LinkerPath"
      self.lazyPaths
      substStr << @@linkerExe
    elsif var == "Roots"
      substStr << "___ROOTS___"
    elsif var == "/"
      substStr << File::SEPARATOR
    elsif var == ":"
      substStr << File::PATH_SEPARATOR
    elsif ENV[var]
      substStr << ENV[var]
    else
      if !(["ASMCompilerPrefix", "CompilerPrefix", "ArchiverPrefix", "LinkerPrefix"].include?(var))
        empty(elem, var, mandatory, "it's not set") if mandatory || Bake.options.verbose >= 2
      end
    end

    posSubst = posEnd + 1
  end
  substStr << str[posSubst..-1]
  @@unresolvedVars << elem if substStr.include?("$(")
  substStr
end

.substToolchain(elem) ⇒ Object



364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
# File 'lib/bake/subst.rb', line 364

def self.substToolchain(elem)
  if Hash === elem
    elem.each do |k, e|
      if Hash === e or Array === e
        substToolchain(e)
      elsif String === e
        elem[k] = substString(e)
      end
    end
  elsif Array === elem
    elem.each_with_index do |e, i|
      if Hash === e or Array === e
        substToolchain(e)
      elsif String === e
        elem[i] = substString(e)
      end
    end
  end
end