Mercurial > lcfOS
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