Clone of official tools
export/iar/__init__.py
- Committer:
- theotherjimmy
- Date:
- 2018-09-25
- Revision:
- 43:2a7da56ebd24
- Parent:
- 40:7d3fa6b99b2b
File content as of revision 43:2a7da56ebd24:
from __future__ import print_function, absolute_import from builtins import str 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.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 clean(project_name): 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') @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: IAR.clean(project_name) if ret_code !=0: # Seems like something went wrong. return -1 else: return 0