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

« Back to documentation index

Show/hide line numbers iar.py Source File

iar.py

00001 """
00002 mbed SDK
00003 Copyright (c) 2011-2013 ARM Limited
00004 
00005 Licensed under the Apache License, Version 2.0 (the "License");
00006 you may not use this file except in compliance with the License.
00007 You may obtain a copy of the License at
00008 
00009     http://www.apache.org/licenses/LICENSE-2.0
00010 
00011 Unless required by applicable law or agreed to in writing, software
00012 distributed under the License is distributed on an "AS IS" BASIS,
00013 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014 See the License for the specific language governing permissions and
00015 limitations under the License.
00016 """
00017 import re
00018 from os import remove
00019 from os.path import join, splitext, exists
00020 
00021 from tools.toolchains import mbedToolchain, TOOLCHAIN_PATHS
00022 from tools.hooks import hook_tool
00023 
00024 class IAR(mbedToolchain):
00025     LIBRARY_EXT = '.a'
00026     LINKER_EXT = '.icf'
00027     STD_LIB_NAME = "%s.a"
00028 
00029     DIAGNOSTIC_PATTERN = re.compile('"(?P<file>[^"]+)",(?P<line>[\d]+)\s+(?P<severity>Warning|Error|Fatal error)(?P<message>.+)')
00030     INDEX_PATTERN  = re.compile('(?P<col>\s*)\^')
00031 
00032     @staticmethod
00033     def check_executable():
00034         """Returns True if the executable (arm-none-eabi-gcc) location
00035         specified by the user exists OR the executable can be found on the PATH.
00036         Returns False otherwise."""
00037         return mbedToolchain.generic_check_executable("IAR", 'iccarm', 2, "bin")
00038 
00039     def __init__(self, target, notify=None, macros=None,
00040                  silent=False, extra_verbose=False, build_profile=None,
00041                  build_dir=None):
00042         mbedToolchain.__init__(self, target, notify, macros, silent,
00043                                build_dir=build_dir,
00044                                extra_verbose=extra_verbose,
00045                                build_profile=build_profile)
00046         if target.core == "Cortex-M7F" or target.core == "Cortex-M7FD":
00047             cpuchoice = "Cortex-M7"
00048         elif target.core.startswith("Cortex-M23"):
00049             cpuchoice = "8-M.baseline"
00050         elif target.core.startswith("Cortex-M33"):
00051             cpuchoice = "8-M.mainline"
00052         else:
00053             cpuchoice = target.core
00054 
00055         # flags_cmd are used only by our scripts, the project files have them already defined,
00056         # using this flags results in the errors (duplication)
00057         # asm accepts --cpu Core or --fpu FPU, not like c/c++ --cpu=Core
00058         asm_flags_cmd = ["--cpu", cpuchoice]
00059         # custom c flags
00060         c_flags_cmd = ["--cpu", cpuchoice]
00061 
00062         c_flags_cmd.extend([
00063             "--thumb", "--dlib_config", "DLib_Config_Full.h"
00064         ])
00065         # custom c++ cmd flags
00066         cxx_flags_cmd = [
00067             "--c++", "--no_rtti", "--no_exceptions"
00068         ]
00069         if target.core == "Cortex-M7FD":
00070             asm_flags_cmd += ["--fpu", "VFPv5"]
00071             c_flags_cmd.append("--fpu=VFPv5")
00072         elif target.core == "Cortex-M7F":
00073             asm_flags_cmd += ["--fpu", "VFPv5_sp"]
00074             c_flags_cmd.append("--fpu=VFPv5_sp")
00075         elif target.core == "Cortex-M23" or target.core == "Cortex-M33":
00076             self.flags["asm"] += ["--cmse"]
00077 
00078         IAR_BIN = join(TOOLCHAIN_PATHS['IAR'], "bin")
00079         main_cc = join(IAR_BIN, "iccarm")
00080 
00081         self.asm  = [join(IAR_BIN, "iasmarm")] + asm_flags_cmd + self.flags["asm"]
00082         self.cc   = [main_cc]
00083         self.cppc = [main_cc]
00084         self.cc += self.flags["common"] + c_flags_cmd + self.flags["c"]
00085         self.cppc += self.flags["common"] + c_flags_cmd + cxx_flags_cmd + self.flags["cxx"]
00086         
00087         self.ld   = [join(IAR_BIN, "ilinkarm")] + self.flags['ld']
00088         self.ar = join(IAR_BIN, "iarchive")
00089         self.elf2bin = join(IAR_BIN, "ielftool")
00090 
00091     def parse_dependencies(self, dep_path):
00092         return [(self.CHROOT if self.CHROOT else '')+path.strip() for path in open(dep_path).readlines()
00093                 if (path and not path.isspace())]
00094 
00095     def parse_output(self, output):
00096         msg = None
00097         for line in output.splitlines():
00098             match = IAR.DIAGNOSTIC_PATTERN.match(line)
00099             if match is not None:
00100                 if msg is not None:
00101                     self.cc_info(msg)
00102                     msg = None
00103                 msg = {
00104                     'severity': match.group('severity').lower(),
00105                     'file': match.group('file'),
00106                     'line': match.group('line'),
00107                     'col': 0,
00108                     'message': match.group('message'),
00109                     'text': '',
00110                     'target_name': self.target.name,
00111                     'toolchain_name': self.name
00112                 }
00113             elif msg is not None:
00114                 # Determine the warning/error column by calculating the ^ position
00115                 match = IAR.INDEX_PATTERN.match(line)
00116                 if match is not None:
00117                     msg['col'] = len(match.group('col'))
00118                     self.cc_info(msg)
00119                     msg = None
00120                 else:
00121                     msg['text'] += line+"\n"
00122 
00123         if msg is not None:
00124             self.cc_info(msg)
00125 
00126     def get_dep_option(self, object):
00127         base, _ = splitext(object)
00128         dep_path = base + '.d'
00129         return ["--dependencies", dep_path]
00130 
00131     def cc_extra(self, object):
00132         base, _ = splitext(object)
00133         return ["-l", base + '.s.txt']
00134 
00135     def get_config_option(self, config_header):
00136         return ['--preinclude=' + config_header]
00137 
00138     def get_compile_options(self, defines, includes, for_asm=False):
00139         opts = ['-D%s' % d for d in defines]
00140         if for_asm :
00141             return opts
00142         if self.RESPONSE_FILES:
00143             opts += ['-f', self.get_inc_file(includes)]
00144         else:
00145             opts += ["-I%s" % i for i in includes]
00146 
00147         config_header = self.get_config_header()
00148         if config_header is not None:
00149             opts = opts + self.get_config_option(config_header)
00150         return opts
00151 
00152     @hook_tool
00153     def assemble(self, source, object, includes):
00154         # Build assemble command
00155         cmd = self.asm + self.get_compile_options(self.get_symbols(True), includes, True) + ["-o", object, source]
00156 
00157         # Call cmdline hook
00158         cmd = self.hook.get_cmdline_assembler(cmd)
00159 
00160         # Return command array, don't execute
00161         return [cmd]
00162 
00163     @hook_tool
00164     def compile(self, cc, source, object, includes):
00165         # Build compile command
00166         cmd = cc +  self.get_compile_options(self.get_symbols(), includes)
00167 
00168         cmd.extend(self.get_dep_option(object))
00169 
00170         cmd.extend(self.cc_extra(object))
00171         
00172         cmd.extend(["-o", object, source])
00173 
00174         # Call cmdline hook
00175         cmd = self.hook.get_cmdline_compiler(cmd)
00176 
00177         return [cmd]
00178 
00179     def compile_c(self, source, object, includes):
00180         return self.compile(self.cc, source, object, includes)
00181 
00182     def compile_cpp(self, source, object, includes):
00183         return self.compile(self.cppc, source, object, includes)
00184 
00185     @hook_tool
00186     def link(self, output, objects, libraries, lib_dirs, mem_map):
00187         # Build linker command
00188         map_file = splitext(output)[0] + ".map"
00189         cmd = self.ld + [ "-o", output, "--map=%s" % map_file] + objects + libraries
00190 
00191         if mem_map:
00192             cmd.extend(["--config", mem_map])
00193 
00194         # Call cmdline hook
00195         cmd = self.hook.get_cmdline_linker(cmd)
00196 
00197         if self.RESPONSE_FILES:
00198             # Split link command to linker executable + response file
00199             cmd_linker = cmd[0]
00200             link_files = self.get_link_file(cmd[1:])
00201             cmd = [cmd_linker, '-f', link_files]
00202 
00203         # Exec command
00204         self.cc_verbose("Link: %s" % ' '.join(cmd))
00205         self.default_cmd(cmd)
00206 
00207     @hook_tool
00208     def archive(self, objects, lib_path):
00209         if self.RESPONSE_FILES:
00210             param = ['-f', self.get_arch_file(objects)]
00211         else:
00212             param = objects
00213 
00214         if exists(lib_path):
00215             remove(lib_path)
00216 
00217         self.default_cmd([self.ar, lib_path] + param)
00218 
00219     @hook_tool
00220     def binary(self, resources, elf, bin):
00221         _, fmt = splitext(bin)
00222         bin_arg = {".bin": "--bin", ".hex": "--ihex"}[fmt]
00223         # Build binary command
00224         cmd = [self.elf2bin, bin_arg, elf, bin]
00225 
00226         # Call cmdline hook
00227         cmd = self.hook.get_cmdline_binary(cmd)
00228 
00229         # Exec command
00230         self.cc_verbose("FromELF: %s" % ' '.join(cmd))
00231         self.default_cmd(cmd)
00232 
00233     @staticmethod
00234     def name_mangle(name):
00235         return "_Z%i%sv" % (len(name), name)
00236 
00237     @staticmethod
00238     def make_ld_define(name, value):
00239         return "--config_def %s=0x%x" % (name, value)
00240 
00241     @staticmethod
00242     def redirect_symbol(source, sync, build_dir):
00243         return "--redirect %s=%s" % (source, sync)