changeset 331:a78b41ff6ad2

Added better recipe files
author Windel Bouwman
date Fri, 07 Feb 2014 12:39:59 +0100
parents a79ac866732f
children 87feb8a23b4d
files kernel/arch_arm.c3 kernel/make.py python/hexutil.py python/ppci/__init__.py python/ppci/buildtasks.py python/ppci/report.py python/zcc.py test/bare/qemutst.sh test/testzcc.py user/makeuser.py user/recipe.yaml
diffstat 11 files changed, 246 insertions(+), 211 deletions(-) [+]
line wrap: on
line diff
--- a/kernel/arch_arm.c3	Fri Feb 07 12:08:40 2014 +0100
+++ b/kernel/arch_arm.c3	Fri Feb 07 12:39:59 2014 +0100
@@ -2,6 +2,9 @@
 
 function void init()
 {
+    var int *UART0DR;
+    UART0DR = cast<int*>(0x10009000);
+    *UART0DR = 0x65;
 }
 
 function void halt()
--- a/kernel/make.py	Fri Feb 07 12:08:40 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,18 +0,0 @@
-#!/usr/bin/env python
-
-import sys
-import os
-
-def make_kernel(args=[]):
-    import zcc
-    arglist = ['memory.c3', 'kernel.c3', 'syscall.c3', 'process.c3']
-    arglist += ['schedule.c3', 'arch_arm.c3']
-    arglist += ['--target', 'arm']
-    arglist += args
-
-    args = zcc.parser.parse_args(arglist)
-    zcc.main(args)
-
-if __name__ == '__main__':
-    sys.path.insert(0, os.path.join('..', 'python'))
-    make_kernel(sys.argv[1:])
--- a/python/hexutil.py	Fri Feb 07 12:08:40 2014 +0100
+++ b/python/hexutil.py	Fri Feb 07 12:39:59 2014 +0100
@@ -12,7 +12,7 @@
 
 parser = argparse.ArgumentParser(
    description='hexfile manipulation tool by Windel Bouwman')
