targets/toolchain_gcc.py
changeset 285 e5782a52dcea
parent 203 cb9901076a21
child 290 3bd617ae7a05
equal deleted inserted replaced
284:3fecc96090c8 285:e5782a52dcea
     1 import os
     1 import os, re, operator
     2 from wxPopen import ProcessLogger
     2 from wxPopen import ProcessLogger
     3 import hashlib
     3 import hashlib
       
     4 
       
     5 includes_re =  re.compile('\s*#include\s*["<]([^">]*)[">].*')
     4 
     6 
     5 class toolchain_gcc():
     7 class toolchain_gcc():
     6     """
     8     """
     7     This abstract class contains GCC specific code.
     9     This abstract class contains GCC specific code.
     8     It cannot be used as this and should be inherited in a target specific
    10     It cannot be used as this and should be inherited in a target specific
    13         self.logger = PuginsRootInstance.logger
    15         self.logger = PuginsRootInstance.logger
    14         self.exe = PuginsRootInstance.GetProjectName() + self.extension
    16         self.exe = PuginsRootInstance.GetProjectName() + self.extension
    15         self.buildpath = PuginsRootInstance._getBuildPath()
    17         self.buildpath = PuginsRootInstance._getBuildPath()
    16         self.exe_path = os.path.join(self.buildpath, self.exe)
    18         self.exe_path = os.path.join(self.buildpath, self.exe)
    17         self.md5key = None
    19         self.md5key = None
       
    20         self.srcmd5 = {}
    18 
    21 
    19     def GetBinaryCode(self):
    22     def GetBinaryCode(self):
    20         try:
    23         try:
    21             return open(self.exe_path, "rb").read()
    24             return open(self.exe_path, "rb").read()
    22         except Exception, e:
    25         except Exception, e:
    31         else:
    34         else:
    32             try:
    35             try:
    33                 return open(self._GetMD5FileName(), "r").read()
    36                 return open(self._GetMD5FileName(), "r").read()
    34             except Exception, e:
    37             except Exception, e:
    35                 return None
    38                 return None
       
    39 
       
    40     def check_and_update_hash_and_deps(self, bn):
       
    41         # Get latest computed hash and deps
       
    42         oldhash, deps = self.srcmd5.get(bn,(None,[]))
       
    43         # read source
       
    44         src = open(os.path.join(self.buildpath, bn)).read()
       
    45         # compute new hash
       
    46         newhash = hashlib.md5(src).hexdigest()
       
    47         # compare
       
    48         match = (oldhash == newhash)
       
    49         if not match:
       
    50             # file have changed
       
    51             # update direct dependencies
       
    52             deps = []
       
    53             for l in src.splitlines():
       
    54                 res = includes_re.match(l)
       
    55                 if res is not None:
       
    56                     depfn = res.groups()[0]
       
    57                     if os.path.exists(os.path.join(self.buildpath, depfn)):
       
    58                         #print bn + " depends on "+depfn
       
    59                         deps.append(depfn)
       
    60             # store that hashand deps
       
    61             self.srcmd5[bn] = (newhash, deps)
       
    62         # recurse through deps
       
    63         # TODO detect cicular deps.
       
    64         return reduce(operator.and_, map(self.check_and_update_hash_and_deps, deps), match)
    36                 
    65                 
    37     
       
    38     def build(self):
    66     def build(self):
    39         # Retrieve toolchain user parameters
    67         # Retrieve toolchain user parameters
    40         toolchain_params = self.PuginsRootInstance.BeremizRoot.getTargetType().getcontent()["value"]
    68         toolchain_params = self.PuginsRootInstance.BeremizRoot.getTargetType().getcontent()["value"]
    41         self.compiler = toolchain_params.getCompiler()
    69         self.compiler = toolchain_params.getCompiler()
    42         self._CFLAGS = toolchain_params.getCFLAGS()
    70         self._CFLAGS = toolchain_params.getCFLAGS()
    50             if Location:
    78             if Location:
    51                 self.logger.write("Plugin : " + self.PuginsRootInstance.GetChildByIECLocation(Location).GetCurrentName() + " " + str(Location)+"\n")
    79                 self.logger.write("Plugin : " + self.PuginsRootInstance.GetChildByIECLocation(Location).GetCurrentName() + " " + str(Location)+"\n")
    52             else:
    80             else:
    53                 self.logger.write("PLC :\n")
    81                 self.logger.write("PLC :\n")
    54                 
    82                 
       
    83             relink = False
    55             for CFile, CFLAGS in CFilesAndCFLAGS:
    84             for CFile, CFLAGS in CFilesAndCFLAGS:
    56                 bn = os.path.basename(CFile)
    85                 bn = os.path.basename(CFile)
    57                 obn = os.path.splitext(bn)[0]+".o"
    86                 obn = os.path.splitext(bn)[0]+".o"
       
    87                 objectfilename = os.path.splitext(CFile)[0]+".o"
       
    88 
       
    89                 match = self.check_and_update_hash_and_deps(bn)
       
    90                 
       
    91                 if match:
       
    92                     self.logger.write("   [pass]  "+bn+" -> "+obn+"\n")
       
    93                 else:
       
    94                     relink = True
       
    95 
       
    96                     self.logger.write("   [CC]  "+bn+" -> "+obn+"\n")
       
    97                     
       
    98                     status, result, err_result = ProcessLogger(
       
    99                            self.logger,
       
   100                            "\"%s\" -c \"%s\" -o \"%s\" %s %s"%
       
   101                                (self.compiler, CFile, objectfilename, self._CFLAGS, CFLAGS)
       
   102                            ).spin()
       
   103 
       
   104                     if status :
       
   105                         self.logger.write_error("C compilation of "+ bn +" failed.\n")
       
   106                         return False
       
   107 
    58                 obns.append(obn)
   108                 obns.append(obn)
    59                 self.logger.write("   [CC]  "+bn+" -> "+obn+"\n")
       
    60                 objectfilename = os.path.splitext(CFile)[0]+".o"
       
    61                 
       
    62                 status, result, err_result = ProcessLogger(
       
    63                        self.logger,
       
    64                        "\"%s\" -c \"%s\" -o \"%s\" %s %s"%
       
    65                            (self.compiler, CFile, objectfilename, self._CFLAGS, CFLAGS)
       
    66                        ).spin()
       
    67 
       
    68                 if status :
       
    69                     self.logger.write_error("C compilation of "+ bn +" failed.\n")
       
    70                     return False
       
    71                 objs.append(objectfilename)
   109                 objs.append(objectfilename)
    72 
   110 
    73         ######### GENERATE library FILE ########################################
   111         ######### GENERATE library FILE ########################################
    74         # Link all the object files into one binary file
   112         # Link all the object files into one binary file
    75         self.logger.write("Linking :\n")
   113         self.logger.write("Linking :\n")
    76         objstring = []
   114         if relink:
    77 
   115             objstring = []
    78         # Generate list .o files
   116     
    79         listobjstring = '"' + '"  "'.join(objs) + '"'
   117             # Generate list .o files
    80 
   118             listobjstring = '"' + '"  "'.join(objs) + '"'
    81         ALLldflags = ' '.join(self.CustomLDFLAGS+self.PuginsRootInstance.LDFLAGS+[self._LDFLAGS])
   119     
    82 
   120             ALLldflags = ' '.join(self.CustomLDFLAGS+self.PuginsRootInstance.LDFLAGS+[self._LDFLAGS])
    83         self.logger.write("   [CC]  " + ' '.join(obns)+" -> " + self.exe + "\n")
   121     
    84 
   122             self.logger.write("   [CC]  " + ' '.join(obns)+" -> " + self.exe + "\n")
    85         status, result, err_result = ProcessLogger(
   123     
    86                self.logger,
   124             status, result, err_result = ProcessLogger(
    87                "\"%s\" %s -o \"%s\" %s"%
   125                    self.logger,
    88                    (self.linker,
   126                    "\"%s\" %s -o \"%s\" %s"%
    89                     listobjstring,
   127                        (self.linker,
    90                     self.exe_path,
   128                         listobjstring,
    91                     ALLldflags)
   129                         self.exe_path,
    92                ).spin()
   130                         ALLldflags)
    93         
   131                    ).spin()
    94         if status :
   132             
    95             return False
   133             if status :
    96         else :
   134                 return False
    97             # Calculate md5 key and get data for the new created PLC
   135             else :
    98             data=self.GetBinaryCode()
   136                 # Calculate md5 key and get data for the new created PLC
    99             self.md5key = hashlib.md5(data).hexdigest()
   137                 data=self.GetBinaryCode()
   100 
   138                 self.md5key = hashlib.md5(data).hexdigest()
   101             # Store new PLC filename based on md5 key
   139     
   102             file = open(self._GetMD5FileName(), "w")
   140                 # Store new PLC filename based on md5 key
   103             file.write(self.md5key)
   141                 f = open(self._GetMD5FileName(), "w")
   104             file.close()
   142                 f.write(self.md5key)
       
   143                 f.close()
       
   144         else:
       
   145             self.logger.write("   [pass]  " + ' '.join(obns)+" -> " + self.exe + "\n")
       
   146             
   105         
   147         
   106         return True
   148         return True
   107 
   149