Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers __init__.py Source File

__init__.py

00001 from __future__ import print_function, absolute_import
00002 from builtins import str
00003 
00004 import os
00005 from os.path import sep, join, exists
00006 from collections import namedtuple
00007 from subprocess import Popen, PIPE
00008 import shutil
00009 import re
00010 import sys
00011 
00012 from tools.targets import TARGET_MAP
00013 from tools.export.exporters import Exporter, TargetNotSupportedException
00014 import json
00015 from tools.export.cmsis import DeviceCMSIS
00016 from tools.utils import NotSupportedException
00017 from multiprocessing import cpu_count
00018 
00019 
00020 def _supported(mcu, iar_targets):
00021     if "IAR" not in mcu.supported_toolchains:
00022         return False
00023     if hasattr(mcu, 'device_name') and mcu.device_name in iar_targets:
00024         return True
00025     if mcu.name in iar_targets:
00026         return True
00027     return False
00028 
00029 
00030 _iar_defs = os.path.join(
00031     os.path.dirname(os.path.abspath(__file__)), 'iar_definitions.json')
00032 
00033 with open(_iar_defs, 'r') as f:
00034     _GUI_OPTIONS = json.load(f)
00035 
00036 
00037 class IAR(Exporter):
00038     NAME = 'iar'
00039     TOOLCHAIN = 'IAR'
00040 
00041     @classmethod
00042     def is_target_supported(cls, target_name):
00043         target = TARGET_MAP[target_name]
00044         return _supported(target, _GUI_OPTIONS.keys())
00045 
00046 
00047     def iar_groups(self, grouped_src):
00048         """Return a namedtuple of group info
00049         Positional Arguments:
00050         grouped_src: dictionary mapping a group(str) to sources
00051             within it (list of file names)
00052         Relevant part of IAR template
00053         {% for group in groups %}
00054         <group>
00055             <name>group.name</name>
00056             {% for file in group.files %}
00057             <file>
00058             <name>$PROJ_DIR${{file}}</name>
00059             </file>
00060             {% endfor %}
00061         </group>
00062         {% endfor %}
00063         """
00064         IARgroup = namedtuple('IARgroup', ['name','files'])
00065         groups = []
00066         for name, files in grouped_src.items():
00067             groups.append(IARgroup(name,files))
00068         return groups
00069 
00070     def iar_device(self):
00071         """Retrieve info from iar_definitions.json"""
00072         tgt = TARGET_MAP[self.target]
00073         device_name = (tgt.device_name if hasattr(tgt, "device_name") else
00074                        tgt.name)
00075         device_info = _GUI_OPTIONS[device_name]
00076         iar_defaults ={
00077             "OGChipSelectEditMenu": "",
00078             "CoreVariant": '',
00079             "GFPUCoreSlave": '',
00080             "GFPUCoreSlave2": 40,
00081             "GBECoreSlave": 35,
00082             "GBECoreSlave2": '',
00083             "FPU2": 0,
00084             "NrRegs": 0,
00085             "NEON": '',
00086             "CExtraOptionsCheck": 0,
00087             "CExtraOptions": "",
00088             "CMSISDAPJtagSpeedList": 0,
00089         }
00090 
00091         iar_defaults.update(device_info)
00092         IARdevice = namedtuple('IARdevice', iar_defaults.keys())
00093         return IARdevice(**iar_defaults)
00094 
00095     def format_file(self, file):
00096         """Make IAR compatible path"""
00097         return join('$PROJ_DIR$',file)
00098 
00099     def format_src(self, srcs):
00100         """Group source files"""
00101         grouped = self.group_project_files(srcs)
00102         for group, files in grouped.items():
00103             grouped[group] = [self.format_file(src) for src in files]
00104         return grouped
00105 
00106     def generate(self):
00107         """Generate the .eww, .ewd, and .ewp files"""
00108         if not self.resources.linker_script:
00109             raise NotSupportedException("No linker script found.")
00110         srcs = self.resources.headers + self.resources.s_sources + \
00111                self.resources.c_sources + self.resources.cpp_sources + \
00112                self.resources.objects + self.resources.libraries
00113         flags = self.flags
00114         c_flags = list(set(flags['common_flags']
00115                                     + flags['c_flags']
00116                                     + flags['cxx_flags']))
00117         # Flags set in template to be set by user in IDE
00118         template = ["--vla", "--no_static_destruction"]
00119         # Flag invalid if set in template
00120         # Optimizations are also set in template
00121         invalid_flag = lambda x: x in template or re.match("-O(\d|time|n|hz?)", x)
00122         flags['c_flags'] = [flag for flag in c_flags if not invalid_flag(flag)]
00123 
00124         try:
00125             debugger = DeviceCMSIS(self.target).debug.replace('-','').upper()
00126         except TargetNotSupportedException:
00127             debugger = "CMSISDAP"
00128 
00129         ctx = {
00130             'name': self.project_name,
00131             'groups': self.iar_groups(self.format_src(srcs)),
00132             'linker_script': self.format_file(self.resources.linker_script),
00133             'include_paths': [self.format_file(src) for src in self.resources.inc_dirs],
00134             'device': self.iar_device(),
00135             'ewp': sep+self.project_name + ".ewp",
00136             'debugger': debugger
00137         }
00138         ctx.update(flags)
00139 
00140         self.gen_file('iar/eww.tmpl', ctx, self.project_name + ".eww")
00141         self.gen_file('iar/ewd.tmpl', ctx, self.project_name + ".ewd")
00142         self.gen_file('iar/ewp.tmpl', ctx, self.project_name + ".ewp")
00143 
00144     @staticmethod
00145     def clean(project_name):
00146         os.remove(project_name + ".ewp")
00147         os.remove(project_name + ".ewd")
00148         os.remove(project_name + ".eww")
00149         # legacy output file location
00150         if exists('.build'):
00151             shutil.rmtree('.build')
00152         if exists('BUILD'):
00153             shutil.rmtree('BUILD')
00154 
00155     @staticmethod
00156     def build(project_name, log_name="build_log.txt", cleanup=True):
00157         """ Build IAR project """
00158         # > IarBuild [project_path] -build [project_name]
00159         proj_file = project_name + ".ewp"
00160         cmd = ["IarBuild", proj_file, '-build', project_name]
00161 
00162         # IAR does not support a '0' option to automatically use all
00163         # available CPUs, so we use Python's multiprocessing library
00164         # to detect the number of CPUs available
00165         cpus_available = cpu_count()
00166         jobs = cpus_available if cpus_available else None
00167 
00168         # Only add the parallel flag if we're using more than one CPU
00169         if jobs:
00170             cmd += ['-parallel', str(jobs)]
00171 
00172         # Build the project
00173         p = Popen(cmd, stdout=PIPE, stderr=PIPE)
00174         out, err = p.communicate()
00175         ret_code = p.returncode
00176 
00177         out_string = "=" * 10 + "STDOUT" + "=" * 10 + "\n"
00178         out_string += out
00179         out_string += "=" * 10 + "STDERR" + "=" * 10 + "\n"
00180         out_string += err
00181 
00182         if ret_code == 0:
00183             out_string += "SUCCESS"
00184         else:
00185             out_string += "FAILURE"
00186 
00187         print(out_string)
00188 
00189         if log_name:
00190             # Write the output to the log file
00191             with open(log_name, 'w+') as f:
00192                 f.write(out_string)
00193 
00194         # Cleanup the exported and built files
00195         if cleanup:
00196             IAR.clean(project_name)
00197 
00198         if ret_code !=0:
00199             # Seems like something went wrong.
00200             return -1
00201         else:
00202             return 0
00203 
00204