Edouard@1: import os, re, operator Edouard@1: from util.ProcessLogger import ProcessLogger Edouard@1: import hashlib Edouard@1: Edouard@1: import time Edouard@1: Edouard@1: includes_re = re.compile('\s*#include\s*["<]([^">]*)[">].*') Edouard@1: Edouard@1: class toolchain_makefile(): Edouard@1: def __init__(self, CTRInstance): Edouard@1: self.CTRInstance = CTRInstance Edouard@1: self.md5key = None Edouard@1: self.buildpath = None Edouard@1: self.SetBuildPath(self.CTRInstance._getBuildPath()) Edouard@1: Edouard@1: def SetBuildPath(self, buildpath): Edouard@1: if self.buildpath != buildpath: Edouard@1: self.buildpath = buildpath Edouard@1: self.md5key = None Edouard@1: Edouard@1: def GetBinaryCode(self): Edouard@1: return None Edouard@1: Edouard@1: def _GetMD5FileName(self): Edouard@1: return os.path.join(self.buildpath, "lastbuildPLC.md5") Edouard@1: Edouard@1: def ResetBinaryCodeMD5(self): Edouard@1: self.md5key = None Edouard@1: try: Edouard@1: os.remove(self._GetMD5FileName()) Edouard@1: except Exception, e: Edouard@1: pass Edouard@1: Edouard@1: def GetBinaryCodeMD5(self): Edouard@1: if self.md5key is not None: Edouard@1: return self.md5key Edouard@1: else: Edouard@1: try: Edouard@1: return open(self._GetMD5FileName(), "r").read() Edouard@1: except IOError, e: Edouard@1: return None Edouard@1: Edouard@1: def concat_deps(self, bn): Edouard@1: # read source Edouard@1: src = open(os.path.join(self.buildpath, bn),"r").read() Edouard@1: # update direct dependencies Edouard@1: deps = [] Edouard@1: for l in src.splitlines(): Edouard@1: res = includes_re.match(l) Edouard@1: if res is not None: Edouard@1: depfn = res.groups()[0] Edouard@1: if os.path.exists(os.path.join(self.buildpath, depfn)): Edouard@1: #print bn + " depends on "+depfn Edouard@1: deps.append(depfn) Edouard@1: # recurse through deps Edouard@1: # TODO detect cicular deps. Edouard@1: return reduce(operator.concat, map(self.concat_deps, deps), src) Edouard@1: Edouard@1: def build(self): Edouard@1: srcfiles= [] Edouard@1: cflags = [] Edouard@1: wholesrcdata = "" Edouard@1: for Location, CFilesAndCFLAGS, DoCalls in self.CTRInstance.LocationCFilesAndCFLAGS: Edouard@1: # Get CFiles list to give it to makefile Edouard@1: for CFile, CFLAGS in CFilesAndCFLAGS: Edouard@1: CFileName = os.path.basename(CFile) Edouard@1: wholesrcdata += self.concat_deps(CFileName) Edouard@1: #wholesrcdata += open(CFile, "r").read() Edouard@1: srcfiles.append(CFileName) Edouard@1: if CFLAGS not in cflags: Edouard@1: cflags.append(CFLAGS) Edouard@1: Edouard@1: oldmd5 = self.md5key Edouard@1: self.md5key = hashlib.md5(wholesrcdata).hexdigest() Edouard@1: props = self.CTRInstance.GetProjectProperties() Edouard@1: self.md5key += '#'.join([props[key] for key in ['companyName', Edouard@1: 'projectName', Edouard@1: 'productName']]) Edouard@1: self.md5key += '#' #+','.join(map(str,time.localtime())) Edouard@1: # Store new PLC filename based on md5 key Edouard@1: f = open(self._GetMD5FileName(), "w") Edouard@1: f.write(self.md5key) Edouard@1: f.close() Edouard@1: Edouard@1: if oldmd5 != self.md5key : Edouard@1: beremizcommand = {"src": ' '.join(srcfiles), Edouard@1: "cflags": ' '.join(cflags), Edouard@1: "md5": '"'+self.md5key+'"' Edouard@1: } Edouard@1: Edouard@1: target = self.CTRInstance.GetTarget().getcontent()["value"] Edouard@1: command = target.getCommand().split(' ') +\ Edouard@1: [target.getBuildPath()] +\ Edouard@1: [arg % beremizcommand for arg in target.getArguments().split(' ')] +\ Edouard@1: target.getRule().split(' ') Edouard@1: Edouard@1: # Call Makefile to build PLC code and link it with target specific code Edouard@1: status, result, err_result = ProcessLogger(self.CTRInstance.logger, Edouard@1: command).spin() Edouard@1: if status : Edouard@1: self.md5key = None Edouard@1: self.CTRInstance.logger.write_error(_("C compilation failed.\n")) Edouard@1: return False Edouard@1: return True Edouard@1: else : Edouard@1: self.CTRInstance.logger.write(_("Source didn't change, no build.\n")) Edouard@1: return True Edouard@1: