mbed-os/tools/export/iar/__init__.py

198 lines
6.4 KiB
Python
Raw Normal View History

2016-09-07 19:01:45 +00:00
import os
from os.path import sep, join, exists
from collections import namedtuple
from subprocess import Popen, PIPE
import shutil
2016-09-07 19:01:45 +00:00
import re
2016-09-13 21:15:37 +00:00
import sys
2016-09-07 19:01:45 +00:00
from tools.targets import TARGET_MAP
from tools.export.exporters import Exporter, TargetNotSupportedException
2016-09-07 19:01:45 +00:00
import json
2016-09-21 21:41:16 +00:00
from tools.export.cmsis import DeviceCMSIS
from tools.utils import NotSupportedException
from multiprocessing import cpu_count
2016-09-21 21:41:16 +00:00
2017-06-20 21:04:27 +00:00
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)
2016-09-07 19:01:45 +00:00
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())
2016-09-07 19:01:45 +00:00
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):
2016-09-21 21:41:16 +00:00
"""Retrieve info from iar_definitions.json"""
tgt = TARGET_MAP[self.target]
device_name = (tgt.device_name if hasattr(tgt, "device_name") else
tgt.name)
2017-06-20 21:04:27 +00:00
device_info = _GUI_OPTIONS[device_name]
2016-09-07 19:01:45 +00:00
iar_defaults ={
"OGChipSelectEditMenu": "",
"CoreVariant": '',
"GFPUCoreSlave": '',
"GFPUCoreSlave2": 40,
"GBECoreSlave": 35,
"GBECoreSlave2": '',
"FPU2": 0,
"NrRegs": 0,
"NEON": '',
"CExtraOptionsCheck": 0,
"CExtraOptions": "",
"CMSISDAPJtagSpeedList": 0,
2016-09-07 19:01:45 +00:00
}
iar_defaults.update(device_info)
IARdevice = namedtuple('IARdevice', iar_defaults.keys())
return IARdevice(**iar_defaults)
def format_file(self, file):
2016-09-21 21:41:16 +00:00
"""Make IAR compatible path"""
2016-09-07 19:01:45 +00:00
return join('$PROJ_DIR$',file)
def format_src(self, srcs):
2016-09-21 21:41:16 +00:00
"""Group source files"""
2016-09-07 19:01:45 +00:00
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):
2016-09-21 21:41:16 +00:00
"""Generate the .eww, .ewd, and .ewp files"""
if not self.resources.linker_script:
raise NotSupportedException("No linker script found.")
2016-09-07 19:01:45 +00:00
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']
2016-09-07 19:01:45 +00:00
+ 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"
2016-09-07 19:01:45 +00:00
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(),
2016-09-21 21:41:16 +00:00
'ewp': sep+self.project_name + ".ewp",
'debugger': debugger
2016-09-07 19:01:45 +00:00
}
ctx.update(flags)
2016-12-13 00:46:47 +00:00
self.gen_file('iar/eww.tmpl', ctx, self.project_name + ".eww")
2016-09-21 21:41:16 +00:00
self.gen_file('iar/ewd.tmpl', ctx, self.project_name + ".ewd")
2016-12-13 00:46:47 +00:00
self.gen_file('iar/ewp.tmpl', ctx, self.project_name + ".ewp")
2016-09-07 19:01:45 +00:00
@staticmethod
def build(project_name, log_name="build_log.txt", cleanup=True):
2016-09-07 19:01:45 +00:00
""" 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
2016-09-13 21:15:37 +00:00
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:
2016-09-07 19:01:45 +00:00
# Seems like something went wrong.
return -1
else:
return 0
2017-06-20 21:04:27 +00:00