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
|
2016-10-31 21:00:15 +00:00
|
|
|
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
|
2016-11-01 16:18:40 +00:00
|
|
|
from tools.export.exporters import Exporter
|
2016-09-07 19:01:45 +00:00
|
|
|
import json
|
2016-09-21 21:41:16 +00:00
|
|
|
from tools.export.cmsis import DeviceCMSIS
|
2016-10-20 16:06:24 +00:00
|
|
|
from multiprocessing import cpu_count
|
2016-09-21 21:41:16 +00:00
|
|
|
|
2016-09-07 19:01:45 +00:00
|
|
|
class IAR(Exporter):
|
|
|
|
NAME = 'iar'
|
|
|
|
TOOLCHAIN = 'IAR'
|
|
|
|
|
2016-09-21 21:41:16 +00:00
|
|
|
#iar_definitions.json location
|
2016-09-07 19:01:45 +00:00
|
|
|
def_loc = os.path.join(
|
|
|
|
os.path.dirname(os.path.abspath(__file__)), '..', '..', '..',
|
|
|
|
'tools','export', 'iar', 'iar_definitions.json')
|
|
|
|
|
2016-09-21 21:41:16 +00:00
|
|
|
#create a dictionary of the definitions
|
2016-09-07 19:01:45 +00:00
|
|
|
with open(def_loc, 'r') as f:
|
|
|
|
IAR_DEFS = json.load(f)
|
2016-09-21 21:41:16 +00:00
|
|
|
|
|
|
|
#supported targets have a device name and corresponding definition in
|
|
|
|
#iar_definitions.json
|
2016-09-07 19:01:45 +00:00
|
|
|
TARGETS = [target for target, obj in TARGET_MAP.iteritems()
|
|
|
|
if hasattr(obj, 'device_name') and
|
2016-11-28 14:42:54 +00:00
|
|
|
obj.device_name in IAR_DEFS.keys() and "IAR" in obj.supported_toolchains]
|
2016-09-07 19:01:45 +00:00
|
|
|
|
|
|
|
SPECIAL_TEMPLATES = {
|
|
|
|
'rz_a1h' : 'iar/iar_rz_a1h.ewp.tmpl',
|
2016-09-13 21:31:33 +00:00
|
|
|
'nucleo_f746zg' : 'iar/iar_nucleo_f746zg.ewp.tmpl'
|
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"""
|
2016-09-07 19:01:45 +00:00
|
|
|
device_name = TARGET_MAP[self.target].device_name
|
|
|
|
device_info = self.IAR_DEFS[device_name]
|
|
|
|
iar_defaults ={
|
|
|
|
"OGChipSelectEditMenu": "",
|
|
|
|
"CoreVariant": '',
|
|
|
|
"GFPUCoreSlave": '',
|
|
|
|
"GFPUCoreSlave2": 40,
|
|
|
|
"GBECoreSlave": 35
|
|
|
|
}
|
|
|
|
|
|
|
|
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 get_ewp_template(self):
|
|
|
|
return self.SPECIAL_TEMPLATES.get(self.target.lower(), 'iar/ewp.tmpl')
|
|
|
|
|
|
|
|
def generate(self):
|
2016-09-21 21:41:16 +00:00
|
|
|
"""Generate the .eww, .ewd, and .ewp files"""
|
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
|
|
|
|
flags['c_flags'] = list(set(flags['common_flags']
|
|
|
|
+ flags['c_flags']
|
|
|
|
+ flags['cxx_flags']))
|
2016-09-23 19:16:51 +00:00
|
|
|
if '--vla' in flags['c_flags']:
|
|
|
|
flags['c_flags'].remove('--vla')
|
|
|
|
if '--no_static_destruction' in flags['c_flags']:
|
|
|
|
flags['c_flags'].remove('--no_static_destruction')
|
2016-10-20 16:06:24 +00:00
|
|
|
#Optimizations
|
2016-10-04 20:07:41 +00:00
|
|
|
if '-Oh' in flags['c_flags']:
|
|
|
|
flags['c_flags'].remove('-Oh')
|
2016-11-28 14:42:54 +00:00
|
|
|
|
|
|
|
try:
|
|
|
|
debugger = DeviceCMSIS(self.target).debug.replace('-','').upper()
|
|
|
|
except:
|
|
|
|
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",
|
2016-11-28 14:42:54 +00:00
|
|
|
'debugger': debugger
|
2016-09-07 19:01:45 +00:00
|
|
|
}
|
|
|
|
ctx.update(flags)
|
|
|
|
|
|
|
|
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-09-07 19:01:45 +00:00
|
|
|
self.gen_file(self.get_ewp_template(), ctx, self.project_name + ".ewp")
|
|
|
|
|
2016-10-31 21:00:15 +00:00
|
|
|
@staticmethod
|
2016-11-03 18:13:50 +00:00
|
|
|
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]
|
2016-10-31 21:00:15 +00:00
|
|
|
proj_file = project_name + ".ewp"
|
2016-11-03 18:13:50 +00:00
|
|
|
cmd = ["IarBuild", proj_file, '-build', project_name]
|
2016-10-20 16:06:24 +00:00
|
|
|
|
|
|
|
# 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)]
|
|
|
|
|
2016-11-03 18:13:50 +00:00
|
|
|
# Build the project
|
2016-09-13 21:15:37 +00:00
|
|
|
p = Popen(cmd, stdout=PIPE, stderr=PIPE)
|
2016-11-03 18:13:50 +00:00
|
|
|
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)
|
2016-10-31 21:00:15 +00:00
|
|
|
|
2016-11-03 18:13:50 +00:00
|
|
|
# Cleanup the exported and built files
|
2016-10-31 21:47:27 +00:00
|
|
|
if cleanup:
|
2016-10-31 21:00:15 +00:00
|
|
|
os.remove(project_name + ".ewp")
|
|
|
|
os.remove(project_name + ".ewd")
|
|
|
|
os.remove(project_name + ".eww")
|
2016-11-18 05:55:10 +00:00
|
|
|
# legacy output file location
|
2016-11-03 18:13:50 +00:00
|
|
|
if exists('.build'):
|
|
|
|
shutil.rmtree('.build')
|
2016-11-18 05:55:10 +00:00
|
|
|
if exists('BUILD'):
|
|
|
|
shutil.rmtree('BUILD')
|
2016-10-31 21:00:15 +00:00
|
|
|
|
2016-11-03 18:13:50 +00:00
|
|
|
if ret_code !=0:
|
2016-09-07 19:01:45 +00:00
|
|
|
# Seems like something went wrong.
|
2016-10-31 21:00:15 +00:00
|
|
|
return -1
|
2016-11-03 18:13:50 +00:00
|
|
|
else:
|
|
|
|
return 0
|