Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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
Generated on Tue Aug 9 2022 00:37:08 by
 1.7.2
 1.7.2