Mercurial > lcfOS
diff python/ppci/buildtasks.py @ 377:9667d78ba79e
Switched to xml for project description
author | Windel Bouwman |
---|---|
date | Fri, 11 Apr 2014 15:47:50 +0200 |
parents | 39bf68bf1891 |
children | 6df89163e114 |
line wrap: on
line diff
--- a/python/ppci/buildtasks.py Tue Mar 25 19:36:51 2014 +0100 +++ b/python/ppci/buildtasks.py Fri Apr 11 15:47:50 2014 +0200 @@ -5,142 +5,116 @@ """ import logging +import json -from .c3 import Builder -from .irutils import Verifier -from .codegen import CodeGenerator -from .transform import CleanPass, RemoveAddZero -from .tasks import Task, TaskError -from . import DiagnosticsManager, CompilerError -from .assembler import Assembler -from .objectfile import ObjectFile -from .linker import Linker -from .outstream import BinaryOutputStream, MasterOutputStream, LoggerOutputStream -from .target.target_list import targets -from .target import Target +from .tasks import Task, TaskError, register_task +from .buildfunctions import c3compile, link, assemble +from pyyacc import ParserException +from . import CompilerError -def fix_target(tg): - """ Try to return an instance of the Target class """ - if isinstance(tg, Target): - return tg - elif isinstance(tg, str): - if tg in targets: - return targets[tg] - else: - raise TaskError('Target {} not found'.format(tg)) - raise TaskError('Invalid target {}'.format(tg)) +@register_task("empty") +class EmptyTask(Task): + """ Basic task that does nothing """ + def run(self): + pass + + +@register_task("echo") +class EchoTask(Task): + """ Simple task that echoes a message """ + def run(self): + message = self.arguments['message'] + print(message) -def fix_file(f): - """ Determine if argument is a file like object or make it so! """ - if hasattr(f, 'read'): - # Assume this is a file like object - return f - elif isinstance(f, str): - return open(f, 'r') - else: - raise TaskError('cannot use {} as input'.format(f)) - -def fix_object(o): - if isinstance(o, ObjectFile): - return o - else: - raise TaskError('Cannot use {} as objectfile'.format(o)) - -class BuildTask(Task): - """ Base task for all kind of weird build tasks """ - def __init__(self, name): - super().__init__(name) - self.logger = logging.getLogger('buildtask') +@register_task("property") +class Property(Task): + """ Sets a property to a value """ + def run(self): + name = self.arguments['name'] + value = self.arguments['value'] + self.target.project.set_property(name, value) -class Assemble(BuildTask): +@register_task("assemble") +class AssembleTask(Task): """ Task that can runs the assembler over the source and enters the output into an object file """ - def __init__(self, source, target, output_object): - super().__init__('Assemble') - self.source = fix_file(source) - self.output = output_object - o2 = BinaryOutputStream(self.output) - o1 = LoggerOutputStream() - self.ostream = MasterOutputStream([o1, o2]) - self.assembler = Assembler(fix_target(target)) def run(self): - self.logger.debug('Assembling into code section') - self.ostream.select_section('code') - self.assembler.assemble(self.source, self.ostream) + target = self.get_argument('target') + source = self.relpath(self.get_argument('source')) + output_filename = self.relpath(self.get_argument('output')) + + try: + output = assemble(source, target) + except ParserException as e: + raise TaskError('Error during assembly:' + str(e)) + except CompilerError as e: + raise TaskError('Error during assembly:' + str(e)) + with open(output_filename, 'w') as f: + output.save(f) self.logger.debug('Assembling finished') -class Compile(BuildTask): +@register_task("compile") +class C3cTask(Task): """ Task that compiles C3 source for some target into an object file """ - def __init__(self, sources, includes, target, output_object): - super().__init__('Compile') - self.sources = list(map(fix_file, sources)) - self.includes = list(map(fix_file, includes)) - self.target = fix_target(target) - self.output = output_object - def run(self): - self.logger.debug('Compile started') - diag = DiagnosticsManager() - c3b = Builder(diag, self.target) - cg = CodeGenerator(self.target) - - for ircode in c3b.build(self.sources, self.includes): - if not ircode: - # Something went wrong, do not continue the code generation - continue + target = self.get_argument('target') + sources = self.open_file_set(self.arguments['sources']) + output_filename = self.relpath(self.get_argument('output')) + if 'includes' in self.arguments: + includes = self.open_file_set(self.arguments['includes']) + else: + includes = [] - d = {'ircode':ircode} - self.logger.debug('Verifying code {}'.format(ircode), extra=d) - Verifier().verify(ircode) + output = c3compile(sources, includes, target) + # Store output: + with open(output_filename, 'w') as f: + output.save(f) - # 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} - self.logger.debug('Starting code generation for {}'.format(ircode), extra=d) - - o2 = BinaryOutputStream(self.output) - o1 = LoggerOutputStream() - o = MasterOutputStream([o1, o2]) - cg.generate(ircode, o) - - if not c3b.ok: - diag.printErrors() - raise TaskError('Compile errors') +def make_num(txt): + if txt.startswith('0x'): + return int(txt[2:], 16) + else: + return int(txt) -class Link(BuildTask): +def load_layout(filename): + """ Load a linker layout file which contains directives where sections + must be placed into memory. """ + try: + with open(filename, 'r') as f: + layout = json.load(f) + except OSError as e: + raise TaskError(str(e)) + for s in layout: + layout[s] = make_num(layout[s]) + return layout + + +@register_task("link") +class LinkTask(Task): """ Link together a collection of object files """ - def __init__(self, objects, layout, output_file): - super().__init__('Link') - self.objects = list(map(fix_object, objects)) - self.linker = Linker() - self.duration = 0.1337 - self.layout = layout - self.output_file = output_file + def run(self): + layout = load_layout(self.relpath(self.get_argument('layout'))) + objects = self.open_file_set(self.get_argument('objects')) + output_file = self.relpath(self.get_argument('output')) - def run(self): try: - output_obj = self.linker.link(self.objects, self.layout) + output_obj = link(objects, layout) except CompilerError as e: raise TaskError(e.msg) + # TODO: use layout here: code = output_obj.get_section('code').data - with open(self.output_file, 'wb') as f: + with open(output_file, 'wb') as f: f.write(code) -class ObjCopy(BuildTask): - def __init__(self, objects, output_file): - super().__init__('ObjCopy') +class ObjCopyTask(Task): + def run(self): + pass