lib/blocks/compile.rb in bake-toolkit-2.32.0 vs lib/blocks/compile.rb in bake-toolkit-2.33.0
- old
+ new
@@ -1,8 +1,10 @@
require 'blocks/blockBase'
+
require 'multithread/job'
require 'common/process'
+require 'common/ext/dir'
require 'common/utils'
require 'bake/toolchain/colorizing_formatter'
require 'bake/config/loader'
module Bake
@@ -11,10 +13,14 @@
class Compile < BlockBase
attr_reader :objects, :include_list
+ def mutex
+ @mutex ||= Mutex.new
+ end
+
def initialize(block, config, referencedConfigs)
super(block, config, referencedConfigs)
@objects = []
@object_files = {}
@system_includes = Set.new
@@ -39,51 +45,54 @@
def needed?(source, object, type, dep_filename_conv)
return "because analyzer toolchain is configured" if Bake.options.analyze
return "because prepro was specified and source is no assembler file" if Bake.options.prepro
- return "because object does not exist" if not File.exist?(object)
- oTime = File.mtime(object)
+ Dir.mutex.synchronize do
+ Dir.chdir(@projectDir) do
+ return "because object does not exist" if not File.exist?(object)
+ oTime = File.mtime(object)
- return "because source is newer than object" if oTime < File.mtime(source)
+ return "because source is newer than object" if oTime < File.mtime(source)
- if type != :ASM
- return "because dependency file does not exist" if not File.exist?(dep_filename_conv)
+ if type != :ASM
+ return "because dependency file does not exist" if not File.exist?(dep_filename_conv)
- begin
- File.readlines(dep_filename_conv).map{|line| line.strip}.each do |dep|
- Thread.current[:filelist].add(File.expand_path(dep)) if Bake.options.filelist
+ begin
+ File.readlines(dep_filename_conv).map{|line| line.strip}.each do |dep|
+ Thread.current[:filelist].add(File.expand_path(dep, @projectDir)) if Bake.options.filelist
- if not File.exist?(dep)
- # we need a hack here. with some windows configurations the compiler prints unix paths
- # into the dep file which cannot be found easily. this will be true for system includes,
- # e.g. /usr/lib/...xy.h
- if (Bake::Utils::OS.windows? and dep.start_with?"/") or
- (not Bake::Utils::OS.windows? and dep.length > 1 and dep[1] == ":")
- puts "Dependency header file #{dep} ignored!" if Bake.options.debug
- else
- return "because dependent header #{dep} does not exist"
+ if not File.exist?(dep)
+ # we need a hack here. with some windows configurations the compiler prints unix paths
+ # into the dep file which cannot be found easily. this will be true for system includes,
+ # e.g. /usr/lib/...xy.h
+ if (Bake::Utils::OS.windows? and dep.start_with?"/") or
+ (not Bake::Utils::OS.windows? and dep.length > 1 and dep[1] == ":")
+ puts "Dependency header file #{dep} ignored!" if Bake.options.debug
+ else
+ return "because dependent header #{dep} does not exist"
+ end
+ else
+ return "because dependent header #{dep} is newer than object" if oTime < File.mtime(dep)
+ end
end
- else
- return "because dependent header #{dep} is newer than object" if oTime < File.mtime(dep)
+ rescue Exception => ex
+ if Bake.options.debug
+ puts "While reading #{dep_filename_conv}:"
+ puts ex.message
+ puts ex.backtrace
+ end
+ return "because dependency file could not be loaded"
end
end
- rescue Exception => ex
- if Bake.options.debug
- puts "While reading #{dep_filename_conv}:"
- puts ex.message
- puts ex.backtrace
- end
- return "because dependency file could not be loaded"
end
end
-
- false
+ return false
end
def calcCmdlineFile(object)
- object[0..-3] + ".cmdline"
+ File.expand_path(object[0..-3] + ".cmdline", @projectDir)
end
def calcDepFile(object, type)
dep_filename = nil
if type != :ASM
@@ -123,11 +132,11 @@
if not reason
cmdLineCheck = true
reason = config_changed?(cmdLineFile)
end
- Thread.current[:filelist].add(File.expand_path(source)) if Bake.options.filelist
+ Thread.current[:filelist].add(File.expand_path(source, @projectDir)) if Bake.options.filelist
if @fileTcs.include?(source)
compiler = @fileTcs[source][:COMPILER][type]
defines = getDefines(compiler)
flags = getFlags(compiler)
@@ -187,27 +196,30 @@
cmdJson = cmd.is_a?(Array) ? cmd.join(' ') : cmd
Blocks::CC2J << { :directory => @projectDir, :command => cmdJson, :file => source }
end
if not (cmdLineCheck and BlockBase.isCmdLineEqual?(cmd, cmdLineFile))
- BlockBase.prepareOutput(object)
+ BlockBase.prepareOutput(File.expand_path(object,@projectDir))
outputType = Bake.options.analyze ? "Analyzing" : (Bake.options.prepro ? "Preprocessing" : "Compiling")
- printCmd(cmd, "#{outputType} #{source}", reason, false)
- flushOutput()
+ printCmd(cmd, "#{outputType} #{@projectName} (#{@config.name}): #{source}", reason, false)
+ SyncOut.flushOutput()
BlockBase.writeCmdLineFile(cmd, cmdLineFile)
success = true
consoleOutput = ""
- success, consoleOutput = ProcessHelper.run(cmd, false, false) if !Bake.options.dry
+ success, consoleOutput = ProcessHelper.run(cmd, false, false, nil, [0], @projectDir) if !Bake.options.dry
incList = process_result(cmd, consoleOutput, compiler[:ERROR_PARSER], nil, reason, success)
-
if type != :ASM and not Bake.options.analyze and not Bake.options.prepro
- incList = Compile.read_depfile(dep_filename, @projectDir, @block.tcs[:COMPILER][:DEP_FILE_SINGLE_LINE]) if incList.nil?
- Compile.write_depfile(incList, dep_filename_conv)
+ Dir.mutex.synchronize do
+ Dir.chdir(@projectDir) do
+ incList = Compile.read_depfile(dep_filename, @projectDir, @block.tcs[:COMPILER][:DEP_FILE_SINGLE_LINE]) if incList.nil?
+ Compile.write_depfile(incList, dep_filename_conv)
+ end
+ end
incList.each do |h|
- Thread.current[:filelist].add(File.expand_path(h))
+ Thread.current[:filelist].add(File.expand_path(h, @projectDir))
end if Bake.options.filelist
end
check_config_file
end
@@ -262,104 +274,70 @@
return nil
end
end
end
- def mutex
- @mutex ||= Mutex.new
- end
-
- def flushOutput
- mutex.synchronize do
- tmp = Thread.current[:stdout]
- if tmp.string.length > 0
- Thread.current[:stdout] = Thread.current[:tmpStdout]
- puts tmp.string
- tmp.reopen("")
- Thread.current[:stdout] = tmp
- end
- end
- end
-
-
def execute
- Dir.chdir(@projectDir) do
+ #Dir.chdir(@projectDir) do
calcSources
calcObjects
- @error_strings = {}
-
fileListBlock = Set.new if Bake.options.filelist
compileJobs = Multithread::Jobs.new(@source_files) do |jobs|
while source = jobs.get_next_or_nil do
- if (jobs.failed and Bake.options.stopOnFirstError) or Bake::IDEInterface.instance.get_abort
+ if ((jobs.failed || !Blocks::Block.delayed_result) and Bake.options.stopOnFirstError) or Bake::IDEInterface.instance.get_abort
break
end
- s = StringIO.new
- Thread.current[:tmpStdout] = Thread.current[:stdout]
- Thread.current[:stdout] = s unless Thread.current[:tmpStdout]
- Thread.current[:filelist] = Set.new if Bake.options.filelist
- Thread.current[:lastCommand] = nil
-
- result = false
+ SyncOut.startStream()
begin
- compileFile(source)
- result = true
- rescue Bake::SystemCommandFailed => scf # normal compilation error
- rescue SystemExit => exSys
- rescue Exception => ex1
- if not Bake::IDEInterface.instance.get_abort
- Bake.formatter.printError("Error: #{ex1.message}")
- puts ex1.backtrace if Bake.options.debug
- end
- end
+ Thread.current[:filelist] = Set.new if Bake.options.filelist
+ Thread.current[:lastCommand] = nil
- jobs.set_failed if not result
-
- Thread.current[:stdout] = Thread.current[:tmpStdout]
-
- mutex.synchronize do
- fileListBlock.merge(Thread.current[:filelist]) if Bake.options.filelist
-
- if s.string.length > 0
- if Bake.options.stopOnFirstError and not result
- @error_strings[source] = s.string
- else
- puts s.string
+ result = false
+ begin
+ compileFile(source)
+ result = true
+ rescue Bake::SystemCommandFailed => scf # normal compilation error
+ rescue SystemExit => exSys
+ rescue Exception => ex1
+ if not Bake::IDEInterface.instance.get_abort
+ Bake.formatter.printError("Error: #{ex1.message}")
+ puts ex1.backtrace if Bake.options.debug
end
end
+
+ jobs.set_failed if not result
+ ensure
+ SyncOut.stopStream(result)
end
+ self.mutex.synchronize do
+ fileListBlock.merge(Thread.current[:filelist]) if Bake.options.filelist
+ end
end
end
compileJobs.join
if Bake.options.filelist && !Bake.options.dry
Bake.options.filelist.merge(fileListBlock.merge(fileListBlock))
- FileUtils.mkdir_p(@block.output_dir)
- File.open(@block.output_dir + "/" + "file-list.txt", 'wb') do |f|
+ odir = File.expand_path(@block.output_dir, @projectDir)
+ FileUtils.mkdir_p(odir)
+ File.open(odir + "/" + "file-list.txt", 'wb') do |f|
fileListBlock.sort.each do |entry|
f.puts(entry)
end
end
end
-
- # can only happen in case of bail_on_first_error.
- # if not sorted, it may be confusing when builing more than once and the order of the error appearances changes from build to build
- # (it is not deterministic which file compilation finishes first)
- @error_strings.sort.each {|es| puts es[1]}
-
raise SystemCommandFailed.new if compileJobs.failed
-
- end
+ #end
return true
end
def clean
if (Bake.options.filename or Bake.options.analyze)
@@ -417,68 +395,67 @@
end
end
def calcSources(cleaning = false, keep = false)
return @source_files if @source_files and not @source_files.empty?
- Dir.chdir(@projectDir) do
- @source_files = []
+ @source_files = []
- exclude_files = Set.new
- @config.excludeFiles.each do |p|
- Dir.glob(p.name).each {|f| exclude_files << f}
- end
+ exclude_files = Set.new
+ @config.excludeFiles.each do |p|
+ Dir.glob_dir(p.name, @projectDir).each {|f| exclude_files << f}
+ end
- source_files = Set.new
- @config.files.each do |sources|
- p = sources.name
- p = p[2..-1] if p.start_with?"./"
+ source_files = Set.new
+ @config.files.each do |sources|
+ p = sources.name
+ p = p[2..-1] if p.start_with?"./"
- res = Dir.glob(p).sort
- if res.length == 0 and cleaning == false
- if not p.include?"*" and not p.include?"?"
- Bake.formatter.printError("Source file '#{p}' not found", sources)
- raise SystemCommandFailed.new
- elsif Bake.options.verbose >= 1
- Bake.formatter.printInfo("Source file pattern '#{p}' does not match to any file", sources)
- end
+ res = Dir.glob_dir(p, @projectDir).sort
+ if res.length == 0 and cleaning == false
+ if not p.include?"*" and not p.include?"?"
+ Bake.formatter.printError("Source file '#{p}' not found", sources)
+ raise SystemCommandFailed.new
+ elsif Bake.options.verbose >= 1
+ Bake.formatter.printInfo("Source file pattern '#{p}' does not match to any file", sources)
end
- res.each do |f|
- next if exclude_files.include?(f)
- next if source_files.include?(f)
- source_files << f
- @source_files << f
- end
end
+ res.each do |f|
+ next if exclude_files.include?(f)
+ next if source_files.include?(f)
+ source_files << f
+ @source_files << f
+ end
+ end
- if Bake.options.filename
- @source_files.keep_if do |source|
- source.include?Bake.options.filename
- end
- if @source_files.length == 0 and cleaning == false and @config.files.length > 0
- Bake.formatter.printInfo("#{Bake.options.filename} does not match to any source", @config)
- end
+ if Bake.options.filename
+ @source_files.keep_if do |source|
+ source.include?Bake.options.filename
end
+ if @source_files.length == 0 and cleaning == false and @config.files.length > 0
+ Bake.formatter.printInfo("#{Bake.options.filename} does not match to any source", @config)
+ end
+ end
- if Bake.options.eclipseOrder # directories reverse order, files in directories in alphabetical order
- dirs = []
- filemap = {}
- @source_files.sort.reverse.each do |o|
- d = File.dirname(o)
- if filemap.include?(d)
- filemap[d] << o
- else
- filemap[d] = [o]
- dirs << d
- end
+ if Bake.options.eclipseOrder # directories reverse order, files in directories in alphabetical order
+ dirs = []
+ filemap = {}
+ @source_files.sort.reverse.each do |o|
+ d = File.dirname(o)
+ if filemap.include?(d)
+ filemap[d] << o
+ else
+ filemap[d] = [o]
+ dirs << d
end
- @source_files = []
- dirs.each do |d|
- filemap[d].reverse.each do |f|
- @source_files << f
- end
+ end
+ @source_files = []
+ dirs.each do |d|
+ filemap[d].reverse.each do |f|
+ @source_files << f
end
end
end
+
@source_files
end
def mapInclude(inc, orgBlock)
\ No newline at end of file