34 import time |
34 import time |
35 from time import localtime |
35 from time import localtime |
36 import shutil |
36 import shutil |
37 import re |
37 import re |
38 import tempfile |
38 import tempfile |
|
39 import hashlib |
39 from datetime import datetime |
40 from datetime import datetime |
40 from weakref import WeakKeyDictionary |
41 from weakref import WeakKeyDictionary |
41 from functools import reduce |
42 from functools import reduce |
42 from itertools import izip |
43 from itertools import izip |
43 from distutils.dir_util import copy_tree |
44 from distutils.dir_util import copy_tree |
274 self.previous_plcstate = None |
275 self.previous_plcstate = None |
275 # copy StatusMethods so that it can be later customized |
276 # copy StatusMethods so that it can be later customized |
276 self.StatusMethods = [dic.copy() for dic in self.StatusMethods] |
277 self.StatusMethods = [dic.copy() for dic in self.StatusMethods] |
277 self.DebugToken = None |
278 self.DebugToken = None |
278 self.debug_status = PlcStatus.Stopped |
279 self.debug_status = PlcStatus.Stopped |
|
280 |
|
281 self.IECcodeDigest = None |
|
282 self.LastBuiltIECcodeDigest = None |
279 |
283 |
280 def __del__(self): |
284 def __del__(self): |
281 self.KillDebugThread() |
285 self.KillDebugThread() |
282 |
286 |
283 def LoadLibraries(self): |
287 def LoadLibraries(self): |
777 if len(errors) > 0: |
781 if len(errors) > 0: |
778 # Failed ! |
782 # Failed ! |
779 self.logger.write_error( |
783 self.logger.write_error( |
780 _("Error in ST/IL/SFC code generator :\n%s\n") % errors[0]) |
784 _("Error in ST/IL/SFC code generator :\n%s\n") % errors[0]) |
781 return False |
785 return False |
782 plc_file = open(self._getIECcodepath(), "w") |
786 |
783 # Add ST Library from confnodes |
787 # Add ST Library from confnodes |
784 plc_file.write(self.GetLibrariesSTCode()) |
788 IECCodeContent = self.GetLibrariesSTCode() |
785 if os.path.isfile(self._getIECrawcodepath()): |
789 |
786 plc_file.write(open(self._getIECrawcodepath(), "r").read()) |
790 IECrawcodepath = self._getIECrawcodepath() |
787 plc_file.write("\n") |
791 if os.path.isfile(IECrawcodepath): |
788 plc_file.close() |
792 IECCodeContent += open(IECrawcodepath, "r").read() + "\n" |
789 plc_file = open(self._getIECcodepath(), "r") |
793 |
790 self.ProgramOffset = 0 |
794 |
791 for dummy in plc_file.readlines(): |
795 # Compute offset before ST resulting of transformation from user POUs |
792 self.ProgramOffset += 1 |
796 self.ProgramOffset = IECCodeContent.count("\n") |
793 plc_file.close() |
797 |
794 plc_file = open(self._getIECcodepath(), "a") |
798 IECCodeContent += open(self._getIECgeneratedcodepath(), "r").read() |
795 plc_file.write(open(self._getIECgeneratedcodepath(), "r").read()) |
799 |
796 plc_file.close() |
800 with open(self._getIECcodepath(), "w") as plc_file: |
|
801 plc_file.write(IECCodeContent) |
|
802 |
|
803 hasher = hashlib.md5() |
|
804 hasher.update(IECCodeContent) |
|
805 self.IECcodeDigest = hasher.hexdigest() |
|
806 |
797 return True |
807 return True |
798 |
808 |
799 def _Compile_ST_to_SoftPLC(self): |
809 def _Compile_ST_to_SoftPLC(self): |
800 iec2c_libpath = self.iec2c_cfg.getLibPath() |
810 iec2c_libpath = self.iec2c_cfg.getLibPath() |
801 if iec2c_libpath is None: |
811 if iec2c_libpath is None: |
802 self.logger.write_error(_("matiec installation is not found\n")) |
812 self.logger.write_error(_("matiec installation is not found\n")) |
803 return False |
813 return False |
|
814 |
|
815 if self.LastBuiltIECcodeDigest == self.IECcodeDigest: |
|
816 self.logger.write(_("IEC program did no change, not re-compiling into C code.\n")) |
|
817 return True |
804 |
818 |
805 self.logger.write(_("Compiling IEC Program into C code...\n")) |
819 self.logger.write(_("Compiling IEC Program into C code...\n")) |
806 buildpath = self._getBuildPath() |
820 buildpath = self._getBuildPath() |
807 buildcmd = "\"%s\" %s -I \"%s\" -T \"%s\" \"%s\"" % ( |
821 buildcmd = "\"%s\" %s -I \"%s\" -T \"%s\" \"%s\"" % ( |
808 self.iec2c_cfg.getCmd(), |
822 self.iec2c_cfg.getCmd(), |
887 self.PLCGeneratedLocatedVars = self.GetLocations() |
901 self.PLCGeneratedLocatedVars = self.GetLocations() |
888 # Keep track of generated C files for later use by self.CTNGenerate_C |
902 # Keep track of generated C files for later use by self.CTNGenerate_C |
889 self.PLCGeneratedCFiles = C_files |
903 self.PLCGeneratedCFiles = C_files |
890 # compute CFLAGS for plc |
904 # compute CFLAGS for plc |
891 self.plcCFLAGS = '"-I%s" -Wno-unused-function' % self.iec2c_cfg.getLibCPath() |
905 self.plcCFLAGS = '"-I%s" -Wno-unused-function' % self.iec2c_cfg.getLibCPath() |
|
906 |
|
907 self.LastBuiltIECcodeDigest = self.IECcodeDigest |
|
908 |
892 return True |
909 return True |
893 |
910 |
894 def GetBuilder(self): |
911 def GetBuilder(self): |
895 """ |
912 """ |
896 Return a Builder (compile C code into machine code) |
913 Return a Builder (compile C code into machine code) |