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