def __init__(self, parent=None): QtCore.QThread.__init__(self, parent) self.parent = parent self.Configs = CompilerConfig(self) self.Configs.saveCompilerSettings() # platform dependent settings self.isWin32Platform = False if os.sys.platform == 'win32': self.isWin32Platform = True self.TCHAIN = self.Configs.getCompiler() self.make = self.Configs.getMakeCmd() self.UserCode = None self.CleanBuild = True self.CompilerProcess = None # todo: use QtCore.QProcess class instead self.LogList = QtCore.QStringList()
def __init__(self, parent=None): QtCore.QThread.__init__(self, parent) self.parent = parent self.Configs = CompilerConfig(self) self.Configs.saveCompilerSettings() # platform dependent settings self.isWin32Platform = False if os.sys.platform == 'win32': self.isWin32Platform = True self.CC = self.Configs.getCompiler() self.cflags = self.Configs.getCflags() self.lflags = self.Configs.getLflags() self.CompilerCommands = None self.CompilerProcess = None # todo: use QtCore.QProcess class instead self.LogList = QtCore.QStringList()
class GccCompilerThread(QtCore.QThread): ''' classdocs ''' def __init__(self, parent=None): QtCore.QThread.__init__(self, parent) self.parent = parent self.Configs = CompilerConfig(self) self.Configs.saveCompilerSettings() # platform dependent settings self.isWin32Platform = False if os.sys.platform == 'win32': self.isWin32Platform = True self.TCHAIN = self.Configs.getCompiler() self.make = self.Configs.getMakeCmd() self.UserCode = None self.CleanBuild = True self.CompilerProcess = None # todo: use QtCore.QProcess class instead self.LogList = QtCore.QStringList() def run(self): if not self.TCHAIN: print 'no supported compiler!' return self.LogList.clear() if not self.UserCode: # just get version info command = [ self.TCHAIN + 'gcc', '--version' ] else: projectName = os.path.splitext(os.path.basename(self.UserCode))[0] # output folder - same location with user code outpath = os.path.join( os.path.dirname(self.UserCode) , OUT_DIR ) Result, Includes, Sources = parseUserCode( self.UserCode, outpath ) #print Includes, Sources if not Result or not self.generateMakefile(outpath, projectName, Includes, Sources, self.CleanBuild): self.BuildProcess = None self.LogList.append( "<font color=red>file write error</font>" ) return command = [ self.make , '-f'+os.path.join(outpath, MAKEFILE)] if self.CleanBuild: command.append('clean') command.append('all') try: self.CompilerProcess = subprocess.Popen( command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=self.isWin32Platform ) error_count = 0 while True: self.usleep(50000) if not self.CompilerProcess: break; # read single lines buff = self.CompilerProcess.stdout.readline() if buff == '': # got nothing if self.CompilerProcess.poll() != None: # process exited self.CompilerProcess = None # print 'compiler process finished.' break else: msg = str(buff) msg_lowered = msg.lower() # string to QString if msg_lowered.find("warning:") >= 0: self.LogList.append( "<font color=orange>%s</font>" % msg ) # todo: other error messages elif msg_lowered.find("error:") >= 0 \ or msg_lowered.find("make: ***") >= 0 \ or msg_lowered.find(": multiple definition") >= 0 \ or msg_lowered.find("undefined reference to") >= 0: self.LogList.append( "<font color=red>%s</font>" % msg ) error_count += 1 else: self.LogList.append( "<font color=green>%s</font>" % msg ) except: print 'got errors in compiler thread!' self.LogList.append( "<font color=red>ERROR: build failed!</font>") self.LogList.append( "<font color=red>%s</font>" % self.TCHAIN) self.CompilerProcess = None if not error_count: self.LogList.append( "<font size=4 color=cyan>done.</font>" ) else: self.LogList.append( "<font size=4 color=red>done with error(s) !</font>" ) print 'compiler thread done.' def getCompilerInfo(self): if self.isRunning(): return None self.UserCode = None self.start() while True: self.usleep(1000) if not self.isRunning(): break; if not self.LogList.count(): return None else: self.LogList.takeLast() info = '' for msg in self.LogList: info += msg return info def buildProject(self, userCode=None, cleanBuild=False): if self.isRunning(): return False, "busy" if not os.path.isfile(userCode): return False, "file not found" self.UserCode = str(userCode) self.CleanBuild = cleanBuild self.start() return True, "Build process running. Please wait..." def pollBuildProcess(self, stopProcess=False): if self.isRunning() or self.LogList.count()>0: if stopProcess: self.LogList.clear() try: self.CompilerProcess.kill() # needs Admin privilege on Windows! self.CompilerProcess = None self.exit() return True, "killed" except: print "n0 u can't kill me! :-p" self.CompilerProcess.wait() # just wait for the process to finish self.CompilerProcess = None self.exit() return False, "waited" if self.LogList.count(): return True, str(self.LogList.takeFirst()) else: return True, '' else: return False, "process not running" def generateMakefile(self, outPath='.', projectName='a', includePaths='', sourceFiles='', verbose=False): objects = [] try: fout = open( os.path.join(outPath, MAKEFILE), 'w' ) fout.write( '#\n# Automatically generated Makefile\n#\n\n' ) fout.write( 'PROJECT = ' + projectName + '\n\n' ) fout.write( 'OUTPUT_DIR = ' + outPath + '\n' ) fout.write( 'ELF_FILE = $(OUTPUT_DIR)/$(PROJECT).elf\n' ) fout.write( 'BIN_FILE = $(OUTPUT_DIR)/$(PROJECT).bin\n' ) fout.write( 'MAP_FILE = $(OUTPUT_DIR)/$(PROJECT).map\n' ) fout.write( 'LKR_SCRIPT = ' + getLinkerScript() + '\n\n') fout.write( 'TCHAIN = ' + self.TCHAIN.replace('\\','/') + '\n\n' ) fout.write( 'INCLUDES = \\\n' ) for path in includePaths: fout.write( '\t' + path + ' \\\n' ) fout.write( '\n\n' ) fout.write( 'DEFINES = ' + getCompilerDefines() + '\n') fout.write( 'CFLAGS = ' + self.Configs.getCflags() + ' $(DEFINES)\n') fout.write( 'CXXFLAGS = ' + self.Configs.getCxxflags() + ' $(DEFINES)\n') fout.write( 'AFLAGS = ' + self.Configs.getAflags() + '\n' ) fout.write( 'LFLAGS = ' + self.Configs.getLflags() + '\n\n' ) fout.write( 'LIBGCC = ${shell ${TCHAIN}gcc ${CFLAGS} -print-libgcc-file-name}\n' ) fout.write( 'LIBC = ${shell ${TCHAIN}gcc ${CFLAGS} -print-file-name=libc.a}\n' ) fout.write( 'LIBM = ${shell ${TCHAIN}gcc ${CFLAGS} -print-file-name=libm.a}\n' ) fout.write( 'LIBNOSYS = ${shell ${TCHAIN}gcc ${CXXFLAGS} -print-file-name=libnosys.a}\n' ) fout.write( 'LIBCPP = ${shell ${TCHAIN}g++ ${CXXFLAGS} -print-file-name=libstdc++.a}\n\n\n' ) fout.write( 'RM = ' + self.Configs.getRmCmd() + '\n\n\n' ) fout.write( 'OBJECTS = \\\n' ) for src in sourceFiles: src = str(src) folder, objname = os.path.split( src[:src.rfind('.')] + '.o' ) if folder.find('libraries')!=0 and folder.find('hardware')!=0: folder = 'user' objdir = os.path.join(outPath, 'obj', folder) if not os.path.exists(objdir): os.makedirs( objdir ) obj = '$(OUTPUT_DIR)/obj/' + folder + '/' + objname fout.write( '\t' + obj + ' \\\n' ) objects.append(obj) fout.write( '\n\n' ) fout.write( 'all : $(BIN_FILE)\n' ) fout.write( '\t@$(TCHAIN)size $(ELF_FILE)\n\n' ) fout.write( 'clean:\n' ) fout.write( '\t@$(RM) $(OBJECTS)\n' ) fout.write( '\t@$(RM) $(OUTPUT_DIR)/$(PROJECT).*\n\n\n' ) fout.write( '$(ELF_FILE): $(OBJECTS)\n' ) fout.write( '\t@echo [LINKER] $(@F)\n\t') if not verbose: fout.write( '@' ) fout.write( '$(TCHAIN)ld $(LFLAGS) $^ -o $@ $(LIBGCC) $(LIBC) $(LIBM) $(LIBNOSYS) $(LIBCPP)\n\n' ) fout.write( '$(BIN_FILE): $(ELF_FILE)\n' ) fout.write( '\t@echo [BIN Copy] $(@F)\n') fout.write( '\t@$(TCHAIN)objcopy -Obinary $< $@\n\n\n' ) i = 0 for src in sourceFiles: src = str(src) fout.write( objects[i] + ' : ' + src + '\n') src_ext = os.path.splitext(src)[1].lower() if src_ext == USER_CODE_EXT: fout.write( '\t@echo [CXX] $< \n\t' ) if not verbose: fout.write( '@' ) fout.write( '$(TCHAIN)gcc $(INCLUDES) $(CXXFLAGS) -x c++ $< -o $@\n\n') elif src_ext == '.s': fout.write( '\t@echo [AS] $(<F)\n\t' ) if not verbose: fout.write( '@' ) fout.write( '$(TCHAIN)as $(AFLAGS) $< -o $@\n\n') elif src_ext == '.c': fout.write( '\t@echo [CC] $(<F)\n\t' ) if not verbose: fout.write( '@' ) fout.write( '$(TCHAIN)gcc $(INCLUDES) $(CFLAGS) $< -o $@\n\n') elif src_ext == '.cpp': fout.write( '\t@echo [CPP] $(<F)\n\t' ) if not verbose: fout.write( '@' ) fout.write( '$(TCHAIN)g++ $(INCLUDES) $(CXXFLAGS) $< -o $@\n\n') i += 1 fout.close() return True except: return False def getExpectedBinFileName(self, userCode=None): if not userCode: return None outpath = os.path.dirname( str(userCode) ) + '/' + OUT_DIR fname = os.path.basename( str(userCode) ) dotpos = fname.rfind('.') if dotpos > 0: binfile = outpath + '/' + fname[:dotpos] + '.bin' else: binfile = outpath + '/' + fname + '.bin' return binfile
class GccCompilerThread(QtCore.QThread): ''' classdocs ''' # enum tasks GET_INFO = 0 BUILD_PROJECT = 1 PROGRAM_HEX = 2 _task = GET_INFO def __init__(self, parent=None): QtCore.QThread.__init__(self, parent) self.parent = parent self.Configs = CompilerConfig(self) self.Configs.saveCompilerSettings() # platform dependent settings self.isWin32Platform = False if os.sys.platform == 'win32': self.isWin32Platform = True self.TCHAIN = self.Configs.getCompiler() self.make = self.Configs.getMakeCmd() self.McuPart = None self.UserCode = None self.CleanBuild = True self.serialPortName = None self.CompilerProcess = None # todo: use QtCore.QProcess class instead self.LogList = QtCore.QStringList() def run(self): if not self.TCHAIN: print 'no supported compiler!' return self.LogList.clear() if self._task == self.GET_INFO: command = [self.TCHAIN + 'gcc', '--version'] elif self._task == self.PROGRAM_HEX: # output folder - same location with user code outpath = os.path.join(os.path.dirname(self.UserCode), OUT_DIR) command = [self.make, '-f' + os.path.join(outpath, MAKEFILE)] command.append('COMPORT=%s' % self.serialPortName) command.append('program') #print command else: # self._task == self.BUILD_PROJECT projectName = os.path.splitext(os.path.basename(self.UserCode))[0] # output folder - same location with user code outpath = os.path.join(os.path.dirname(self.UserCode), OUT_DIR) Result, Includes, Sources = parseUserCode(self.UserCode, outpath, self.McuPart) #print Includes, Sources if not Result or not self.generateMakefile( outpath, projectName, Includes, Sources, self.CleanBuild): self.BuildProcess = None self.LogList.append("<font color=red>file write error</font>") return command = [self.make, '-f' + os.path.join(outpath, MAKEFILE)] if self.CleanBuild: command.append('clean') command.append('all') try: self.CompilerProcess = subprocess.Popen(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=self.isWin32Platform) error_count = 0 while True: self.usleep(50000) if not self.CompilerProcess: break # read single lines buff = self.CompilerProcess.stdout.readline() if buff == '': # got nothing if self.CompilerProcess.poll() != None: # process exited self.CompilerProcess = None # print 'compiler process finished.' break else: msg = str(buff) msg_lowered = msg.lower() # string to QString if msg_lowered.find("warning:") >= 0: self.LogList.append("<font color=orange>%s</font>" % msg) # todo: other error messages elif msg_lowered.find("error:") >= 0 \ or msg_lowered.find("make: ***") >= 0 \ or msg_lowered.find(": multiple definition") >= 0 \ or msg_lowered.find("undefined reference to") >= 0: self.LogList.append("<font color=red>%s</font>" % msg) error_count += 1 else: self.LogList.append("<font color=green>%s</font>" % msg) except: print 'got errors in compiler thread!' self.LogList.append("<font color=red>ERROR: build failed!</font>") self.LogList.append("<font color=red>%s</font>" % self.TCHAIN) self.CompilerProcess = None if not error_count: self.LogList.append("<font size=4 color=cyan>done.</font>") else: self.LogList.append( "<font size=4 color=red>done with error(s) !</font>") print 'compiler thread done.' def getCompilerInfo(self): if self.isRunning(): return None self._task = self.GET_INFO self.start() while True: self.usleep(1000) if not self.isRunning(): break if not self.LogList.count(): return None else: self.LogList.takeLast() info = '' for msg in self.LogList: info += msg return info def buildProject(self, mcuPart, userCode, cleanBuild=False): if self.isRunning(): return False, "busy" if not os.path.isfile(userCode): return False, "file not found" self._task = self.BUILD_PROJECT self.McuPart = str(mcuPart) self.UserCode = str(userCode) self.CleanBuild = cleanBuild self.start() return True, "Build process running. Please wait..." def programHex(self, mcuPart, userCode, serialPort=None): if self.isRunning(): return False, "busy" if not serialPort: return False, "no port selected" self.McuPart = str(mcuPart) self.serialPortName = str(serialPort) self.UserCode = str(userCode) outpath = os.path.join(os.path.dirname(self.UserCode), OUT_DIR) makefile = os.path.join(outpath, MAKEFILE) hexfile = self.getExpectedHexFileName(userCode) if not os.path.isfile(makefile) or not os.path.isfile(hexfile): return False, "No *.hex file found! (re)build first the project." self._task = self.PROGRAM_HEX self.start() return True, "Flash Loader running. Please wait..." def pollBuildProcess(self, stopProcess=False): if self.isRunning() or self.LogList.count() > 0: if stopProcess: self.LogList.clear() try: self.CompilerProcess.kill( ) # needs Admin privilege on Windows! self.CompilerProcess = None self.exit() return True, "killed" except: print "n0 u can't kill me! :-p" self.CompilerProcess.wait( ) # just wait for the process to finish self.CompilerProcess = None self.exit() return False, "waited" if self.LogList.count(): return True, str(self.LogList.takeFirst()) else: return True, '' else: return False, "process not running" def generateMakefile(self, outPath='.', projectName='a', includePaths='', sourceFiles='', verbose=False): objects = [] try: fout = open(os.path.join(outPath, MAKEFILE), 'w') fout.write('#\n# Automatically generated Makefile\n#\n\n') fout.write('PROJECT = ' + projectName + '\n') fout.write('MCUARCH = ' + getMcuArchitecture(self.McuPart) + '\n') fout.write('MCUPART = ' + self.McuPart + '\n\n') fout.write('OUTPUT_DIR = ' + outPath + '\n') fout.write('ELF_FILE = $(OUTPUT_DIR)/$(PROJECT).elf\n') fout.write('HEX_FILE = $(OUTPUT_DIR)/$(PROJECT).hex\n') fout.write('MAP_FILE = $(OUTPUT_DIR)/$(PROJECT).map\n') fout.write('LKR_SCRIPT = ' + getLinkerScript(self.McuPart) + '\n\n') fout.write('TCHAIN = ' + self.TCHAIN.replace('\\', '/') + '\n\n') fout.write('INCLUDES = \\\n') for path in includePaths: fout.write('\t' + path + ' \\\n') fout.write('\n\n') fout.write('DEFINES = ' + getCompilerDefines() + '\n') fout.write('CFLAGS = ' + self.Configs.getCflags() + ' $(DEFINES)\n') fout.write('CXXFLAGS = ' + self.Configs.getCxxflags() + ' $(DEFINES)\n') fout.write('AFLAGS = ' + self.Configs.getAflags() + '\n') fout.write('LFLAGS = ' + self.Configs.getLflags() + '\n\n\n') fout.write('RM = ' + self.Configs.getRmCmd() + '\n\n\n') fout.write('OBJECTS = \\\n') for src in sourceFiles: src = str(src) folder, objname = os.path.split(src[:src.rfind('.')] + '.o') if folder.find('libraries') != 0 and folder.find( 'hardware') != 0: folder = 'user' objdir = os.path.join(outPath, 'obj', folder) if not os.path.exists(objdir): os.makedirs(objdir) obj = '$(OUTPUT_DIR)/obj/' + folder + '/' + objname fout.write('\t' + obj + ' \\\n') objects.append(obj) fout.write('\n\n') fout.write('all : $(OBJECTS)\n') fout.write('\t@echo [LINK] $(notdir $(ELF_FILE))\n\t') if not verbose: fout.write('@') fout.write('$(TCHAIN)g++ $(LFLAGS) $^ -o $(ELF_FILE)\n') fout.write('\t@echo [HEX] $(notdir $(HEX_FILE))\n') fout.write( '\t@$(TCHAIN)objcopy -O ihex -R .eeprom -R .fuse -R .lock -R .signature $(ELF_FILE) $(HEX_FILE)\n' ) fout.write('\t@$(TCHAIN)size $(ELF_FILE)\n\n') fout.write('clean:\n') fout.write('\t@$(RM) $(OBJECTS)\n') fout.write('\t@$(RM) $(ELF_FILE) $(HEX_FILE) $(MAP_FILE)\n\n\n') fout.write('program: $(HEX_FILE)\n') fout.write( '\tbatchisp -device at32$(MCUPART) -hardware RS232 -port $(COMPORT) ' ) fout.write( '-operation erase f memory flash blankcheck loadbuffer $(HEX_FILE) ' ) fout.write('program verify start reset 0\n\n\n') i = 0 for src in sourceFiles: src = str(src) fout.write(objects[i] + ' : ' + src + '\n') src_ext = os.path.splitext(src)[1].lower() if src_ext == USER_CODE_EXT: fout.write('\t@echo [CXX] $< \n\t') if not verbose: fout.write('@') fout.write( '$(TCHAIN)g++ $(INCLUDES) $(CXXFLAGS) -x c++ $< -o $@\n\n' ) elif src_ext == '.s': fout.write('\t@echo [AS] $(<F)\n\t') if not verbose: fout.write('@') fout.write( '$(TCHAIN)gcc -x assembler-with-cpp $(AFLAGS) $< -o $@\n\n' ) elif src_ext == '.c': fout.write('\t@echo [CC] $(<F)\n\t') if not verbose: fout.write('@') fout.write( '$(TCHAIN)gcc $(INCLUDES) $(CFLAGS) $< -o $@\n\n') elif src_ext == '.cpp': fout.write('\t@echo [CPP] $(<F)\n\t') if not verbose: fout.write('@') fout.write( '$(TCHAIN)g++ $(INCLUDES) $(CXXFLAGS) $< -o $@\n\n') i += 1 fout.close() return True except: return False def getExpectedHexFileName(self, userCode=None): if not userCode: return None outpath = os.path.dirname(str(userCode)) + '/' + OUT_DIR fname = os.path.basename(str(userCode)) dotpos = fname.rfind('.') if dotpos > 0: hexfile = outpath + '/' + fname[:dotpos] + '.hex' else: hexfile = outpath + '/' + fname + '.hex' return hexfile
class GccCompilerThread(QtCore.QThread): ''' classdocs ''' # enum tasks GET_INFO = 0 BUILD_PROJECT = 1 PROGRAM_HEX = 2 _task = GET_INFO def __init__(self, parent=None): QtCore.QThread.__init__(self, parent) self.parent = parent self.Configs = CompilerConfig(self) self.Configs.saveCompilerSettings() # platform dependent settings self.isWin32Platform = False if os.sys.platform == 'win32': self.isWin32Platform = True self.TCHAIN = self.Configs.getCompiler() self.make = self.Configs.getMakeCmd() self.McuPart = None self.UserCode = None self.CleanBuild = True self.serialPortName = None self.CompilerProcess = None # todo: use QtCore.QProcess class instead self.LogList = list() def run(self): if not self.TCHAIN: print('no supported compiler!') return self.LogList.clear() if self._task == self.GET_INFO: command = [ self.TCHAIN + 'gcc', '--version' ] elif self._task == self.PROGRAM_HEX: # output folder - same location with user code outpath = os.path.join( os.path.dirname(self.UserCode) , OUT_DIR ) command = [ self.make , '-f'+os.path.join(outpath, MAKEFILE)] command.append( 'COMPORT=%s' % self.serialPortName ) command.append( 'program' ) #print command else: # self._task == self.BUILD_PROJECT projectName = os.path.splitext(os.path.basename(self.UserCode))[0] # output folder - same location with user code outpath = os.path.join( os.path.dirname(self.UserCode) , OUT_DIR ) Result, Includes, Sources = parseUserCode( self.UserCode, outpath, self.McuPart ) #print Includes, Sources if not Result or not self.generateMakefile(outpath, projectName, Includes, Sources, self.CleanBuild): self.BuildProcess = None self.LogList.append( "<font color=red>file write error</font>" ) return command = [ self.make , '-f'+os.path.join(outpath, MAKEFILE)] if self.CleanBuild: command.append('clean') command.append('all') try: self.CompilerProcess = subprocess.Popen( command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=self.isWin32Platform ) error_count = 0 while True: self.usleep(50000) if not self.CompilerProcess: break; # read single lines buff = self.CompilerProcess.stdout.readline().strip().decode('utf-8') if not len(buff): # got nothing if self.CompilerProcess.poll() != None: # process exited self.CompilerProcess = None # print 'compiler process finished.' break else: msg = str(buff) msg_lowered = msg.lower() # string to QString if msg_lowered.find("warning:") >= 0: self.LogList.append( "<font color=orange>%s</font>" % msg ) # todo: other error messages elif msg_lowered.find("error:") >= 0 \ or msg_lowered.find("make: ***") >= 0 \ or msg_lowered.find(": multiple definition") >= 0 \ or msg_lowered.find("undefined reference to") >= 0: self.LogList.append( "<font color=red>%s</font>" % msg ) error_count += 1 else: self.LogList.append( "<font color=green>%s</font>" % msg ) except: print('got errors in compiler thread!') self.LogList.append( "<font color=red>ERROR: build failed!</font>") self.LogList.append( "<font color=red>%s</font>" % self.TCHAIN) self.CompilerProcess = None if not error_count: self.LogList.append( "<font size=4 color=cyan>done.</font>" ) else: self.LogList.append( "<font size=4 color=red>done with error(s) !</font>" ) print('compiler thread done.') def getCompilerInfo(self): if self.isRunning(): return None self._task = self.GET_INFO self.start() while True: self.usleep(1000) if not self.isRunning(): break; if not len(self.LogList): return None else: self.LogList.pop() # takeLast info = '' for msg in self.LogList: info += msg return info def buildProject(self, mcuPart, userCode, cleanBuild=False): if self.isRunning(): return False, "busy" if not os.path.isfile(userCode): return False, "file not found" self._task = self.BUILD_PROJECT self.McuPart = str(mcuPart) self.UserCode = str(userCode) self.CleanBuild = cleanBuild self.start() return True, "Build process running. Please wait..." def programHex(self, mcuPart, userCode, serialPort=None): if self.isRunning(): return False, "busy" if not serialPort: return False, "no port selected" self.McuPart = str(mcuPart) self.serialPortName = str(serialPort) self.UserCode = str(userCode) outpath = os.path.join( os.path.dirname(self.UserCode) , OUT_DIR ) makefile = os.path.join(outpath, MAKEFILE) hexfile = self.getExpectedHexFileName(userCode) if not os.path.isfile(makefile) or not os.path.isfile(hexfile): return False, "No *.hex file found! (re)build first the project." self._task = self.PROGRAM_HEX self.start() return True, "Flash Loader running. Please wait..." def pollBuildProcess(self, stopProcess=False): if self.isRunning() or len(self.LogList): if stopProcess: self.LogList.clear() try: self.CompilerProcess.kill() # needs Admin privilege on Windows! self.CompilerProcess = None self.exit() return True, "killed" except: #print("n0 u can't kill me! :-p") self.CompilerProcess.wait() # just wait for the process to finish self.CompilerProcess = None self.exit() return False, "waited" if len(self.LogList): return True, str(self.LogList.pop(0)) # takeFirst else: return True, '' else: return False, "process not running" def generateMakefile(self, outPath='.', projectName='a', includePaths='', sourceFiles='', verbose=False): objects = [] try: fout = open( os.path.join(outPath, MAKEFILE), 'w' ) fout.write( '#\n# Automatically generated Makefile\n#\n\n' ) fout.write( 'PROJECT = ' + projectName + '\n' ) fout.write( 'MCUARCH = ' + getMcuArchitecture(self.McuPart) + '\n' ) fout.write( 'MCUPART = ' + self.McuPart + '\n\n' ) fout.write( 'OUTPUT_DIR = ' + outPath + '\n' ) fout.write( 'ELF_FILE = $(OUTPUT_DIR)/$(PROJECT).elf\n' ) fout.write( 'HEX_FILE = $(OUTPUT_DIR)/$(PROJECT).hex\n' ) fout.write( 'MAP_FILE = $(OUTPUT_DIR)/$(PROJECT).map\n' ) fout.write( 'LKR_SCRIPT = ' + getLinkerScript(self.McuPart) + '\n\n') fout.write( 'TCHAIN = ' + self.TCHAIN.replace('\\','/') + '\n\n' ) fout.write( 'INCLUDES = \\\n' ) for path in includePaths: fout.write( '\t' + path + ' \\\n' ) fout.write( '\n\n' ) fout.write( 'DEFINES = ' + getCompilerDefines() + '\n') fout.write( 'CFLAGS = ' + self.Configs.getCflags() + ' $(DEFINES)\n') fout.write( 'CXXFLAGS = ' + self.Configs.getCxxflags() + ' $(DEFINES)\n') fout.write( 'AFLAGS = ' + self.Configs.getAflags() + '\n' ) fout.write( 'LFLAGS = ' + self.Configs.getLflags() + '\n\n\n' ) fout.write( 'RM = ' + self.Configs.getRmCmd() + '\n\n\n' ) fout.write( 'OBJECTS = \\\n' ) for src in sourceFiles: src = str(src) folder, objname = os.path.split( src[:src.rfind('.')] + '.o' ) if folder.find('libraries')!=0 and folder.find('hardware')!=0: folder = 'user' objdir = os.path.join(outPath, 'obj', folder) if not os.path.exists(objdir): os.makedirs( objdir ) obj = '$(OUTPUT_DIR)/obj/' + folder + '/' + objname fout.write( '\t' + obj + ' \\\n' ) objects.append(obj) fout.write( '\n\n' ) fout.write( 'all : $(OBJECTS)\n' ) fout.write( '\t@echo [LINK] $(notdir $(ELF_FILE))\n\t') if not verbose: fout.write( '@' ) fout.write( '$(TCHAIN)g++ $(LFLAGS) $^ -o $(ELF_FILE)\n' ) fout.write( '\t@echo [HEX] $(notdir $(HEX_FILE))\n') fout.write( '\t@$(TCHAIN)objcopy -O ihex -R .eeprom -R .fuse -R .lock -R .signature $(ELF_FILE) $(HEX_FILE)\n' ) fout.write( '\t@$(TCHAIN)size $(ELF_FILE)\n\n' ) fout.write( 'clean:\n' ) fout.write( '\t@$(RM) $(OBJECTS)\n' ) fout.write( '\t@$(RM) $(ELF_FILE) $(HEX_FILE) $(MAP_FILE)\n\n\n' ) fout.write( 'program: $(HEX_FILE)\n' ) fout.write( '\tbatchisp -device at32$(MCUPART) -hardware RS232 -port $(COMPORT) ' ) fout.write( '-operation erase f memory flash blankcheck loadbuffer $(HEX_FILE) ' ) fout.write( 'program verify start reset 0\n\n\n' ) i = 0 for src in sourceFiles: src = str(src) fout.write( objects[i] + ' : ' + src + '\n') src_ext = os.path.splitext(src)[1].lower() if src_ext == USER_CODE_EXT: fout.write( '\t@echo [CXX] $< \n\t' ) if not verbose: fout.write( '@' ) fout.write( '$(TCHAIN)g++ $(INCLUDES) $(CXXFLAGS) -x c++ $< -o $@\n\n') elif src_ext == '.s': fout.write( '\t@echo [AS] $(<F)\n\t' ) if not verbose: fout.write( '@' ) fout.write( '$(TCHAIN)gcc -x assembler-with-cpp $(AFLAGS) $< -o $@\n\n') elif src_ext == '.c': fout.write( '\t@echo [CC] $(<F)\n\t' ) if not verbose: fout.write( '@' ) fout.write( '$(TCHAIN)gcc $(INCLUDES) $(CFLAGS) $< -o $@\n\n') elif src_ext == '.cpp': fout.write( '\t@echo [CPP] $(<F)\n\t' ) if not verbose: fout.write( '@' ) fout.write( '$(TCHAIN)g++ $(INCLUDES) $(CXXFLAGS) $< -o $@\n\n') i += 1 fout.close() return True except: return False def getExpectedHexFileName(self, userCode=None): if not userCode: return None outpath = os.path.dirname( str(userCode) ) + '/' + OUT_DIR fname = os.path.basename( str(userCode) ) dotpos = fname.rfind('.') if dotpos > 0: hexfile = outpath + '/' + fname[:dotpos] + '.hex' else: hexfile = outpath + '/' + fname + '.hex' return hexfile
class PicCompilerThread(QtCore.QThread): ''' classdocs ''' def __init__(self, parent=None): QtCore.QThread.__init__(self, parent) self.parent = parent self.Configs = CompilerConfig(self) self.Configs.saveCompilerSettings() # platform dependent settings self.isWin32Platform = False if os.sys.platform == 'win32': self.isWin32Platform = True self.CC = self.Configs.getCompiler() self.cflags = self.Configs.getCflags() self.lflags = self.Configs.getLflags() self.CompilerCommands = None self.CompilerProcess = None # todo: use QtCore.QProcess class instead self.LogList = QtCore.QStringList() def run(self): if not self.CC: print 'no supported compiler!' return #print self.CC self.LogList.clear() bStop = False for command in self.CompilerCommands: if bStop: break try: arguments = [] for arg in command: arguments.append(arg) self.CompilerProcess = subprocess.Popen( arguments, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=self.isWin32Platform ) while True: self.usleep(50000) if not self.CompilerProcess: break; # read single lines buff = self.CompilerProcess.stdout.readline() if buff == '': # got nothing if self.CompilerProcess.poll() != None: # process exited self.CompilerProcess = None # print 'compiler process finished.' break else: msg = str(buff) msg_lowered = msg.lower() # string to QString if msg_lowered.find("warning") >= 0: self.LogList.append( "<font color=orange>%s</font>" % msg ) # todo: other error messages elif msg_lowered.find("error") >= 0 \ or msg_lowered.find("exit status = 1") >= 0 \ or msg_lowered.find("^ (") >= 0 \ or msg_lowered.find("defined") >= 0 \ or msg_lowered.find("conflicts with") >= 0 \ or msg_lowered.find("cannot find the path specified") >= 0 : self.LogList.append( "<font color=red>%s</font>" % msg ) bStop = True else: self.LogList.append( "<font color=green>%s</font>" % msg ) except: print 'got errors in compiler thread!' self.LogList.append( "<font color=red>%s</font>" % self.CC) self.CompilerProcess = None bStop = True self.CompilerCommands = None if bStop: self.LogList.append( "<font size=4 color=red>ERROR: build failed!</font>") else: self.LogList.append( "<font size=4 color=cyan>Done building.</font>") def getCompilerInfo(self): if self.isRunning(): return None self.CompilerCommands = [[ self.CC, '--ver' ]] # get version info self.start() while True: self.usleep(1000) if not self.isRunning(): break; if not self.LogList.count(): return None else: info = '' self.LogList.takeLast() for msg in self.LogList: info += msg return info def buildProject(self, userCode=None, boardName='', verbose=False): if self.isRunning(): return False, "busy" if not os.path.isfile(userCode): return False, "file not found" if boardName == 'Anito-877A': self.chip = '16F877A' elif boardName == 'Anito-4520': self.chip = '18F4520' else: return False, "board not supported" # output folder - same location with user code outpath = os.path.dirname( str(userCode) ) + '/' + OUT_DIR Result, Includes, Sources, Defines = parseUserCode( userCode, outpath + '/' + LIB_OUT_DIR ) # print Result, Includes, Sources, Defines if not Result: self.BuildProcess = None return False, "file write error" self.CompilerCommands = [] pcodeFiles = [] for i in range(len(Sources)): src = Sources[i] command = [ self.CC, '--CHIP=' + self.chip ] command += Includes command += Defines command += self.cflags.split(' ') if verbose: command += ['-V', '-V'] # 2 V's else: command += ['-Q'] if i==0: # user code command += ['--OUTDIR=' + outpath, src] self.CompilerCommands.append( [ '@echo', '[CC]', os.path.basename(str(userCode)) ] ) pcodeFiles.append( outpath + '/' + os.path.basename(src)[:-2] + '.p1' ) else: # separate folder for library intermediates ext = os.path.splitext(src)[1] if ext == '.as': command += ['--OUTDIR=' + outpath + '/' + LIB_OUT_DIR, src] self.CompilerCommands.append( [ '@echo', '[AS]', os.path.basename(src) ] ) pcodeFiles.append( outpath + '/' + LIB_OUT_DIR + '/' + os.path.basename(src)[:-3] + '.obj' ) else: command += ['--OUTDIR=' + outpath + '/' + LIB_OUT_DIR, src] self.CompilerCommands.append( [ '@echo', '[CC]', os.path.basename(src) ] ) pcodeFiles.append( outpath + '/' + LIB_OUT_DIR + '/' + os.path.basename(src)[:-2] + '.p1' ) self.CompilerCommands.append(command) self.CompilerCommands.append( [ '@echo', '[LD]', os.path.basename(str(userCode)) + '.hex' ] ) command = [ self.CC, '--CHIP=' + self.chip ] command += ['--OUTDIR=' + outpath] command += self.lflags.split(' ') if verbose: command += ['-V', '-V', '--TIME'] # 2 V's else: command += ['-Q'] command += pcodeFiles self.CompilerCommands.append(command) self.start() return True, "Build process running. Please wait..." def pollBuildProcess(self, stopProcess=False): if self.isRunning() or self.LogList.count()>0: if stopProcess: self.LogList.clear() try: self.CompilerProcess.kill() # needs Admin privilege on Windows! self.CompilerProcess = None self.exit() return True, "killed" except: print "n0 u can't kill me! :-p" self.CompilerProcess.wait() # just wait for the process to finish self.CompilerProcess = None self.exit() return False, "waited" if self.LogList.count(): return True, str(self.LogList.takeFirst()) else: return True, '' else: return False, "process not running" def getExpectedHexFileName(self, userCode=None): if not userCode: return None outpath = os.path.dirname( str(userCode) ) + '/' + OUT_DIR fname = os.path.basename( str(userCode) ) return outpath + '/' + fname + '.hex'