changeset 329:8f6f3ace4e78

Added build tasks
author Windel Bouwman
date Wed, 05 Feb 2014 21:29:31 +0100
parents 0bb16d2a5699
children a79ac866732f
files python/ppci/buildtasks.py python/ppci/tasks.py python/zcc.py test/testzcc.py
diffstat 4 files changed, 147 insertions(+), 70 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/ppci/buildtasks.py	Wed Feb 05 21:29:31 2014 +0100
@@ -0,0 +1,85 @@
+
+"""
+Defines task classes that can compile, link etc..
+Task can depend upon one another.
+"""
+
+import logging
+
+from .c3 import Builder
+from .irutils import Verifier
+from .codegen import CodeGenerator
+from .transform import CleanPass, RemoveAddZero
+from .tasks import Task
+from . import DiagnosticsManager
+
+
+class Assemble(Task):
+    def __init__(self):
+        super().__init__('Assemble')
+
+    def run(self):
+        pass
+
+
+class Compile(Task):
+    """ Task that compiles source to some target """
+    def __init__(self, sources, includes, target, output_object):
+        super().__init__('Compile')
+        self.sources = sources
+        self.includes = includes
+        self.target = target
+        self.output = output_object
+
+    def run(self):
+        logger = logging.getLogger('zcc')
+        logger.info('Zcc started {}'.format(self.sources))
+        diag = DiagnosticsManager()
+        c3b = Builder(diag, self.target)
+        cg = CodeGenerator(self.target)
+
+        for ircode in c3b.build(self.sources, self.includes):
+            if not ircode:
+                return
+
+            d = {'ircode':ircode}
+            logger.info('Verifying code {}'.format(ircode), extra=d)
+            Verifier().verify(ircode)
+
+            # Optimization passes:
+            CleanPass().run(ircode)
+            Verifier().verify(ircode)
+            RemoveAddZero().run(ircode)
+            Verifier().verify(ircode)
+            CleanPass().run(ircode)
+            Verifier().verify(ircode)
+
+            # Code generation:
+            d = {'ircode':ircode}
+            logger.info('Starting code generation for {}'.format(ircode), extra=d)
+            cg.generate(ircode, self.output)
+
+        # TODO: fixup references, do this in another way?
+        self.output.backpatch()
+        if not c3b.ok:
+            diag.printErrors()
+            raise TaskError('Compile errors')
+
+
+class Link(Task):
+    def __init__(self, objects, output_file):
+        super().__init__('Link')
+
+
+class ObjCopy(Task):
+    pass
+
+
+def load_recipe(recipe, runner):
+    """ Loads a recipe dictionary into a task runner """
+    if 'compile' in recipe:
+        #sources =
+        runner.add_task(Compile())
+    else:
+        raise Exception()
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/ppci/tasks.py	Wed Feb 05 21:29:31 2014 +0100
@@ -0,0 +1,46 @@
+
+class TaskError(Exception):
+    pass
+
+
+class Task:
+    """ Task that can run, and depend on other tasks """
+    def __init__(self, name):
+        self.name = name
+        self.subtasks = []
+        self.completed = False
+        self.dependencies = []
+
+    def run(self):
+        raise NotImplementedError("Implement this abstract method!")
+
+    def fire(self):
+        assert all(t.completed for t in self.dependencies)
+        self.run()
+        self.completed = True
+
+    def addSubTask(self, tsk):
+        self.subtasks.append(tsk)
+        return tsk
+
+    def addDependency(self, task):
+        self.dependencies.append(task)
+        return task
+
+
+class TaskRunner:
+    def __init__(self):
+        self.task_list = []
+    
+    def add_task(self, task):
+        self.task_list.append(task)
+
+    def run_tasks(self):
+        try:
+            for t in self.task_list:
+                #print('Running {}'.format(t.name))
+                t.fire()
+        except TaskError as e:
+            print('Error: {}'.format(e))
+            return 1
+        return 0
--- a/python/zcc.py	Tue Feb 04 09:01:11 2014 +0100
+++ b/python/zcc.py	Wed Feb 05 21:29:31 2014 +0100
@@ -4,17 +4,15 @@
 import argparse
 import logging
 
-from ppci.c3 import Builder, AstPrinter
-import ppci
-from ppci.irutils import Verifier, Writer
-from ppci.codegen import CodeGenerator
+from ppci.c3 import AstPrinter
+from ppci.buildtasks import Compile
+from ppci.tasks import TaskRunner
 import outstream
 from utils import HexFile
 import target
 from target.target_list import target_list
 from ppci import irutils
 import io
-from ppci.transform import CleanPass, RemoveAddZero
 
 
 logformat='%(asctime)s|%(levelname)s|%(name)s|%(message)s'
