Brian Daniels / mbed-tools

Fork of mbed-tools by Morpheus

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
00019 
00020 from tools.toolchains import mbedToolchain
00021 from tools.settings import GCC_ARM_PATH, GCC_CR_PATH
00022 from tools.settings import GOANNA_PATH
00023 from tools.hooks import hook_tool
00024 
00025 class GCC(mbedToolchain):
00026     LINKER_EXT = '.ld'
00027     LIBRARY_EXT = '.a'
00028 
00029     STD_LIB_NAME = "lib%s.a"
00030     CIRCULAR_DEPENDENCIES = True
00031     DIAGNOSTIC_PATTERN = re.compile('((?P<line>\d+):)(\d+:)? (?P<severity>warning|error): (?P<message>.+)')
00032 
00033     def __init__(self, target, options=None, notify=None, macros=None, silent=False, tool_path="", extra_verbose=False):
00034         mbedToolchain.__init__(self, target, options, notify, macros, silent, extra_verbose=extra_verbose)
00035 
00036         if target.core == "Cortex-M0+":
00037             cpu = "cortex-m0plus"
00038         elif target.core == "Cortex-M4F":
00039             cpu = "cortex-m4"
00040         elif target.core == "Cortex-M7F":
00041             cpu = "cortex-m7"
00042         else:
00043             cpu = target.core.lower()
00044 
00045         self.cpu = ["-mcpu=%s" % cpu]
00046         if target.core.startswith("Cortex"):
00047             self.cpu.append("-mthumb")
00048 
00049         if target.core == "Cortex-M4F":
00050             self.cpu.append("-mfpu=fpv4-sp-d16")
00051             self.cpu.append("-mfloat-abi=softfp")
00052         elif target.core == "Cortex-M7F":
00053             self.cpu.append("-mfpu=fpv5-d16")
00054             self.cpu.append("-mfloat-abi=softfp")
00055 
00056         if target.core == "Cortex-A9":
00057             self.cpu.append("-mthumb-interwork")
00058             self.cpu.append("-marm")
00059             self.cpu.append("-march=armv7-a")
00060             self.cpu.append("-mfpu=vfpv3")
00061             self.cpu.append("-mfloat-abi=hard")
00062             self.cpu.append("-mno-unaligned-access")
00063 
00064 
00065         # Note: We are using "-O2" instead of "-Os" to avoid this known GCC bug:
00066         # http://gcc.gnu.org/bugzilla/show_bug.cgi?id=46762
00067         common_flags = ["-c", "-Wall", "-Wextra",
00068             "-Wno-unused-parameter", "-Wno-missing-field-initializers",
00069             "-fmessage-length=0", "-fno-exceptions", "-fno-builtin",
00070             "-ffunction-sections", "-fdata-sections",
00071             "-MMD", "-fno-delete-null-pointer-checks", "-fomit-frame-pointer"
00072             ] + self.cpu
00073 
00074         if "save-asm" in self.options:
00075             common_flags.append("-save-temps")
00076 
00077         if "debug-info" in self.options:
00078             common_flags.append("-g")
00079             common_flags.append("-O0")
00080         else:
00081             common_flags.append("-O2")
00082 
00083         main_cc = join(tool_path, "arm-none-eabi-gcc")
00084         main_cppc = join(tool_path, "arm-none-eabi-g++")
00085         self.asm = [main_cc, "-x", "assembler-with-cpp"] + common_flags
00086         if not "analyze" in self.options:
00087             self.cc  = [main_cc, "-std=gnu99"] + common_flags
00088             self.cppc =[main_cppc, "-std=gnu++98", "-fno-rtti"] + common_flags
00089         else:
00090             self.cc  = [join(GOANNA_PATH, "goannacc"), "--with-cc=" + main_cc.replace('\\', '/'), "-std=gnu99", "--dialect=gnu", '--output-format="%s"' % self.GOANNA_FORMAT] + common_flags
00091             self.cppc= [join(GOANNA_PATH, "goannac++"), "--with-cxx=" + main_cppc.replace('\\', '/'), "-std=gnu++98", "-fno-rtti", "--dialect=gnu", '--output-format="%s"' % self.GOANNA_FORMAT] + common_flags
00092 
00093         self.ld = [join(tool_path, "arm-none-eabi-gcc"), "-Wl,--gc-sections", "-Wl,--wrap,main"] + self.cpu
00094         self.sys_libs = ["stdc++", "supc++", "m", "c", "gcc"]
00095 
00096         self.ar = join(tool_path, "arm-none-eabi-ar")
00097         self.elf2bin = join(tool_path, "arm-none-eabi-objcopy")
00098 
00099     def assemble(self, source, object, includes):
00100         return [self.hook.get_cmdline_assembler(self.asm + ['-D%s' % s for s in self.get_symbols() + self.macros] + ["-I%s" % i for i in includes] + ["-o", object, source])]
00101 
00102     def parse_dependencies(self, dep_path):
00103         dependencies = []
00104         for line in open(dep_path).readlines()[1:]:
00105             file = line.replace('\\\n', '').strip()
00106             if file:
00107                 # GCC might list more than one dependency on a single line, in this case
00108                 # the dependencies are separated by a space. However, a space might also
00109                 # indicate an actual space character in a dependency path, but in this case
00110                 # the space character is prefixed by a backslash.
00111                 # Temporary replace all '\ ' with a special char that is not used (\a in this
00112                 # case) to keep them from being interpreted by 'split' (they will be converted
00113                 # back later to a space char)
00114                 file = file.replace('\\ ', '\a')
00115                 if file.find(" ") == -1:
00116                     dependencies.append(file.replace('\a', ' '))
00117                 else:
00118                     dependencies = dependencies + [f.replace('\a', ' ') for f in file.split(" ")]
00119         return dependencies
00120 
00121     def is_not_supported_error(self, output):
00122         return "error: #error [NOT_SUPPORTED]" in output
00123 
00124     def parse_output(self, output):
00125         # The warning/error notification is multiline
00126         WHERE, WHAT = 0, 1
00127         state, file, message = WHERE, None, None
00128         for line in output.splitlines():
00129             match = self.goanna_parse_line(line)
00130             if match is not None:
00131                 self.cc_info(
00132                     match.group('severity').lower(),
00133                     match.group('file'),
00134                     match.group('line'),
00135                     match.group('message'),
00136                     target_name=self.target.name,
00137                     toolchain_name=self.name
00138                 )
00139                 continue
00140 
00141             # Each line should start with the file information: "filepath: ..."
00142             # i should point past the file path                          ^
00143             # avoid the first column in Windows (C:\)
00144             i = line.find(':', 2)
00145             if i == -1: continue
00146 
00147             if state == WHERE:
00148                 file = line[:i]
00149                 message = line[i+1:].strip() + ' '
00150                 state = WHAT
00151 
00152             elif state == WHAT:
00153                 match = GCC.DIAGNOSTIC_PATTERN.match(line[i+1:])
00154                 if match is None:
00155                     state = WHERE
00156                     continue
00157 
00158                 self.cc_info(
00159                     match.group('severity'),
00160                     file, match.group('line'),
00161                     message + match.group('message')
00162                 )
00163 
00164     def archive(self, objects, lib_path):
00165         self.default_cmd([self.ar, "rcs", lib_path] + objects)
00166 
00167     def link(self, output, objects, libraries, lib_dirs, mem_map):
00168         libs = []
00169         for l in libraries:
00170             name, _ = splitext(basename(l))
00171             libs.append("-l%s" % name[3:])
00172         libs.extend(["-l%s" % l for l in self.sys_libs])
00173 
00174         # NOTE: There is a circular dependency between the mbed library and the clib
00175         # We could define a set of week symbols to satisfy the clib dependencies in "sys.o",
00176         # but if an application uses only clib symbols and not mbed symbols, then the final
00177         # image is not correctly retargeted
00178         if self.CIRCULAR_DEPENDENCIES:
00179             libs.extend(libs)
00180 
00181         self.default_cmd(self.hook.get_cmdline_linker(self.ld + ["-T%s" % mem_map, "-o", output] +
00182             objects + ["-L%s" % L for L in lib_dirs] + libs))
00183 
00184     @hook_tool
00185     def binary(self, resources, elf, bin):
00186         self.default_cmd(self.hook.get_cmdline_binary([self.elf2bin, "-O", "binary", elf, bin]))
00187 
00188 
00189 class GCC_ARM(GCC):
00190     def __init__(self, target, options=None, notify=None, macros=None, silent=False, extra_verbose=False):
00191         GCC.__init__(self, target, options, notify, macros, silent, GCC_ARM_PATH, extra_verbose=extra_verbose)
00192 
00193         # Use latest gcc nanolib
00194         self.ld.append("--specs=nano.specs")
00195         if target.name in ["LPC1768", "LPC4088", "LPC4088_DM", "LPC4330", "UBLOX_C027", "LPC2368"]:
00196             self.ld.extend(["-u _printf_float", "-u _scanf_float"])
00197         elif target.name in ["RZ_A1H", "ARCH_MAX", "DISCO_F407VG", "DISCO_F429ZI", "DISCO_F469NI", "NUCLEO_F401RE", "NUCLEO_F410RB", "NUCLEO_F411RE", "NUCLEO_F446RE", "ELMO_F411RE", "MTS_MDOT_F411RE", "MTS_DRAGONFLY_F411RE", "DISCO_F746NG"]:
00198             self.ld.extend(["-u_printf_float", "-u_scanf_float"])
00199 
00200         self.sys_libs.append("nosys")
00201 
00202 
00203 class GCC_CR(GCC):
00204     def __init__(self, target, options=None, notify=None, macros=None, silent=False, extra_verbose=False):
00205         GCC.__init__(self, target, options, notify, macros, silent, GCC_CR_PATH, extra_verbose=extra_verbose)
00206 
00207         additional_compiler_flags = [
00208             "-D__NEWLIB__", "-D__CODE_RED", "-D__USE_CMSIS", "-DCPP_USE_HEAP",
00209         ]
00210         self.cc += additional_compiler_flags
00211         self.cppc += additional_compiler_flags
00212 
00213         # Use latest gcc nanolib
00214         self.ld.append("--specs=nano.specs")
00215         if target.name in ["LPC1768", "LPC4088", "LPC4088_DM", "LPC4330", "UBLOX_C027", "LPC2368"]:
00216             self.ld.extend(["-u _printf_float", "-u _scanf_float"])
00217         self.ld += ["-nostdlib"]
00218