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.
Dependents: mbed-os-example-blinky-gr-lychee GR-Boads_Camera_sample GR-Boards_Audio_Recoder GR-Boads_Camera_DisplayApp ... more
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
Generated on Tue Jul 12 2022 11:02:24 by
1.7.2