Clone of official tools

Committer:
theotherjimmy
Date:
Tue Sep 25 13:43:09 2018 -0500
Revision:
43:2a7da56ebd24
Parent:
40:7d3fa6b99b2b
Release 5.10.0

Who changed what in which revision?

UserRevisionLine numberNew contents of line
theotherjimmy 43:2a7da56ebd24 1 from __future__ import print_function, absolute_import
theotherjimmy 43:2a7da56ebd24 2 from builtins import str
theotherjimmy 43:2a7da56ebd24 3
The Other Jimmy 31:8ea194f6145b 4 import os
The Other Jimmy 31:8ea194f6145b 5 from os.path import sep, join, exists
The Other Jimmy 31:8ea194f6145b 6 from collections import namedtuple
The Other Jimmy 31:8ea194f6145b 7 from subprocess import Popen, PIPE
The Other Jimmy 31:8ea194f6145b 8 import shutil
The Other Jimmy 31:8ea194f6145b 9 import re
The Other Jimmy 31:8ea194f6145b 10 import sys
The Other Jimmy 31:8ea194f6145b 11
The Other Jimmy 31:8ea194f6145b 12 from tools.targets import TARGET_MAP
The Other Jimmy 31:8ea194f6145b 13 from tools.export.exporters import Exporter, TargetNotSupportedException
The Other Jimmy 31:8ea194f6145b 14 import json
The Other Jimmy 31:8ea194f6145b 15 from tools.export.cmsis import DeviceCMSIS
The Other Jimmy 36:96847d42f010 16 from tools.utils import NotSupportedException
The Other Jimmy 31:8ea194f6145b 17 from multiprocessing import cpu_count
The Other Jimmy 31:8ea194f6145b 18
The Other Jimmy 38:399953da035d 19
The Other Jimmy 38:399953da035d 20 def _supported(mcu, iar_targets):
The Other Jimmy 38:399953da035d 21 if "IAR" not in mcu.supported_toolchains:
The Other Jimmy 38:399953da035d 22 return False
The Other Jimmy 38:399953da035d 23 if hasattr(mcu, 'device_name') and mcu.device_name in iar_targets:
The Other Jimmy 38:399953da035d 24 return True
The Other Jimmy 38:399953da035d 25 if mcu.name in iar_targets:
The Other Jimmy 38:399953da035d 26 return True
The Other Jimmy 38:399953da035d 27 return False
The Other Jimmy 38:399953da035d 28
The Other Jimmy 38:399953da035d 29
The Other Jimmy 38:399953da035d 30 _iar_defs = os.path.join(
The Other Jimmy 38:399953da035d 31 os.path.dirname(os.path.abspath(__file__)), 'iar_definitions.json')
The Other Jimmy 38:399953da035d 32
The Other Jimmy 38:399953da035d 33 with open(_iar_defs, 'r') as f:
The Other Jimmy 38:399953da035d 34 _GUI_OPTIONS = json.load(f)
The Other Jimmy 38:399953da035d 35
The Other Jimmy 38:399953da035d 36
The Other Jimmy 31:8ea194f6145b 37 class IAR(Exporter):
The Other Jimmy 31:8ea194f6145b 38 NAME = 'iar'
The Other Jimmy 31:8ea194f6145b 39 TOOLCHAIN = 'IAR'
The Other Jimmy 31:8ea194f6145b 40
theotherjimmy 40:7d3fa6b99b2b 41 @classmethod
theotherjimmy 40:7d3fa6b99b2b 42 def is_target_supported(cls, target_name):
theotherjimmy 40:7d3fa6b99b2b 43 target = TARGET_MAP[target_name]
theotherjimmy 40:7d3fa6b99b2b 44 return _supported(target, _GUI_OPTIONS.keys())
The Other Jimmy 31:8ea194f6145b 45
The Other Jimmy 31:8ea194f6145b 46
The Other Jimmy 31:8ea194f6145b 47 def iar_groups(self, grouped_src):
The Other Jimmy 31:8ea194f6145b 48 """Return a namedtuple of group info
The Other Jimmy 31:8ea194f6145b 49 Positional Arguments:
The Other Jimmy 31:8ea194f6145b 50 grouped_src: dictionary mapping a group(str) to sources
The Other Jimmy 31:8ea194f6145b 51 within it (list of file names)
The Other Jimmy 31:8ea194f6145b 52 Relevant part of IAR template
The Other Jimmy 31:8ea194f6145b 53 {% for group in groups %}
The Other Jimmy 31:8ea194f6145b 54 <group>
The Other Jimmy 31:8ea194f6145b 55 <name>group.name</name>
The Other Jimmy 31:8ea194f6145b 56 {% for file in group.files %}
The Other Jimmy 31:8ea194f6145b 57 <file>
The Other Jimmy 31:8ea194f6145b 58 <name>$PROJ_DIR${{file}}</name>
The Other Jimmy 31:8ea194f6145b 59 </file>
The Other Jimmy 31:8ea194f6145b 60 {% endfor %}
The Other Jimmy 31:8ea194f6145b 61 </group>
The Other Jimmy 31:8ea194f6145b 62 {% endfor %}
The Other Jimmy 31:8ea194f6145b 63 """
The Other Jimmy 31:8ea194f6145b 64 IARgroup = namedtuple('IARgroup', ['name','files'])
The Other Jimmy 31:8ea194f6145b 65 groups = []
The Other Jimmy 31:8ea194f6145b 66 for name, files in grouped_src.items():
The Other Jimmy 31:8ea194f6145b 67 groups.append(IARgroup(name,files))
The Other Jimmy 31:8ea194f6145b 68 return groups
The Other Jimmy 31:8ea194f6145b 69
The Other Jimmy 31:8ea194f6145b 70 def iar_device(self):
The Other Jimmy 31:8ea194f6145b 71 """Retrieve info from iar_definitions.json"""
The Other Jimmy 35:da9c89f8be7d 72 tgt = TARGET_MAP[self.target]
The Other Jimmy 35:da9c89f8be7d 73 device_name = (tgt.device_name if hasattr(tgt, "device_name") else
The Other Jimmy 35:da9c89f8be7d 74 tgt.name)
The Other Jimmy 38:399953da035d 75 device_info = _GUI_OPTIONS[device_name]
The Other Jimmy 31:8ea194f6145b 76 iar_defaults ={
The Other Jimmy 31:8ea194f6145b 77 "OGChipSelectEditMenu": "",
The Other Jimmy 31:8ea194f6145b 78 "CoreVariant": '',
The Other Jimmy 31:8ea194f6145b 79 "GFPUCoreSlave": '',
The Other Jimmy 31:8ea194f6145b 80 "GFPUCoreSlave2": 40,
The Other Jimmy 31:8ea194f6145b 81 "GBECoreSlave": 35,
The Other Jimmy 35:da9c89f8be7d 82 "GBECoreSlave2": '',
The Other Jimmy 31:8ea194f6145b 83 "FPU2": 0,
The Other Jimmy 31:8ea194f6145b 84 "NrRegs": 0,
The Other Jimmy 35:da9c89f8be7d 85 "NEON": '',
The Other Jimmy 36:96847d42f010 86 "CExtraOptionsCheck": 0,
The Other Jimmy 36:96847d42f010 87 "CExtraOptions": "",
The Other Jimmy 36:96847d42f010 88 "CMSISDAPJtagSpeedList": 0,
The Other Jimmy 31:8ea194f6145b 89 }
The Other Jimmy 31:8ea194f6145b 90
The Other Jimmy 31:8ea194f6145b 91 iar_defaults.update(device_info)
The Other Jimmy 31:8ea194f6145b 92 IARdevice = namedtuple('IARdevice', iar_defaults.keys())
The Other Jimmy 31:8ea194f6145b 93 return IARdevice(**iar_defaults)
The Other Jimmy 31:8ea194f6145b 94
The Other Jimmy 31:8ea194f6145b 95 def format_file(self, file):
The Other Jimmy 31:8ea194f6145b 96 """Make IAR compatible path"""
The Other Jimmy 31:8ea194f6145b 97 return join('$PROJ_DIR$',file)
The Other Jimmy 31:8ea194f6145b 98
The Other Jimmy 31:8ea194f6145b 99 def format_src(self, srcs):
The Other Jimmy 31:8ea194f6145b 100 """Group source files"""
The Other Jimmy 31:8ea194f6145b 101 grouped = self.group_project_files(srcs)
The Other Jimmy 31:8ea194f6145b 102 for group, files in grouped.items():
The Other Jimmy 31:8ea194f6145b 103 grouped[group] = [self.format_file(src) for src in files]
The Other Jimmy 31:8ea194f6145b 104 return grouped
The Other Jimmy 31:8ea194f6145b 105
The Other Jimmy 31:8ea194f6145b 106 def generate(self):
The Other Jimmy 31:8ea194f6145b 107 """Generate the .eww, .ewd, and .ewp files"""
The Other Jimmy 36:96847d42f010 108 if not self.resources.linker_script:
The Other Jimmy 36:96847d42f010 109 raise NotSupportedException("No linker script found.")
The Other Jimmy 31:8ea194f6145b 110 srcs = self.resources.headers + self.resources.s_sources + \
The Other Jimmy 31:8ea194f6145b 111 self.resources.c_sources + self.resources.cpp_sources + \
theotherjimmy 43:2a7da56ebd24 112 self.resources.objects + self.libraries
The Other Jimmy 31:8ea194f6145b 113 flags = self.flags
The Other Jimmy 35:da9c89f8be7d 114 c_flags = list(set(flags['common_flags']
theotherjimmy 43:2a7da56ebd24 115 + flags['c_flags']
theotherjimmy 43:2a7da56ebd24 116 + flags['cxx_flags']))
The Other Jimmy 35:da9c89f8be7d 117 # Flags set in template to be set by user in IDE
The Other Jimmy 35:da9c89f8be7d 118 template = ["--vla", "--no_static_destruction"]
The Other Jimmy 35:da9c89f8be7d 119 # Flag invalid if set in template
The Other Jimmy 35:da9c89f8be7d 120 # Optimizations are also set in template
The Other Jimmy 36:96847d42f010 121 invalid_flag = lambda x: x in template or re.match("-O(\d|time|n|hz?)", x)
The Other Jimmy 35:da9c89f8be7d 122 flags['c_flags'] = [flag for flag in c_flags if not invalid_flag(flag)]
The Other Jimmy 31:8ea194f6145b 123
The Other Jimmy 31:8ea194f6145b 124 try:
The Other Jimmy 31:8ea194f6145b 125 debugger = DeviceCMSIS(self.target).debug.replace('-','').upper()
The Other Jimmy 31:8ea194f6145b 126 except TargetNotSupportedException:
The Other Jimmy 31:8ea194f6145b 127 debugger = "CMSISDAP"
The Other Jimmy 31:8ea194f6145b 128
The Other Jimmy 31:8ea194f6145b 129 ctx = {
The Other Jimmy 31:8ea194f6145b 130 'name': self.project_name,
The Other Jimmy 31:8ea194f6145b 131 'groups': self.iar_groups(self.format_src(srcs)),
The Other Jimmy 31:8ea194f6145b 132 'linker_script': self.format_file(self.resources.linker_script),
The Other Jimmy 31:8ea194f6145b 133 'include_paths': [self.format_file(src) for src in self.resources.inc_dirs],
The Other Jimmy 31:8ea194f6145b 134 'device': self.iar_device(),
The Other Jimmy 31:8ea194f6145b 135 'ewp': sep+self.project_name + ".ewp",
theotherjimmy 43:2a7da56ebd24 136 'debugger': debugger,
The Other Jimmy 31:8ea194f6145b 137 }
The Other Jimmy 31:8ea194f6145b 138 ctx.update(flags)
The Other Jimmy 31:8ea194f6145b 139
The Other Jimmy 31:8ea194f6145b 140 self.gen_file('iar/eww.tmpl', ctx, self.project_name + ".eww")
The Other Jimmy 31:8ea194f6145b 141 self.gen_file('iar/ewd.tmpl', ctx, self.project_name + ".ewd")
The Other Jimmy 31:8ea194f6145b 142 self.gen_file('iar/ewp.tmpl', ctx, self.project_name + ".ewp")
The Other Jimmy 31:8ea194f6145b 143
The Other Jimmy 31:8ea194f6145b 144 @staticmethod
theotherjimmy 43:2a7da56ebd24 145 def clean(project_name):
theotherjimmy 43:2a7da56ebd24 146 os.remove(project_name + ".ewp")
theotherjimmy 43:2a7da56ebd24 147 os.remove(project_name + ".ewd")
theotherjimmy 43:2a7da56ebd24 148 os.remove(project_name + ".eww")
theotherjimmy 43:2a7da56ebd24 149 # legacy output file location
theotherjimmy 43:2a7da56ebd24 150 if exists('.build'):
theotherjimmy 43:2a7da56ebd24 151 shutil.rmtree('.build')
theotherjimmy 43:2a7da56ebd24 152 if exists('BUILD'):
theotherjimmy 43:2a7da56ebd24 153 shutil.rmtree('BUILD')
theotherjimmy 43:2a7da56ebd24 154
theotherjimmy 43:2a7da56ebd24 155 @staticmethod
The Other Jimmy 31:8ea194f6145b 156 def build(project_name, log_name="build_log.txt", cleanup=True):
The Other Jimmy 31:8ea194f6145b 157 """ Build IAR project """
The Other Jimmy 31:8ea194f6145b 158 # > IarBuild [project_path] -build [project_name]
The Other Jimmy 31:8ea194f6145b 159 proj_file = project_name + ".ewp"
The Other Jimmy 31:8ea194f6145b 160 cmd = ["IarBuild", proj_file, '-build', project_name]
The Other Jimmy 31:8ea194f6145b 161
The Other Jimmy 31:8ea194f6145b 162 # IAR does not support a '0' option to automatically use all
The Other Jimmy 31:8ea194f6145b 163 # available CPUs, so we use Python's multiprocessing library
The Other Jimmy 31:8ea194f6145b 164 # to detect the number of CPUs available
The Other Jimmy 31:8ea194f6145b 165 cpus_available = cpu_count()
The Other Jimmy 31:8ea194f6145b 166 jobs = cpus_available if cpus_available else None
The Other Jimmy 31:8ea194f6145b 167
The Other Jimmy 31:8ea194f6145b 168 # Only add the parallel flag if we're using more than one CPU
The Other Jimmy 31:8ea194f6145b 169 if jobs:
The Other Jimmy 31:8ea194f6145b 170 cmd += ['-parallel', str(jobs)]
The Other Jimmy 31:8ea194f6145b 171
The Other Jimmy 31:8ea194f6145b 172 # Build the project
The Other Jimmy 31:8ea194f6145b 173 p = Popen(cmd, stdout=PIPE, stderr=PIPE)
The Other Jimmy 31:8ea194f6145b 174 out, err = p.communicate()
The Other Jimmy 31:8ea194f6145b 175 ret_code = p.returncode
The Other Jimmy 31:8ea194f6145b 176
The Other Jimmy 31:8ea194f6145b 177 out_string = "=" * 10 + "STDOUT" + "=" * 10 + "\n"
The Other Jimmy 31:8ea194f6145b 178 out_string += out
The Other Jimmy 31:8ea194f6145b 179 out_string += "=" * 10 + "STDERR" + "=" * 10 + "\n"
The Other Jimmy 31:8ea194f6145b 180 out_string += err
The Other Jimmy 31:8ea194f6145b 181
The Other Jimmy 31:8ea194f6145b 182 if ret_code == 0:
The Other Jimmy 31:8ea194f6145b 183 out_string += "SUCCESS"
The Other Jimmy 31:8ea194f6145b 184 else:
The Other Jimmy 31:8ea194f6145b 185 out_string += "FAILURE"
The Other Jimmy 31:8ea194f6145b 186
theotherjimmy 43:2a7da56ebd24 187 print(out_string)
The Other Jimmy 31:8ea194f6145b 188
The Other Jimmy 31:8ea194f6145b 189 if log_name:
The Other Jimmy 31:8ea194f6145b 190 # Write the output to the log file
The Other Jimmy 31:8ea194f6145b 191 with open(log_name, 'w+') as f:
The Other Jimmy 31:8ea194f6145b 192 f.write(out_string)
The Other Jimmy 31:8ea194f6145b 193
The Other Jimmy 31:8ea194f6145b 194 # Cleanup the exported and built files
The Other Jimmy 31:8ea194f6145b 195 if cleanup:
theotherjimmy 43:2a7da56ebd24 196 IAR.clean(project_name)
The Other Jimmy 31:8ea194f6145b 197
The Other Jimmy 31:8ea194f6145b 198 if ret_code !=0:
The Other Jimmy 31:8ea194f6145b 199 # Seems like something went wrong.
The Other Jimmy 31:8ea194f6145b 200 return -1
The Other Jimmy 31:8ea194f6145b 201 else:
The Other Jimmy 31:8ea194f6145b 202 return 0