ON Semiconductor / mbed-os

Dependents:   mbed-TFT-example-NCS36510 mbed-Accelerometer-example-NCS36510 mbed-Accelerometer-example-NCS36510

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, TOOLCHAIN_PATHS
00021 from tools.hooks import hook_tool
00022 
00023 class GCC(mbedToolchain):
00024     LINKER_EXT = '.ld'
00025     LIBRARY_EXT = '.a'
00026 
00027     STD_LIB_NAME = "lib%s.a"
00028     DIAGNOSTIC_PATTERN = re.compile('((?P<file>[^:]+):(?P<line>\d+):)(\d+:)? (?P<severity>warning|error): (?P<message>.+)')
00029     INDEX_PATTERN  = re.compile('(?P<col>\s*)\^')
00030 
00031     def __init__(self, target,  notify=None, macros=None,
00032                  silent=False, tool_path="", extra_verbose=False,
00033                  build_profile=None):
00034         mbedToolchain.__init__(self, target, notify, macros, silent,
00035                                extra_verbose=extra_verbose,
00036                                build_profile=build_profile)
00037 
00038         # Add flags for current size setting
00039         default_lib = "std"
00040         if hasattr(target, "default_lib"):
00041             default_lib = target.default_lib
00042         elif hasattr(target, "default_build"): # Legacy
00043             default_lib = target.default_build
00044 
00045         if default_lib == "small":
00046             self.flags["common"].append("-DMBED_RTOS_SINGLE_THREAD")
00047             self.flags["ld"].append("--specs=nano.specs")
00048 
00049         if target.core == "Cortex-M0+":
00050             cpu = "cortex-m0plus"
00051         elif target.core == "Cortex-M4F":
00052             cpu = "cortex-m4"
00053         elif target.core == "Cortex-M7F":
00054             cpu = "cortex-m7"
00055         elif target.core == "Cortex-M7FD":
00056             cpu = "cortex-m7"
00057         else:
00058             cpu = target.core.lower()
00059 
00060         self.cpu = ["-mcpu=%s" % cpu]
00061         if target.core.startswith("Cortex"):
00062             self.cpu.append("-mthumb")
00063 
00064         # FPU handling, M7 possibly to have double FPU
00065         if target.core == "Cortex-M4F":
00066             self.cpu.append("-mfpu=fpv4-sp-d16")
00067             self.cpu.append("-mfloat-abi=softfp")
00068         elif target.core == "Cortex-M7F":
00069             self.cpu.append("-mfpu=fpv5-sp-d16")
00070             self.cpu.append("-mfloat-abi=softfp")
00071         elif target.core == "Cortex-M7FD":
00072             self.cpu.append("-mfpu=fpv5-d16")
00073             self.cpu.append("-mfloat-abi=softfp")
00074 
00075         if target.core == "Cortex-A9":
00076             self.cpu.append("-mthumb-interwork")
00077             self.cpu.append("-marm")
00078             self.cpu.append("-march=armv7-a")
00079             self.cpu.append("-mfpu=vfpv3")
00080             self.cpu.append("-mfloat-abi=hard")
00081             self.cpu.append("-mno-unaligned-access")
00082 
00083         self.flags["common"] += self.cpu
00084 
00085         main_cc = join(tool_path, "arm-none-eabi-gcc")
00086         main_cppc = join(tool_path, "arm-none-eabi-g++")
00087         self.asm = [main_cc] + self.flags['asm'] + self.flags["common"]
00088         self.cc  = [main_cc]
00089         self.cppc =[main_cppc]
00090         self.cc += self.flags['c'] + self.flags['common']
00091         self.cppc += self.flags['cxx'] + self.flags['common']
00092 
00093         self.flags['ld'] += self.cpu
00094         self.ld = [join(tool_path, "arm-none-eabi-gcc")] + self.flags['ld']
00095         self.sys_libs = ["stdc++", "supc++", "m", "c", "gcc"]
00096 
00097         self.ar = join(tool_path, "arm-none-eabi-ar")
00098         self.elf2bin = join(tool_path, "arm-none-eabi-objcopy")
00099 
00100     def parse_dependencies(self, dep_path):
00101         dependencies = []
00102         buff = open(dep_path).readlines()
00103         buff[0] = re.sub('^(.*?)\: ', '', buff[0])
00104         for line in buff:
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((self.CHROOT if self.CHROOT else '') + file.replace('\a', ' '))
00117                 else:
00118                     dependencies = dependencies + [(self.CHROOT if self.CHROOT else '') + 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         msg = None
00127         for line in output.splitlines():
00128             match = GCC.DIAGNOSTIC_PATTERN.search(line)
00129             if match is not None:
00130                 if msg is not None:
00131                     self.cc_info(msg)
00132                     msg = None
00133                 msg = {
00134                     'severity': match.group('severity').lower(),
00135                     'file': match.group('file'),
00136                     'line': match.group('line'),
00137                     'col': 0,
00138                     'message': match.group('message'),
00139                     'text': '',
00140                     'target_name': self.target.name,
00141                     'toolchain_name': self.name
00142                 }
00143             elif msg is not None:
00144                 # Determine the warning/error column by calculating the ^ position
00145                 match = GCC.INDEX_PATTERN.match(line)
00146                 if match is not None:
00147                     msg['col'] = len(match.group('col'))
00148                     self.cc_info(msg)
00149                     msg = None
00150                 else:
00151                     msg['text'] += line+"\n"
00152 
00153         if msg is not None:
00154             self.cc_info(msg)
00155 
00156     def get_dep_option(self, object):
00157         base, _ = splitext(object)
00158         dep_path = base + '.d'
00159         return ["-MD", "-MF", dep_path]
00160 
00161     def get_config_option(self, config_header):
00162         return ['-include', config_header]
00163 
00164     def get_compile_options(self, defines, includes, for_asm=False):
00165         opts = ['-D%s' % d for d in defines]
00166         if self.RESPONSE_FILES:
00167             opts += ['@%s' % self.get_inc_file(includes)]
00168         else:
00169             opts += ["-I%s" % i for i in includes]
00170 
00171         if not for_asm:
00172             config_header = self.get_config_header()
00173             if config_header is not None:
00174                 opts = opts + self.get_config_option(config_header)
00175         return opts
00176 
00177     @hook_tool
00178     def assemble(self, source, object, includes):
00179         # Build assemble command
00180         cmd = self.asm + self.get_compile_options(self.get_symbols(True), includes) + ["-o", object, source]
00181 
00182         # Call cmdline hook
00183         cmd = self.hook.get_cmdline_assembler(cmd)
00184 
00185         # Return command array, don't execute
00186         return [cmd]
00187 
00188     @hook_tool
00189     def compile(self, cc, source, object, includes):
00190         # Build compile command
00191         cmd = cc + self.get_compile_options(self.get_symbols(), includes)
00192 
00193         cmd.extend(self.get_dep_option(object))
00194 
00195         cmd.extend(["-o", object, source])
00196 
00197         # Call cmdline hook
00198         cmd = self.hook.get_cmdline_compiler(cmd)
00199 
00200         return [cmd]
00201 
00202     def compile_c(self, source, object, includes):
00203         return self.compile(self.cc, source, object, includes)
00204 
00205     def compile_cpp(self, source, object, includes):
00206         return self.compile(self.cppc, source, object, includes)
00207 
00208     @hook_tool
00209     def link(self, output, objects, libraries, lib_dirs, mem_map):
00210         libs = []
00211         for l in libraries:
00212             name, _ = splitext(basename(l))
00213             libs.append("-l%s" % name[3:])
00214         libs.extend(["-l%s" % l for l in self.sys_libs])
00215 
00216         # Build linker command
00217         map_file = splitext(output)[0] + ".map"
00218         cmd = self.ld + ["-o", output, "-Wl,-Map=%s" % map_file] + objects + ["-Wl,--start-group"] + libs + ["-Wl,--end-group"]
00219         if mem_map:
00220             cmd.extend(['-T', mem_map])
00221 
00222         for L in lib_dirs:
00223             cmd.extend(['-L', L])
00224         cmd.extend(libs)
00225 
00226         # Call cmdline hook
00227         cmd = self.hook.get_cmdline_linker(cmd)
00228 
00229         if self.RESPONSE_FILES:
00230             # Split link command to linker executable + response file
00231             cmd_linker = cmd[0]
00232             link_files = self.get_link_file(cmd[1:])
00233             cmd = [cmd_linker, "@%s" % link_files]
00234 
00235         # Exec command
00236         self.cc_verbose("Link: %s" % ' '.join(cmd))
00237         self.default_cmd(cmd)
00238 
00239     @hook_tool
00240     def archive(self, objects, lib_path):
00241         if self.RESPONSE_FILES:
00242             param = ["@%s" % self.get_arch_file(objects)]
00243         else:
00244             param = objects
00245 
00246         # Exec command
00247         self.default_cmd([self.ar, 'rcs', lib_path] + param)
00248 
00249     @hook_tool
00250     def binary(self, resources, elf, bin):
00251         # Build binary command
00252         cmd = [self.elf2bin, "-O", "binary", elf, bin]
00253 
00254         # Call cmdline hook
00255         cmd = self.hook.get_cmdline_binary(cmd)
00256 
00257         # Exec command
00258         self.cc_verbose("FromELF: %s" % ' '.join(cmd))
00259         self.default_cmd(cmd)
00260 
00261 
00262 class GCC_ARM(GCC):
00263     @staticmethod
00264     def check_executable():
00265         """Returns True if the executable (arm-none-eabi-gcc) location
00266         specified by the user exists OR the executable can be found on the PATH.
00267         Returns False otherwise."""
00268         return mbedToolchain.generic_check_executable("GCC_ARM", 'arm-none-eabi-gcc', 1)
00269 
00270     def __init__(self, target, notify=None, macros=None,
00271                  silent=False, extra_verbose=False, build_profile=None):
00272         GCC.__init__(self, target, notify, macros, silent,
00273                      TOOLCHAIN_PATHS['GCC_ARM'], extra_verbose=extra_verbose,
00274                      build_profile=build_profile)
00275 
00276         self.sys_libs.append("nosys")
00277 
00278 
00279 class GCC_CR(GCC):
00280     @staticmethod
00281     def check_executable():
00282         """Returns True if the executable (arm-none-eabi-gcc) location
00283         specified by the user exists OR the executable can be found on the PATH.
00284         Returns False otherwise."""
00285         return mbedToolchain.generic_check_executable("GCC_CR", 'arm-none-eabi-gcc', 1)
00286 
00287     def __init__(self, target, notify=None, macros=None,
00288                  silent=False, extra_verbose=False, build_profile=None):
00289         GCC.__init__(self, target, notify, macros, silent,
00290                      TOOLCHAIN_PATHS['GCC_CR'], extra_verbose=extra_verbose,
00291                      build_profile=build_profile)
00292 
00293         additional_compiler_flags = [
00294             "-D__NEWLIB__", "-D__CODE_RED", "-D__USE_CMSIS", "-DCPP_USE_HEAP",
00295         ]
00296         self.cc += additional_compiler_flags
00297         self.cppc += additional_compiler_flags
00298 
00299         # Use latest gcc nanolib
00300         self.ld.append("--specs=nano.specs")
00301         if target.name in ["LPC1768", "LPC4088", "LPC4088_DM", "LPC4330", "UBLOX_C027", "LPC2368"]:
00302             self.ld.extend(["-u _printf_float", "-u _scanf_float"])
00303         self.ld += ["-nostdlib"]