CoreValidation: Moved common parts of command line build script to Utilities.
diff --git a/CMSIS/CoreValidation/Examples/MDK-FVP/build.py b/CMSIS/CoreValidation/Examples/MDK-FVP/build.py
index 9045f8e..2a8a5ef 100644
--- a/CMSIS/CoreValidation/Examples/MDK-FVP/build.py
+++ b/CMSIS/CoreValidation/Examples/MDK-FVP/build.py
@@ -1,38 +1,52 @@
#! python
-from subprocess import call
-from xml.etree import ElementTree
-import os.path
+import sys
+from argparse import ArgumentParser
+from datetime import datetime
-print "Build CMSIS-Core Validation using MDK"
+sys.path.append('../../../Utilities/buildutils')
-TARGET_FVP = 'FVP'
+from uv4cmd import Uv4Cmd
+from fvpcmd import FvpCmd
+from testresult import TestResult
+
+DEVICE_CM0 = 'Cortex-M0'
+DEVICE_CM3 = 'Cortex-M3'
+DEVICE_CM4f = 'Cortex-M4f'
+DEVICE_CM7 = 'Cortex-M7'
+DEVICE_CM23 = 'Cortex-M23'
+DEVICE_CM33 = 'Cortex-M33'
+
CC_AC6 = 'AC6'
CC_AC5 = 'AC5'
CC_GCC = 'GCC'
-UV4 = "UV4.exe"
-PRJ = "CMSIS_CV.uvprojx"
-# DEVICES = [ 'Cortex-M0', 'Cortex-M3', 'Cortex-M4f', 'Cortex-M7', 'Cortex-M23', 'Cortex-M33' ]
-# DEVICES = [ 'Cortex-M0', 'Cortex-M3', 'Cortex-M4f', 'Cortex-M7' ]
-DEVICES = [ 'Cortex-M4f' ]
+TARGET_FVP = 'FVP'
+
+DEVICES = [ DEVICE_CM0, DEVICE_CM3, DEVICE_CM4f, DEVICE_CM7 ]
COMPILERS = [ CC_AC5, CC_AC6, CC_GCC ]
TARGETS = [ TARGET_FVP ]
-FVP_MODELS = {
- 'Cortex-M0' : [ "fvp_mps2_cortex-m0.exe", "--cyclelimit", "2000000", "" ],
- 'Cortex-M3' : [ "fvp_mps2_cortex-m3.exe", "--cyclelimit", "2000000", "" ],
- 'Cortex-M4f' : [ "fvp_mps2_cortex-m4.exe", "--cyclelimit", "5000000", "" ],
- 'Cortex-M7' : [ "fvp_mps2_cortex-m7.exe", "--cyclelimit", "5000000", "" ],
- 'Cortex-M23' : [ "fvp_mps2_cortex-m23.exe", "--cyclelimit", "10000000", "-f", "ARMCM23_TZ_config.txt", "-a", "cpu0=" ],
- 'Cortex-M33' : [ "fvp_mps2_cortex-m33.exe", "--cyclelimit", "10000000", "-f", "ARMCM33_DSP_FP_TZ_config.txt", "-a", "cpu0=" ]
- }
-
SKIP = [
- ['Cortex-M23', CC_GCC, None ],
- ['Cortex-M33', CC_GCC, None ]
+ [ DEVICE_CM23, CC_GCC, None ],
+ [ DEVICE_CM33, CC_GCC, None ]
]
+APP_FORMAT = {
+ CC_AC6: "axf",
+ CC_AC5: "axf",
+ CC_GCC: "elf"
+}
+
+FVP_MODELS = {
+ DEVICE_CM0 : { 'cmd': "fvp_mps2_cortex-m0.exe", 'args': { 'limit': "2000000" } },
+ DEVICE_CM3 : { 'cmd': "fvp_mps2_cortex-m3.exe", 'args': { 'limit': "2000000" } },
+ DEVICE_CM4f : { 'cmd': "fvp_mps2_cortex-m4.exe", 'args': { 'limit': "5000000" } },
+ DEVICE_CM7 : { 'cmd': "fvp_mps2_cortex-m7.exe", 'args': { 'limit': "5000000" } },
+ DEVICE_CM23 : { 'cmd': "fvp_mps2_cortex-m23.exe", 'args': { 'limit': "5000000", 'config': "ARMCM23_TZ_config.txt", 'target': "cpu0" } },
+ DEVICE_CM33 : { 'cmd': "fvp_mps2_cortex-m33.exe", 'args': { 'limit': "5000000", 'config': "ARMCM33_DSP_FP_TZ_config.txt", 'target': "cpu0" } }
+ }
+
def isSkipped(dev, cc, target):
for skip in SKIP:
skipDev = (skip[0] == None or skip[0] == dev)
@@ -42,95 +56,67 @@
return True
return False
-def ret2result(ret):
- if ret == 0:
- return "successfull"
- elif ret == 1:
- return "successfull with warnings"
- else:
- return "failed!"
+def prepare(steps, args):
+ for dev in args.devices:
+ for cc in args.compilers:
+ for target in args.targets:
+ if not isSkipped(dev, cc, target):
+ config = "{dev} ({cc}, {target})".format(dev = dev, cc = cc, target = target)
+ prefix = "{dev}_{cc}_{target}".format(dev = dev, cc = cc, target = target)
+ if args.execute_only:
+ build = None
+ else:
+ build = Uv4Cmd("CMSIS_CV.uvprojx", config)
+ if args.build_only:
+ test = None
+ else:
+ test = FvpCmd(FVP_MODELS[dev]['cmd'], "Objects\CMSIS_CV."+APP_FORMAT[cc], **FVP_MODELS[dev]['args'])
+ steps += [ { 'name': config, 'prefix': prefix, 'build': build, 'test': test } ]
-def binary(cc):
- if cc == CC_GCC:
- return 'Objects/CMSIS_CV.elf'
- else:
- return 'Objects/CMSIS_CV.axf'
-
-def build(dev, cc, target):
- print "Building..."
- config = "{dev} ({cc}, {target})".format(dev = dev, cc = cc, target = target)
- log = "build_{dev}_{cc}_{target}.log".format(dev = dev, cc = cc, target = target)
- print "{cmd} -t {config} -r {prj} -j0 -o {log}".format(cmd = UV4, config = config, prj = PRJ, log = log)
- try:
- ret = call([UV4, "-t", config, "-r", PRJ, "-j0", "-o", log])
- print open(log, "r").read()
- print "Build " + ret2result(ret)
- return (ret <= 1)
- except:
- print "Build failed!"
- return False
-
-def run(dev, cc, target):
- print "Running..."
- config = "{dev} ({cc}, {target})".format(dev = dev, cc = cc, target = target)
- log = "run_{dev}_{cc}_{target}.log".format(dev = dev, cc = cc, target = target)
- xml = "result_{dev}_{cc}_{target}.xml".format(dev = dev, cc = cc, target = target)
-
- if target == TARGET_FVP:
- model = FVP_MODELS[dev][:]
- app = binary(cc)
- model[-1] = model[-1] + app
- print ' '.join(model)
- logfile = open(log, "w")
- call(model, stdout=logfile)
-
- logfile = open(log, "r")
- xmlfile = open(xml, "w")
- dump = False
- for line in logfile:
- if dump:
- xmlfile.write(line)
- if line.strip() == "</report>":
- dump = False
+def execute(steps):
+ for step in steps:
+ print step['name']
+ if step['build']:
+ step['build'].run()
else:
- if line.strip() == "Simulation is started":
- dump = True
- print line,
+ print "Skipping build"
+
+ if (not step['build']) or step['build'].isSuccess():
+ step['test'].run()
+ step['result'] = TestResult(step['test'].getOutput())
+ step['result'].saveXml("result_{0}_{1}.xml".format(step['prefix'], datetime.now().strftime("%Y%m%d%H%M%S")))
+ else:
+ print "Skipping test"
+
+def printSummary(steps):
+ print ""
+ print "Test Summary"
+ print "============"
+ print
+ print "Test run Total Exec Pass Fail "
+ print "-------------------------------------------------------"
+ for step in steps:
+ try:
+ print "{0:30} {1:>4} {2:>4} {3:>4} {4:>4}".format(step['name'], *step['result'].getSummary())
+ except:
+ print "{0:30} ------ NO RESULTS ------".format(step['name'])
+
+def main(argv):
+ parser = ArgumentParser()
+ parser.add_argument('-b', '--build-only', action='store_true')
+ parser.add_argument('-e', '--execute-only', action='store_true')
+ parser.add_argument('-d', '--devices', nargs='*', choices=DEVICES, default=DEVICES, help = 'Devices to be considered.')
+ parser.add_argument('-c', '--compilers', nargs='*', choices=COMPILERS, default=COMPILERS, help = 'Compilers to be considered.')
+ parser.add_argument('-t', '--targets', nargs='*', choices=TARGETS, default=TARGETS, help = 'Targets to be considered.')
+ args = parser.parse_args()
+
+ steps = []
+
+ prepare(steps, args)
- return True
-
-for dev in DEVICES:
- for cc in COMPILERS:
- for target in TARGETS:
- if not isSkipped(dev, cc, target):
- print ""
- print "{dev} with {cc} on {target}".format(dev = dev, cc = cc, target = target)
- success = build(dev, cc, target)
- if success:
- run(dev, cc, target)
-
-# Test Summary
-print ""
-print "Test Summary"
-print "============"
-print
-print "Test run Total Exec Pass Fail "
-print "-------------------------------------------------------"
-for dev in DEVICES:
- for cc in COMPILERS:
- for target in TARGETS:
- name = "{dev} ({cc}, {target})".format(dev = dev, cc = cc, target = target)
- if isSkipped(dev, cc, target):
- print "{0:30} ------- skipped --------".format(name)
- else:
- try:
- xml = "result_{dev}_{cc}_{target}.xml".format(dev = dev, cc = cc, target = target)
- report = ElementTree.parse(xml).getroot()
- summary = report[0].findall('summary')[0]
- tests = summary.find('tcnt').text
- executed = summary.find('exec').text
- passed = summary.find('pass').text
- failed = summary.find('fail').text
- print "{0:30} {1:>4} {2:>4} {3:>4} {4:>4}".format(name, tests, executed, passed, failed)
- except:
- print "{0:30} ------ NO RESULTS ------".format(name)
+ execute(steps)
+
+ printSummary(steps)
+
+if __name__ == "__main__":
+ main(sys.argv[1:])
\ No newline at end of file
diff --git a/CMSIS/Utilities/buildutils/.gitignore b/CMSIS/Utilities/buildutils/.gitignore
new file mode 100644
index 0000000..7e99e36
--- /dev/null
+++ b/CMSIS/Utilities/buildutils/.gitignore
@@ -0,0 +1 @@
+*.pyc
\ No newline at end of file
diff --git a/CMSIS/Utilities/buildutils/__init__.py b/CMSIS/Utilities/buildutils/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/CMSIS/Utilities/buildutils/__init__.py
diff --git a/CMSIS/Utilities/buildutils/buildcmd.py b/CMSIS/Utilities/buildutils/buildcmd.py
new file mode 100644
index 0000000..ceabe64
--- /dev/null
+++ b/CMSIS/Utilities/buildutils/buildcmd.py
@@ -0,0 +1,43 @@
+#! python
+
+from subprocess import call, Popen
+from tempfile import TemporaryFile
+
+class BuildCmd:
+ def __init__(self):
+ self._result = -1
+ self._output = TemporaryFile(mode="r+")
+
+ def getCommand(self):
+ raise NotImplementedError
+
+ def getArguments(self):
+ return []
+
+ def getOutput(self):
+ return self._output
+
+ def getLog(self):
+ return None
+
+ def isSuccess(self):
+ return self._output == 0
+
+ def run(self):
+ cmd = [ self.getCommand() ] + self.getArguments()
+ print "Running: " + ' '.join(cmd)
+ try:
+ self._result = call(cmd, stdout = self._output)
+ except:
+ print "Fatal error!"
+ self._output.seek(0)
+ print self._output.read()
+
+ logfile = self.getLog()
+ if logfile != None:
+ print logfile.read()
+
+ print "Command returned: {0}".format(self._result)
+
+ return self._result
+
\ No newline at end of file
diff --git a/CMSIS/Utilities/buildutils/dircmd.py b/CMSIS/Utilities/buildutils/dircmd.py
new file mode 100644
index 0000000..5a0f211
--- /dev/null
+++ b/CMSIS/Utilities/buildutils/dircmd.py
@@ -0,0 +1,13 @@
+#! python
+
+from buildcmd import BuildCmd
+
+class DirCmd(BuildCmd):
+
+ def __init__(self):
+ BuildCmd.__init__(self)
+
+ def getCommand(self):
+ return "dir"
+
+
\ No newline at end of file
diff --git a/CMSIS/Utilities/buildutils/fvpcmd.py b/CMSIS/Utilities/buildutils/fvpcmd.py
new file mode 100644
index 0000000..d3a4d94
--- /dev/null
+++ b/CMSIS/Utilities/buildutils/fvpcmd.py
@@ -0,0 +1,25 @@
+#! python
+
+from buildcmd import BuildCmd
+
+class FvpCmd(BuildCmd):
+
+ def __init__(self, model, app, **args):
+ BuildCmd.__init__(self)
+ self._model = model
+ self._app = app
+ self._args = args
+
+ def getCommand(self):
+ return self._model
+
+ def getArguments(self):
+ args = []
+ if self._args.has_key('limit'): args += [ "--cyclelimit", self._args['limit'] ]
+ if self._args.has_key('config'): args += [ "-f", self._args['config'] ]
+ if self._args.has_key('target'):
+ args += [ "-a", "{0}={1}".format(self._args['target'], self._app ) ]
+ else:
+ args += [ self._app ]
+ return args
+
\ No newline at end of file
diff --git a/CMSIS/Utilities/buildutils/testresult.py b/CMSIS/Utilities/buildutils/testresult.py
new file mode 100644
index 0000000..6e24d6d
--- /dev/null
+++ b/CMSIS/Utilities/buildutils/testresult.py
@@ -0,0 +1,40 @@
+#! python
+
+import shutil
+from StringIO import StringIO
+from xml.etree import ElementTree
+
+class TestResult:
+
+ def _extractXml(self, log, xml):
+ dump = False
+ log.seek(0)
+ for line in log:
+ if dump:
+ xml.write(line)
+ if line.strip() == '</report>':
+ dump = False
+ else:
+ if line.strip() == '<?xml version="1.0"?>':
+ dump = True
+ xml.write(line)
+
+ def __init__(self, log):
+ self._xml = StringIO()
+ self._extractXml(log, self._xml)
+ self._xml.seek(0)
+
+ report = ElementTree.parse(self._xml).getroot()
+ summary = report[0].findall('summary')[0]
+ self._tests = summary.find('tcnt').text
+ self._executed = summary.find('exec').text
+ self._passed = summary.find('pass').text
+ self._failed = summary.find('fail').text
+
+ def saveXml(self, filename):
+ with open(filename, "w") as file:
+ self._xml.seek(0)
+ shutil.copyfileobj(self._xml, file)
+
+ def getSummary(self):
+ return self._tests, self._executed, self._passed, self._failed
\ No newline at end of file
diff --git a/CMSIS/Utilities/buildutils/uv4cmd.py b/CMSIS/Utilities/buildutils/uv4cmd.py
new file mode 100644
index 0000000..8c7f932
--- /dev/null
+++ b/CMSIS/Utilities/buildutils/uv4cmd.py
@@ -0,0 +1,29 @@
+#! python
+
+from buildcmd import BuildCmd
+from string import maketrans
+from datetime import datetime
+import mmap
+
+class Uv4Cmd(BuildCmd):
+
+ def __init__(self, project, config):
+ BuildCmd.__init__(self)
+ self._project = project
+ self._config = config
+ self._log = "UV4_{0}_{1}.log".format(self._config.translate(maketrans(" ", "_"), "()[],"), datetime.now().strftime("%Y%m%d%H%M%S"))
+
+ def getCommand(self):
+ return "UV4.exe"
+
+ def getArguments(self):
+ return [ "-t", self._config, "-cr", self._project, "-j0", "-o", self._log ]
+
+ def isSuccess(self):
+ return self._result <= 1
+
+ def getLog(self):
+ try:
+ return open(self._log, "r")
+ except:
+ return None