@@ -123,63 +121,19 @@
 parser.add_argument('-i', '--imp', type=argparse.FileType('r'), \
   help='Possible import module', action='append', default=[])
 
+#sub_parsers = parser.add_subparsers()
+#recipe = sub_parsers.add_parser('recipe')
 parser.add_argument('--optimize', action='store_true', help="Optimize")
 parser.add_argument('--target', help="Backend selection",
     choices=targetnames, required=True)
 parser.add_argument('-o', '--output', help='Output file', metavar='filename')
-parser.add_argument('--hexfile', help='Output hexfile',
-    type=argparse.FileType('w'))
-parser.add_argument('--log', help='Log level (INFO,DEBUG,[WARN])', 
+parser.add_argument('--log', help='Log level (INFO,DEBUG,[WARN])',
                     type=logLevel, default='WARN')
 parser.add_argument('--report', 
-            help='Specify a file to write the compile report to', 
+            help='Specify a file to write the compile report to',
             type=argparse.FileType('w'))
 
 
-def zcc(srcs, imps, tg, outs, diag):
-    """
-        Compiler driver
-        Compile sources into output stream.
-        Sources is an iterable of open files.
-    """
-    logger = logging.getLogger('zcc')
-    logger.info('Zcc started {}'.format(srcs))
-    # Front end:
-    c3b = Builder(diag, tg)
-    cg = CodeGenerator(tg)
-
-    # TODO: remove this arm specifics:
-    outs.getSection('code').address = 0x08000000
-    outs.getSection('data').address = 0x20000000
-
-    # Emit some custom start code:
-    tg.startCode(outs)
-    for ircode in c3b.build(srcs, imps):
-        if not ircode:
-            return
-
-        d = {'ircode':ircode}
-        logger.info('Verifying code {}'.format(ircode), extra=d)
-        Verifier().verify(ircode)
-
-        # Optimization passes:
-        CleanPass().run(ircode)
-        Verifier().verify(ircode)
-        RemoveAddZero().run(ircode)
-        Verifier().verify(ircode)
-        CleanPass().run(ircode)
-        Verifier().verify(ircode)
-
-        # Code generation:
-        d = {'ircode':ircode}
-        logger.info('Starting code generation for {}'.format(ircode), extra=d)
-        cg.generate(ircode, outs)
-    # TODO: fixup references, do this in another way?
-    outs.backpatch()
-    outs.backpatch()  # Why two times?
-    return c3b.ok
-
-
 def main(args):
     # Configure some logging:
     logging.getLogger().setLevel(logging.DEBUG)
@@ -193,14 +147,14 @@
         logging.getLogger().addHandler(fh)
 
     tg = targets[args.target]
-    diag = ppci.DiagnosticsManager()
     outs = outstream.TextOutputStream()
 
-    res = zcc(args.source, args.imp, tg, outs, diag)
-    if not res:
-        diag.printErrors()
+    tr = TaskRunner()
+    tr.add_task(Compile(args.source, args.imp, tg, outs))
+
+    res = tr.run_tasks()
+    if res > 0:
         return 1
-
     logging.info('Assembly created', extra={'zcc_outs':outs})
 
     code_bytes = outs.sections['code'].to_bytes()
@@ -209,12 +163,6 @@
         with open(output_filename, 'wb') as f:
             f.write(code_bytes)
 
-    if args.hexfile:
-        logging.info('Creating hexfile')
-        hf = HexFile()
-        hf.addRegion(0x08000000, code_bytes)
-        hf.save(args.hexfile)
-
     if args.report:
         logging.getLogger().removeHandler(fh)
     logging.getLogger().removeHandler(ch)
--- a/test/testzcc.py	Tue Feb 04 09:01:11 2014 +0100
+++ b/test/testzcc.py	Wed Feb 05 21:29:31 2014 +0100
@@ -8,7 +8,6 @@
 import io
 import target
 
-
 # Store testdir for safe switch back to directory:
 testdir = os.path.dirname(os.path.abspath(__file__))
 
@@ -75,14 +74,13 @@
             function void t2() {var int t3; t3 = 2;}
         """
         f = io.StringIO(src)
-        diag = ppci.DiagnosticsManager()
         outs = outstream.TextOutputStream()
         tg = target.target_list.armtarget
-        self.assertTrue(zcc.zcc([f], [], tg, outs, diag))
+        tr = ppci.tasks.TaskRunner()
+        tr.add_task(ppci.buildtasks.Compile([f], [], tg, outs))
+        tr.run_tasks()
         code = outs.getSection('code')
-        self.assertEqual(0x08000000, code.address)
-        data = outs.getSection('data')
-        self.assertEqual(0x20000000, data.address)
+        self.assertEqual(0x0, code.address)
 
 
 if __name__ == '__main__':