21 # |
21 # |
22 # You should have received a copy of the GNU General Public License |
22 # You should have received a copy of the GNU General Public License |
23 # along with this program; if not, write to the Free Software |
23 # along with this program; if not, write to the Free Software |
24 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
24 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
25 |
25 |
26 import os, re, operator |
26 import os |
|
27 import re |
|
28 import operator |
27 from util.ProcessLogger import ProcessLogger |
29 from util.ProcessLogger import ProcessLogger |
28 import hashlib |
30 import hashlib |
29 |
31 |
30 includes_re = re.compile('\s*#include\s*["<]([^">]*)[">].*') |
32 includes_re = re.compile('\s*#include\s*["<]([^">]*)[">].*') |
|
33 |
31 |
34 |
32 class toolchain_gcc(): |
35 class toolchain_gcc(): |
33 """ |
36 """ |
34 This abstract class contains GCC specific code. |
37 This abstract class contains GCC specific code. |
35 It cannot be used as this and should be inherited in a target specific |
38 It cannot be used as this and should be inherited in a target specific |
49 def getBuilderLDFLAGS(self): |
52 def getBuilderLDFLAGS(self): |
50 """ |
53 """ |
51 Returns list of builder specific LDFLAGS |
54 Returns list of builder specific LDFLAGS |
52 """ |
55 """ |
53 return self.CTRInstance.LDFLAGS + \ |
56 return self.CTRInstance.LDFLAGS + \ |
54 [self.CTRInstance.GetTarget().getcontent().getLDFLAGS()] |
57 [self.CTRInstance.GetTarget().getcontent().getLDFLAGS()] |
55 |
58 |
56 def getCompiler(self): |
59 def getCompiler(self): |
57 """ |
60 """ |
58 Returns compiler |
61 Returns compiler |
59 """ |
62 """ |
60 return self.CTRInstance.GetTarget().getcontent().getCompiler() |
63 return self.CTRInstance.GetTarget().getcontent().getCompiler() |
61 |
64 |
62 def getLinker(self): |
65 def getLinker(self): |
63 """ |
66 """ |
64 Returns linker |
67 Returns linker |
65 """ |
68 """ |
66 return self.CTRInstance.GetTarget().getcontent().getLinker() |
69 return self.CTRInstance.GetTarget().getcontent().getLinker() |
67 |
70 |
68 def GetBinaryCode(self): |
71 def GetBinaryCode(self): |
69 try: |
72 try: |
70 return open(self.exe_path, "rb").read() |
73 return open(self.exe_path, "rb").read() |
71 except Exception, e: |
74 except Exception, e: |
72 return None |
75 return None |
73 |
76 |
74 def _GetMD5FileName(self): |
77 def _GetMD5FileName(self): |
75 return os.path.join(self.buildpath, "lastbuildPLC.md5") |
78 return os.path.join(self.buildpath, "lastbuildPLC.md5") |
76 |
79 |
77 def ResetBinaryCodeMD5(self): |
80 def ResetBinaryCodeMD5(self): |
78 self.md5key = None |
81 self.md5key = None |
79 try: |
82 try: |
80 os.remove(self._GetMD5FileName()) |
83 os.remove(self._GetMD5FileName()) |
81 except Exception, e: |
84 except Exception, e: |
82 pass |
85 pass |
83 |
86 |
84 def GetBinaryCodeMD5(self): |
87 def GetBinaryCodeMD5(self): |
85 if self.md5key is not None: |
88 if self.md5key is not None: |
86 return self.md5key |
89 return self.md5key |
87 else: |
90 else: |
88 try: |
91 try: |
89 return open(self._GetMD5FileName(), "r").read() |
92 return open(self._GetMD5FileName(), "r").read() |
90 except Exception, e: |
93 except Exception, e: |
91 return None |
94 return None |
92 |
95 |
93 def SetBuildPath(self, buildpath): |
96 def SetBuildPath(self, buildpath): |
94 if self.buildpath != buildpath: |
97 if self.buildpath != buildpath: |
95 self.buildpath = buildpath |
98 self.buildpath = buildpath |
96 self.exe = self.CTRInstance.GetProjectName() + self.extension |
99 self.exe = self.CTRInstance.GetProjectName() + self.extension |
97 self.exe_path = os.path.join(self.buildpath, self.exe) |
100 self.exe_path = os.path.join(self.buildpath, self.exe) |
98 self.md5key = None |
101 self.md5key = None |
99 self.srcmd5 = {} |
102 self.srcmd5 = {} |
100 |
103 |
101 def append_cfile_deps(self, src, deps): |
104 def append_cfile_deps(self, src, deps): |
102 for l in src.splitlines(): |
105 for l in src.splitlines(): |
103 res = includes_re.match(l) |
106 res = includes_re.match(l) |
104 if res is not None: |
107 if res is not None: |
105 depfn = res.groups()[0] |
108 depfn = res.groups()[0] |
106 if os.path.exists(os.path.join(self.buildpath, depfn)): |
109 if os.path.exists(os.path.join(self.buildpath, depfn)): |
107 deps.append(depfn) |
110 deps.append(depfn) |
108 |
111 |
109 def concat_deps(self, bn): |
112 def concat_deps(self, bn): |
110 # read source |
113 # read source |
111 src = open(os.path.join(self.buildpath, bn),"r").read() |
114 src = open(os.path.join(self.buildpath, bn), "r").read() |
112 # update direct dependencies |
115 # update direct dependencies |
113 deps = [] |
116 deps = [] |
114 self.append_cfile_deps(src, deps) |
117 self.append_cfile_deps(src, deps) |
115 # recurse through deps |
118 # recurse through deps |
116 # TODO detect cicular deps. |
119 # TODO detect cicular deps. |
117 return reduce(operator.concat, map(self.concat_deps, deps), src) |
120 return reduce(operator.concat, map(self.concat_deps, deps), src) |
118 |
121 |
119 def check_and_update_hash_and_deps(self, bn): |
122 def check_and_update_hash_and_deps(self, bn): |
120 # Get latest computed hash and deps |
123 # Get latest computed hash and deps |
121 oldhash, deps = self.srcmd5.get(bn,(None,[])) |
124 oldhash, deps = self.srcmd5.get(bn, (None, [])) |
122 # read source |
125 # read source |
123 src = open(os.path.join(self.buildpath, bn)).read() |
126 src = open(os.path.join(self.buildpath, bn)).read() |
124 # compute new hash |
127 # compute new hash |
125 newhash = hashlib.md5(src).hexdigest() |
128 newhash = hashlib.md5(src).hexdigest() |
126 # compare |
129 # compare |
133 # store that hashand deps |
136 # store that hashand deps |
134 self.srcmd5[bn] = (newhash, deps) |
137 self.srcmd5[bn] = (newhash, deps) |
135 # recurse through deps |
138 # recurse through deps |
136 # TODO detect cicular deps. |
139 # TODO detect cicular deps. |
137 return reduce(operator.and_, map(self.check_and_update_hash_and_deps, deps), match) |
140 return reduce(operator.and_, map(self.check_and_update_hash_and_deps, deps), match) |
138 |
141 |
139 def calc_source_md5(self): |
142 def calc_source_md5(self): |
140 wholesrcdata = "" |
143 wholesrcdata = "" |
141 for Location, CFilesAndCFLAGS, DoCalls in self.CTRInstance.LocationCFilesAndCFLAGS: |
144 for Location, CFilesAndCFLAGS, DoCalls in self.CTRInstance.LocationCFilesAndCFLAGS: |
142 # Get CFiles list to give it to makefile |
145 # Get CFiles list to give it to makefile |
143 for CFile, CFLAGS in CFilesAndCFLAGS: |
146 for CFile, CFLAGS in CFilesAndCFLAGS: |
144 CFileName = os.path.basename(CFile) |
147 CFileName = os.path.basename(CFile) |
145 wholesrcdata += self.concat_deps(CFileName) |
148 wholesrcdata += self.concat_deps(CFileName) |
146 return hashlib.md5(wholesrcdata).hexdigest() |
149 return hashlib.md5(wholesrcdata).hexdigest() |
147 |
150 |
148 def calc_md5(self): |
151 def calc_md5(self): |
149 return hashlib.md5(self.GetBinaryCode()).hexdigest() |
152 return hashlib.md5(self.GetBinaryCode()).hexdigest() |
150 |
153 |
151 def build(self): |
154 def build(self): |
152 # Retrieve compiler and linker |
155 # Retrieve compiler and linker |
153 self.compiler = self.getCompiler() |
156 self.compiler = self.getCompiler() |
154 self.linker = self.getLinker() |
157 self.linker = self.getLinker() |
155 |
158 |
156 Builder_CFLAGS = ' '.join(self.getBuilderCFLAGS()) |
159 Builder_CFLAGS = ' '.join(self.getBuilderCFLAGS()) |
157 |
160 |
158 ######### GENERATE OBJECT FILES ######################################## |
161 # ----------------- GENERATE OBJECT FILES ------------------------ |
159 obns = [] |
162 obns = [] |
160 objs = [] |
163 objs = [] |
161 relink = self.GetBinaryCode() is None |
164 relink = self.GetBinaryCode() is None |
162 for Location, CFilesAndCFLAGS, DoCalls in self.CTRInstance.LocationCFilesAndCFLAGS: |
165 for Location, CFilesAndCFLAGS, DoCalls in self.CTRInstance.LocationCFilesAndCFLAGS: |
163 if CFilesAndCFLAGS: |
166 if CFilesAndCFLAGS: |
164 if Location : |
167 if Location: |
165 self.CTRInstance.logger.write(".".join(map(str,Location))+" :\n") |
168 self.CTRInstance.logger.write(".".join(map(str, Location))+" :\n") |
166 else: |
169 else: |
167 self.CTRInstance.logger.write(_("PLC :\n")) |
170 self.CTRInstance.logger.write(_("PLC :\n")) |
168 |
171 |
169 for CFile, CFLAGS in CFilesAndCFLAGS: |
172 for CFile, CFLAGS in CFilesAndCFLAGS: |
170 if CFile.endswith(".c"): |
173 if CFile.endswith(".c"): |
171 bn = os.path.basename(CFile) |
174 bn = os.path.basename(CFile) |
172 obn = os.path.splitext(bn)[0]+".o" |
175 obn = os.path.splitext(bn)[0]+".o" |
173 objectfilename = os.path.splitext(CFile)[0]+".o" |
176 objectfilename = os.path.splitext(CFile)[0]+".o" |
174 |
177 |
175 match = self.check_and_update_hash_and_deps(bn) |
178 match = self.check_and_update_hash_and_deps(bn) |
176 |
179 |
177 if match: |
180 if match: |
178 self.CTRInstance.logger.write(" [pass] "+bn+" -> "+obn+"\n") |
181 self.CTRInstance.logger.write(" [pass] "+bn+" -> "+obn+"\n") |
179 else: |
182 else: |
180 relink = True |
183 relink = True |
181 |
184 |
182 self.CTRInstance.logger.write(" [CC] "+bn+" -> "+obn+"\n") |
185 self.CTRInstance.logger.write(" [CC] "+bn+" -> "+obn+"\n") |
183 |
186 |
184 status, result, err_result = ProcessLogger( |
187 status, result, err_result = ProcessLogger( |
185 self.CTRInstance.logger, |
188 self.CTRInstance.logger, |
186 "\"%s\" -c \"%s\" -o \"%s\" %s %s"% |
189 "\"%s\" -c \"%s\" -o \"%s\" %s %s" % |
187 (self.compiler, CFile, objectfilename, Builder_CFLAGS, CFLAGS) |
190 (self.compiler, CFile, objectfilename, Builder_CFLAGS, CFLAGS) |
188 ).spin() |
191 ).spin() |
189 |
192 |
190 if status : |
193 if status: |
191 self.srcmd5.pop(bn) |
194 self.srcmd5.pop(bn) |
192 self.CTRInstance.logger.write_error(_("C compilation of %s failed.\n")%bn) |
195 self.CTRInstance.logger.write_error(_("C compilation of %s failed.\n") % bn) |
193 return False |
196 return False |
194 obns.append(obn) |
197 obns.append(obn) |
195 objs.append(objectfilename) |
198 objs.append(objectfilename) |
196 elif CFile.endswith(".o"): |
199 elif CFile.endswith(".o"): |
197 obns.append(os.path.basename(CFile)) |
200 obns.append(os.path.basename(CFile)) |
198 objs.append(CFile) |
201 objs.append(CFile) |
199 |
202 |
200 ######### GENERATE OUTPUT FILE ######################################## |
203 # ---------------- GENERATE OUTPUT FILE -------------------------- |
201 # Link all the object files into one binary file |
204 # Link all the object files into one binary file |
202 self.CTRInstance.logger.write(_("Linking :\n")) |
205 self.CTRInstance.logger.write(_("Linking :\n")) |
203 if relink: |
206 if relink: |
204 objstring = [] |
207 objstring = [] |
205 |
208 |
206 # Generate list .o files |
209 # Generate list .o files |
207 listobjstring = '"' + '" "'.join(objs) + '"' |
210 listobjstring = '"' + '" "'.join(objs) + '"' |
208 |
211 |
209 ALLldflags = ' '.join(self.getBuilderLDFLAGS()) |
212 ALLldflags = ' '.join(self.getBuilderLDFLAGS()) |
210 |
213 |
211 self.CTRInstance.logger.write(" [CC] " + ' '.join(obns)+" -> " + self.exe + "\n") |
214 self.CTRInstance.logger.write(" [CC] " + ' '.join(obns)+" -> " + self.exe + "\n") |
212 |
215 |
213 status, result, err_result = ProcessLogger( |
216 status, result, err_result = ProcessLogger( |
214 self.CTRInstance.logger, |
217 self.CTRInstance.logger, |
215 "\"%s\" %s -o \"%s\" %s"% |
218 "\"%s\" %s -o \"%s\" %s" % |
216 (self.linker, |
219 (self.linker, |
217 listobjstring, |
220 listobjstring, |
218 self.exe_path, |
221 self.exe_path, |
219 ALLldflags) |
222 ALLldflags) |
220 ).spin() |
223 ).spin() |
221 |
224 |
222 if status : |
225 if status: |
223 return False |
226 return False |
224 |
227 |
225 else: |
228 else: |
226 self.CTRInstance.logger.write(" [pass] " + ' '.join(obns)+" -> " + self.exe + "\n") |
229 self.CTRInstance.logger.write(" [pass] " + ' '.join(obns)+" -> " + self.exe + "\n") |
227 |
230 |
228 # Calculate md5 key and get data for the new created PLC |
231 # Calculate md5 key and get data for the new created PLC |
229 self.md5key = self.calc_md5() |
232 self.md5key = self.calc_md5() |
230 |
233 |
231 # Store new PLC filename based on md5 key |
234 # Store new PLC filename based on md5 key |
232 f = open(self._GetMD5FileName(), "w") |
235 f = open(self._GetMD5FileName(), "w") |
233 f.write(self.md5key) |
236 f.write(self.md5key) |
234 f.close() |
237 f.close() |
235 |
238 |
236 return True |
239 return True |
237 |
|