Marco Zecchini
/
Example_RTOS
Rtos API example
Embed:
(wiki syntax)
Show/hide line numbers
exporters.py
00001 """Just a template for subclassing""" 00002 import os 00003 from abc import abstractmethod, ABCMeta 00004 import logging 00005 from os.path import join, dirname, relpath, basename, realpath, normpath 00006 from itertools import groupby 00007 from jinja2 import FileSystemLoader, StrictUndefined 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 def deprecated_exporter(CLS): 00029 old_init = CLS.__init__ 00030 old_name = CLS.NAME 00031 def __init__(*args, **kwargs): 00032 print("==================== DEPRECATION NOTICE ====================") 00033 print("The exporter %s is no longer maintained, and deprecated." % old_name) 00034 print("%s will be removed from mbed OS for the mbed OS 5.6 release." % old_name) 00035 old_init(*args, **kwargs) 00036 CLS.__init__ = __init__ 00037 CLS.NAME = "%s (DEPRECATED)" % old_name 00038 return CLS 00039 00040 class Exporter (object): 00041 """Exporter base class 00042 00043 This class is meant to be extended by individual exporters, and provides a 00044 few helper methods for implementing an exporter with either jinja2 or 00045 progen. 00046 """ 00047 __metaclass__ = ABCMeta 00048 TEMPLATE_DIR = dirname(__file__) 00049 DOT_IN_RELATIVE_PATH = False 00050 NAME = None 00051 TARGETS = set() 00052 TOOLCHAIN = None 00053 00054 00055 def __init__ (self, target, export_dir, project_name, toolchain, 00056 extra_symbols=None, resources=None): 00057 """Initialize an instance of class exporter 00058 Positional arguments: 00059 target - the target mcu/board for this project 00060 export_dir - the directory of the exported project files 00061 project_name - the name of the project 00062 toolchain - an instance of class toolchain 00063 00064 Keyword arguments: 00065 extra_symbols - a list of extra macros for the toolchain 00066 resources - an instance of class Resources 00067 """ 00068 self.export_dir = export_dir 00069 self.target = target 00070 self.project_name = project_name 00071 self.toolchain = toolchain 00072 jinja_loader = FileSystemLoader(os.path.dirname(os.path.abspath(__file__))) 00073 self.jinja_environment = Environment(loader=jinja_loader) 00074 self.resources = resources 00075 self.generated_files = [] 00076 self.static_files = ( 00077 join(self.TEMPLATE_DIR , "GettingStarted.html"), 00078 join(self.TEMPLATE_DIR , ".mbed"), 00079 ) 00080 self.builder_files_dict = {} 00081 self.add_config () 00082 00083 def get_toolchain (self): 00084 """A helper getter function that we should probably eliminate""" 00085 return self.TOOLCHAIN 00086 00087 def add_config (self): 00088 """Add the containgin directory of mbed_config.h to include dirs""" 00089 config = self.toolchain .get_config_header() 00090 if config: 00091 self.resources .inc_dirs.append( 00092 dirname(relpath(config, 00093 self.resources .file_basepath[config]))) 00094 00095 @property 00096 def flags (self): 00097 """Returns a dictionary of toolchain flags. 00098 Keys of the dictionary are: 00099 cxx_flags - c++ flags 00100 c_flags - c flags 00101 ld_flags - linker flags 00102 asm_flags - assembler flags 00103 common_flags - common options 00104 """ 00105 config_header = self.toolchain .get_config_header() 00106 flags = {key + "_flags": copy.deepcopy(value) for key, value 00107 in self.toolchain .flags.iteritems()} 00108 asm_defines = self.toolchain .get_compile_options( 00109 self.toolchain .get_symbols(for_asm=True), 00110 filter(None, self.resources .inc_dirs), 00111 for_asm=True) 00112 c_defines = ["-D" + symbol for symbol in self.toolchain .get_symbols()] 00113 flags['asm_flags'] += asm_defines 00114 flags['c_flags'] += c_defines 00115 flags['cxx_flags'] += c_defines 00116 if config_header: 00117 config_header = relpath(config_header, 00118 self.resources .file_basepath[config_header]) 00119 flags['c_flags'] += self.toolchain .get_config_option(config_header) 00120 flags['cxx_flags'] += self.toolchain .get_config_option( 00121 config_header) 00122 return flags 00123 00124 def get_source_paths (self): 00125 """Returns a list of the directories where source files are contained""" 00126 source_keys = ['s_sources', 'c_sources', 'cpp_sources', 'hex_files', 00127 'objects', 'libraries'] 00128 source_files = [] 00129 for key in source_keys: 00130 source_files.extend(getattr(self.resources , key)) 00131 return list(set([os.path.dirname(src) for src in source_files])) 00132 00133 def gen_file (self, template_file, data, target_file, **kwargs): 00134 """Generates a project file from a template using jinja""" 00135 jinja_loader = FileSystemLoader( 00136 os.path.dirname(os.path.abspath(__file__))) 00137 jinja_environment = Environment(loader=jinja_loader, 00138 undefined=StrictUndefined, **kwargs) 00139 00140 template = jinja_environment.get_template(template_file) 00141 target_text = template.render(data) 00142 00143 target_path = join(self.export_dir , target_file) 00144 logging.debug("Generating: %s", target_path) 00145 open(target_path, "w").write(target_text) 00146 self.generated_files += [target_path] 00147 00148 def make_key (self, src): 00149 """From a source file, extract group name 00150 Positional Arguments: 00151 src - the src's location 00152 """ 00153 rel_path = relpath(src, self.resources .file_basepath[src]) 00154 path_list = os.path.normpath(rel_path).split(os.sep) 00155 assert len(path_list) >= 1 00156 if len(path_list) == 1: 00157 key = self.project_name 00158 else: 00159 key = path_list[0] 00160 return key 00161 00162 def group_project_files (self, sources): 00163 """Group the source files by their encompassing directory 00164 Positional Arguments: 00165 sources - array of source locations 00166 00167 Returns a dictionary of {group name: list of source locations} 00168 """ 00169 data = sorted(sources, key=self.make_key ) 00170 return {k: list(g) for k,g in groupby(data, self.make_key )} 00171 00172 @staticmethod 00173 def build (project_name, log_name='build_log.txt', cleanup=True): 00174 """Invoke exporters build command within a subprocess. 00175 This method is assumed to be executed at the same level as exporter 00176 project files and project source code. 00177 See uvision/__init__.py, iar/__init__.py, and makefile/__init__.py for 00178 example implemenation. 00179 00180 Positional Arguments: 00181 project_name - the name of the project to build; often required by 00182 exporter's build command. 00183 00184 Keyword Args: 00185 log_name - name of the build log to create. Written and printed out, 00186 deleted if cleanup = True 00187 cleanup - a boolean dictating whether exported project files and 00188 build log are removed after build 00189 00190 Returns -1 on failure and 0 on success 00191 """ 00192 raise NotImplemented("Implement in derived Exporter class.") 00193 00194 @abstractmethod 00195 def generate (self): 00196 """Generate an IDE/tool specific project file""" 00197 raise NotImplemented("Implement a generate function in Exporter child class") 00198 00199 @classmethod 00200 def is_target_supported (cls, target_name): 00201 """Query support for a particular target 00202 00203 NOTE: override this method if your exporter does not provide a static list of targets 00204 00205 Positional Arguments: 00206 target_name - the name of the target. 00207 """ 00208 target = TARGET_MAP[target_name] 00209 return bool(set(target.resolution_order_names).intersection(set(cls.TARGETS))) \ 00210 and cls.TOOLCHAIN in target.supported_toolchains 00211 00212 00213 @classmethod 00214 def all_supported_targets(cls): 00215 return [t for t in TARGET_MAP.keys() if cls.is_target_supported(t)] 00216 00217 00218 def apply_supported_whitelist (compiler, whitelist, target): 00219 """Generate a list of supported targets for a given compiler and post-binary hook 00220 white-list.""" 00221 if compiler not in target.supported_toolchains: 00222 return False 00223 if not hasattr(target, "post_binary_hook"): 00224 return True 00225 if target.post_binary_hook['function'] in whitelist: 00226 return True 00227 else: 00228 return False
Generated on Sun Jul 17 2022 08:25:22 by 1.7.2