Includes library modifications to allow access to AIN_4 (AIN_0 / 5)

Committer:
bryantaylor
Date:
Tue Sep 20 21:26:12 2016 +0000
Revision:
0:eafc3fd41f75
hackathon

Who changed what in which revision?

UserRevisionLine numberNew contents of line
bryantaylor 0:eafc3fd41f75 1 """Just a template for subclassing"""
bryantaylor 0:eafc3fd41f75 2 import os
bryantaylor 0:eafc3fd41f75 3 import sys
bryantaylor 0:eafc3fd41f75 4 import logging
bryantaylor 0:eafc3fd41f75 5 from os.path import join, dirname, relpath
bryantaylor 0:eafc3fd41f75 6 from itertools import groupby
bryantaylor 0:eafc3fd41f75 7 from jinja2 import FileSystemLoader
bryantaylor 0:eafc3fd41f75 8 from jinja2.environment import Environment
bryantaylor 0:eafc3fd41f75 9
bryantaylor 0:eafc3fd41f75 10 from tools.targets import TARGET_MAP
bryantaylor 0:eafc3fd41f75 11 from project_generator.tools import tool
bryantaylor 0:eafc3fd41f75 12 from project_generator.tools_supported import ToolsSupported
bryantaylor 0:eafc3fd41f75 13 from project_generator.settings import ProjectSettings
bryantaylor 0:eafc3fd41f75 14 from project_generator_definitions.definitions import ProGenDef
bryantaylor 0:eafc3fd41f75 15
bryantaylor 0:eafc3fd41f75 16
bryantaylor 0:eafc3fd41f75 17 class OldLibrariesException(Exception):
bryantaylor 0:eafc3fd41f75 18 """Exception that indicates an export can not complete due to an out of date
bryantaylor 0:eafc3fd41f75 19 library version.
bryantaylor 0:eafc3fd41f75 20 """
bryantaylor 0:eafc3fd41f75 21 pass
bryantaylor 0:eafc3fd41f75 22
bryantaylor 0:eafc3fd41f75 23 class FailedBuildException(Exception):
bryantaylor 0:eafc3fd41f75 24 """Exception that indicates that a build failed"""
bryantaylor 0:eafc3fd41f75 25 pass
bryantaylor 0:eafc3fd41f75 26
bryantaylor 0:eafc3fd41f75 27 class TargetNotSupportedException(Exception):
bryantaylor 0:eafc3fd41f75 28 """Indicates that an IDE does not support a particular MCU"""
bryantaylor 0:eafc3fd41f75 29 pass
bryantaylor 0:eafc3fd41f75 30
bryantaylor 0:eafc3fd41f75 31 class ExporterTargetsProperty(object):
bryantaylor 0:eafc3fd41f75 32 """ Exporter descriptor for TARGETS
bryantaylor 0:eafc3fd41f75 33 TARGETS as class attribute for backward compatibility
bryantaylor 0:eafc3fd41f75 34 (allows: if in Exporter.TARGETS)
bryantaylor 0:eafc3fd41f75 35 """
bryantaylor 0:eafc3fd41f75 36 def __init__(self, func):
bryantaylor 0:eafc3fd41f75 37 self.func = func
bryantaylor 0:eafc3fd41f75 38 def __get__(self, inst, cls):
bryantaylor 0:eafc3fd41f75 39 return self.func(cls)
bryantaylor 0:eafc3fd41f75 40
bryantaylor 0:eafc3fd41f75 41 class Exporter(object):
bryantaylor 0:eafc3fd41f75 42 """Exporter base class
bryantaylor 0:eafc3fd41f75 43
bryantaylor 0:eafc3fd41f75 44 This class is meant to be extended by individual exporters, and provides a
bryantaylor 0:eafc3fd41f75 45 few helper methods for implementing an exporter with either jinja2 or
bryantaylor 0:eafc3fd41f75 46 progen.
bryantaylor 0:eafc3fd41f75 47 """
bryantaylor 0:eafc3fd41f75 48 TEMPLATE_DIR = dirname(__file__)
bryantaylor 0:eafc3fd41f75 49 DOT_IN_RELATIVE_PATH = False
bryantaylor 0:eafc3fd41f75 50 NAME = None
bryantaylor 0:eafc3fd41f75 51 TARGETS = None
bryantaylor 0:eafc3fd41f75 52 TOOLCHAIN = None
bryantaylor 0:eafc3fd41f75 53
bryantaylor 0:eafc3fd41f75 54 def __init__(self, target, export_dir, project_name, toolchain,
bryantaylor 0:eafc3fd41f75 55 extra_symbols=None, resources=None):
bryantaylor 0:eafc3fd41f75 56 """Initialize an instance of class exporter
bryantaylor 0:eafc3fd41f75 57 Positional arguments:
bryantaylor 0:eafc3fd41f75 58 target - the target mcu/board for this project
bryantaylor 0:eafc3fd41f75 59 export_dir - the directory of the exported project files
bryantaylor 0:eafc3fd41f75 60 project_name - the name of the project
bryantaylor 0:eafc3fd41f75 61 toolchain - an instance of class toolchain
bryantaylor 0:eafc3fd41f75 62
bryantaylor 0:eafc3fd41f75 63 Keyword arguments:
bryantaylor 0:eafc3fd41f75 64 extra_symbols - a list of extra macros for the toolchain
bryantaylor 0:eafc3fd41f75 65 resources - an instance of class Resources
bryantaylor 0:eafc3fd41f75 66 """
bryantaylor 0:eafc3fd41f75 67 self.export_dir = export_dir
bryantaylor 0:eafc3fd41f75 68 self.target = target
bryantaylor 0:eafc3fd41f75 69 self.project_name = project_name
bryantaylor 0:eafc3fd41f75 70 self.toolchain = toolchain
bryantaylor 0:eafc3fd41f75 71 jinja_loader = FileSystemLoader(os.path.dirname(os.path.abspath(__file__)))
bryantaylor 0:eafc3fd41f75 72 self.jinja_environment = Environment(loader=jinja_loader)
bryantaylor 0:eafc3fd41f75 73 self.resources = resources
bryantaylor 0:eafc3fd41f75 74 self.generated_files = []
bryantaylor 0:eafc3fd41f75 75 self.builder_files_dict = {}
bryantaylor 0:eafc3fd41f75 76
bryantaylor 0:eafc3fd41f75 77 def get_toolchain(self):
bryantaylor 0:eafc3fd41f75 78 """A helper getter function that we should probably eliminate"""
bryantaylor 0:eafc3fd41f75 79 return self.TOOLCHAIN
bryantaylor 0:eafc3fd41f75 80
bryantaylor 0:eafc3fd41f75 81 @property
bryantaylor 0:eafc3fd41f75 82 def flags(self):
bryantaylor 0:eafc3fd41f75 83 """Returns a dictionary of toolchain flags.
bryantaylor 0:eafc3fd41f75 84 Keys of the dictionary are:
bryantaylor 0:eafc3fd41f75 85 cxx_flags - c++ flags
bryantaylor 0:eafc3fd41f75 86 c_flags - c flags
bryantaylor 0:eafc3fd41f75 87 ld_flags - linker flags
bryantaylor 0:eafc3fd41f75 88 asm_flags - assembler flags
bryantaylor 0:eafc3fd41f75 89 common_flags - common options
bryantaylor 0:eafc3fd41f75 90 """
bryantaylor 0:eafc3fd41f75 91 config_header = self.toolchain.get_config_header()
bryantaylor 0:eafc3fd41f75 92 flags = {key + "_flags": value for key, value
bryantaylor 0:eafc3fd41f75 93 in self.toolchain.flags.iteritems()}
bryantaylor 0:eafc3fd41f75 94 asm_defines = ["-D" + symbol for symbol in self.toolchain.get_symbols(True)]
bryantaylor 0:eafc3fd41f75 95 c_defines = ["-D" + symbol for symbol in self.toolchain.get_symbols()]
bryantaylor 0:eafc3fd41f75 96 flags['asm_flags'] += asm_defines
bryantaylor 0:eafc3fd41f75 97 flags['c_flags'] += c_defines
bryantaylor 0:eafc3fd41f75 98 flags['cxx_flags'] += c_defines
bryantaylor 0:eafc3fd41f75 99 if config_header:
bryantaylor 0:eafc3fd41f75 100 config_header = relpath(config_header,
bryantaylor 0:eafc3fd41f75 101 self.resources.file_basepath[config_header])
bryantaylor 0:eafc3fd41f75 102 flags['c_flags'] += self.toolchain.get_config_option(config_header)
bryantaylor 0:eafc3fd41f75 103 flags['cxx_flags'] += self.toolchain.get_config_option(
bryantaylor 0:eafc3fd41f75 104 config_header)
bryantaylor 0:eafc3fd41f75 105 return flags
bryantaylor 0:eafc3fd41f75 106
bryantaylor 0:eafc3fd41f75 107 def get_source_paths(self):
bryantaylor 0:eafc3fd41f75 108 """Returns a list of the directories where source files are contained"""
bryantaylor 0:eafc3fd41f75 109 source_keys = ['s_sources', 'c_sources', 'cpp_sources', 'hex_files',
bryantaylor 0:eafc3fd41f75 110 'objects', 'libraries']
bryantaylor 0:eafc3fd41f75 111 source_files = []
bryantaylor 0:eafc3fd41f75 112 for key in source_keys:
bryantaylor 0:eafc3fd41f75 113 source_files.extend(getattr(self.resources, key))
bryantaylor 0:eafc3fd41f75 114 return list(set([os.path.dirname(src) for src in source_files]))
bryantaylor 0:eafc3fd41f75 115
bryantaylor 0:eafc3fd41f75 116 def progen_get_project_data(self):
bryantaylor 0:eafc3fd41f75 117 """ Get ProGen project data """
bryantaylor 0:eafc3fd41f75 118 # provide default data, some tools don't require any additional
bryantaylor 0:eafc3fd41f75 119 # tool specific settings
bryantaylor 0:eafc3fd41f75 120
bryantaylor 0:eafc3fd41f75 121 def make_key(src):
bryantaylor 0:eafc3fd41f75 122 """turn a source file into it's group name"""
bryantaylor 0:eafc3fd41f75 123 key = os.path.basename(os.path.dirname(src))
bryantaylor 0:eafc3fd41f75 124 if not key:
bryantaylor 0:eafc3fd41f75 125 key = os.path.basename(os.path.normpath(self.export_dir))
bryantaylor 0:eafc3fd41f75 126 return key
bryantaylor 0:eafc3fd41f75 127
bryantaylor 0:eafc3fd41f75 128 def grouped(sources):
bryantaylor 0:eafc3fd41f75 129 """Group the source files by their encompassing directory"""
bryantaylor 0:eafc3fd41f75 130 data = sorted(sources, key=make_key)
bryantaylor 0:eafc3fd41f75 131 return {k: list(g) for k, g in groupby(data, make_key)}
bryantaylor 0:eafc3fd41f75 132
bryantaylor 0:eafc3fd41f75 133 if self.toolchain.get_config_header():
bryantaylor 0:eafc3fd41f75 134 config_header = self.toolchain.get_config_header()
bryantaylor 0:eafc3fd41f75 135 config_header = relpath(config_header,
bryantaylor 0:eafc3fd41f75 136 self.resources.file_basepath[config_header])
bryantaylor 0:eafc3fd41f75 137 else:
bryantaylor 0:eafc3fd41f75 138 config_header = None
bryantaylor 0:eafc3fd41f75 139
bryantaylor 0:eafc3fd41f75 140 # we want to add this to our include dirs
bryantaylor 0:eafc3fd41f75 141 config_dir = os.path.dirname(config_header) if config_header else []
bryantaylor 0:eafc3fd41f75 142
bryantaylor 0:eafc3fd41f75 143 project_data = tool.get_tool_template()
bryantaylor 0:eafc3fd41f75 144
bryantaylor 0:eafc3fd41f75 145 project_data['target'] = TARGET_MAP[self.target].progen['target']
bryantaylor 0:eafc3fd41f75 146 project_data['source_paths'] = self.get_source_paths()
bryantaylor 0:eafc3fd41f75 147 project_data['include_paths'] = self.resources.inc_dirs + [config_dir]
bryantaylor 0:eafc3fd41f75 148 project_data['include_files'] = grouped(self.resources.headers)
bryantaylor 0:eafc3fd41f75 149 project_data['source_files_s'] = grouped(self.resources.s_sources)
bryantaylor 0:eafc3fd41f75 150 project_data['source_files_c'] = grouped(self.resources.c_sources)
bryantaylor 0:eafc3fd41f75 151 project_data['source_files_cpp'] = grouped(self.resources.cpp_sources)
bryantaylor 0:eafc3fd41f75 152 project_data['source_files_obj'] = grouped(self.resources.objects)
bryantaylor 0:eafc3fd41f75 153 project_data['source_files_lib'] = grouped(self.resources.libraries)
bryantaylor 0:eafc3fd41f75 154 project_data['output_dir']['path'] = self.export_dir
bryantaylor 0:eafc3fd41f75 155 project_data['linker_file'] = self.resources.linker_script
bryantaylor 0:eafc3fd41f75 156 project_data['macros'] = []
bryantaylor 0:eafc3fd41f75 157 project_data['build_dir'] = 'build'
bryantaylor 0:eafc3fd41f75 158 project_data['template'] = None
bryantaylor 0:eafc3fd41f75 159 project_data['name'] = self.project_name
bryantaylor 0:eafc3fd41f75 160 project_data['output_type'] = 'exe'
bryantaylor 0:eafc3fd41f75 161 project_data['debugger'] = None
bryantaylor 0:eafc3fd41f75 162 return project_data
bryantaylor 0:eafc3fd41f75 163
bryantaylor 0:eafc3fd41f75 164 def progen_gen_file(self, project_data):
bryantaylor 0:eafc3fd41f75 165 """ Generate project using ProGen Project API
bryantaylor 0:eafc3fd41f75 166 Positional arguments:
bryantaylor 0:eafc3fd41f75 167 tool_name - the tool for which to generate project files
bryantaylor 0:eafc3fd41f75 168 project_data - a dict whose base key, values are specified in
bryantaylor 0:eafc3fd41f75 169 progen_get_project_data, the items will have been
bryantaylor 0:eafc3fd41f75 170 modified by Exporter subclasses
bryantaylor 0:eafc3fd41f75 171
bryantaylor 0:eafc3fd41f75 172 Keyword arguments:
bryantaylor 0:eafc3fd41f75 173 progen_build - A boolean that determines if the tool will build the
bryantaylor 0:eafc3fd41f75 174 project
bryantaylor 0:eafc3fd41f75 175 """
bryantaylor 0:eafc3fd41f75 176 if not self.check_supported(self.NAME):
bryantaylor 0:eafc3fd41f75 177 raise TargetNotSupportedException("Target not supported")
bryantaylor 0:eafc3fd41f75 178 settings = ProjectSettings()
bryantaylor 0:eafc3fd41f75 179 exporter = ToolsSupported().get_tool(self.NAME)
bryantaylor 0:eafc3fd41f75 180 self.builder_files_dict = {self.NAME:exporter(project_data, settings).export_project()}
bryantaylor 0:eafc3fd41f75 181 for middle in self.builder_files_dict.values():
bryantaylor 0:eafc3fd41f75 182 for field, thing in middle.iteritems():
bryantaylor 0:eafc3fd41f75 183 if field == "files":
bryantaylor 0:eafc3fd41f75 184 for filename in thing.values():
bryantaylor 0:eafc3fd41f75 185 self.generated_files.append(filename)
bryantaylor 0:eafc3fd41f75 186
bryantaylor 0:eafc3fd41f75 187 def progen_build(self):
bryantaylor 0:eafc3fd41f75 188 """Build a project that was already generated by progen"""
bryantaylor 0:eafc3fd41f75 189 print("Project {} exported, building for {}...".format(
bryantaylor 0:eafc3fd41f75 190 self.project_name, self.NAME))
bryantaylor 0:eafc3fd41f75 191 sys.stdout.flush()
bryantaylor 0:eafc3fd41f75 192 builder = ToolsSupported().get_tool(self.NAME)
bryantaylor 0:eafc3fd41f75 193 result = builder(self.builder_files_dict[self.NAME], ProjectSettings()).build_project()
bryantaylor 0:eafc3fd41f75 194 if result == -1:
bryantaylor 0:eafc3fd41f75 195 raise FailedBuildException("Build Failed")
bryantaylor 0:eafc3fd41f75 196
bryantaylor 0:eafc3fd41f75 197 def check_supported(self, ide):
bryantaylor 0:eafc3fd41f75 198 """Indicated if this combination of IDE and MCU is supported"""
bryantaylor 0:eafc3fd41f75 199 if self.target not in self.TARGETS or \
bryantaylor 0:eafc3fd41f75 200 self.TOOLCHAIN not in TARGET_MAP[self.target].supported_toolchains:
bryantaylor 0:eafc3fd41f75 201 return False
bryantaylor 0:eafc3fd41f75 202 if not ProGenDef(ide).is_supported(
bryantaylor 0:eafc3fd41f75 203 TARGET_MAP[self.target].progen['target']):
bryantaylor 0:eafc3fd41f75 204 return False
bryantaylor 0:eafc3fd41f75 205 return True
bryantaylor 0:eafc3fd41f75 206
bryantaylor 0:eafc3fd41f75 207 def gen_file(self, template_file, data, target_file):
bryantaylor 0:eafc3fd41f75 208 """Generates a project file from a template using jinja"""
bryantaylor 0:eafc3fd41f75 209 jinja_loader = FileSystemLoader(
bryantaylor 0:eafc3fd41f75 210 os.path.dirname(os.path.abspath(__file__)))
bryantaylor 0:eafc3fd41f75 211 jinja_environment = Environment(loader=jinja_loader)
bryantaylor 0:eafc3fd41f75 212
bryantaylor 0:eafc3fd41f75 213 template = jinja_environment.get_template(template_file)
bryantaylor 0:eafc3fd41f75 214 target_text = template.render(data)
bryantaylor 0:eafc3fd41f75 215
bryantaylor 0:eafc3fd41f75 216 target_path = join(self.export_dir, target_file)
bryantaylor 0:eafc3fd41f75 217 logging.debug("Generating: %s", target_path)
bryantaylor 0:eafc3fd41f75 218 open(target_path, "w").write(target_text)
bryantaylor 0:eafc3fd41f75 219 self.generated_files += [target_path]