158 return [],"" |
158 return [],"" |
159 |
159 |
160 def _Generate_C(self, buildpath, locations, logger): |
160 def _Generate_C(self, buildpath, locations, logger): |
161 # Generate plugins [(Cfiles, CFLAGS)], LDFLAGS |
161 # Generate plugins [(Cfiles, CFLAGS)], LDFLAGS |
162 PlugCFilesAndCFLAGS, PlugLDFLAGS = self.PlugGenerate_C(buildpath, locations, logger) |
162 PlugCFilesAndCFLAGS, PlugLDFLAGS = self.PlugGenerate_C(buildpath, locations, logger) |
|
163 # if some files heve been generated put them in the list with their location |
|
164 if PlugCFilesAndCFLAGS: |
|
165 LocationCFilesAndCFLAGS = [(self.GetCurrentLocation(), PlugCFilesAndCFLAGS)] |
|
166 else: |
|
167 LocationCFilesAndCFLAGS = [] |
|
168 |
|
169 # plugin asks some some LDFLAGS |
|
170 if PlugLDFLAGS: |
|
171 # LDFLAGS can be either string |
|
172 if type(PlugLDFLAGS)==type(str()): |
|
173 LDFLAGS=[PlugLDFLAGS] |
|
174 #or list of strings |
|
175 elif type(PlugLDFLAGS)==type(list()): |
|
176 LDFLAGS=PlugLDFLAGS[:] |
|
177 else: |
|
178 LDFLAGS=[] |
|
179 |
163 # recurse through all childs, and stack their results |
180 # recurse through all childs, and stack their results |
164 for PlugChild in self.IterChilds(): |
181 for PlugChild in self.IECSortedChilds(): |
165 new_location = PlugChild.GetCurrentLocation() |
182 new_location = PlugChild.GetCurrentLocation() |
166 # How deep are we in the tree ? |
183 # How deep are we in the tree ? |
167 depth=len(new_location) |
184 depth=len(new_location) |
168 CFilesAndCFLAGS, LDFLAGS = \ |
185 _LocationCFilesAndCFLAGS, _LDFLAGS = \ |
169 PlugChild._Generate_C( |
186 PlugChild._Generate_C( |
170 #keep the same path |
187 #keep the same path |
171 buildpath, |
188 buildpath, |
172 # filter locations that start with current IEC location |
189 # filter locations that start with current IEC location |
173 [loc for loc in locations if loc["LOC"][0:depth] == new_location ], |
190 [loc for loc in locations if loc["LOC"][0:depth] == new_location ], |
174 #propagete logger |
191 #propagete logger |
175 logger) |
192 logger) |
176 # stack the result |
193 # stack the result |
177 PlugCFilesAndCFLAGS += CFilesAndCFLAGS |
194 LocationCFilesAndCFLAGS += _LocationCFilesAndCFLAGS |
178 PlugLDFLAGS += LDFLAGS |
195 LDFLAGS += _LDFLAGS |
179 |
196 |
180 return PlugCFilesAndCFLAGS,PlugLDFLAGS |
197 return LocationCFilesAndCFLAGS,LDFLAGS |
181 |
198 |
182 def BlockTypesFactory(self): |
199 def BlockTypesFactory(self): |
183 return [] |
200 return [] |
184 |
201 |
185 def STLibraryFactory(self): |
202 def STLibraryFactory(self): |
188 def IterChilds(self): |
205 def IterChilds(self): |
189 for PlugType, PluggedChilds in self.PluggedChilds.items(): |
206 for PlugType, PluggedChilds in self.PluggedChilds.items(): |
190 for PlugInstance in PluggedChilds: |
207 for PlugInstance in PluggedChilds: |
191 yield PlugInstance |
208 yield PlugInstance |
192 |
209 |
193 def _GetChildBySomething(self, sep, something, matching): |
210 def IECSortedChilds(self): |
194 toks = matching.split(sep,1) |
211 # reorder childs by IEC_channels |
|
212 ordered = [(chld.BaseParams.getIEC_Channel(),chld) for chld in self.IterChilds()] |
|
213 if ordered: |
|
214 ordered.sort() |
|
215 return zip(*ordered)[1] |
|
216 else: |
|
217 return [] |
|
218 |
|
219 def _GetChildBySomething(self, something, toks): |
195 for PlugInstance in self.IterChilds(): |
220 for PlugInstance in self.IterChilds(): |
196 # if match component of the name |
221 # if match component of the name |
197 if getattr(PlugInstance.BaseParams, something) == toks[0]: |
222 if getattr(PlugInstance.BaseParams, something) == toks[0]: |
198 # if Name have other components |
223 # if Name have other components |
199 if len(toks) == 2: |
224 if len(toks) >= 2: |
200 # Recurse in order to find the latest object |
225 # Recurse in order to find the latest object |
201 return PlugInstance._GetChildBySomething( sep, something, toks[1]) |
226 return PlugInstance._GetChildBySomething( something, toks[1:]) |
202 # No sub name -> found |
227 # No sub name -> found |
203 return PlugInstance |
228 return PlugInstance |
204 # Not found |
229 # Not found |
205 return None |
230 return None |
206 |
231 |
207 def GetChildByName(self, Name): |
232 def GetChildByName(self, Name): |
208 return self._GetChildBySomething('.',"Name", Name) |
233 if Name: |
|
234 toks = Name.split('.') |
|
235 return self._GetChildBySomething("Name", toks) |
|
236 else: |
|
237 return self |
209 |
238 |
210 def GetChildByIECLocation(self, Location): |
239 def GetChildByIECLocation(self, Location): |
211 return self._GetChildBySomething('_',"IEC_Channel", Name) |
240 if Location: |
|
241 return self._GetChildBySomething("IEC_Channel", Location) |
|
242 else: |
|
243 return self |
212 |
244 |
213 def GetCurrentLocation(self): |
245 def GetCurrentLocation(self): |
214 """ |
246 """ |
215 @return: Tupple containing plugin IEC location of current plugin : %I0.0.4.5 => (0,0,4,5) |
247 @return: Tupple containing plugin IEC location of current plugin : %I0.0.4.5 => (0,0,4,5) |
216 """ |
248 """ |
217 return self.PlugParent.GetCurrentLocation() + (self.BaseParams.getIEC_Channel(),) |
249 return self.PlugParent.GetCurrentLocation() + (self.BaseParams.getIEC_Channel(),) |
|
250 |
|
251 def GetCurrentName(self): |
|
252 """ |
|
253 @return: String "ParentParentName.ParentName.Name" |
|
254 """ |
|
255 return self.PlugParent._GetCurrentName() + self.BaseParams.getName() |
|
256 |
|
257 def _GetCurrentName(self): |
|
258 """ |
|
259 @return: String "ParentParentName.ParentName.Name." |
|
260 """ |
|
261 return self.PlugParent._GetCurrentName() + self.BaseParams.getName() + "." |
218 |
262 |
219 def GetPlugRoot(self): |
263 def GetPlugRoot(self): |
220 return self.PlugParent.GetPlugRoot() |
264 return self.PlugParent.GetPlugRoot() |
221 |
265 |
222 def GetPlugInfos(self): |
266 def GetPlugInfos(self): |
223 childs = [] |
267 childs = [] |
224 # reorder childs by IEC_channels |
268 # reorder childs by IEC_channels |
225 ordered = [(chld.BaseParams.getIEC_Channel(),chld) for chld in self.IterChilds()] |
269 for child in self.IECSortedChilds(): |
226 if ordered: |
270 childs.append(child.GetPlugInfos()) |
227 ordered.sort() |
|
228 for child in zip(*ordered)[1]: |
|
229 childs.append(child.GetPlugInfos()) |
|
230 return {"name" : "%d-%s"%(self.BaseParams.getIEC_Channel(),self.BaseParams.getName()), "type" : self.BaseParams.getName(), "values" : childs} |
271 return {"name" : "%d-%s"%(self.BaseParams.getIEC_Channel(),self.BaseParams.getName()), "type" : self.BaseParams.getName(), "values" : childs} |
231 |
|
232 |
272 |
233 def FindNewName(self, DesiredName, logger): |
273 def FindNewName(self, DesiredName, logger): |
234 """ |
274 """ |
235 Changes Name to DesiredName if available, Name-N if not. |
275 Changes Name to DesiredName if available, Name-N if not. |
236 @param DesiredName: The desired Name (string) |
276 @param DesiredName: The desired Name (string) |
462 # For root object, available Childs Types are modules of the plugin packages. |
502 # For root object, available Childs Types are modules of the plugin packages. |
463 PlugChildsTypes = [(name, _GetClassFunction(name)) for name in plugins.__all__] |
503 PlugChildsTypes = [(name, _GetClassFunction(name)) for name in plugins.__all__] |
464 |
504 |
465 XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?> |
505 XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?> |
466 <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"> |
506 <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"> |
467 <xsd:simpleType name="Win32Compiler"> |
|
468 <xsd:restriction base="xsd:string"> |
|
469 <xsd:enumeration value="Cygwin"/> |
|
470 <xsd:enumeration value="MinGW"/> |
|
471 <xsd:enumeration value="VC++"/> |
|
472 </xsd:restriction> |
|
473 </xsd:simpleType> |
|
474 <xsd:element name="BeremizRoot"> |
507 <xsd:element name="BeremizRoot"> |
475 <xsd:complexType> |
508 <xsd:complexType> |
476 <xsd:element name="TargetType"> |
509 <xsd:element name="TargetType"> |
477 <xsd:complexType> |
510 <xsd:complexType> |
478 <xsd:choice> |
511 <xsd:choice> |
479 <xsd:element name="Win32"> |
512 <xsd:element name="Win32"> |
480 <xsd:complexType> |
513 <xsd:complexType> |
481 <xsd:attribute name="ToolChain" type="ppx:Win32Compiler" use="required" default="MinGW"/> |
|
482 <xsd:attribute name="Priority" type="xsd:integer" use="required"/> |
514 <xsd:attribute name="Priority" type="xsd:integer" use="required"/> |
483 </xsd:complexType> |
515 </xsd:complexType> |
484 </xsd:element> |
516 </xsd:element> |
485 <xsd:element name="Linux"> |
517 <xsd:element name="Linux"> |
486 <xsd:complexType> |
518 <xsd:complexType> |
487 <xsd:attribute name="Compiler" type="xsd:string" use="required" default="gcc"/> |
|
488 <xsd:attribute name="Nice" type="xsd:integer" use="required"/> |
519 <xsd:attribute name="Nice" type="xsd:integer" use="required"/> |
489 </xsd:complexType> |
520 </xsd:complexType> |
490 </xsd:element> |
521 </xsd:element> |
491 <xsd:element name="Xenomai"> |
522 <xsd:element name="Xenomai"> |
492 <xsd:complexType> |
523 <xsd:complexType> |
493 <xsd:attribute name="xeno-config" type="xsd:string" use="required" default="/usr/xenomai/"/> |
524 <xsd:attribute name="xeno-config" type="xsd:string" use="required" default="/usr/xenomai/"/> |
494 <xsd:attribute name="Compiler" type="xsd:string" use="required"/> |
|
495 <xsd:attribute name="Priority" type="xsd:integer" use="required"/> |
525 <xsd:attribute name="Priority" type="xsd:integer" use="required"/> |
496 </xsd:complexType> |
526 </xsd:complexType> |
497 </xsd:element> |
527 </xsd:element> |
498 <xsd:element name="RTAI"> |
528 <xsd:element name="RTAI"> |
499 <xsd:complexType> |
529 <xsd:complexType> |
500 <xsd:attribute name="xeno-config" type="xsd:string" use="required"/> |
530 <xsd:attribute name="rtai-config" type="xsd:string" use="required"/> |
501 <xsd:attribute name="Compiler" type="xsd:string" use="required"/> |
|
502 <xsd:attribute name="Priority" type="xsd:integer" use="required"/> |
531 <xsd:attribute name="Priority" type="xsd:integer" use="required"/> |
503 </xsd:complexType> |
532 </xsd:complexType> |
504 </xsd:element> |
533 </xsd:element> |
505 <xsd:element name="Library"> |
534 <xsd:element name="Library"> |
506 <xsd:complexType> |
535 <xsd:complexType> |
507 <xsd:attribute name="Dynamic" type="xsd:boolean" use="required" default="true"/> |
536 <xsd:attribute name="Dynamic" type="xsd:boolean" use="required" default="true"/> |
508 <xsd:attribute name="Compiler" type="xsd:string" use="required"/> |
|
509 </xsd:complexType> |
537 </xsd:complexType> |
510 </xsd:element> |
538 </xsd:element> |
511 </xsd:choice> |
539 </xsd:choice> |
512 </xsd:complexType> |
540 </xsd:complexType> |
513 </xsd:element> |
541 </xsd:element> |
|
542 <xsd:attribute name="Compiler" type="xsd:string" use="required" default="gcc"/> |
514 </xsd:complexType> |
543 </xsd:complexType> |
515 </xsd:element> |
544 </xsd:element> |
516 </xsd:schema> |
545 </xsd:schema> |
517 """ |
546 """ |
518 |
547 |
643 @param locations: List of complete variables locations \ |
678 @param locations: List of complete variables locations \ |
644 [(IEC_loc, IEC_Direction, IEC_Type, Name)]\ |
679 [(IEC_loc, IEC_Direction, IEC_Type, Name)]\ |
645 ex: [((0,0,4,5),'I','STRING','__IX_0_0_4_5'),...] |
680 ex: [((0,0,4,5),'I','STRING','__IX_0_0_4_5'),...] |
646 @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND |
681 @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND |
647 """ |
682 """ |
648 return [(C_file_name, "") for C_file_name in self.PLCGeneratedCFiles ] , "" |
683 return [(C_file_name, "-I"+ieclib_path) for C_file_name in self.PLCGeneratedCFiles ] , "" |
649 |
684 |
650 def _getBuildPath(self): |
685 def _getBuildPath(self): |
651 return os.path.join(self.ProjectPath, "build") |
686 return os.path.join(self.ProjectPath, "build") |
652 |
687 |
653 def _getIECcodepath(self): |
688 def _getIECcodepath(self): |
672 result = self.GenerateProgram(plc_file) |
707 result = self.GenerateProgram(plc_file) |
673 if not result: |
708 if not result: |
674 # Failed ! |
709 # Failed ! |
675 logger.write_error("Error : ST/IL/SFC code generator returned %d\n"%result) |
710 logger.write_error("Error : ST/IL/SFC code generator returned %d\n"%result) |
676 return False |
711 return False |
677 logger.write("Compiling ST Program in to C Program...\n") |
712 logger.write("Compiling IEC Program in to C code...\n") |
678 # Now compile IEC code into many C files |
713 # Now compile IEC code into many C files |
679 # files are listed to stdout, and errors to stderr. |
714 # files are listed to stdout, and errors to stderr. |
680 status, result, err_result = logger.LogCommand("%s %s -I %s %s"%(iec2cc_path, plc_file, ieclib_path, buildpath)) |
715 status, result, err_result = logger.LogCommand("%s %s -I %s %s"%(iec2cc_path, plc_file, ieclib_path, buildpath), no_stdout=True) |
681 if status: |
716 if status: |
682 # Failed ! |
717 # Failed ! |
683 logger.write_error("Error : IEC to C compiler returned %d\n"%status) |
718 logger.write_error("Error : IEC to C compiler returned %d\n"%status) |
684 return False |
719 return False |
685 # Now extract C files of stdout |
720 # Now extract C files of stdout |
732 # Generate SoftPLC code |
767 # Generate SoftPLC code |
733 if not self._Generate_SoftPLC(logger): |
768 if not self._Generate_SoftPLC(logger): |
734 logger.write_error("SoftPLC code generation failed !\n") |
769 logger.write_error("SoftPLC code generation failed !\n") |
735 return False |
770 return False |
736 |
771 |
737 logger.write("SoftPLC code generation successfull\n") |
772 #logger.write("SoftPLC code generation successfull\n") |
|
773 |
|
774 logger.write("Generating plugins code ...\n") |
738 |
775 |
739 # Generate C code and compilation params from plugin hierarchy |
776 # Generate C code and compilation params from plugin hierarchy |
740 try: |
777 try: |
741 CFilesAndCFLAGS, LDFLAGS = self._Generate_C( |
778 LocationCFilesAndCFLAGS,LDFLAGS = self._Generate_C( |
742 buildpath, |
779 buildpath, |
743 self.PLCGeneratedLocatedVars, |
780 self.PLCGeneratedLocatedVars, |
744 logger) |
781 logger) |
745 except Exception, msg: |
782 except Exception, msg: |
746 logger.write_error("Plugins code generation Failed !\n") |
783 logger.write_error("Plugins code generation Failed !\n") |
747 logger.write_error(str(msg)) |
784 logger.write_error(str(msg)) |
748 return False |
785 return False |
749 |
786 |
750 logger.write("Plugins code generation successfull\n") |
787 |
751 |
788 #debug |
|
789 #import pprint |
|
790 #pp = pprint.PrettyPrinter(indent=4) |
|
791 #logger.write("LocationCFilesAndCFLAGS :\n"+pp.pformat(LocationCFilesAndCFLAGS)+"\n") |
|
792 #logger.write("LDFLAGS :\n"+pp.pformat(LDFLAGS)+"\n") |
|
793 |
752 # Compile the resulting code into object files. |
794 # Compile the resulting code into object files. |
753 for CFile, CFLAG in CFilesAndCFLAGS: |
795 compiler = self.BeremizRoot.getCompiler() |
754 logger.write(str((CFile,CFLAG))) |
796 for Location, CFilesAndCFLAGS in LocationCFilesAndCFLAGS: |
|
797 if Location: |
|
798 logger.write("Plugin : " + self.GetChildByIECLocation(Location).GetCurrentName() + " " + str(Location)+"\n") |
|
799 else: |
|
800 logger.write("PLC :\n") |
|
801 |
|
802 for CFile, CFLAGS in CFilesAndCFLAGS: |
|
803 bn = os.path.basename(CFile) |
|
804 logger.write(" [CC] "+bn+" -> "+os.path.splitext(bn)[0]+".o\n") |
|
805 objectfilename = os.path.splitext(bn)[0]+".o" |
|
806 status, result, err_result = logger.LogCommand("%s -c %s -o %s %s"%(compiler, CFile, objectfilename, CFLAGS)) |
|
807 |
755 |
808 |
756 # Link object files into something that can be executed on target |
809 # Link object files into something that can be executed on target |
757 logger.write(LDFLAGS) |
|
758 |
810 |
759 def _showIECcode(self, logger): |
811 def _showIECcode(self, logger): |
760 plc_file = self._getIECcodepath() |
812 plc_file = self._getIECcodepath() |
761 new_dialog = wx.Frame(None) |
813 new_dialog = wx.Frame(None) |
762 ST_viewer = TextViewer(new_dialog, None, None) |
814 ST_viewer = TextViewer(new_dialog, None, None) |