takashi kadono / Mbed OS Nucleo_446

Dependencies:   ssd1331

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