Gleb Klochkov / Mbed OS Climatcontroll_Main

Dependencies:   esp8266-driver

Committer:
glebiuskv
Date:
Fri Apr 13 08:53:46 2018 +0000
Revision:
0:2f0e1e23c242
initial

Who changed what in which revision?

UserRevisionLine numberNew contents of line
glebiuskv 0:2f0e1e23c242 1 """Just a template for subclassing"""
glebiuskv 0:2f0e1e23c242 2 import os
glebiuskv 0:2f0e1e23c242 3 from abc import abstractmethod, ABCMeta
glebiuskv 0:2f0e1e23c242 4 import logging
glebiuskv 0:2f0e1e23c242 5 from os.path import join, dirname, relpath, basename, realpath, normpath, exists
glebiuskv 0:2f0e1e23c242 6 from itertools import groupby
glebiuskv 0:2f0e1e23c242 7 from jinja2 import FileSystemLoader, StrictUndefined
glebiuskv 0:2f0e1e23c242 8 from jinja2.environment import Environment
glebiuskv 0:2f0e1e23c242 9 import copy
glebiuskv 0:2f0e1e23c242 10
glebiuskv 0:2f0e1e23c242 11 from tools.targets import TARGET_MAP
glebiuskv 0:2f0e1e23c242 12
glebiuskv 0:2f0e1e23c242 13
glebiuskv 0:2f0e1e23c242 14 class TargetNotSupportedException(Exception):
glebiuskv 0:2f0e1e23c242 15 """Indicates that an IDE does not support a particular MCU"""
glebiuskv 0:2f0e1e23c242 16 pass
glebiuskv 0:2f0e1e23c242 17
glebiuskv 0:2f0e1e23c242 18 class ExporterTargetsProperty(object):
glebiuskv 0:2f0e1e23c242 19 """ Exporter descriptor for TARGETS
glebiuskv 0:2f0e1e23c242 20 TARGETS as class attribute for backward compatibility
glebiuskv 0:2f0e1e23c242 21 (allows: if in Exporter.TARGETS)
glebiuskv 0:2f0e1e23c242 22 """
glebiuskv 0:2f0e1e23c242 23 def __init__(self, func):
glebiuskv 0:2f0e1e23c242 24 self.func = func
glebiuskv 0:2f0e1e23c242 25 def __get__(self, inst, cls):
glebiuskv 0:2f0e1e23c242 26 return self.func(cls)
glebiuskv 0:2f0e1e23c242 27
glebiuskv 0:2f0e1e23c242 28 def deprecated_exporter(CLS):
glebiuskv 0:2f0e1e23c242 29 old_init = CLS.__init__
glebiuskv 0:2f0e1e23c242 30 old_name = CLS.NAME
glebiuskv 0:2f0e1e23c242 31 def __init__(*args, **kwargs):
glebiuskv 0:2f0e1e23c242 32 print("==================== DEPRECATION NOTICE ====================")
glebiuskv 0:2f0e1e23c242 33 print("The exporter %s is no longer maintained, and deprecated." % old_name)
glebiuskv 0:2f0e1e23c242 34 print("%s will be removed from mbed OS for the mbed OS 5.6 release." % old_name)
glebiuskv 0:2f0e1e23c242 35 old_init(*args, **kwargs)
glebiuskv 0:2f0e1e23c242 36 CLS.__init__ = __init__
glebiuskv 0:2f0e1e23c242 37 CLS.NAME = "%s (DEPRECATED)" % old_name
glebiuskv 0:2f0e1e23c242 38 return CLS
glebiuskv 0:2f0e1e23c242 39
glebiuskv 0:2f0e1e23c242 40 class Exporter(object):
glebiuskv 0:2f0e1e23c242 41 """Exporter base class
glebiuskv 0:2f0e1e23c242 42
glebiuskv 0:2f0e1e23c242 43 This class is meant to be extended by individual exporters, and provides a
glebiuskv 0:2f0e1e23c242 44 few helper methods for implementing an exporter with either jinja2 or
glebiuskv 0:2f0e1e23c242 45 progen.
glebiuskv 0:2f0e1e23c242 46 """
glebiuskv 0:2f0e1e23c242 47 __metaclass__ = ABCMeta
glebiuskv 0:2f0e1e23c242 48 TEMPLATE_DIR = dirname(__file__)
glebiuskv 0:2f0e1e23c242 49 DOT_IN_RELATIVE_PATH = False
glebiuskv 0:2f0e1e23c242 50 NAME = None
glebiuskv 0:2f0e1e23c242 51 TARGETS = set()
glebiuskv 0:2f0e1e23c242 52 TOOLCHAIN = None
glebiuskv 0:2f0e1e23c242 53 CLEAN_FILES = ("GettingStarted.html",)
glebiuskv 0:2f0e1e23c242 54
glebiuskv 0:2f0e1e23c242 55
glebiuskv 0:2f0e1e23c242 56 def __init__(self, target, export_dir, project_name, toolchain,
glebiuskv 0:2f0e1e23c242 57 extra_symbols=None, resources=None):
glebiuskv 0:2f0e1e23c242 58 """Initialize an instance of class exporter
glebiuskv 0:2f0e1e23c242 59 Positional arguments:
glebiuskv 0:2f0e1e23c242 60 target - the target mcu/board for this project
glebiuskv 0:2f0e1e23c242 61 export_dir - the directory of the exported project files
glebiuskv 0:2f0e1e23c242 62 project_name - the name of the project
glebiuskv 0:2f0e1e23c242 63 toolchain - an instance of class toolchain
glebiuskv 0:2f0e1e23c242 64
glebiuskv 0:2f0e1e23c242 65 Keyword arguments:
glebiuskv 0:2f0e1e23c242 66 extra_symbols - a list of extra macros for the toolchain
glebiuskv 0:2f0e1e23c242 67 resources - an instance of class Resources
glebiuskv 0:2f0e1e23c242 68 """
glebiuskv 0:2f0e1e23c242 69 self.export_dir = export_dir
glebiuskv 0:2f0e1e23c242 70 self.target = target
glebiuskv 0:2f0e1e23c242 71 self.project_name = project_name
glebiuskv 0:2f0e1e23c242 72 self.toolchain = toolchain
glebiuskv 0:2f0e1e23c242 73 jinja_loader = FileSystemLoader(os.path.dirname(os.path.abspath(__file__)))
glebiuskv 0:2f0e1e23c242 74 self.jinja_environment = Environment(loader=jinja_loader)
glebiuskv 0:2f0e1e23c242 75 self.resources = resources
glebiuskv 0:2f0e1e23c242 76 self.generated_files = []
glebiuskv 0:2f0e1e23c242 77 self.static_files = (
glebiuskv 0:2f0e1e23c242 78 join(self.TEMPLATE_DIR, "GettingStarted.html"),
glebiuskv 0:2f0e1e23c242 79 join(self.TEMPLATE_DIR, ".mbed"),
glebiuskv 0:2f0e1e23c242 80 )
glebiuskv 0:2f0e1e23c242 81 self.builder_files_dict = {}
glebiuskv 0:2f0e1e23c242 82 self.add_config()
glebiuskv 0:2f0e1e23c242 83
glebiuskv 0:2f0e1e23c242 84 def get_toolchain(self):
glebiuskv 0:2f0e1e23c242 85 """A helper getter function that we should probably eliminate"""
glebiuskv 0:2f0e1e23c242 86 return self.TOOLCHAIN
glebiuskv 0:2f0e1e23c242 87
glebiuskv 0:2f0e1e23c242 88 def add_config(self):
glebiuskv 0:2f0e1e23c242 89 """Add the containgin directory of mbed_config.h to include dirs"""
glebiuskv 0:2f0e1e23c242 90 config = self.toolchain.get_config_header()
glebiuskv 0:2f0e1e23c242 91 if config:
glebiuskv 0:2f0e1e23c242 92 self.resources.inc_dirs.append(
glebiuskv 0:2f0e1e23c242 93 dirname(relpath(config,
glebiuskv 0:2f0e1e23c242 94 self.resources.file_basepath[config])))
glebiuskv 0:2f0e1e23c242 95
glebiuskv 0:2f0e1e23c242 96 @property
glebiuskv 0:2f0e1e23c242 97 def flags(self):
glebiuskv 0:2f0e1e23c242 98 """Returns a dictionary of toolchain flags.
glebiuskv 0:2f0e1e23c242 99 Keys of the dictionary are:
glebiuskv 0:2f0e1e23c242 100 cxx_flags - c++ flags
glebiuskv 0:2f0e1e23c242 101 c_flags - c flags
glebiuskv 0:2f0e1e23c242 102 ld_flags - linker flags
glebiuskv 0:2f0e1e23c242 103 asm_flags - assembler flags
glebiuskv 0:2f0e1e23c242 104 common_flags - common options
glebiuskv 0:2f0e1e23c242 105 """
glebiuskv 0:2f0e1e23c242 106 config_header = self.toolchain.get_config_header()
glebiuskv 0:2f0e1e23c242 107 flags = {key + "_flags": copy.deepcopy(value) for key, value
glebiuskv 0:2f0e1e23c242 108 in self.toolchain.flags.items()}
glebiuskv 0:2f0e1e23c242 109 asm_defines = self.toolchain.get_compile_options(
glebiuskv 0:2f0e1e23c242 110 self.toolchain.get_symbols(for_asm=True),
glebiuskv 0:2f0e1e23c242 111 filter(None, self.resources.inc_dirs),
glebiuskv 0:2f0e1e23c242 112 for_asm=True)
glebiuskv 0:2f0e1e23c242 113 c_defines = ["-D" + symbol for symbol in self.toolchain.get_symbols()]
glebiuskv 0:2f0e1e23c242 114 flags['asm_flags'] += asm_defines
glebiuskv 0:2f0e1e23c242 115 flags['c_flags'] += c_defines
glebiuskv 0:2f0e1e23c242 116 flags['cxx_flags'] += c_defines
glebiuskv 0:2f0e1e23c242 117 if config_header:
glebiuskv 0:2f0e1e23c242 118 config_header = relpath(config_header,
glebiuskv 0:2f0e1e23c242 119 self.resources.file_basepath[config_header])
glebiuskv 0:2f0e1e23c242 120 flags['c_flags'] += self.toolchain.get_config_option(config_header)
glebiuskv 0:2f0e1e23c242 121 flags['cxx_flags'] += self.toolchain.get_config_option(
glebiuskv 0:2f0e1e23c242 122 config_header)
glebiuskv 0:2f0e1e23c242 123 return flags
glebiuskv 0:2f0e1e23c242 124
glebiuskv 0:2f0e1e23c242 125 def get_source_paths(self):
glebiuskv 0:2f0e1e23c242 126 """Returns a list of the directories where source files are contained"""
glebiuskv 0:2f0e1e23c242 127 source_keys = ['s_sources', 'c_sources', 'cpp_sources', 'hex_files',
glebiuskv 0:2f0e1e23c242 128 'objects', 'libraries']
glebiuskv 0:2f0e1e23c242 129 source_files = []
glebiuskv 0:2f0e1e23c242 130 for key in source_keys:
glebiuskv 0:2f0e1e23c242 131 source_files.extend(getattr(self.resources, key))
glebiuskv 0:2f0e1e23c242 132 return list(set([os.path.dirname(src) for src in source_files]))
glebiuskv 0:2f0e1e23c242 133
glebiuskv 0:2f0e1e23c242 134 def gen_file_dest(self, target_file):
glebiuskv 0:2f0e1e23c242 135 """Generate the project file location in an exported project"""
glebiuskv 0:2f0e1e23c242 136 return join(self.export_dir, target_file)
glebiuskv 0:2f0e1e23c242 137
glebiuskv 0:2f0e1e23c242 138 def gen_file(self, template_file, data, target_file, **kwargs):
glebiuskv 0:2f0e1e23c242 139 """Generates a project file from a template using jinja"""
glebiuskv 0:2f0e1e23c242 140 target_text = self._gen_file_inner(template_file, data, target_file, **kwargs)
glebiuskv 0:2f0e1e23c242 141 target_path = self.gen_file_dest(target_file)
glebiuskv 0:2f0e1e23c242 142 logging.debug("Generating: %s", target_path)
glebiuskv 0:2f0e1e23c242 143 open(target_path, "w").write(target_text)
glebiuskv 0:2f0e1e23c242 144 self.generated_files += [target_path]
glebiuskv 0:2f0e1e23c242 145
glebiuskv 0:2f0e1e23c242 146 def gen_file_nonoverwrite(self, template_file, data, target_file, **kwargs):
glebiuskv 0:2f0e1e23c242 147 """Generates a project file from a template using jinja"""
glebiuskv 0:2f0e1e23c242 148 target_text = self._gen_file_inner(template_file, data, target_file, **kwargs)
glebiuskv 0:2f0e1e23c242 149 target_path = self.gen_file_dest(target_file)
glebiuskv 0:2f0e1e23c242 150 if exists(target_path):
glebiuskv 0:2f0e1e23c242 151 with open(target_path) as fdin:
glebiuskv 0:2f0e1e23c242 152 old_text = fdin.read()
glebiuskv 0:2f0e1e23c242 153 if target_text not in old_text:
glebiuskv 0:2f0e1e23c242 154 with open(target_path, "a") as fdout:
glebiuskv 0:2f0e1e23c242 155 fdout.write(target_text)
glebiuskv 0:2f0e1e23c242 156 else:
glebiuskv 0:2f0e1e23c242 157 logging.debug("Generating: %s", target_path)
glebiuskv 0:2f0e1e23c242 158 open(target_path, "w").write(target_text)
glebiuskv 0:2f0e1e23c242 159 self.generated_files += [target_path]
glebiuskv 0:2f0e1e23c242 160
glebiuskv 0:2f0e1e23c242 161 def _gen_file_inner(self, template_file, data, target_file, **kwargs):
glebiuskv 0:2f0e1e23c242 162 """Generates a project file from a template using jinja"""
glebiuskv 0:2f0e1e23c242 163 jinja_loader = FileSystemLoader(
glebiuskv 0:2f0e1e23c242 164 os.path.dirname(os.path.abspath(__file__)))
glebiuskv 0:2f0e1e23c242 165 jinja_environment = Environment(loader=jinja_loader,
glebiuskv 0:2f0e1e23c242 166 undefined=StrictUndefined, **kwargs)
glebiuskv 0:2f0e1e23c242 167
glebiuskv 0:2f0e1e23c242 168 template = jinja_environment.get_template(template_file)
glebiuskv 0:2f0e1e23c242 169 target_text = template.render(data)
glebiuskv 0:2f0e1e23c242 170 return target_text
glebiuskv 0:2f0e1e23c242 171
glebiuskv 0:2f0e1e23c242 172 target_path = join(self.export_dir, target_file)
glebiuskv 0:2f0e1e23c242 173 logging.debug("Generating: %s", target_path)
glebiuskv 0:2f0e1e23c242 174 open(target_path, "w").write(target_text)
glebiuskv 0:2f0e1e23c242 175 self.generated_files += [target_path]
glebiuskv 0:2f0e1e23c242 176
glebiuskv 0:2f0e1e23c242 177 def make_key(self, src):
glebiuskv 0:2f0e1e23c242 178 """From a source file, extract group name
glebiuskv 0:2f0e1e23c242 179 Positional Arguments:
glebiuskv 0:2f0e1e23c242 180 src - the src's location
glebiuskv 0:2f0e1e23c242 181 """
glebiuskv 0:2f0e1e23c242 182 rel_path = relpath(src, self.resources.file_basepath[src])
glebiuskv 0:2f0e1e23c242 183 path_list = os.path.normpath(rel_path).split(os.sep)
glebiuskv 0:2f0e1e23c242 184 assert len(path_list) >= 1
glebiuskv 0:2f0e1e23c242 185 if len(path_list) == 1:
glebiuskv 0:2f0e1e23c242 186 key = self.project_name
glebiuskv 0:2f0e1e23c242 187 else:
glebiuskv 0:2f0e1e23c242 188 key = path_list[0]
glebiuskv 0:2f0e1e23c242 189 return key
glebiuskv 0:2f0e1e23c242 190
glebiuskv 0:2f0e1e23c242 191 def group_project_files(self, sources):
glebiuskv 0:2f0e1e23c242 192 """Group the source files by their encompassing directory
glebiuskv 0:2f0e1e23c242 193 Positional Arguments:
glebiuskv 0:2f0e1e23c242 194 sources - array of source locations
glebiuskv 0:2f0e1e23c242 195
glebiuskv 0:2f0e1e23c242 196 Returns a dictionary of {group name: list of source locations}
glebiuskv 0:2f0e1e23c242 197 """
glebiuskv 0:2f0e1e23c242 198 data = sorted(sources, key=self.make_key)
glebiuskv 0:2f0e1e23c242 199 return {k: list(g) for k,g in groupby(data, self.make_key)}
glebiuskv 0:2f0e1e23c242 200
glebiuskv 0:2f0e1e23c242 201 @staticmethod
glebiuskv 0:2f0e1e23c242 202 def build(project_name, log_name='build_log.txt', cleanup=True):
glebiuskv 0:2f0e1e23c242 203 """Invoke exporters build command within a subprocess.
glebiuskv 0:2f0e1e23c242 204 This method is assumed to be executed at the same level as exporter
glebiuskv 0:2f0e1e23c242 205 project files and project source code.
glebiuskv 0:2f0e1e23c242 206 See uvision/__init__.py, iar/__init__.py, and makefile/__init__.py for
glebiuskv 0:2f0e1e23c242 207 example implemenation.
glebiuskv 0:2f0e1e23c242 208
glebiuskv 0:2f0e1e23c242 209 Positional Arguments:
glebiuskv 0:2f0e1e23c242 210 project_name - the name of the project to build; often required by
glebiuskv 0:2f0e1e23c242 211 exporter's build command.
glebiuskv 0:2f0e1e23c242 212
glebiuskv 0:2f0e1e23c242 213 Keyword Args:
glebiuskv 0:2f0e1e23c242 214 log_name - name of the build log to create. Written and printed out,
glebiuskv 0:2f0e1e23c242 215 deleted if cleanup = True
glebiuskv 0:2f0e1e23c242 216 cleanup - a boolean dictating whether exported project files and
glebiuskv 0:2f0e1e23c242 217 build log are removed after build
glebiuskv 0:2f0e1e23c242 218
glebiuskv 0:2f0e1e23c242 219 Returns -1 on failure and 0 on success
glebiuskv 0:2f0e1e23c242 220 """
glebiuskv 0:2f0e1e23c242 221 raise NotImplementedError("Implement in derived Exporter class.")
glebiuskv 0:2f0e1e23c242 222
glebiuskv 0:2f0e1e23c242 223 @staticmethod
glebiuskv 0:2f0e1e23c242 224 def clean(project_name):
glebiuskv 0:2f0e1e23c242 225 """Clean a previously exported project
glebiuskv 0:2f0e1e23c242 226 This method is assumed to be executed at the same level as exporter
glebiuskv 0:2f0e1e23c242 227 project files and project source code.
glebiuskv 0:2f0e1e23c242 228 See uvision/__init__.py, iar/__init__.py, and makefile/__init__.py for
glebiuskv 0:2f0e1e23c242 229 example implemenation.
glebiuskv 0:2f0e1e23c242 230
glebiuskv 0:2f0e1e23c242 231 Positional Arguments:
glebiuskv 0:2f0e1e23c242 232 project_name - the name of the project to build; often required by
glebiuskv 0:2f0e1e23c242 233 exporter's build command.
glebiuskv 0:2f0e1e23c242 234
glebiuskv 0:2f0e1e23c242 235 Returns nothing. May raise exceptions
glebiuskv 0:2f0e1e23c242 236 """
glebiuskv 0:2f0e1e23c242 237 raise NotImplementedError("Implement in derived Exporter class.")
glebiuskv 0:2f0e1e23c242 238
glebiuskv 0:2f0e1e23c242 239 @abstractmethod
glebiuskv 0:2f0e1e23c242 240 def generate(self):
glebiuskv 0:2f0e1e23c242 241 """Generate an IDE/tool specific project file"""
glebiuskv 0:2f0e1e23c242 242 raise NotImplementedError("Implement a generate function in Exporter child class")
glebiuskv 0:2f0e1e23c242 243
glebiuskv 0:2f0e1e23c242 244 @classmethod
glebiuskv 0:2f0e1e23c242 245 def is_target_supported(cls, target_name):
glebiuskv 0:2f0e1e23c242 246 """Query support for a particular target
glebiuskv 0:2f0e1e23c242 247
glebiuskv 0:2f0e1e23c242 248 NOTE: override this method if your exporter does not provide a static list of targets
glebiuskv 0:2f0e1e23c242 249
glebiuskv 0:2f0e1e23c242 250 Positional Arguments:
glebiuskv 0:2f0e1e23c242 251 target_name - the name of the target.
glebiuskv 0:2f0e1e23c242 252 """
glebiuskv 0:2f0e1e23c242 253 target = TARGET_MAP[target_name]
glebiuskv 0:2f0e1e23c242 254 return bool(set(target.resolution_order_names).intersection(set(cls.TARGETS))) \
glebiuskv 0:2f0e1e23c242 255 and cls.TOOLCHAIN in target.supported_toolchains
glebiuskv 0:2f0e1e23c242 256
glebiuskv 0:2f0e1e23c242 257
glebiuskv 0:2f0e1e23c242 258 @classmethod
glebiuskv 0:2f0e1e23c242 259 def all_supported_targets(cls):
glebiuskv 0:2f0e1e23c242 260 return [t for t in TARGET_MAP.keys() if cls.is_target_supported(t)]
glebiuskv 0:2f0e1e23c242 261
glebiuskv 0:2f0e1e23c242 262 @staticmethod
glebiuskv 0:2f0e1e23c242 263 def filter_dot(str):
glebiuskv 0:2f0e1e23c242 264 """
glebiuskv 0:2f0e1e23c242 265 Remove the './' or '.\\' prefix, if present.
glebiuskv 0:2f0e1e23c242 266 """
glebiuskv 0:2f0e1e23c242 267 if str == None:
glebiuskv 0:2f0e1e23c242 268 return None
glebiuskv 0:2f0e1e23c242 269 if str[:2] == './':
glebiuskv 0:2f0e1e23c242 270 return str[2:]
glebiuskv 0:2f0e1e23c242 271 if str[:2] == '.\\':
glebiuskv 0:2f0e1e23c242 272 return str[2:]
glebiuskv 0:2f0e1e23c242 273 return str
glebiuskv 0:2f0e1e23c242 274
glebiuskv 0:2f0e1e23c242 275
glebiuskv 0:2f0e1e23c242 276
glebiuskv 0:2f0e1e23c242 277 def apply_supported_whitelist(compiler, whitelist, target):
glebiuskv 0:2f0e1e23c242 278 """Generate a list of supported targets for a given compiler and post-binary hook
glebiuskv 0:2f0e1e23c242 279 white-list."""
glebiuskv 0:2f0e1e23c242 280 if compiler not in target.supported_toolchains:
glebiuskv 0:2f0e1e23c242 281 return False
glebiuskv 0:2f0e1e23c242 282 if not hasattr(target, "post_binary_hook"):
glebiuskv 0:2f0e1e23c242 283 return True
glebiuskv 0:2f0e1e23c242 284 if target.post_binary_hook['function'] in whitelist:
glebiuskv 0:2f0e1e23c242 285 return True
glebiuskv 0:2f0e1e23c242 286 else:
glebiuskv 0:2f0e1e23c242 287 return False