-subparsers = parser.add_subparsers(title='commands', 
+subparsers = parser.add_subparsers(title='commands',
          description='possible commands', dest='command')
 
 p = subparsers.add_parser('info', help='dump info about hexfile')
@@ -31,10 +31,10 @@
 
 def main(args):
     if args.command == 'info':
-        hf = HexFile()
-        hf.load(args.hexfile)
-        print(hf)
-        for region in hf.regions:
+        hexfile = HexFile()
+        hexfile.load(args.hexfile)
+        print(hexfile)
+        for region in hexfile.regions:
             print(region)
     elif args.command == 'new':
         hf = HexFile()
--- a/python/ppci/__init__.py	Fri Feb 07 12:08:40 2014 +0100
+++ b/python/ppci/__init__.py	Fri Feb 07 12:39:59 2014 +0100
@@ -11,3 +11,6 @@
 
 from .common import SourceLocation, SourceRange, Token
 from .common import CompilerError, DiagnosticsManager
+
+logformat='%(asctime)s|%(levelname)s|%(name)s|%(message)s'
+
--- a/python/ppci/buildtasks.py	Fri Feb 07 12:08:40 2014 +0100
+++ b/python/ppci/buildtasks.py	Fri Feb 07 12:39:59 2014 +0100
@@ -14,7 +14,13 @@
 from . import DiagnosticsManager
 
 
-class Assemble(Task):
+class BuildTask(Task):
+    def __init__(self, name):
+        super().__init__(name)
+        self.logger = logging.getLogger('buildtask')
+
+
+class Assemble(BuildTask):
     def __init__(self):
         super().__init__('Assemble')
 
@@ -22,7 +28,7 @@
         pass
 
 
-class Compile(Task):
+class Compile(BuildTask):
     """ Task that compiles source to some target """
     def __init__(self, sources, includes, target, output_object):
         super().__init__('Compile')
@@ -32,8 +38,7 @@
         self.output = output_object
 
     def run(self):
-        logger = logging.getLogger('zcc')
-        logger.info('Zcc started {}'.format(self.sources))
+        self.logger.info('Zcc started {}'.format(self.sources))
         diag = DiagnosticsManager()
         c3b = Builder(diag, self.target)
         cg = CodeGenerator(self.target)
@@ -43,7 +48,7 @@
                 return
 
             d = {'ircode':ircode}
-            logger.info('Verifying code {}'.format(ircode), extra=d)
+            self.logger.info('Verifying code {}'.format(ircode), extra=d)
             Verifier().verify(ircode)
 
             # Optimization passes:
@@ -56,7 +61,7 @@
 
             # Code generation:
             d = {'ircode':ircode}
-            logger.info('Starting code generation for {}'.format(ircode), extra=d)
+            self.logger.info('Starting code generation for {}'.format(ircode), extra=d)
             cg.generate(ircode, self.output)
 
         # TODO: fixup references, do this in another way?
@@ -66,7 +71,7 @@
             raise TaskError('Compile errors')
 
 
-class Link(Task):
+class Link(BuildTask):
     def __init__(self, objects, output_file):
         super().__init__('Link')
 
@@ -75,11 +80,13 @@
     pass
 
 
-def load_recipe(recipe, runner):
+def load_recipe(recipe_file, runner):
     """ Loads a recipe dictionary into a task runner """
-    if 'compile' in recipe:
-        #sources =
-        runner.add_task(Compile())
-    else:
-        raise Exception()
+    for command, value in recipe:
+        if command == 'compile':
+            sources = value['']
+            target = value['target']
+            runner.add_task(Compile())
+        else:
+            raise Exception()
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/ppci/report.py	Fri Feb 07 12:39:59 2014 +0100
@@ -0,0 +1,93 @@
+
+import logging
+import io
+
+import outstream
+from .c3 import AstPrinter
+from . import logformat
+from .irutils import Writer
+
+class RstFormatter(logging.Formatter):
+    """ Formatter that tries to create an rst document """
+    def __init__(self):
+        super().__init__(fmt=logformat)
+
+    def format(self, record):
+        s = super().format(record)
+        s += '\n'
+        if hasattr(record, 'c3_ast'):
+            f = io.StringIO()
+            print('', file=f)
+            print('', file=f)
+            print('.. code::', file=f)
+            print('', file=f)
+            AstPrinter().printAst(record.c3_ast, f)
+            print('', file=f)
+            s += '\n' + f.getvalue()
+        if hasattr(record, 'ircode'):
+            f = io.StringIO()
+            print('', file=f)
+            print('', file=f)
+            print('.. code::', file=f)
+            print('', file=f)
+            Writer('  ').write(record.ircode, f)
+            print('', file=f)
+            s += '\n' + f.getvalue()
+        if hasattr(record, 'irfunc'):
+            f = io.StringIO()
+            print('', file=f)
+            print('', file=f)
+            print('.. code::', file=f)
+            print('', file=f)
+            Writer('  ').write_function(record.irfunc, f)
+            print('', file=f)
+            s += '\n' + f.getvalue()
+        if hasattr(record, 'ppci_frame'):
+            f = io.StringIO()
+            frame = record.ppci_frame
+            print('', file=f)
+            print('.. code::', file=f)
+            print('', file=f)
+            print('  {}'.format(frame.name), file=f)
+            for i in frame.instructions:
+                print('   {}'.format(i),file=f)
+            print('', file=f)
+            s += '\n' + f.getvalue()
+        if hasattr(record, 'ra_cfg'):
+            f = io.StringIO()
+            print('', file=f)
+            print('', file=f)
+            print('.. graphviz::', file=f)
+            print('', file=f)
+            print('  digraph G {', file=f)
+            print('    size="8,80";', file=f)
+            cfg = record.ra_cfg
+            cfg.to_dot(f)
+            print('  }', file=f)
+            print('', file=f)
+            s += '\n' + f.getvalue()
+        if hasattr(record, 'ra_ig'):
+            f = io.StringIO()
+            print('', file=f)
+            print('', file=f)
+            print('.. graphviz::', file=f)
+            print('', file=f)
+            print('  digraph G {', file=f)
+            print('    ratio="compress";', file=f)
+            print('    size="8,80";', file=f)
+            ig = record.ra_ig
+            ig.to_dot(f)
+            print('  }', file=f)
+            print('', file=f)
+            s += '\n' + f.getvalue()
+        if hasattr(record, 'zcc_outs'):
+            f = io.StringIO()
+            print('', file=f)
+            print('', file=f)
+            print('.. code::', file=f)
+            print('', file=f)
+            outstream.OutputStreamWriter('  ').dump(record.zcc_outs, f)
+            print('', file=f)
+            s += '\n' + f.getvalue()
+        return s
+
--- a/python/zcc.py	Fri Feb 07 12:08:40 2014 +0100
+++ b/python/zcc.py	Fri Feb 07 12:39:59 2014 +0100
@@ -1,21 +1,17 @@
 #!/usr/bin/env python
 
 import sys
+import os
 import argparse
 import logging
+import yaml
 
-from ppci.c3 import AstPrinter
 from ppci.buildtasks import Compile
 from ppci.tasks import TaskRunner
+from ppci.report import RstFormatter
 import outstream
-from utils import HexFile
-import target
 from target.target_list import target_list
-from ppci import irutils
-import io
-
-
-logformat='%(asctime)s|%(levelname)s|%(name)s|%(message)s'
+import ppci
 
 
 def logLevel(s):
@@ -26,149 +22,97 @@
     return numeric_level
 
 
-class RstFormatter(logging.Formatter):
-    """ Formatter that tries to create an rst document """
-    def __init__(self):
-        super().__init__(fmt=logformat)
-
-    def format(self, record):
-        s = super().format(record)
-        s += '\n'
-        if hasattr(record, 'c3_ast'):
-            f = io.StringIO()
-            print('', file=f)
-            print('', file=f)
-            print('.. code::', file=f)
-            print('', file=f)
-            AstPrinter().printAst(record.c3_ast, f)
-            print('', file=f)
-            s += '\n' + f.getvalue()
-        if hasattr(record, 'ircode'):
-            f = io.StringIO()
-            print('', file=f)
-            print('', file=f)
-            print('.. code::', file=f)
-            print('', file=f)
-            Writer('  ').write(record.ircode, f)
-            print('', file=f)
-            s += '\n' + f.getvalue()
-        if hasattr(record, 'irfunc'):
-            f = io.StringIO()
-            print('', file=f)
-            print('', file=f)
-            print('.. code::', file=f)
-            print('', file=f)
-            Writer('  ').write_function(record.irfunc, f)
-            print('', file=f)
-            s += '\n' + f.getvalue()
-        if hasattr(record, 'ppci_frame'):
-            f = io.StringIO()
-            frame = record.ppci_frame
-            print('', file=f)
-            print('.. code::', file=f)
-            print('', file=f)
-            print('  {}'.format(frame.name), file=f)
-            for i in frame.instructions:
-                print('   {}'.format(i),file=f)
-            print('', file=f)
-            s += '\n' + f.getvalue()
-        if hasattr(record, 'ra_cfg'):
-            f = io.StringIO()
-            print('', file=f)
-            print('', file=f)
-            print('.. graphviz::', file=f)
-            print('', file=f)
-            print('  digraph G {', file=f)
-            print('    size="8,80";', file=f)
-            cfg = record.ra_cfg
-            cfg.to_dot(f)
-            print('  }', file=f)
-            print('', file=f)
-            s += '\n' + f.getvalue()
-        if hasattr(record, 'ra_ig'):
-            f = io.StringIO()
-            print('', file=f)
-            print('', file=f)
-            print('.. graphviz::', file=f)
-            print('', file=f)
-            print('  digraph G {', file=f)
-            print('    ratio="compress";', file=f)
-            print('    size="8,80";', file=f)
-            ig = record.ra_ig
-            ig.to_dot(f)
-            print('  }', file=f)
-            print('', file=f)
-            s += '\n' + f.getvalue()
-        if hasattr(record, 'zcc_outs'):
-            f = io.StringIO()
-            print('', file=f)
-            print('', file=f)
-            print('.. code::', file=f)
-            print('', file=f)
-            outstream.OutputStreamWriter('  ').dump(record.zcc_outs, f)
-            print('', file=f)
-            s += '\n' + f.getvalue()
-        return s
-
-
 targets = {t.name: t for t in target_list}
 targetnames = list(targets.keys())
 
-# Parse arguments:
-parser = argparse.ArgumentParser(description='lcfos Compiler')
-parser.add_argument('source', type=argparse.FileType('r'), \
-  help='the source file to build', nargs="+")
-parser.add_argument('-i', '--imp', type=argparse.FileType('r'), \
-  help='Possible import module', action='append', default=[])
+def make_parser():
+    parser = argparse.ArgumentParser(description='lcfos Compiler')
+
+    parser.add_argument('--log', help='Log level (INFO,DEBUG,[WARN])',
+                        type=logLevel, default='WARN')
+    sub_parsers = parser.add_subparsers(title='commands',
+         description='possible commands', dest='command')
+    recipe_parser = sub_parsers.add_parser('recipe', help="Bake recipe")
+    recipe_parser.add_argument('recipe_file', help='recipe file')
+
+    compile_parser = sub_parsers.add_parser('compile', help="compile source")
+    compile_parser.add_argument('source', type=argparse.FileType('r'),
+      help='the source file to build', nargs="+")
+    compile_parser.add_argument('-i', '--imp', type=argparse.FileType('r'),
+      help='Possible import module', action='append', default=[])
+    compile_parser.add_argument('--target', help="Backend selection",
+        choices=targetnames, required=True)
+    compile_parser.add_argument('-o', '--output', help='Output file',
+        metavar='filename')
+    compile_parser.add_argument('--report',
+                help='Specify a file to write the compile report to',
+                type=argparse.FileType('w'))
+    return parser
+
 
-#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('--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',
-            type=argparse.FileType('w'))
+class RecipeLoader:
+    def load_file(self, recipe_file, runner):
+        """ Loads a recipe dictionary into a task runner """
+        self.recipe_dir = os.path.abspath(os.path.dirname(recipe_file))
+        with open(recipe_file, 'r') as f:
+            recipe = yaml.load(f)
+        self.load_dict(recipe, runner)
+
+    def relpath(self, filename):
+        return os.path.join(self.recipe_dir, filename)
+
+    def openfile(self, filename):
+        return open(self.relpath(filename), 'r')
+
+    def load_dict(self, recipe, runner):
+        for command, value in recipe.items():
+            if command == 'compile':
+                sources = [self.openfile(s) for s in value['sources']]
+                includes = [self.openfile(i) for i in value['includes']]
+                target = targets[value['machine']]
+                output = outstream.TextOutputStream()
+                runner.add_task(Compile(sources, includes, target, output))
+            elif command == 'link':
+                self.load_dict(value['inputs'], runner)
+                #runner.add_task(Link())
+            elif command == 'assemble':
+                pass
+            elif command == 'apps':
+                for a in value:
+                    self.load_dict(a, runner)
+            else:
+                raise NotImplementedError(command)
 
 
 def main(args):
     # Configure some logging:
     logging.getLogger().setLevel(logging.DEBUG)
     ch = logging.StreamHandler()
