mbed-os
Dependents: cobaLCDJoyMotor_Thread odometry_omni_3roda_v3 odometry_omni_3roda_v1 odometry_omni_3roda_v2 ... more
Diff: tools/export/iar/__init__.py
- Revision:
- 0:b74591d5ab33
diff -r 000000000000 -r b74591d5ab33 tools/export/iar/__init__.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/export/iar/__init__.py Mon Dec 11 17:54:04 2017 +0000 @@ -0,0 +1,197 @@ +import os +from os.path import sep, join, exists +from collections import namedtuple +from subprocess import Popen, PIPE +import shutil +import re +import sys + +from tools.targets import TARGET_MAP +from tools.export.exporters import Exporter, TargetNotSupportedException +import json +from tools.export.cmsis import DeviceCMSIS +from tools.utils import NotSupportedException +from multiprocessing import cpu_count + + +def _supported(mcu, iar_targets): + if "IAR" not in mcu.supported_toolchains: + return False + if hasattr(mcu, 'device_name') and mcu.device_name in iar_targets: + return True + if mcu.name in iar_targets: + return True + return False + + +_iar_defs = os.path.join( + os.path.dirname(os.path.abspath(__file__)), 'iar_definitions.json') + +with open(_iar_defs, 'r') as f: + _GUI_OPTIONS = json.load(f) + + +class IAR(Exporter): + NAME = 'iar' + TOOLCHAIN = 'IAR' + + @classmethod + def is_target_supported(cls, target_name): + target = TARGET_MAP[target_name] + return _supported(target, _GUI_OPTIONS.keys()) + + + def iar_groups(self, grouped_src): + """Return a namedtuple of group info + Positional Arguments: + grouped_src: dictionary mapping a group(str) to sources + within it (list of file names) + Relevant part of IAR template + {% for group in groups %} + <group> + <name>group.name</name> + {% for file in group.files %} + <file> + <name>$PROJ_DIR${{file}}</name> + </file> + {% endfor %} + </group> + {% endfor %} + """ + IARgroup = namedtuple('IARgroup', ['name','files']) + groups = [] + for name, files in grouped_src.items(): + groups.append(IARgroup(name,files)) + return groups + + def iar_device(self): + """Retrieve info from iar_definitions.json""" + tgt = TARGET_MAP[self.target] + device_name = (tgt.device_name if hasattr(tgt, "device_name") else + tgt.name) + device_info = _GUI_OPTIONS[device_name] + iar_defaults ={ + "OGChipSelectEditMenu": "", + "CoreVariant": '', + "GFPUCoreSlave": '', + "GFPUCoreSlave2": 40, + "GBECoreSlave": 35, + "GBECoreSlave2": '', + "FPU2": 0, + "NrRegs": 0, + "NEON": '', + "CExtraOptionsCheck": 0, + "CExtraOptions": "", + "CMSISDAPJtagSpeedList": 0, + } + + iar_defaults.update(device_info) + IARdevice = namedtuple('IARdevice', iar_defaults.keys()) + return IARdevice(**iar_defaults) + + def format_file(self, file): + """Make IAR compatible path""" + return join('$PROJ_DIR$',file) + + def format_src(self, srcs): + """Group source files""" + grouped = self.group_project_files(srcs) + for group, files in grouped.items(): + grouped[group] = [self.format_file(src) for src in files] + return grouped + + def generate(self): + """Generate the .eww, .ewd, and .ewp files""" + if not self.resources.linker_script: + raise NotSupportedException("No linker script found.") + srcs = self.resources.headers + self.resources.s_sources + \ + self.resources.c_sources + self.resources.cpp_sources + \ + self.resources.objects + self.resources.libraries + flags = self.flags + c_flags = list(set(flags['common_flags'] + + flags['c_flags'] + + flags['cxx_flags'])) + # Flags set in template to be set by user in IDE + template = ["--vla", "--no_static_destruction"] + # Flag invalid if set in template + # Optimizations are also set in template + invalid_flag = lambda x: x in template or re.match("-O(\d|time|n|hz?)", x) + flags['c_flags'] = [flag for flag in c_flags if not invalid_flag(flag)] + + try: + debugger = DeviceCMSIS(self.target).debug.replace('-','').upper() + except TargetNotSupportedException: + debugger = "CMSISDAP" + + ctx = { + 'name': self.project_name, + 'groups': self.iar_groups(self.format_src(srcs)), + 'linker_script': self.format_file(self.resources.linker_script), + 'include_paths': [self.format_file(src) for src in self.resources.inc_dirs], + 'device': self.iar_device(), + 'ewp': sep+self.project_name + ".ewp", + 'debugger': debugger + } + ctx.update(flags) + + self.gen_file('iar/eww.tmpl', ctx, self.project_name + ".eww") + self.gen_file('iar/ewd.tmpl', ctx, self.project_name + ".ewd") + self.gen_file('iar/ewp.tmpl', ctx, self.project_name + ".ewp") + + @staticmethod + def build(project_name, log_name="build_log.txt", cleanup=True): + """ Build IAR project """ + # > IarBuild [project_path] -build [project_name] + proj_file = project_name + ".ewp" + cmd = ["IarBuild", proj_file, '-build', project_name] + + # IAR does not support a '0' option to automatically use all + # available CPUs, so we use Python's multiprocessing library + # to detect the number of CPUs available + cpus_available = cpu_count() + jobs = cpus_available if cpus_available else None + + # Only add the parallel flag if we're using more than one CPU + if jobs: + cmd += ['-parallel', str(jobs)] + + # Build the project + p = Popen(cmd, stdout=PIPE, stderr=PIPE) + out, err = p.communicate() + ret_code = p.returncode + + out_string = "=" * 10 + "STDOUT" + "=" * 10 + "\n" + out_string += out + out_string += "=" * 10 + "STDERR" + "=" * 10 + "\n" + out_string += err + + if ret_code == 0: + out_string += "SUCCESS" + else: + out_string += "FAILURE" + + print out_string + + if log_name: + # Write the output to the log file + with open(log_name, 'w+') as f: + f.write(out_string) + + # Cleanup the exported and built files + if cleanup: + os.remove(project_name + ".ewp") + os.remove(project_name + ".ewd") + os.remove(project_name + ".eww") + # legacy output file location + if exists('.build'): + shutil.rmtree('.build') + if exists('BUILD'): + shutil.rmtree('BUILD') + + if ret_code !=0: + # Seems like something went wrong. + return -1 + else: + return 0 + +