mbed-os

Dependents:   cobaLCDJoyMotor_Thread odometry_omni_3roda_v3 odometry_omni_3roda_v1 odometry_omni_3roda_v2 ... more

Revision:
0:b74591d5ab33
--- /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
+
+