3 Copyright (c) 2011-2013 ARM Limited
5 Licensed under the Apache License, Version 2.0 (the "License");
6 you may not use this file except in compliance with the License.
7 You may obtain a copy of the License at
9 http://www.apache.org/licenses/LICENSE-2.0
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
18 from os.path import join, basename, splitext
20 from workspace_tools.toolchains import mbedToolchain
21 from workspace_tools.settings import GCC_ARM_PATH, GCC_CR_PATH, GCC_CS_PATH, CW_EWL_PATH, CW_GCC_PATH
22 from workspace_tools.settings import GOANNA_PATH
23 from workspace_tools.hooks import hook_tool
25 class GCC(mbedToolchain):
29 STD_LIB_NAME = "lib%s.a"
30 CIRCULAR_DEPENDENCIES = True
31 DIAGNOSTIC_PATTERN = re.compile('((?P<line>\d+):)(\d+:)? (?P<severity>warning|error): (?P<message>.+)')
33 def __init__(self, target, options=None, notify=None, macros=None, silent=False, tool_path=""):
34 mbedToolchain.__init__(self, target, options, notify, macros, silent)
36 if target.core == "Cortex-M0+":
38 elif target.core == "Cortex-M4F":
41 cpu = target.core.lower()
43 self.cpu = ["-mcpu=%s" % cpu]
44 if target.core.startswith("Cortex"):
45 self.cpu.append("-mthumb")
47 if target.core == "Cortex-M4F":
48 self.cpu.append("-mfpu=fpv4-sp-d16")
49 self.cpu.append("-mfloat-abi=softfp")
51 if target.core == "Cortex-A9":
52 self.cpu.append("-mthumb-interwork")
53 self.cpu.append("-marm")
54 self.cpu.append("-march=armv7-a")
55 self.cpu.append("-mfpu=vfpv3-d16")
56 self.cpu.append("-mfloat-abi=hard")
57 self.cpu.append("-mno-unaligned-access")
60 # Note: We are using "-O2" instead of "-Os" to avoid this known GCC bug:
61 # http://gcc.gnu.org/bugzilla/show_bug.cgi?id=46762
62 common_flags = ["-c", "-Wall", "-Wextra",
63 "-Wno-unused-parameter", "-Wno-missing-field-initializers",
64 "-fmessage-length=0", "-fno-exceptions", "-fno-builtin",
65 "-ffunction-sections", "-fdata-sections",
66 "-MMD", "-fno-delete-null-pointer-checks", "-fomit-frame-pointer"
69 if "save-asm" in self.options:
70 common_flags.append("-save-temps")
72 if "debug-info" in self.options:
73 common_flags.append("-g")
74 common_flags.append("-O0")
76 common_flags.append("-O2")
78 main_cc = join(tool_path, "arm-none-eabi-gcc")
79 main_cppc = join(tool_path, "arm-none-eabi-g++")
80 self.asm = [main_cc, "-x", "assembler-with-cpp"] + common_flags
81 if not "analyze" in self.options:
82 self.cc = [main_cc, "-std=gnu99"] + common_flags
83 self.cppc =[main_cppc, "-std=gnu++98", "-fno-rtti"] + common_flags
85 self.cc = [join(GOANNA_PATH, "goannacc"), "--with-cc=" + main_cc.replace('\\', '/'), "-std=gnu99", "--dialect=gnu", '--output-format="%s"' % self.GOANNA_FORMAT] + common_flags
86 self.cppc= [join(GOANNA_PATH, "goannac++"), "--with-cxx=" + main_cppc.replace('\\', '/'), "-std=gnu++98", "-fno-rtti", "--dialect=gnu", '--output-format="%s"' % self.GOANNA_FORMAT] + common_flags
88 self.ld = [join(tool_path, "arm-none-eabi-gcc"), "-Wl,--gc-sections", "-Wl,--wrap,main"] + self.cpu
89 self.sys_libs = ["stdc++", "supc++", "m", "c", "gcc"]
91 self.ar = join(tool_path, "arm-none-eabi-ar")
92 self.elf2bin = join(tool_path, "arm-none-eabi-objcopy")
94 def assemble(self, source, object, includes):
95 return [self.hook.get_cmdline_assembler(self.asm + ['-D%s' % s for s in self.get_symbols() + self.macros] + ["-I%s" % i for i in includes] + ["-o", object, source])]
97 def parse_dependencies(self, dep_path):
99 for line in open(dep_path).readlines()[1:]:
100 file = line.replace('\\\n', '').strip()
102 # GCC might list more than one dependency on a single line, in this case
103 # the dependencies are separated by a space. However, a space might also
104 # indicate an actual space character in a dependency path, but in this case
105 # the space character is prefixed by a backslash.
106 # Temporary replace all '\ ' with a special char that is not used (\a in this
107 # case) to keep them from being interpreted by 'split' (they will be converted
108 # back later to a space char)
109 file = file.replace('\\ ', '\a')
110 if file.find(" ") == -1:
111 dependencies.append(file.replace('\a', ' '))
113 dependencies = dependencies + [f.replace('\a', ' ') for f in file.split(" ")]
116 def parse_output(self, output):
117 # The warning/error notification is multiline
119 state, file, message = WHERE, None, None
120 for line in output.splitlines():
121 match = self.goanna_parse_line(line)
122 if match is not None:
124 match.group('severity').lower(),
127 match.group('message'),
128 target_name=self.target.name,
129 toolchain_name=self.name
133 # Each line should start with the file information: "filepath: ..."
134 # i should point past the file path ^
135 # avoid the first column in Windows (C:\)
136 i = line.find(':', 2)
141 message = line[i+1:].strip() + ' '
145 match = GCC.DIAGNOSTIC_PATTERN.match(line[i+1:])
151 match.group('severity'),
152 file, match.group('line'),
153 message + match.group('message')
156 def archive(self, objects, lib_path):
157 self.default_cmd([self.ar, "rcs", lib_path] + objects)
159 def link(self, output, objects, libraries, lib_dirs, mem_map):
162 name, _ = splitext(basename(l))
163 libs.append("-l%s" % name[3:])
164 libs.extend(["-l%s" % l for l in self.sys_libs])
166 # NOTE: There is a circular dependency between the mbed library and the clib
167 # We could define a set of week symbols to satisfy the clib dependencies in "sys.o",
168 # but if an application uses only clib symbols and not mbed symbols, then the final
169 # image is not correctly retargeted
170 if self.CIRCULAR_DEPENDENCIES:
173 self.default_cmd(self.hook.get_cmdline_linker(self.ld + ["-T%s" % mem_map, "-o", output] +
174 objects + ["-L%s" % L for L in lib_dirs] + libs))
177 def binary(self, resources, elf, bin):
178 self.default_cmd(self.hook.get_cmdline_binary([self.elf2bin, "-O", "binary", elf, bin]))
182 def __init__(self, target, options=None, notify=None, macros=None, silent=False):
183 GCC.__init__(self, target, options, notify, macros, silent, GCC_ARM_PATH)
185 # Use latest gcc nanolib
186 self.ld.append("--specs=nano.specs")
187 if target.name in ["LPC1768", "LPC4088", "LPC4088_DM", "LPC4330", "UBLOX_C027", "LPC2368"]:
188 self.ld.extend(["-u _printf_float", "-u _scanf_float"])
189 elif target.name in ["RZ_A1H", "ARCH_MAX", "DISCO_F407VG", "DISCO_F429ZI", "NUCLEO_F401RE", "NUCLEO_F411RE"]:
190 self.ld.extend(["-u_printf_float", "-u_scanf_float"])
192 self.sys_libs.append("nosys")
196 def __init__(self, target, options=None, notify=None, macros=None, silent=False):
197 GCC.__init__(self, target, options, notify, macros, silent, GCC_CR_PATH)
199 additional_compiler_flags = [
200 "-D__NEWLIB__", "-D__CODE_RED", "-D__USE_CMSIS", "-DCPP_USE_HEAP",
202 self.cc += additional_compiler_flags
203 self.cppc += additional_compiler_flags
205 # Use latest gcc nanolib
206 self.ld.append("--specs=nano.specs")
207 if target.name in ["LPC1768", "LPC4088", "LPC4088_DM", "LPC4330", "UBLOX_C027", "LPC2368"]:
208 self.ld.extend(["-u _printf_float", "-u _scanf_float"])
209 self.ld += ["-nostdlib"]
213 def __init__(self, target, options=None, notify=None, macros=None, silent=False):
214 GCC.__init__(self, target, options, notify, macros, silent, GCC_CS_PATH)
219 "Cortex-M0+": "armv6-m",
222 def __init__(self, target, options=None, notify=None, macros=None, silent=False):
223 GCC.__init__(self, target, options, notify, macros, silent, CW_GCC_PATH)
226 class GCC_CW_EWL(GCC_CW):
227 def __init__(self, target, options=None, notify=None, macros=None, silent=False):
228 GCC_CW.__init__(self, target, options, notify, macros, silent)
233 '-nostdinc', '-I%s' % join(CW_EWL_PATH, "EWL_C", "include"),
235 self.cc += common + [
236 '-include', join(CW_EWL_PATH, "EWL_C", "include", 'lib_c99.prefix')
238 self.cppc += common + [
239 '-nostdinc++', '-I%s' % join(CW_EWL_PATH, "EWL_C++", "include"),
240 '-include', join(CW_EWL_PATH, "EWL_C++", "include", 'lib_ewl_c++.prefix')
245 self.CIRCULAR_DEPENDENCIES = False
246 self.ld = [join(CW_GCC_PATH, "arm-none-eabi-g++"),
247 "-Xlinker --gc-sections",
248 "-L%s" % join(CW_EWL_PATH, "lib", GCC_CW.ARCH_LIB[target.core]),
249 "-n", "-specs=ewl_c++.specs", "-mfloat-abi=soft",
250 "-Xlinker --undefined=__pformatter_", "-Xlinker --defsym=__pformatter=__pformatter_",
251 "-Xlinker --undefined=__sformatter", "-Xlinker --defsym=__sformatter=__sformatter",
255 class GCC_CW_NEWLIB(GCC_CW):
256 def __init__(self, target, options=None, notify=None, macros=None, silent=False):
257 GCC_CW.__init__(self, target, options, notify, macros, silent)