Marco Mayer / Mbed OS Queue
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers __init__.py Source File

__init__.py

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