Mercurial > lcfOS
diff python/zcc.py @ 331:a78b41ff6ad2
Added better recipe files
author | Windel Bouwman |
---|---|
date | Fri, 07 Feb 2014 12:39:59 +0100 |
parents | 8f6f3ace4e78 |
children | 87feb8a23b4d |
line wrap: on
line diff
--- 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))