-    ch.setFormatter(logging.Formatter(logformat))
+    ch.setFormatter(logging.Formatter(ppci.logformat))
     ch.setLevel(args.log)
     logging.getLogger().addHandler(ch)
-    if args.report:
-        fh = logging.StreamHandler(stream=args.report)
-        fh.setFormatter(RstFormatter())
-        logging.getLogger().addHandler(fh)
-
-    tg = targets[args.target]
-    outs = outstream.TextOutputStream()
-
-    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})
+    runner = TaskRunner()
+    if args.command == 'compile':
+        tg = targets[args.target]
+        outs = outstream.TextOutputStream()
+        runner.add_task(Compile(args.source, args.imp, tg, outs))
+    elif args.command == 'recipe':
+        recipe_loader = RecipeLoader()
+        recipe_loader.load_file(args.recipe_file, runner)
+    else:
+        raise NotImplementedError('Invalid option')
 
-    code_bytes = outs.sections['code'].to_bytes()
-    if args.output:
-        output_filename = args.output
-        with open(output_filename, 'wb') as f:
-            f.write(code_bytes)
+    res = runner.run_tasks()
 
-    if args.report:
-        logging.getLogger().removeHandler(fh)
     logging.getLogger().removeHandler(ch)
-    return 0
+    return res
 
 
 if __name__ == '__main__':
