PageRenderTime 50ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

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

https://github.com/adamgreen/gcc4mbed
Python | 194 lines | 165 code | 8 blank | 21 comment | 8 complexity | 8946bfe989f1a8e0cd66936a3ce71f94 MD5 | raw file
  1. import os
  2. from os.path import sep, join, exists
  3. from collections import namedtuple
  4. from subprocess import Popen, PIPE
  5. import shutil
  6. import re
  7. import sys
  8. from tools.targets import TARGET_MAP
  9. from tools.export.exporters import Exporter, TargetNotSupportedException
  10. import json
  11. from tools.export.cmsis import DeviceCMSIS
  12. from tools.utils import NotSupportedException
  13. from multiprocessing import cpu_count
  14. class IAR(Exporter):
  15. NAME = 'iar'
  16. TOOLCHAIN = 'IAR'
  17. #iar_definitions.json location
  18. def_loc = os.path.join(
  19. os.path.dirname(os.path.abspath(__file__)), '..', '..', '..',
  20. 'tools','export', 'iar', 'iar_definitions.json')
  21. #create a dictionary of the definitions
  22. with open(def_loc, 'r') as f:
  23. IAR_DEFS = json.load(f)
  24. def _iar_support(tgt, iar_targets):
  25. if "IAR" not in tgt.supported_toolchains:
  26. return False
  27. if hasattr(tgt, 'device_name') and tgt.device_name in iar_targets:
  28. return True
  29. if tgt.name in iar_targets:
  30. return True
  31. return False
  32. #supported targets have a name or device_name which maps to a definition
  33. #in iar_definitions.json
  34. TARGETS = [target for target, obj in TARGET_MAP.iteritems() if
  35. _iar_support(obj, IAR_DEFS.keys())]
  36. def iar_groups(self, grouped_src):
  37. """Return a namedtuple of group info
  38. Positional Arguments:
  39. grouped_src: dictionary mapping a group(str) to sources
  40. within it (list of file names)
  41. Relevant part of IAR template
  42. {% for group in groups %}
  43. <group>
  44. <name>group.name</name>
  45. {% for file in group.files %}
  46. <file>
  47. <name>$PROJ_DIR${{file}}</name>
  48. </file>
  49. {% endfor %}
  50. </group>
  51. {% endfor %}
  52. """
  53. IARgroup = namedtuple('IARgroup', ['name','files'])
  54. groups = []
  55. for name, files in grouped_src.items():
  56. groups.append(IARgroup(name,files))
  57. return groups
  58. def iar_device(self):
  59. """Retrieve info from iar_definitions.json"""
  60. tgt = TARGET_MAP[self.target]
  61. device_name = (tgt.device_name if hasattr(tgt, "device_name") else
  62. tgt.name)
  63. device_info = self.IAR_DEFS[device_name]
  64. iar_defaults ={
  65. "OGChipSelectEditMenu": "",
  66. "CoreVariant": '',
  67. "GFPUCoreSlave": '',
  68. "GFPUCoreSlave2": 40,
  69. "GBECoreSlave": 35,
  70. "GBECoreSlave2": '',
  71. "FPU2": 0,
  72. "NrRegs": 0,
  73. "NEON": '',
  74. "CExtraOptionsCheck": 0,
  75. "CExtraOptions": "",
  76. "CMSISDAPJtagSpeedList": 0,
  77. }
  78. iar_defaults.update(device_info)
  79. IARdevice = namedtuple('IARdevice', iar_defaults.keys())
  80. return IARdevice(**iar_defaults)
  81. def format_file(self, file):
  82. """Make IAR compatible path"""
  83. return join('$PROJ_DIR$',file)
  84. def format_src(self, srcs):
  85. """Group source files"""
  86. grouped = self.group_project_files(srcs)
  87. for group, files in grouped.items():
  88. grouped[group] = [self.format_file(src) for src in files]
  89. return grouped
  90. def generate(self):
  91. """Generate the .eww, .ewd, and .ewp files"""
  92. if not self.resources.linker_script:
  93. raise NotSupportedException("No linker script found.")
  94. srcs = self.resources.headers + self.resources.s_sources + \
  95. self.resources.c_sources + self.resources.cpp_sources + \
  96. self.resources.objects + self.resources.libraries
  97. flags = self.flags
  98. c_flags = list(set(flags['common_flags']
  99. + flags['c_flags']
  100. + flags['cxx_flags']))
  101. # Flags set in template to be set by user in IDE
  102. template = ["--vla", "--no_static_destruction"]
  103. # Flag invalid if set in template
  104. # Optimizations are also set in template
  105. invalid_flag = lambda x: x in template or re.match("-O(\d|time|n)", x)
  106. flags['c_flags'] = [flag for flag in c_flags if not invalid_flag(flag)]
  107. try:
  108. debugger = DeviceCMSIS(self.target).debug.replace('-','').upper()
  109. except TargetNotSupportedException:
  110. debugger = "CMSISDAP"
  111. ctx = {
  112. 'name': self.project_name,
  113. 'groups': self.iar_groups(self.format_src(srcs)),
  114. 'linker_script': self.format_file(self.resources.linker_script),
  115. 'include_paths': [self.format_file(src) for src in self.resources.inc_dirs],
  116. 'device': self.iar_device(),
  117. 'ewp': sep+self.project_name + ".ewp",
  118. 'debugger': debugger
  119. }
  120. ctx.update(flags)
  121. self.gen_file('iar/eww.tmpl', ctx, self.project_name + ".eww")
  122. self.gen_file('iar/ewd.tmpl', ctx, self.project_name + ".ewd")
  123. self.gen_file('iar/ewp.tmpl', ctx, self.project_name + ".ewp")
  124. @staticmethod
  125. def build(project_name, log_name="build_log.txt", cleanup=True):
  126. """ Build IAR project """
  127. # > IarBuild [project_path] -build [project_name]
  128. proj_file = project_name + ".ewp"
  129. cmd = ["IarBuild", proj_file, '-build', project_name]
  130. # IAR does not support a '0' option to automatically use all
  131. # available CPUs, so we use Python's multiprocessing library
  132. # to detect the number of CPUs available
  133. cpus_available = cpu_count()
  134. jobs = cpus_available if cpus_available else None
  135. # Only add the parallel flag if we're using more than one CPU
  136. if jobs:
  137. cmd += ['-parallel', str(jobs)]
  138. # Build the project
  139. p = Popen(cmd, stdout=PIPE, stderr=PIPE)
  140. out, err = p.communicate()
  141. ret_code = p.returncode
  142. out_string = "=" * 10 + "STDOUT" + "=" * 10 + "\n"
  143. out_string += out
  144. out_string += "=" * 10 + "STDERR" + "=" * 10 + "\n"
  145. out_string += err
  146. if ret_code == 0:
  147. out_string += "SUCCESS"
  148. else:
  149. out_string += "FAILURE"
  150. print out_string
  151. if log_name:
  152. # Write the output to the log file
  153. with open(log_name, 'w+') as f:
  154. f.write(out_string)
  155. # Cleanup the exported and built files
  156. if cleanup:
  157. os.remove(project_name + ".ewp")
  158. os.remove(project_name + ".ewd")
  159. os.remove(project_name + ".eww")
  160. # legacy output file location
  161. if exists('.build'):
  162. shutil.rmtree('.build')
  163. if exists('BUILD'):
  164. shutil.rmtree('BUILD')
  165. if ret_code !=0:
  166. # Seems like something went wrong.
  167. return -1
  168. else:
  169. return 0