Rizky Ardi Maulana / mbed-os
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 OldLibrariesException (Exception):
00015     """Exception that indicates an export can not complete due to an out of date
00016     library version.
00017     """
00018     pass
00019 
00020 class FailedBuildException (Exception):
00021     """Exception that indicates that a build failed"""
00022     pass
00023 
00024 class TargetNotSupportedException (Exception):
00025     """Indicates that an IDE does not support a particular MCU"""
00026     pass
00027 
00028 class ExporterTargetsProperty (object):
00029     """ Exporter descriptor for TARGETS
00030     TARGETS as class attribute for backward compatibility
00031     (allows: if in Exporter.TARGETS)
00032     """
00033     def __init__(self, func):
00034         self.func = func
00035     def __get__(self, inst, cls):
00036         return self.func(cls)
00037 
00038 class Exporter (object):
00039     """Exporter base class
00040 
00041     This class is meant to be extended by individual exporters, and provides a
00042     few helper methods for implementing an exporter with either jinja2 or
00043     progen.
00044     """
00045     TEMPLATE_DIR = dirname(__file__)
00046     DOT_IN_RELATIVE_PATH = False
00047     NAME = None
00048     TARGETS = None
00049     TOOLCHAIN = None
00050 
00051     def __init__ (self, target, export_dir, project_name, toolchain,
00052                  extra_symbols=None, resources=None):
00053         """Initialize an instance of class exporter
00054         Positional arguments:
00055         target        - the target mcu/board for this project
00056         export_dir    - the directory of the exported project files
00057         project_name  - the name of the project
00058         toolchain     - an instance of class toolchain
00059 
00060         Keyword arguments:
00061         extra_symbols - a list of extra macros for the toolchain
00062         resources     - an instance of class Resources
00063         """
00064         self.export_dir  = export_dir
00065         self.target  = target
00066         self.project_name  = project_name
00067         self.toolchain  = toolchain
00068         jinja_loader = FileSystemLoader(os.path.dirname(os.path.abspath(__file__)))
00069         self.jinja_environment  = Environment(loader=jinja_loader)
00070         self.resources  = resources
00071         self.generated_files  = [join(self.TEMPLATE_DIR ,"GettingStarted.html")]
00072         self.builder_files_dict  = {}
00073         self.add_config ()
00074 
00075     def get_toolchain (self):
00076         """A helper getter function that we should probably eliminate"""
00077         return self.TOOLCHAIN 
00078 
00079     def add_config (self):
00080         """Add the containgin directory of mbed_config.h to include dirs"""
00081         config = self.toolchain .get_config_header()
00082         if config:
00083             self.resources .inc_dirs.append(
00084                 dirname(relpath(config,
00085                                 self.resources .file_basepath[config])))
00086 
00087     @property
00088     def flags (self):
00089         """Returns a dictionary of toolchain flags.
00090         Keys of the dictionary are:
00091         cxx_flags    - c++ flags
00092         c_flags      - c flags
00093         ld_flags     - linker flags
00094         asm_flags    - assembler flags
00095         common_flags - common options
00096         """
00097         config_header = self.toolchain .get_config_header()
00098         flags = {key + "_flags": copy.deepcopy(value) for key, value
00099                  in self.toolchain .flags.iteritems()}
00100         asm_defines = ["-D" + symbol for symbol in self.toolchain .get_symbols(True)]
00101         c_defines = ["-D" + symbol for symbol in self.toolchain .get_symbols()]
00102         flags['asm_flags'] += asm_defines
00103         flags['c_flags'] += c_defines
00104         flags['cxx_flags'] += c_defines
00105         if config_header:
00106             config_header = relpath(config_header,
00107                                     self.resources .file_basepath[config_header])
00108             flags['c_flags'] += self.toolchain .get_config_option(config_header)
00109             flags['cxx_flags'] += self.toolchain .get_config_option(
00110                 config_header)
00111         return flags
00112 
00113     def get_source_paths (self):
00114         """Returns a list of the directories where source files are contained"""
00115         source_keys = ['s_sources', 'c_sources', 'cpp_sources', 'hex_files',
00116                        'objects', 'libraries']
00117         source_files = []
00118         for key in source_keys:
00119             source_files.extend(getattr(self.resources , key))
00120         return list(set([os.path.dirname(src) for src in source_files]))
00121 
00122     def check_supported (self):
00123         """Indicated if this combination of IDE and MCU is supported"""
00124         if self.target  not in self.TARGETS  or \
00125            self.TOOLCHAIN  not in TARGET_MAP[self.target ].supported_toolchains:
00126             raise TargetNotSupportedException()
00127         return True
00128 
00129     def gen_file (self, template_file, data, target_file):
00130         """Generates a project file from a template using jinja"""
00131         jinja_loader = FileSystemLoader(
00132             os.path.dirname(os.path.abspath(__file__)))
00133         jinja_environment = Environment(loader=jinja_loader)
00134 
00135         template = jinja_environment.get_template(template_file)
00136         target_text = template.render(data)
00137 
00138         target_path = join(self.export_dir , target_file)
00139         logging.debug("Generating: %s", target_path)
00140         open(target_path, "w").write(target_text)
00141         self.generated_files  += [target_path]
00142 
00143     def make_key (self, src):
00144         """From a source file, extract group name
00145         Positional Arguments:
00146         src - the src's location
00147         """
00148         key = basename(dirname(src))
00149         if key == ".":
00150             key = basename(realpath(self.export_dir ))
00151         return key
00152 
00153     def group_project_files (self, sources):
00154         """Group the source files by their encompassing directory
00155         Positional Arguments:
00156         sources - array of sourc locations
00157 
00158         Returns a dictionary of {group name: list of source locations}
00159         """
00160         data = sorted(sources, key=self.make_key )
00161         return {k: list(g) for k,g in groupby(data, self.make_key )}