+    parser = make_parser()
     arguments = parser.parse_args()
+    if not arguments.command:
+        parser.print_usage()
+        sys.exit(1)
     sys.exit(main(arguments))
--- a/test/bare/qemutst.sh	Fri Feb 07 12:08:40 2014 +0100
+++ b/test/bare/qemutst.sh	Fri Feb 07 12:39:59 2014 +0100
@@ -9,7 +9,7 @@
 qemu-system-arm -M realview-pb-a8 -m 128M -nographic -kernel bare.bin \
     -monitor unix:vm.sock,server,nowait -serial file:output.txt &
 
-sleep 2
+sleep 1
 
 # Send quit to the monitor application
 echo "quit" | socat stdio UNIX-CONNECT:vm.sock
--- a/test/testzcc.py	Fri Feb 07 12:08:40 2014 +0100
+++ b/test/testzcc.py	Fri Feb 07 12:39:59 2014 +0100
@@ -20,46 +20,51 @@
     def tearDown(self):
         os.chdir(testdir)
 
-    def do(self, filenames, imps=[]):
+    def do(self, filenames, imps=[], extra_args=[]):
         basedir = os.path.join('..', 'examples', 'c3')
-        arg_list = [os.path.join(basedir, fn) for fn in filenames]
+        arg_list = ['compile']
+        arg_list += [os.path.join(basedir, fn) for fn in filenames]
         for fn in imps:
             arg_list.append('-i')
             arg_list.append(os.path.join(basedir, fn))
         arg_list.append('--target')
         arg_list.append('arm')
