Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers gcc.py Source File

gcc.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.path import join, basename, splitext, dirname, exists
00019 from distutils.spawn import find_executable
00020 
00021 from tools.toolchains import mbedToolchain, TOOLCHAIN_PATHS
00022 from tools.hooks import hook_tool
00023 
00024 class GCC(mbedToolchain):
00025     LINKER_EXT = '.ld'
00026     LIBRARY_EXT = '.a'
00027 
00028     STD_LIB_NAME = "lib%s.a"
00029     DIAGNOSTIC_PATTERN = re.compile('((?P<file>[^:]+):(?P<line>\d+):)(?P<col>\d+):? (?P<severity>warning|[eE]rror|fatal error): (?P<message>.+)')
00030 
00031     def __init__(self, target,  notify=None, macros=None,
00032                  silent=False, extra_verbose=False, build_profile=None,
00033                  build_dir=None):
00034         mbedToolchain.__init__(self, target, notify, macros, silent,
00035                                extra_verbose=extra_verbose,
00036                                build_profile=build_profile, build_dir=build_dir)
00037 
00038         tool_path=TOOLCHAIN_PATHS['GCC_ARM']
00039         # Add flags for current size setting
00040         default_lib = "std"
00041         if hasattr(target, "default_lib"):
00042             default_lib = target.default_lib
00043         elif hasattr(target, "default_build"): # Legacy
00044             default_lib = target.default_build
00045 
00046         if default_lib == "small":
00047             self.flags["common"].append("-DMBED_RTOS_SINGLE_THREAD")
00048             self.flags["ld"].append("--specs=nano.specs")
00049 
00050         if target.core == "Cortex-M0+":
00051             self.cpu = ["-mcpu=cortex-m0plus"]
00052         elif target.core.startswith("Cortex-M4"):
00053             self.cpu = ["-mcpu=cortex-m4"]
00054         elif target.core.startswith("Cortex-M7"):
00055             self.cpu = ["-mcpu=cortex-m7"]
00056         elif target.core.startswith("Cortex-M23"):
00057             self.cpu = ["-mcpu=cortex-m23"]
00058         elif target.core.startswith("Cortex-M33F"):
00059             self.cpu = ["-mcpu=cortex-m33"]
00060         elif target.core.startswith("Cortex-M33"):
00061             self.cpu = ["-march=armv8-m.main"]
00062         else:
00063             self.cpu = ["-mcpu={}".format(target.core.lower())]
00064 
00065         if target.core.startswith("Cortex-M"):
00066             self.cpu.append("-mthumb")
00067 
00068         # FPU handling, M7 possibly to have double FPU
00069         if target.core == "Cortex-M4F":
00070             self.cpu.append("-mfpu=fpv4-sp-d16")
00071             self.cpu.append("-mfloat-abi=softfp")
00072         elif target.core == "Cortex-M7F":
00073             self.cpu.append("-mfpu=fpv5-sp-d16")
00074             self.cpu.append("-mfloat-abi=softfp")
00075         elif target.core == "Cortex-M7FD":
00076             self.cpu.append("-mfpu=fpv5-d16")
00077             self.cpu.append("-mfloat-abi=softfp")
00078 
00079         if target.core == "Cortex-A9":
00080             self.cpu.append("-mthumb-interwork")
00081             self.cpu.append("-marm")
00082             self.cpu.append("-march=armv7-a")
00083             self.cpu.append("-mfpu=vfpv3")
00084             self.cpu.append("-mfloat-abi=hard")
00085             self.cpu.append("-mno-unaligned-access")
00086 
00087         if ((target.core.startswith("Cortex-M23") or
00088              target.core.startswith("Cortex-M33")) and
00089             not target.core.endswith("-NS")):
00090             self.cpu.append("-mcmse")
00091         elif target.core == "Cortex-M23-NS" or target.core == "Cortex-M33-NS":
00092              self.flags["ld"].append("-D__DOMAIN_NS=1")
00093 
00094         self.flags["common"] += self.cpu
00095 
00096         main_cc = join(tool_path, "arm-none-eabi-gcc")
00097         main_cppc = join(tool_path, "arm-none-eabi-g++")
00098         self.asm = [main_cc] + self.flags['asm'] + self.flags["common"]
00099         self.cc  = [main_cc]
00100         self.cppc =[main_cppc]
00101         self.cc += self.flags['c'] + self.flags['common']
00102         self.cppc += self.flags['cxx'] + self.flags['common']
00103 
00104         self.flags['ld'] += self.cpu
00105         self.ld = [join(tool_path, "arm-none-eabi-gcc")] + self.flags['ld']
00106         self.sys_libs = ["stdc++", "supc++", "m", "c", "gcc", "nosys"]
00107         self.preproc = [join(tool_path, "arm-none-eabi-cpp"), "-E", "-P"]
00108 
00109         self.ar = join(tool_path, "arm-none-eabi-ar")
00110         self.elf2bin = join(tool_path, "arm-none-eabi-objcopy")
00111 
00112     def is_not_supported_error(self, output):
00113         return "error: #error [NOT_SUPPORTED]" in output
00114 
00115     def parse_output(self, output):
00116         # The warning/error notification is multiline
00117         msg = None
00118         for line in output.splitlines():
00119             match = self.DIAGNOSTIC_PATTERN.search(line)
00120             if match is not None:
00121                 if msg is not None:
00122                     self.cc_info(msg)
00123                     msg = None
00124                 msg = {
00125                     'severity': match.group('severity').lower(),
00126                     'file': match.group('file'),
00127                     'line': match.group('line'),
00128                     'col': match.group('col'),
00129                     'message': match.group('message'),
00130                     'text': '',
00131                     'target_name': self.target.name,
00132                     'toolchain_name': self.name
00133                 }
00134 
00135         if msg is not None:
00136             self.cc_info(msg)
00137 
00138     def get_dep_option(self, object):
00139         base, _ = splitext(object)
00140         dep_path = base + '.d'
00141         return ["-MD", "-MF", dep_path]
00142 
00143     def get_config_option(self, config_header):
00144         return ['-include', config_header]
00145 
00146     def get_compile_options(self, defines, includes, for_asm=False):
00147         opts = ['-D%s' % d for d in defines]
00148         if self.RESPONSE_FILES:
00149             opts += ['@%s' % self.get_inc_file(includes)]
00150         else:
00151             opts += ["-I%s" % i for i in includes]
00152 
00153         if not for_asm:
00154             config_header = self.get_config_header()
00155             if config_header is not None:
00156                 opts = opts + self.get_config_option(config_header)
00157         return opts
00158 
00159     @hook_tool
00160     def assemble(self, source, object, includes):
00161         # Build assemble command
00162         cmd = self.asm + self.get_compile_options(self.get_symbols(True), includes) + ["-o", object, source]
00163 
00164         # Call cmdline hook
00165         cmd = self.hook.get_cmdline_assembler(cmd)
00166 
00167         # Return command array, don't execute
00168         return [cmd]
00169 
00170     @hook_tool
00171     def compile(self, cc, source, object, includes):
00172         # Build compile command
00173         cmd = cc + self.get_compile_options(self.get_symbols(), includes)
00174 
00175         cmd.extend(self.get_dep_option(object))
00176 
00177         cmd.extend(["-o", object, source])
00178 
00179         # Call cmdline hook
00180         cmd = self.hook.get_cmdline_compiler(cmd)
00181 
00182         return [cmd]
00183 
00184     def compile_c(self, source, object, includes):
00185         return self.compile(self.cc, source, object, includes)
00186 
00187     def compile_cpp(self, source, object, includes):
00188         return self.compile(self.cppc, source, object, includes)
00189 
00190     @hook_tool
00191     def link(self, output, objects, libraries, lib_dirs, mem_map):
00192         libs = []
00193         for l in libraries:
00194             name, _ = splitext(basename(l))
00195             libs.append("-l%s" % name[3:])
00196         libs.extend(["-l%s" % l for l in self.sys_libs])
00197 
00198         # Preprocess
00199         if mem_map:
00200             preproc_output = join(dirname(output), ".link_script.ld")
00201             cmd = (self.preproc + [mem_map] + self.ld[1:] +
00202                    [ "-o", preproc_output])
00203             self.cc_verbose("Preproc: %s" % ' '.join(cmd))
00204             self.default_cmd(cmd)
00205             mem_map = preproc_output
00206 
00207         # Build linker command
00208         map_file = splitext(output)[0] + ".map"
00209         cmd = self.ld + ["-o", output, "-Wl,-Map=%s" % map_file] + objects + ["-Wl,--start-group"] + libs + ["-Wl,--end-group"]
00210         # Create Secure library
00211         if self.target.core == "Cortex-M23" or self.target.core == "Cortex-M33":
00212             secure_file = join(dirname(output), "cmse_lib.o")
00213             cmd.extend(["-Wl,--cmse-implib"])
00214             cmd.extend(["-Wl,--out-implib=%s" % secure_file])
00215 
00216         if mem_map:
00217             cmd.extend(['-T', mem_map])
00218 
00219         for L in lib_dirs:
00220             cmd.extend(['-L', L])
00221         cmd.extend(libs)
00222 
00223         # Call cmdline hook
00224         cmd = self.hook.get_cmdline_linker(cmd)
00225 
00226         if self.RESPONSE_FILES:
00227             # Split link command to linker executable + response file
00228             cmd_linker = cmd[0]
00229             link_files = self.get_link_file(cmd[1:])
00230             cmd = [cmd_linker, "@%s" % link_files]
00231 
00232         # Exec command
00233         self.cc_verbose("Link: %s" % ' '.join(cmd))
00234         self.default_cmd(cmd)
00235         if self.target.core == "Cortex-M23" or self.target.core == "Cortex-M33":
00236             self.info("Secure Library Object %s" %secure_file)
00237 
00238     @hook_tool
00239     def archive(self, objects, lib_path):
00240         if self.RESPONSE_FILES:
00241             param = ["@%s" % self.get_arch_file(objects)]
00242         else:
00243             param = objects
00244 
00245         # Exec command
00246         self.default_cmd([self.ar, 'rcs', lib_path] + param)
00247 
00248     @hook_tool
00249     def binary(self, resources, elf, bin):
00250         # Build binary command
00251         _, fmt = splitext(bin)
00252         bin_arg = {'.bin': 'binary', '.hex': 'ihex'}[fmt]
00253         cmd = [self.elf2bin, "-O", bin_arg, elf, bin]
00254 
00255         # Call cmdline hook
00256         cmd = self.hook.get_cmdline_binary(cmd)
00257 
00258         # Exec command
00259         self.cc_verbose("FromELF: %s" % ' '.join(cmd))
00260         self.default_cmd(cmd)
00261 
00262     @staticmethod
00263     def name_mangle(name):
00264         return "_Z%i%sv" % (len(name), name)
00265 
00266     @staticmethod
00267     def make_ld_define(name, value):
00268         return "-D%s=0x%x" % (name, value)
00269 
00270     @staticmethod
00271     def redirect_symbol(source, sync, build_dir):
00272         return "-Wl,--defsym=%s=%s" % (source, sync)
00273 
00274     @staticmethod
00275     def check_executable():
00276         """Returns True if the executable (arm-none-eabi-gcc) location
00277         specified by the user exists OR the executable can be found on the PATH.
00278         Returns False otherwise."""
00279         if not TOOLCHAIN_PATHS['GCC_ARM'] or not exists(TOOLCHAIN_PATHS['GCC_ARM']):
00280             if find_executable('arm-none-eabi-gcc'):
00281                 TOOLCHAIN_PATHS['GCC_ARM'] = ''
00282                 return True
00283             else:
00284                 return False
00285         else:
00286             exec_name = join(TOOLCHAIN_PATHS['GCC_ARM'], 'arm-none-eabi-gcc')
00287             return exists(exec_name) or exists(exec_name + '.exe')
00288 
00289 class GCC_ARM(GCC):
00290     pass