Re-introduced toolchain_makefile.py. This time, it comes with a 'Generic' target, and a 'genericmake' example
authorEdouard Tisserant
Mon, 20 Jan 2014 11:04:19 +0100
changeset 1387 435965ca8b63
parent 1386 31c63a6248e1
child 1388 67c9a9482d24
Re-introduced toolchain_makefile.py. This time, it comes with a 'Generic' target, and a 'genericmake' example
ProjectController.py
targets/Generic/XSD
targets/Generic/__init__.py
targets/Generic/plc_Generic_main.c
targets/XSD_toolchain_makefile
targets/__init__.py
targets/toolchain_makefile.py
tests/genericmake/beremiz.xml
tests/genericmake/plc.xml
tests/genericmake/project_files/Makefile
--- a/ProjectController.py	Sun Jan 19 22:39:25 2014 +0100
+++ b/ProjectController.py	Mon Jan 20 11:04:19 2014 +0100
@@ -665,7 +665,7 @@
         # Keep track of generated C files for later use by self.CTNGenerate_C
         self.PLCGeneratedCFiles = C_files
         # compute CFLAGS for plc
-        self.plcCFLAGS = "\"-I"+self.ieclib_path+"\""
+        self.plcCFLAGS = "-I"+self.ieclib_path
         return True
 
     def GetBuilder(self):
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/targets/Generic/XSD	Mon Jan 20 11:04:19 2014 +0100
@@ -0,0 +1,6 @@
+
+                  <xsd:element name="Generic">
+                    <xsd:complexType>
+                      %(toolchain_makefile)s
+                    </xsd:complexType>
+                  </xsd:element>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/targets/Generic/__init__.py	Mon Jan 20 11:04:19 2014 +0100
@@ -0,0 +1,4 @@
+from ..toolchain_makefile import toolchain_makefile
+
+class Generic_target(toolchain_makefile):
+    pass
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/targets/Generic/plc_Generic_main.c	Mon Jan 20 11:04:19 2014 +0100
@@ -0,0 +1,4 @@
+/**
+ * No platform specific code for "Generic" target
+ **/
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/targets/XSD_toolchain_makefile	Mon Jan 20 11:04:19 2014 +0100
@@ -0,0 +1,3 @@
+
+          <xsd:attribute name="Command" type="xsd:string" use="optional" default="make -C %(buildpath)s all BEREMIZSRC=%(src)s BEREMIZCFLAGS=%(cflags)s MD5=%(md5)s USE_BEREMIZ=1 FROM_BEREMIZ=1"/>
+          
--- a/targets/__init__.py	Sun Jan 19 22:39:25 2014 +0100
+++ b/targets/__init__.py	Mon Jan 20 11:04:19 2014 +0100
@@ -43,7 +43,8 @@
                     if path.isdir(path.join(_base_path, name)) 
                        and not name.startswith("__")])
 
-toolchains = {"gcc":  path.join(_base_path, "XSD_toolchain_gcc")}
+toolchains = {"gcc":  path.join(_base_path, "XSD_toolchain_gcc"),
+              "makefile":  path.join(_base_path, "XSD_toolchain_makefile")}
 
 def GetBuilder(targetname):
     return targets[targetname]["class"]()
@@ -55,10 +56,8 @@
     # Get all xsd toolchains
     for toolchainname,xsdfilename in toolchains.iteritems() :
          if path.isfile(xsdfilename):