-        args = zcc.parser.parse_args(arg_list)
+        arg_list += extra_args
+        self.callZcc(arg_list)
+
+    def callZcc(self, arg_list):
+        parser = zcc.make_parser()
+        args = parser.parse_args(arg_list)
         self.assertEqual(0, zcc.main(args))
 
+    def buildRecipe(self, recipe):
+        arg_list = ['recipe', recipe]
+        self.callZcc(arg_list)
+
     def testDumpIr(self):
         basedir = os.path.join('..', 'examples', 'c3', 'comments.c3')
-        arg_list = [basedir]
+        arg_list = ['compile', basedir]
         arg_list.append('--target')
         arg_list.append('arm')
-        args = zcc.parser.parse_args(arg_list)
-        self.assertEqual(0, zcc.main(args))
+        self.callZcc(arg_list)
 
     def testKernel(self):
-        # Build kernel using zcc:
-        kerneldir = os.path.normpath(os.path.join('..', 'kernel'))
-        sys.path.insert(0, kerneldir)
-        from make import make_kernel
-        os.chdir(kerneldir)
-        make_kernel()
-        sys.path.pop(-1)
+        """ Build kernel using zcc: """
+        recipe = os.path.join(testdir, '..', 'kernel', 'recipe.yaml')
+        self.buildRecipe(recipe)
 
     def testUser(self):
-        # Build userspace using zcc:
-        userdir = os.path.normpath(os.path.join('..', 'user'))
-        sys.path.insert(0, userdir)
-        from makeuser import make_user
-        os.chdir(userdir)
-        make_user()
-        sys.path.pop(-1)
+        """ Build userspace using zcc: """
+        recipe = os.path.join(testdir, '..', 'user', 'recipe.yaml')
+        self.buildRecipe(recipe)
 
     def testBurn2(self):
         self.do(['burn2.c3'], ['stm32f4xx.c3'])
 
+    #@unittest.skip('s')
+    def testBurn2WithLogging(self):
+        self.do(['burn2.c3'], ['stm32f4xx.c3'], extra_args=['--report', 'x.rst'])
+
     def testCommentsExample(self):
         self.do(['comments.c3'])
 
--- a/user/makeuser.py	Fri Feb 07 12:08:40 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,21 +0,0 @@
-#!/usr/bin/env python
-
-import sys
-import os
-
-def fix(srcs, extra_args):
-    import zcc
-    arglist = srcs
-    arglist += ['--target', 'arm']
-    arglist += extra_args
-    args = zcc.parser.parse_args(arglist)
-    zcc.main(args)
-
-def make_user(extra_args=[]):
-    fix(['lib.c3', 'ipc.c3', 'hello.c3'], extra_args)
-    fix(['lib.c3', 'ipc.c3', 'screen.c3'], extra_args)
-    fix(['lib.c3', 'ipc.c3', 'console.c3'], extra_args)
-
-if __name__ == '__main__':
-    sys.path.insert(0, os.path.join('..', 'python'))
-    make_user(sys.argv[1:])
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/user/recipe.yaml	Fri Feb 07 12:39:59 2014 +0100
@@ -0,0 +1,19 @@
+
+apps:
+  - compile:
+       sources: [lib.c3, ipc.c3, hello.c3]
+       includes: []
+       machine: arm
+       output: kernel.elf2
+
+  - compile:
+       sources: [lib.c3, ipc.c3, screen.c3]
+       includes: []
+       machine: arm
+       output: kernel.elf2
+
+  - compile:
+       sources: [lib.c3, ipc.c3, console.c3]
+       includes: []
+       machine: arm
+       output: kernel.elf2