Greg Steiert / maxim_dev

Dependents:   sensomed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers exporters.py Source File

exporters.py

00001 """Just a template for subclassing"""
00002 import os
00003 import sys
00004 import logging
00005 from os.path import join, dirname, relpath, basename, realpath
00006 from itertools import groupby
00007 from jinja2 import FileSystemLoader
00008 from jinja2.environment import Environment
00009 import copy
00010 
00011 from tools.targets import TARGET_MAP
00012 
00013 
00014 class TargetNotSupportedException (Exception):
00015     """Indicates that an IDE does not support a particular MCU"""
00016     pass
00017 
00018 class ExporterTargetsProperty (object):
00019     """ Exporter descriptor for TARGETS
00020     TARGETS as class attribute for backward compatibility
00021     (allows: if in Exporter.TARGETS)
00022     """
00023     def __init__(self, func):
00024         self.func = func
00025     def __get__(self, inst, cls):
00026         return self.func(cls)
00027 
00028 class Exporter (object):
00029     """Exporter base class
00030 
00031     This class is meant to be extended by individual exporters, and provides a
00032     few helper methods for implementing an exporter with either jinja2 or
00033     progen.
00034     """
00035     TEMPLATE_DIR = dirname(__file__)
00036     DOT_IN_RELATIVE_PATH = False
00037     NAME = None
00038     TARGETS = None
00039     TOOLCHAIN = None
00040 
00041     def __init__ (self, target, export_dir, project_name, toolchain,
00042                  extra_symbols=None, resources=None):
00043         """Initialize an instance of class exporter
00044         Positional arguments:
00045         target        - the target mcu/board for this project
00046         export_dir    - the directory of the exported project files
00047         project_name  - the name of the project
00048         toolchain     - an instance of class toolchain
00049 
00050         Keyword arguments:
00051         extra_symbols - a list of extra macros for the toolchain
00052         resources     - an instance of class Resources
00053         """
00054         self.export_dir  = export_dir
00055         self.target  = target
00056         self.project_name  = project_name
00057         self.toolchain  = toolchain
00058         jinja_loader = FileSystemLoader(os.path.dirname(os.path.abspath(__file__)))
00059         self.jinja_environment  = Environment(loader=jinja_loader)
00060         self.resources  = resources
00061         self.generated_files  = [join(self.TEMPLATE_DIR ,"GettingStarted.html")]
00062         self.builder_files_dict  = {}
00063         self.add_config ()
00064 
00065     def get_toolchain (self):
00066         """A helper getter function that we should probably eliminate"""
00067         return self.TOOLCHAIN 
00068 
00069     def add_config (self):
00070         """Add the containgin directory of mbed_config.h to include dirs"""
00071         config = self.toolchain .get_config_header()
00072         if config:
00073             self.resources .inc_dirs.append(
00074                 dirname(relpath(config,
00075                                 self.resources .file_basepath[config])))
00076 
00077     @property
00078     def flags (self):
00079         """Returns a dictionary of toolchain flags.
00080         Keys of the dictionary are:
00081         cxx_flags    - c++ flags
00082         c_flags      - c flags
00083         ld_flags     - linker flags
00084         asm_flags    - assembler flags
00085         common_flags - common options
00086         """
00087         config_header = self.toolchain .get_config_header()
00088         flags = {key + "_flags": copy.deepcopy(value) for key, value
00089                  in self.toolchain .flags.iteritems()}
00090         asm_defines = ["-D" + symbol for symbol in self.toolchain .get_symbols(True)]
00091         c_defines = ["-D" + symbol for symbol in self.toolchain .get_symbols()]
00092         flags['asm_flags'] += asm_defines
00093         flags['c_flags'] += c_defines
00094         flags['cxx_flags'] += c_defines
00095         if config_header:
00096             config_header = relpath(config_header,
00097                                     self.resources .file_basepath[config_header])
00098             flags['c_flags'] += self.toolchain .get_config_option(config_header)
00099             flags['cxx_flags'] += self.toolchain .get_config_option(
00100                 config_header)
00101         return flags
00102 
00103     def get_source_paths (self):
00104         """Returns a list of the directories where source files are contained"""
00105         source_keys = ['s_sources', 'c_sources', 'cpp_sources', 'hex_files',
00106                        'objects', 'libraries']
00107         source_files = []
00108         for key in source_keys:
00109             source_files.extend(getattr(self.resources , key))
00110         return list(set([os.path.dirname(src) for src in source_files]))
00111 
00112     def gen_file (self, template_file, data, target_file):
00113         """Generates a project file from a template using jinja"""
00114         jinja_loader = FileSystemLoader(
00115             os.path.dirname(os.path.abspath(__file__)))
00116         jinja_environment = Environment(loader=jinja_loader)
00117 
00118         template = jinja_environment.get_template(template_file)
00119         target_text = template.render(data)
00120 
00121         target_path = join(self.export_dir , target_file)
00122         logging.debug("Generating: %s", target_path)
00123         open(target_path, "w").write(target_text)
00124         self.generated_files  += [target_path]
00125 
00126     def make_key (self, src):
00127         """From a source file, extract group name
00128         Positional Arguments:
00129         src - the src's location
00130         """
00131         key = basename(dirname(src))
00132         if key == ".":
00133             key = basename(realpath(self.export_dir ))
00134         return key
00135 
00136     def group_project_files (self, sources):
00137         """Group the source files by their encompassing directory
00138         Positional Arguments:
00139         sources - array of source locations
00140 
00141         Returns a dictionary of {group name: list of source locations}
00142         """
00143         data = sorted(sources, key=self.make_key )
00144         return {k: list(g) for k,g in groupby(data, self.make_key )}
00145 
00146     @staticmethod
00147     def build (project_name, log_name='build_log.txt', cleanup=True):
00148         """Invoke exporters build command within a subprocess.
00149         This method is assumed to be executed at the same level as exporter
00150         project files and project source code.
00151         See uvision/__init__.py, iar/__init__.py, and makefile/__init__.py for
00152         example implemenation.
00153 
00154         Positional Arguments:
00155         project_name - the name of the project to build; often required by
00156         exporter's build command.
00157 
00158         Keyword Args:
00159         log_name - name of the build log to create. Written and printed out,
00160         deleted if cleanup = True
00161         cleanup - a boolean dictating whether exported project files and
00162         build log are removed after build
00163 
00164         Returns -1 on failure and 0 on success
00165         """
00166         raise NotImplemented("Implement in derived Exporter class.")