-             xsd_toolchain_string = ""
-             for line in open(xsdfilename).readlines():
-                 xsd_toolchain_string += line
-             DictXSD_toolchain["toolchain_"+toolchainname] = xsd_toolchain_string
+             DictXSD_toolchain["toolchain_"+toolchainname] = \
+                open(xsdfilename).read()
 
     # Get all xsd targets 
     for targetname,nfo in targets.iteritems():
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/targets/toolchain_makefile.py	Mon Jan 20 11:04:19 2014 +0100
@@ -0,0 +1,105 @@
+import os, re, operator
+from util.ProcessLogger import ProcessLogger
+import hashlib
+
+import time
+
+includes_re =  re.compile('\s*#include\s*["<]([^">]*)[">].*')
+
+class toolchain_makefile():
+    def __init__(self, CTRInstance):
+        self.CTRInstance = CTRInstance
+        self.md5key = None 
+        self.buildpath = None
+        self.SetBuildPath(self.CTRInstance._getBuildPath())
+
+    def SetBuildPath(self, buildpath):
+        if self.buildpath != buildpath:
+            self.buildpath = buildpath
+            self.md5key = None
+
+    def GetBinaryCode(self):
+        return None
+
+    def _GetMD5FileName(self):
+        return os.path.join(self.buildpath, "lastbuildPLC.md5")
+
+    def ResetBinaryCodeMD5(self):
+        self.md5key = None
+        try:
+            os.remove(self._GetMD5FileName())
+        except Exception, e:
+            pass
+
+    def GetBinaryCodeMD5(self):
+        if self.md5key is not None:
+            return self.md5key
+        else:
+            try:
+                return open(self._GetMD5FileName(), "r").read()
+            except IOError, e:
+                return None
+
+    def concat_deps(self, bn):
+        # read source
+        src = open(os.path.join(self.buildpath, bn),"r").read()
+        # update direct dependencies
+        deps = []
+        for l in src.splitlines():
+            res = includes_re.match(l)
+            if res is not None:
+                depfn = res.groups()[0]
+                if os.path.exists(os.path.join(self.buildpath, depfn)):
+                    #print bn + " depends on "+depfn
+                    deps.append(depfn)
+        # recurse through deps
+        # TODO detect cicular deps.
+        return reduce(operator.concat, map(self.concat_deps, deps), src)
+
+    def build(self):
+        srcfiles= []
+        cflags = []
+        wholesrcdata = "" 
+        for Location, CFilesAndCFLAGS, DoCalls in self.CTRInstance.LocationCFilesAndCFLAGS:
+            # Get CFiles list to give it to makefile
+            for CFile, CFLAGS in CFilesAndCFLAGS:
+                CFileName = os.path.basename(CFile)
+                wholesrcdata += self.concat_deps(CFileName)
+                srcfiles.append(CFileName)
+                if CFLAGS not in cflags:
+                    cflags.append(CFLAGS)
+                        
+        oldmd5 = self.md5key
+        self.md5key = hashlib.md5(wholesrcdata).hexdigest()
+        props = self.CTRInstance.GetProjectProperties()
+        self.md5key += '#'.join([props[key] for key in ['companyName',
+                                                        'projectName',
+                                                        'productName']])
+        self.md5key += '#' #+','.join(map(str,time.localtime()))
+        # Store new PLC filename based on md5 key
+        f = open(self._GetMD5FileName(), "w")
+        f.write(self.md5key)
+        f.close()
+
+        if oldmd5 != self.md5key :
+            target = self.CTRInstance.GetTarget().getcontent()
+            beremizcommand = {"src": ' '.join(srcfiles),
+                              "cflags": ' '.join(cflags),
+                              "md5": self.md5key,
+                              "buildpath": self.buildpath
+                             }
+            
+            command = [ token % beremizcommand for token in target.getCommand().split(' ')]
+
+            # Call Makefile to build PLC code and link it with target specific code
+            status, result, err_result = ProcessLogger(self.CTRInstance.logger,
+                                                       command).spin()
+            if status :
+                self.md5key = None
+                self.CTRInstance.logger.write_error(_("C compilation failed.\n"))
+                return False
+            return True
+        else :
+            self.CTRInstance.logger.write(_("Source didn't change, no build.\n"))
+            return True
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/genericmake/beremiz.xml	Mon Jan 20 11:04:19 2014 +0100
@@ -0,0 +1,7 @@
+<?xml version='1.0' encoding='utf-8'?>
+<BeremizRoot xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+  <TargetType>
+    <Generic Command="make -C %(buildpath)s -f ../project_files/Makefile all BEREMIZSRC=%(src)s BEREMIZCFLAGS=%(cflags)s MD5=%(md5)s USE_BEREMIZ=1 FROM_BEREMIZ=1"/>
+  </TargetType>
+  <Libraries Enable_Native_Library="false" Enable_Python_Library="false" Enable_SVGUI_Library="false"/>
+</BeremizRoot>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/genericmake/plc.xml	Mon Jan 20 11:04:19 2014 +0100
@@ -0,0 +1,73 @@
+<?xml version='1.0' encoding='utf-8'?>
+<project xmlns:ns1="http://www.plcopen.org/xml/tc6_0201" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.plcopen.org/xml/tc6_0201">
+  <fileHeader companyName="Unknown" productName="Unnamed" productVersion="1" creationDateTime="2014-01-19T11:14:47"/>
+  <contentHeader name="Unnamed" modificationDateTime="2014-01-20T01:37:01">
+    <coordinateInfo>
+      <fbd>
+        <scaling x="0" y="0"/>
+      </fbd>
+      <ld>
+        <scaling x="0" y="0"/>
+      </ld>
+      <sfc>
+        <scaling x="0" y="0"/>
+      </sfc>
+    </coordinateInfo>
+  </contentHeader>
+  <types>
+    <dataTypes/>
+    <pous>
+      <pou name="program0" pouType="program">
+        <interface>
+          <localVars>
+            <variable name="LocalVara">
+              <type>
+                <INT/>
+              </type>
+            </variable>
+            <variable name="LocalVarb">
+              <type>
+                <INT/>
+              </type>
+            </variable>
+          </localVars>
+        </interface>
+        <body>
+          <FBD>
+            <inVariable localId="1" executionOrderId="0" height="27" width="77" negated="false">
+              <position x="196" y="224"/>
+              <connectionPointOut>
+                <relPosition x="77" y="13"/>
+              </connectionPointOut>
+              <expression>LocalVara</expression>
+            </inVariable>
+            <outVariable localId="2" executionOrderId="0" height="27" width="77" negated="false">
+              <position x="305" y="227"/>
+              <connectionPointIn>
+                <relPosition x="0" y="13"/>
+                <connection refLocalId="1">
+                  <position x="305" y="240"/>
+                  <position x="288" y="240"/>
+                  <position x="288" y="237"/>
+                  <position x="273" y="237"/>
+                </connection>
+              </connectionPointIn>
+              <expression>LocalVarb</expression>
+            </outVariable>
+          </FBD>
+        </body>
+      </pou>
+    </pous>
+  </types>
+  <instances>
+    <configurations>
+      <configuration name="config">
+        <resource name="resource1">
+          <task name="Tsk" priority="0" interval="T#100ms">
+            <pouInstance name="Inst" typeName="program0"/>
+          </task>
+        </resource>
+      </configuration>
+    </configurations>
+  </instances>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/genericmake/project_files/Makefile	Mon Jan 20 11:04:19 2014 +0100
@@ -0,0 +1,13 @@
+BEREMIZ_OBJS = $(BEREMIZSRC:.c=.o)
+
+all: warn some_binary
+	@echo "*** all done ***"
+
+warn:
+	@echo "*** Sample Makefile, does nothing ***"
+
+some_binary: $(BEREMIZ_OBJS)
+	@echo "* Would link $^ -> $@"
+
+%o : %c
+	@echo "* Would compile $< -> $@"