class Bake::Blocks::Block
Attributes
bes[RW]
besDirect[RW]
config[R]
configName[R]
executable[R]
inDeps[RW]
lib_elements[R]
library[R]
output_dir[R]
prebuild[R]
projectDir[R]
projectName[R]
result[RW]
tcs[R]
visited[RW]
Public Class Methods
block_counter()
click to toggle source
# File lib/blocks/block.rb, line 179 def self.block_counter @@block_counter end
delayed_result()
click to toggle source
# File lib/blocks/block.rb, line 195 def self.delayed_result @@delayed_result end
inc_block_counter()
click to toggle source
# File lib/blocks/block.rb, line 175 def self.inc_block_counter() @@block_counter += 1 end
init_threads()
click to toggle source
# File lib/blocks/block.rb, line 527 def self.init_threads() @@threads = [] @@result = true @@mutex = Mutex.new @@mutexStdinSelect = Mutex.new Bake::Multithread::Jobs.init_semaphore() end
new(config, referencedConfigs, prebuild, tcs)
click to toggle source
# File lib/blocks/block.rb, line 77 def initialize(config, referencedConfigs, prebuild, tcs) @inDeps = false @prebuild = prebuild @visited = false @library = nil @executable = nil @config = config @referencedConfigs = referencedConfigs @projectName = config.parent.name @configName = config.name @projectDir = config.get_project_dir @result = true @tcs = tcs @bes = [] @besDirect = [] @lib_elements = [] calcOutputDir end
reset_block_counter()
click to toggle source
# File lib/blocks/block.rb, line 183 def self.reset_block_counter @@block_counter = 1 end
reset_delayed_result()
click to toggle source
# File lib/blocks/block.rb, line 191 def self.reset_delayed_result @@delayed_result = true end
set_delayed_result()
click to toggle source
# File lib/blocks/block.rb, line 187 def self.set_delayed_result @@delayed_result = false end
set_num_projects(blocks)
click to toggle source
# File lib/blocks/block.rb, line 237 def self.set_num_projects(blocks) if Bake.options.verbose >= 2 @@num_projects = blocks.length else counter = 0 blocks.each do |b| counter += 1 if b.isBuildBlock? end @@num_projects = counter end end
threads()
click to toggle source
# File lib/blocks/block.rb, line 199 def self.threads @@threads end
waitForAllThreads()
click to toggle source
# File lib/blocks/block.rb, line 203 def self.waitForAllThreads if @@threads.length > 0 STDOUT.puts "DEBUG_THREADS: Wait for all threads." if Bake.options.debug_threads @@threads.each{|t| while not t.join(2) do end} @@threads = [] STDOUT.puts "DEBUG_THREADS: All threads finished." if Bake.options.debug_threads end end
waitForFreeThread()
click to toggle source
# File lib/blocks/block.rb, line 307 def self.waitForFreeThread if @@threads.length == Bake.options.threads begin STDOUT.puts "DEBUG_THREADS: Wait for free thread." if Bake.options.debug_threads endedThread = ThreadsWait.new(*@@threads).next_wait STDOUT.puts "DEBUG_THREADS: Thread free: #{endedThread.object_id}" if Bake.options.debug_threads @@threads.delete(endedThread) rescue ErrNoWaitingThread end end end
Public Instance Methods
blockAbort?(res)
click to toggle source
# File lib/blocks/block.rb, line 360 def blockAbort?(res) ((not res) || !@@delayed_result) and Bake.options.stopOnFirstError or Bake::IDEInterface.instance.get_abort end
calcIsBuildBlock()
click to toggle source
# File lib/blocks/block.rb, line 212 def calcIsBuildBlock @startupSteps ||= [] return true if Metamodel::ExecutableConfig === @config if Metamodel::CustomConfig === @config return true if @config.step else return true if @config.files.length > 0 end if ((@config.startupSteps && @config.startupSteps.step.length > 0) || (@config.preSteps && @config.preSteps.step.length > 0) || (@config.postSteps && @config.postSteps.step.length > 0) || (@config.exitSteps && @config.exitSteps.step.length > 0) || (@config.cleanSteps && @config.cleanSteps.step.length > 0) || (@config.preSteps && @config.preSteps.step.length > 0)) return true end return false end
calcOutputDir()
click to toggle source
# File lib/blocks/block.rb, line 588 def calcOutputDir if @tcs[:OUTPUT_DIR] != nil p = convPath(@tcs[:OUTPUT_DIR]) p = p[2..-1] if p.start_with?("./") @output_dir = p else qacPart = Bake.options.qac ? (".qac" + Bake.options.buildDirDelimiter) : "" if isMainProject? @output_dir = "build" + Bake.options.buildDirDelimiter + qacPart + Bake.options.build_config else @output_dir = "build" + Bake.options.buildDirDelimiter + qacPart + @config.name + "_" + Bake.options.main_project_name + "_" + Bake.options.build_config end end if @tcs[:OUTPUT_DIR_POSTFIX] != nil @output_dir = @output_dir + @tcs[:OUTPUT_DIR_POSTFIX] end if Bake.options.abs_path_in @output_dir = File.expand_path(@output_dir, @projectDir) end end
callDeps(method)
click to toggle source
# File lib/blocks/block.rb, line 296 def callDeps(method) return true if Bake.options.project depResult = true bes.each do |dep| next if Metamodel::IncludeDir === dep depResult = (ALL_BLOCKS[dep.name+","+dep.config].send(method) and depResult) break if (!depResult) && Bake.options.stopOnFirstError end return depResult end
callSteps(method)
click to toggle source
# File lib/blocks/block.rb, line 370 def callSteps(method) @config.writeEnvVars() Thread.current[:lastCommand] = nil @allSteps = (preSteps + mainSteps + postSteps) # check if we have to delay the output (if the last step of this block is not in a thread) @outputStep = nil @allSteps.each { |step| @outputStep = independent?(method, step) ? step : nil } while !@allSteps.empty? parallel = [] while @allSteps.first && independent?(method, @allSteps.first) parallel << @allSteps.shift end if parallel.length > 0 execute_in_thread(parallel) { lastStep = Thread.current[:steps].last begin Thread.current[:steps].each do |step| Multithread::Jobs.incThread() if !Compile === step begin @result = executeStep(step, :execute) if @result ensure Multithread::Jobs.decThread() if !Compile === step end @@delayed_result &&= @result break if blockAbort?(@result) end ensure SyncOut.stopStream() if lastStep == @outputStep if Bake.options.syncedOutput end } else step = @allSteps.shift Blocks::Block::waitForAllThreads() @result = executeStep(step, method) if @result @outputStep = nil if !@result && blockAbort?(@result) end return @result if blockAbort?(@result) end return @result end
childs()
click to toggle source
# File lib/blocks/block.rb, line 57 def childs @childs ||= [] end
clean()
click to toggle source
# File lib/blocks/block.rb, line 485 def clean return true if (@visited) @visited = true depResult = callDeps(:clean) return false if not depResult and Bake.options.stopOnFirstError if Bake.options.verbose >= 2 typeStr = "Cleaning" if @prebuild typeStr = "Checking" elsif not isBuildBlock? typeStr = "Skipping" end Bake.formatter.printAdditionalInfo "**** #{typeStr} #{Block.block_counter} of #{@@num_projects}: #{@projectName} (#{@configName}) ****" end if Bake.options.verbose >= 2 || (isBuildBlock? && Bake.options.verbose >= 1) Block.inc_block_counter() end @result = callSteps(:clean) if Bake.options.clobber Dir.chdir(@projectDir) do if File.exist?".bake" puts "Deleting folder .bake" if Bake.options.verbose >= 2 if !Bake.options.dry FileUtils.rm_rf(".bake") end end end end cleanSteps.each do |step| @result = executeStep(step, :cleanStep) if @result return false if not @result and Bake.options.stopOnFirstError end return (depResult && @result) end
cleanSteps()
click to toggle source
# File lib/blocks/block.rb, line 49 def cleanSteps @cleanSteps ||= [] end
convPath(dir, elem=nil, warnIfLocal=false)
click to toggle source
# File lib/blocks/block.rb, line 101 def convPath(dir, elem=nil, warnIfLocal=false) if dir.respond_to?("name") d = dir.name elem = dir else d = dir end return d if Bake.options.no_autodir inc = d.split("/") if (inc[0] == "..") # very simple check, but should be okay for 99.9 % of the cases if elem and Bake.options.verbose >= 2 SyncOut.mutex.synchronize do Bake.formatter.printInfo("path starts with \"..\"", elem) end end end res = [] return d if (inc[0] == "." || inc[0] == "..") # prio 0: force local if (inc[0] == @projectName) # prio 1: the real path magic resPathMagic = inc[1..-1].join("/") # within self resPathMagic = "." if resPathMagic == "" res << resPathMagic if warnIfLocal if resPathMagic == "." Bake.formatter.printInfo("\"#{d}\" uses path magic in IncludeDir, please use \".\" instead", elem) else Bake.formatter.printInfo("\"#{d}\" uses path magic in IncludeDir, please omit \"#{inc[0]}/\" or use \"./#{resPathMagic}\"", elem) if warnIfLocal end end elsif @referencedConfigs.include?(inc[0]) dirOther = @referencedConfigs[inc[0]].first.parent.get_project_dir resPathMagic = File.rel_from_to_project(@projectDir, dirOther, false) postfix = inc[1..-1].join("/") resPathMagic = resPathMagic + "/" + postfix if postfix != "" resPathMagic = "." if resPathMagic == "" res << resPathMagic Bake.formatter.printInfo("\"#{d}\" uses path magic in IncludeDir, please use a Dependency to \"#{inc[0]}\" instead", elem) if warnIfLocal end if File.exist?(@projectDir + "/" + d) # prio 2: local, e.g. "include" res << d end # prio 3: check if dir exists without Project.meta entry Bake.options.roots.each do |r| absIncDir = r.dir+"/"+d if File.exist?(absIncDir) res << File.rel_from_to_project(@projectDir,absIncDir,false) Bake.formatter.printInfo("\"#{d}\" uses path magic in IncludeDir, please create a Project.meta in \"#{absIncDir}\" or upwards and use a Dependency instead", elem) if warnIfLocal && res.length == 1 end end return d if res.empty? # prio 4: fallback, no path found res = res.map{ |r| Pathname.new(r).cleanpath.to_s }.uniq if warnIfLocal && res.length > 1 if elem and Bake.options.verbose >= 2 SyncOut.mutex.synchronize do Bake.formatter.printInfo("#{d} matches several paths:", elem) puts " #{res[0]} (chosen)" res[1..-1].each { |r| puts " #{r}" } end end end res[0] end
dependencies()
click to toggle source
# File lib/blocks/block.rb, line 53 def dependencies @dependencies ||= [] end
execute()
click to toggle source
# File lib/blocks/block.rb, line 412 def execute if (@inDeps) if Bake.options.verbose >= 3 SyncOut.mutex.synchronize do Bake.formatter.printWarning("While calculating next config, a circular dependency was found including project #{@projectName} with config #{@configName}", @config) end end return true end SyncOut.mutex.synchronize do if @visited while !defined?(@allSteps) || !@allSteps.empty? sleep(0.1) end return true # maybe to improve later (return false if step has a failed non-independent step) end @visited = true end @inDeps = true begin depResult = callDeps(:execute) rescue Exception => e @allSteps = [] raise end @inDeps = false if blockAbort?(depResult) @allSteps = [] return @result && depResult end Bake::IDEInterface.instance.set_build_info(@projectName, @configName) begin SyncOut.mutex.synchronize do @outputStep = nil SyncOut.startStream() if Bake.options.syncedOutput if !Bake.options.skipBuildingLine && (Bake.options.verbose >= 2 || (isBuildBlock? && Bake.options.verbose >= 1)) typeStr = "Building" if @prebuild typeStr = "Using" elsif not isBuildBlock? typeStr = "Applying" end bcStr = ">>CONF_NUM<<" if !Bake.options.syncedOutput bcStr = Block.block_counter Block.inc_block_counter() end Bake.formatter.printAdditionalInfo "**** #{typeStr} #{bcStr} of #{@@num_projects}: #{@projectName} (#{@configName}) ****" end puts "Project path: #{@projectDir}" if Bake.options.projectPaths end @result = callSteps(:execute) ensure if Bake.options.syncedOutput if !@outputStep SyncOut.stopStream() else SyncOut.discardStreams() end end @allSteps = [] end return (depResult && @result) end
executeStep(step, method)
click to toggle source
# File lib/blocks/block.rb, line 249 def executeStep(step, method) begin @result = step.send(method) && @result rescue Bake::SystemCommandFailed => scf @result = false ProcessHelper.killProcess(true) rescue SystemExit => exSys @result = false ProcessHelper.killProcess(true) rescue Exception => ex1 @result = false if not Bake::IDEInterface.instance.get_abort SyncOut.mutex.synchronize do Bake.formatter.printError("Error: #{ex1.message}") puts ex1.backtrace if Bake.options.debug end end end if Bake::IDEInterface.instance.get_abort raise AbortException.new end # needed for ctrl-c in Cygwin console ##################################### # additionally, the user has to enable raw mode of Cygwin console: "stty raw". # raw mode changes the signals into raw characters. # original problem: Cygwin is compiled with broken control handler config, # which might not be changed due to backward compatibility. # the control handler works only with programs compiled under Cygwin, which is # not true for Windows RubyInstaller packages. ctrl_c_found = false begin @@mutexStdinSelect.synchronize do while IO.select([$stdin],nil,nil,0) do nextChar = $stdin.sysread(1) if nextChar == "\x03" ctrl_c_found = true end end end rescue Exception => e end raise AbortException.new if ctrl_c_found return @result end
execute_in_thread(steps) { || ... }
click to toggle source
# File lib/blocks/block.rb, line 319 def execute_in_thread(steps) @@mutex.synchronize do Block::waitForFreeThread() return if blockAbort?(true) tmpstdout = Thread.current[:tmpStdout].nil? ? nil : Thread.current[:tmpStdout].dup @@threads << Thread.new(Thread.current[:stdout], tmpstdout, steps) { |outStr, tmpStdout, steps| STDOUT.puts "DEBUG_THREADS: Started: #{Thread.current.object_id} (#{@projectName}, #{@config.name})" if Bake.options.debug_threads Thread.current[:stdout] = outStr Thread.current[:tmpStdout] = tmpStdout Thread.current[:steps] = steps exceptionOccured = false begin yield exceptionOccured = true rescue Bake::SystemCommandFailed => scf # normal compilation error rescue SystemExit => exSys rescue AbortException => exSys Bake::IDEInterface.instance.set_abort(true) rescue Exception => ex1 if !Bake::IDEInterface.instance.get_abort SyncOut.mutex.synchronize do Bake.formatter.printError("Error: #{ex1.message}") puts ex1.backtrace if Bake.options.debug end end end if !exceptionOccured @result = false @@delayed_result = false end STDOUT.puts "DEBUG_THREADS: Stopped: #{Thread.current.object_id} (#{@projectName}, #{@config.name})" if Bake.options.debug_threads } Block::waitForFreeThread() return if blockAbort?(true) end raise AbortException.new if Bake::IDEInterface.instance.get_abort end
exitSteps()
click to toggle source
# File lib/blocks/block.rb, line 45 def exitSteps @exitSteps ||= [] end
exits()
click to toggle source
# File lib/blocks/block.rb, line 552 def exits return true if (@visited) @visited = true depResult = callDeps(:exits) if Bake.options.verbose >= 1 and not exitSteps.empty? Bake.formatter.printAdditionalInfo "**** Exiting #{@projectName} (#{@configName}) ****" end exitSteps.each do |step| @result = executeStep(step, :exitStep) && @result end return (depResult && @result) end
getBlocks(method)
click to toggle source
# File lib/blocks/block.rb, line 578 def getBlocks(method) @otherBlocks = [] getSubBlocks(self, method) return @otherBlocks end
getCompileBlocks()
click to toggle source
# File lib/blocks/block.rb, line 97 def getCompileBlocks() mainSteps.select { |m| Compile === m } end
getSubBlocks(b, method)
click to toggle source
# File lib/blocks/block.rb, line 569 def getSubBlocks(b, method) b.send(method).each do |child_b| if not @otherBlocks.include?child_b and not child_b == self @otherBlocks << child_b getSubBlocks(child_b, method) end end end
independent?(method, step)
click to toggle source
# File lib/blocks/block.rb, line 364 def independent?(method, step) method == :execute && (Library === step || Compile === step || (CommandLine === step && step.config.independent) || (Makefile === step && step.config.independent)) end
isBuildBlock?()
click to toggle source
# File lib/blocks/block.rb, line 232 def isBuildBlock? return true if Bake.options.conversion_info @isBuildBlock ||= calcIsBuildBlock end
isMainProject?()
click to toggle source
# File lib/blocks/block.rb, line 584 def isMainProject? @projectName == Bake.options.main_project_name and @config.name == Bake.options.build_config end
mainSteps()
click to toggle source
# File lib/blocks/block.rb, line 37 def mainSteps @mainSteps ||= [] end
parents()
click to toggle source
# File lib/blocks/block.rb, line 61 def parents @parents ||= [] end
postSteps()
click to toggle source
# File lib/blocks/block.rb, line 41 def postSteps @postSteps ||= [] end
preSteps()
click to toggle source
# File lib/blocks/block.rb, line 33 def preSteps @preSteps ||= [] end
qname()
click to toggle source
# File lib/blocks/block.rb, line 73 def qname() @projectName + "," + @configName end
set_executable(executable)
click to toggle source
# File lib/blocks/block.rb, line 69 def set_executable(executable) @executable = executable end
set_library(library)
click to toggle source
# File lib/blocks/block.rb, line 65 def set_library(library) @library = library end
startup()
click to toggle source
# File lib/blocks/block.rb, line 535 def startup return true if (@visited) @visited = true depResult = callDeps(:startup) if Bake.options.verbose >= 1 and not startupSteps.empty? Bake.formatter.printAdditionalInfo "**** Starting up #{@projectName} (#{@configName}) ****" end startupSteps.each do |step| @result = executeStep(step, :startupStep) && @result end return (depResult && @result) end
startupSteps()
click to toggle source
# File lib/blocks/block.rb, line 29 def startupSteps @startupSteps ||= [] end