Daiki Kato / mbed-os-lychee

Dependents:   mbed-os-example-blinky-gr-lychee GR-Boads_Camera_sample GR-Boards_Audio_Recoder GR-Boads_Camera_DisplayApp ... more

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