mbed-os for GR-LYCHEE

Dependents:   mbed-os-example-blinky-gr-lychee GR-Boads_Camera_sample GR-Boards_Audio_Recoder GR-Boads_Camera_DisplayApp ... more

Committer:
dkato
Date:
Fri Feb 02 05:42:23 2018 +0000
Revision:
0:f782d9c66c49
mbed-os for GR-LYCHEE

Who changed what in which revision?

UserRevisionLine numberNew contents of line
dkato 0:f782d9c66c49 1 """Just a template for subclassing"""
dkato 0:f782d9c66c49 2 import os
dkato 0:f782d9c66c49 3 from abc import abstractmethod, ABCMeta
dkato 0:f782d9c66c49 4 import logging
dkato 0:f782d9c66c49 5 from os.path import join, dirname, relpath, basename, realpath, normpath
dkato 0:f782d9c66c49 6 from itertools import groupby
dkato 0:f782d9c66c49 7 from jinja2 import FileSystemLoader, StrictUndefined
dkato 0:f782d9c66c49 8 from jinja2.environment import Environment
dkato 0:f782d9c66c49 9 import copy
dkato 0:f782d9c66c49 10
dkato 0:f782d9c66c49 11 from tools.targets import TARGET_MAP
dkato 0:f782d9c66c49 12
dkato 0:f782d9c66c49 13
dkato 0:f782d9c66c49 14 class TargetNotSupportedException(Exception):
dkato 0:f782d9c66c49 15 """Indicates that an IDE does not support a particular MCU"""
dkato 0:f782d9c66c49 16 pass
dkato 0:f782d9c66c49 17
dkato 0:f782d9c66c49 18 class ExporterTargetsProperty(object):
dkato 0:f782d9c66c49 19 """ Exporter descriptor for TARGETS
dkato 0:f782d9c66c49 20 TARGETS as class attribute for backward compatibility
dkato 0:f782d9c66c49 21 (allows: if in Exporter.TARGETS)
dkato 0:f782d9c66c49 22 """
dkato 0:f782d9c66c49 23 def __init__(self, func):
dkato 0:f782d9c66c49 24 self.func = func
dkato 0:f782d9c66c49 25 def __get__(self, inst, cls):
dkato 0:f782d9c66c49 26 return self.func(cls)
dkato 0:f782d9c66c49 27
dkato 0:f782d9c66c49 28 class Exporter(object):
dkato 0:f782d9c66c49 29 """Exporter base class
dkato 0:f782d9c66c49 30
dkato 0:f782d9c66c49 31 This class is meant to be extended by individual exporters, and provides a
dkato 0:f782d9c66c49 32 few helper methods for implementing an exporter with either jinja2 or
dkato 0:f782d9c66c49 33 progen.
dkato 0:f782d9c66c49 34 """
dkato 0:f782d9c66c49 35 __metaclass__ = ABCMeta
dkato 0:f782d9c66c49 36 TEMPLATE_DIR = dirname(__file__)
dkato 0:f782d9c66c49 37 DOT_IN_RELATIVE_PATH = False
dkato 0:f782d9c66c49 38 NAME = None
dkato 0:f782d9c66c49 39 TARGETS = None
dkato 0:f782d9c66c49 40 TOOLCHAIN = None
dkato 0:f782d9c66c49 41
dkato 0:f782d9c66c49 42
dkato 0:f782d9c66c49 43 def __init__(self, target, export_dir, project_name, toolchain,
dkato 0:f782d9c66c49 44 extra_symbols=None, resources=None):
dkato 0:f782d9c66c49 45 """Initialize an instance of class exporter
dkato 0:f782d9c66c49 46 Positional arguments:
dkato 0:f782d9c66c49 47 target - the target mcu/board for this project
dkato 0:f782d9c66c49 48 export_dir - the directory of the exported project files
dkato 0:f782d9c66c49 49 project_name - the name of the project
dkato 0:f782d9c66c49 50 toolchain - an instance of class toolchain
dkato 0:f782d9c66c49 51
dkato 0:f782d9c66c49 52 Keyword arguments:
dkato 0:f782d9c66c49 53 extra_symbols - a list of extra macros for the toolchain
dkato 0:f782d9c66c49 54 resources - an instance of class Resources
dkato 0:f782d9c66c49 55 """
dkato 0:f782d9c66c49 56 self.export_dir = export_dir
dkato 0:f782d9c66c49 57 self.target = target
dkato 0:f782d9c66c49 58 self.project_name = project_name
dkato 0:f782d9c66c49 59 self.toolchain = toolchain
dkato 0:f782d9c66c49 60 jinja_loader = FileSystemLoader(os.path.dirname(os.path.abspath(__file__)))
dkato 0:f782d9c66c49 61 self.jinja_environment = Environment(loader=jinja_loader)
dkato 0:f782d9c66c49 62 self.resources = resources
dkato 0:f782d9c66c49 63 self.generated_files = [join(self.TEMPLATE_DIR,"GettingStarted.html")]
dkato 0:f782d9c66c49 64 self.builder_files_dict = {}
dkato 0:f782d9c66c49 65 self.add_config()
dkato 0:f782d9c66c49 66
dkato 0:f782d9c66c49 67 def get_toolchain(self):
dkato 0:f782d9c66c49 68 """A helper getter function that we should probably eliminate"""
dkato 0:f782d9c66c49 69 return self.TOOLCHAIN
dkato 0:f782d9c66c49 70
dkato 0:f782d9c66c49 71 def add_config(self):
dkato 0:f782d9c66c49 72 """Add the containgin directory of mbed_config.h to include dirs"""
dkato 0:f782d9c66c49 73 config = self.toolchain.get_config_header()
dkato 0:f782d9c66c49 74 if config:
dkato 0:f782d9c66c49 75 self.resources.inc_dirs.append(
dkato 0:f782d9c66c49 76 dirname(relpath(config,
dkato 0:f782d9c66c49 77 self.resources.file_basepath[config])))
dkato 0:f782d9c66c49 78
dkato 0:f782d9c66c49 79 @property
dkato 0:f782d9c66c49 80 def flags(self):
dkato 0:f782d9c66c49 81 """Returns a dictionary of toolchain flags.
dkato 0:f782d9c66c49 82 Keys of the dictionary are:
dkato 0:f782d9c66c49 83 cxx_flags - c++ flags
dkato 0:f782d9c66c49 84 c_flags - c flags
dkato 0:f782d9c66c49 85 ld_flags - linker flags
dkato 0:f782d9c66c49 86 asm_flags - assembler flags
dkato 0:f782d9c66c49 87 common_flags - common options
dkato 0:f782d9c66c49 88 """
dkato 0:f782d9c66c49 89 config_header = self.toolchain.get_config_header()
dkato 0:f782d9c66c49 90 flags = {key + "_flags": copy.deepcopy(value) for key, value
dkato 0:f782d9c66c49 91 in self.toolchain.flags.iteritems()}
dkato 0:f782d9c66c49 92 asm_defines = ["-D" + symbol for symbol in self.toolchain.get_symbols(True)]
dkato 0:f782d9c66c49 93 c_defines = ["-D" + symbol for symbol in self.toolchain.get_symbols()]
dkato 0:f782d9c66c49 94 flags['asm_flags'] += asm_defines
dkato 0:f782d9c66c49 95 flags['c_flags'] += c_defines
dkato 0:f782d9c66c49 96 flags['cxx_flags'] += c_defines
dkato 0:f782d9c66c49 97 if config_header:
dkato 0:f782d9c66c49 98 config_header = relpath(config_header,
dkato 0:f782d9c66c49 99 self.resources.file_basepath[config_header])
dkato 0:f782d9c66c49 100 flags['c_flags'] += self.toolchain.get_config_option(config_header)
dkato 0:f782d9c66c49 101 flags['cxx_flags'] += self.toolchain.get_config_option(
dkato 0:f782d9c66c49 102 config_header)
dkato 0:f782d9c66c49 103 return flags
dkato 0:f782d9c66c49 104
dkato 0:f782d9c66c49 105 def get_source_paths(self):
dkato 0:f782d9c66c49 106 """Returns a list of the directories where source files are contained"""
dkato 0:f782d9c66c49 107 source_keys = ['s_sources', 'c_sources', 'cpp_sources', 'hex_files',
dkato 0:f782d9c66c49 108 'objects', 'libraries']
dkato 0:f782d9c66c49 109 source_files = []
dkato 0:f782d9c66c49 110 for key in source_keys:
dkato 0:f782d9c66c49 111 source_files.extend(getattr(self.resources, key))
dkato 0:f782d9c66c49 112 return list(set([os.path.dirname(src) for src in source_files]))
dkato 0:f782d9c66c49 113
dkato 0:f782d9c66c49 114 def gen_file(self, template_file, data, target_file, **kwargs):
dkato 0:f782d9c66c49 115 """Generates a project file from a template using jinja"""
dkato 0:f782d9c66c49 116 jinja_loader = FileSystemLoader(
dkato 0:f782d9c66c49 117 os.path.dirname(os.path.abspath(__file__)))
dkato 0:f782d9c66c49 118 jinja_environment = Environment(loader=jinja_loader,
dkato 0:f782d9c66c49 119 undefined=StrictUndefined, **kwargs)
dkato 0:f782d9c66c49 120
dkato 0:f782d9c66c49 121 template = jinja_environment.get_template(template_file)
dkato 0:f782d9c66c49 122 target_text = template.render(data)
dkato 0:f782d9c66c49 123
dkato 0:f782d9c66c49 124 target_path = join(self.export_dir, target_file)
dkato 0:f782d9c66c49 125 logging.debug("Generating: %s", target_path)
dkato 0:f782d9c66c49 126 open(target_path, "w").write(target_text)
dkato 0:f782d9c66c49 127 self.generated_files += [target_path]
dkato 0:f782d9c66c49 128
dkato 0:f782d9c66c49 129 def make_key(self, src):
dkato 0:f782d9c66c49 130 """From a source file, extract group name
dkato 0:f782d9c66c49 131 Positional Arguments:
dkato 0:f782d9c66c49 132 src - the src's location
dkato 0:f782d9c66c49 133 """
dkato 0:f782d9c66c49 134 rel_path = relpath(src, self.resources.file_basepath[src])
dkato 0:f782d9c66c49 135 path_list = os.path.normpath(rel_path).split(os.sep)
dkato 0:f782d9c66c49 136 assert len(path_list) >= 1
dkato 0:f782d9c66c49 137 if len(path_list) == 1:
dkato 0:f782d9c66c49 138 key = self.project_name
dkato 0:f782d9c66c49 139 else:
dkato 0:f782d9c66c49 140 key = path_list[0]
dkato 0:f782d9c66c49 141 return key
dkato 0:f782d9c66c49 142
dkato 0:f782d9c66c49 143 def group_project_files(self, sources):
dkato 0:f782d9c66c49 144 """Group the source files by their encompassing directory
dkato 0:f782d9c66c49 145 Positional Arguments:
dkato 0:f782d9c66c49 146 sources - array of source locations
dkato 0:f782d9c66c49 147
dkato 0:f782d9c66c49 148 Returns a dictionary of {group name: list of source locations}
dkato 0:f782d9c66c49 149 """
dkato 0:f782d9c66c49 150 data = sorted(sources, key=self.make_key)
dkato 0:f782d9c66c49 151 return {k: list(g) for k,g in groupby(data, self.make_key)}
dkato 0:f782d9c66c49 152
dkato 0:f782d9c66c49 153 @staticmethod
dkato 0:f782d9c66c49 154 def build(project_name, log_name='build_log.txt', cleanup=True):
dkato 0:f782d9c66c49 155 """Invoke exporters build command within a subprocess.
dkato 0:f782d9c66c49 156 This method is assumed to be executed at the same level as exporter
dkato 0:f782d9c66c49 157 project files and project source code.
dkato 0:f782d9c66c49 158 See uvision/__init__.py, iar/__init__.py, and makefile/__init__.py for
dkato 0:f782d9c66c49 159 example implemenation.
dkato 0:f782d9c66c49 160
dkato 0:f782d9c66c49 161 Positional Arguments:
dkato 0:f782d9c66c49 162 project_name - the name of the project to build; often required by
dkato 0:f782d9c66c49 163 exporter's build command.
dkato 0:f782d9c66c49 164
dkato 0:f782d9c66c49 165 Keyword Args:
dkato 0:f782d9c66c49 166 log_name - name of the build log to create. Written and printed out,
dkato 0:f782d9c66c49 167 deleted if cleanup = True
dkato 0:f782d9c66c49 168 cleanup - a boolean dictating whether exported project files and
dkato 0:f782d9c66c49 169 build log are removed after build
dkato 0:f782d9c66c49 170
dkato 0:f782d9c66c49 171 Returns -1 on failure and 0 on success
dkato 0:f782d9c66c49 172 """
dkato 0:f782d9c66c49 173 raise NotImplemented("Implement in derived Exporter class.")
dkato 0:f782d9c66c49 174
dkato 0:f782d9c66c49 175 @abstractmethod
dkato 0:f782d9c66c49 176 def generate(self):
dkato 0:f782d9c66c49 177 """Generate an IDE/tool specific project file"""
dkato 0:f782d9c66c49 178 raise NotImplemented("Implement a generate function in Exporter child class")
dkato 0:f782d9c66c49 179
dkato 0:f782d9c66c49 180
dkato 0:f782d9c66c49 181 def filter_supported(compiler, whitelist):
dkato 0:f782d9c66c49 182 """Generate a list of supported targets for a given compiler and post-binary hook
dkato 0:f782d9c66c49 183 white-list."""
dkato 0:f782d9c66c49 184 def supported_p(obj):
dkato 0:f782d9c66c49 185 """Internal inner function used for filtering"""
dkato 0:f782d9c66c49 186 if compiler not in obj.supported_toolchains:
dkato 0:f782d9c66c49 187 return False
dkato 0:f782d9c66c49 188 if not hasattr(obj, "post_binary_hook"):
dkato 0:f782d9c66c49 189 return True
dkato 0:f782d9c66c49 190 if obj.post_binary_hook['function'] in whitelist:
dkato 0:f782d9c66c49 191 return True
dkato 0:f782d9c66c49 192 else:
dkato 0:f782d9c66c49 193 return False
dkato 0:f782d9c66c49 194 return list(target for target, obj in TARGET_MAP.iteritems()
dkato 0:f782d9c66c49 195 if supported_p(obj))