blob: d0ad886fe0f238c190866b4e0be4989b2db2c48f [file] [log] [blame]
Andrew Scull23e93a82018-10-26 14:56:04 +01001# Copyright 2018 Google LLC
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# https://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15declare_args() {
16 # Set by arch toolchain. Prefix for binutils tools.
17 tool_prefix = ""
18}
19
20# Template for embedded toolchains; there is no support for C++ or libraries.
21# Instead, use source_set to group source together.
22template("embedded_cc_toolchain") {
23 toolchain(target_name) {
24 assert(defined(invoker.cc), "\"cc\" must be defined for ${target_name}.")
25 assert(defined(invoker.ld), "\"ld\" must be defined for ${target_name}.")
26
27 # Collect extra flags from the toolchain.
28 extra_defines = ""
29 extra_cflags = "-flto -ffunction-sections -fdata-sections"
30 extra_ldflags = "--gc-sections -pie"
31 if (defined(invoker.extra_defines)) {
32 extra_defines += " ${invoker.extra_defines}"
33 }
34 if (defined(invoker.extra_cflags)) {
35 extra_cflags += " ${invoker.extra_cflags}"
36 }
37 if (defined(invoker.extra_ldflags)) {
38 extra_ldflags += " ${invoker.extra_ldflags}"
39 }
40
41 # Define the tools.
42 tool("cc") {
43 depfile = "{{output}}.d"
44 command = "${invoker.cc} -MMD -MF $depfile ${extra_defines} {{defines}} {{include_dirs}} ${extra_cflags} {{cflags}} {{cflags_c}} -c {{source}} -o {{output}}"
45 depsformat = "gcc"
46 description = "CC {{output}}"
47 outputs = [
48 "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o",
49 ]
50 }
51
52 tool("asm") {
53 depfile = "{{output}}.d"
Alfredo Mazzinghi880f5b22019-02-07 15:42:41 +000054 command = "${invoker.cc} -MMD -MF $depfile ${extra_defines} {{defines}} {{include_dirs}} ${extra_cflags} {{asmflags}} -c {{source}} -o {{output}}"
Andrew Scull23e93a82018-10-26 14:56:04 +010055 depsformat = "gcc"
56 description = "ASM {{output}}"
57 outputs = [
58 "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o",
59 ]
60 }
61
62 tool("link") {
63 outfile = "{{output_dir}}/{{target_output_name}}{{output_extension}}"
64 rspfile = "$outfile.rsp"
65 command = "${invoker.ld} ${extra_ldflags} {{ldflags}} -o $outfile --start-group @$rspfile --end-group"
66 description = "LINK $outfile"
67 default_output_dir = "{{root_out_dir}}"
68 rspfile_content = "{{inputs}}"
69 outputs = [
70 outfile,
71 ]
72 }
73
74 tool("stamp") {
75 command = "touch {{output}}"
76 description = "STAMP {{output}}"
77 }
78
79 tool("copy") {
80 command = "cp -af {{source}} {{output}}"
81 description = "COPY {{source}} {{output}}"
82 }
83
84 toolchain_args = {
85 forward_variables_from(invoker.toolchain_args, "*")
86 }
87 }
88}
89
90# Specialize for clang.
91template("embedded_clang_toolchain") {
92 assert(defined(invoker.target),
93 "\"target\" must be defined for ${target_name}.")
94 assert(defined(invoker.tool_prefix),
95 "\"tool_prefix\" must be defined for ${target_name}.")
Alfredo Mazzinghi880f5b22019-02-07 15:42:41 +000096 assert(defined(invoker.extra_defines),
97 "\"extra_defines\" must be defined for ${target_name}")
98 assert(defined(invoker.extra_cflags),
99 "\"extra_cflags\" must be defined for ${target_name}")
100 assert(defined(invoker.extra_ldflags),
101 "\"extra_ldflags\" must be defined for ${target_name}")
Andrew Scull23e93a82018-10-26 14:56:04 +0100102
103 embedded_cc_toolchain(target_name) {
Alfredo Mazzinghi880f5b22019-02-07 15:42:41 +0000104 cc = "clang"
105 ld = "ld.lld"
Andrew Scull23e93a82018-10-26 14:56:04 +0100106
Alfredo Mazzinghi880f5b22019-02-07 15:42:41 +0000107 forward_variables_from(invoker,
108 [
109 "extra_defines",
110 "extra_cflags",
111 "extra_ldflags",
112 ])
113 extra_cflags += " -target ${invoker.target} -fcolor-diagnostics"
114 extra_ldflags +=
115 " -O2 -lto-O2 --icf=all --fatal-warnings --color-diagnostics"
116
117 toolchain_args = {
118 tool_prefix = invoker.tool_prefix
119 if (defined(invoker.toolchain_args)) {
120 forward_variables_from(invoker.toolchain_args, "*")
121 }
Andrew Scull23e93a82018-10-26 14:56:04 +0100122 }
Alfredo Mazzinghi880f5b22019-02-07 15:42:41 +0000123 }
124}
125
126# Specialize for mixed toolchain with clang and bfd linker.
127template("embedded_clang_bfd_toolchain") {
128 assert(defined(invoker.target),
129 "\"target\" must be defined for ${target_name}.")
130 assert(defined(invoker.tool_prefix),
131 "\"tool_prefix\" must be defined for ${target_name}.")
132 assert(defined(invoker.extra_defines),
133 "\"extra_defines\" must be defined for ${target_name}")
134 assert(defined(invoker.extra_cflags),
135 "\"extra_cflags\" must be defined for ${target_name}")
136 assert(defined(invoker.extra_ldflags),
137 "\"extra_ldflags\" must be defined for ${target_name}")
138
139 embedded_cc_toolchain(target_name) {
140 cc = "clang"
141 ld = "${invoker.tool_prefix}ld.bfd"
142
143 forward_variables_from(invoker,
144 [
145 "extra_defines",
146 "extra_cflags",
147 "extra_ldflags",
148 ])
149 extra_cflags += " -target ${invoker.target} -fcolor-diagnostics"
Andrew Scull23e93a82018-10-26 14:56:04 +0100150
151 toolchain_args = {
152 tool_prefix = invoker.tool_prefix
153 if (defined(invoker.toolchain_args)) {
154 forward_variables_from(invoker.toolchain_args, "*")
155 }
156 }
157 }
158}
159
160# Specialize for gcc.
161template("embedded_gcc_toolchain") {
162 assert(defined(invoker.tool_prefix),
163 "\"tool_prefix\" must be defined for ${target_name}.")
Alfredo Mazzinghi880f5b22019-02-07 15:42:41 +0000164 assert(defined(invoker.extra_defines),
165 "\"extra_defines\" must be defined for ${target_name}.")
166 assert(defined(invoker.extra_cflags),
167 "\"extra_cflags\" must be defined for ${target_name}.")
168 assert(defined(invoker.extra_ldflags),
169 "\"extra_ldflags\" must be defined for ${target_name}.")
Andrew Scull23e93a82018-10-26 14:56:04 +0100170
171 embedded_cc_toolchain(target_name) {
Alfredo Mazzinghi880f5b22019-02-07 15:42:41 +0000172 cc = "${invoker.tool_prefix}gcc"
Andrew Scull23e93a82018-10-26 14:56:04 +0100173 ld = "${invoker.tool_prefix}ld"
174
Alfredo Mazzinghi880f5b22019-02-07 15:42:41 +0000175 forward_variables_from(invoker,
176 [
177 "extra_defines",
178 "extra_cflags",
179 "extra_ldflags",
180 ])
181
182 extra_cflags += " -fdiagnostics-color=always"
Andrew Scull23e93a82018-10-26 14:56:04 +0100183
184 toolchain_args = {
185 tool_prefix = invoker.tool_prefix
186 if (defined(invoker.toolchain_args)) {
187 forward_variables_from(invoker.toolchain_args, "*")
188 }
189 }
190 }
191}
192
193# Expand to clang and gcc variants.
194template("embedded_platform_toolchain") {
195 assert(defined(invoker.arch), "\"arch\" must be defined for ${target_name}.")
196 assert(defined(invoker.target),
197 "\"target\" must be defined for ${target_name}.")
198 assert(defined(invoker.tool_prefix),
199 "\"tool_prefix\" must be defined for ${target_name}.")
200 assert(defined(invoker.origin_address),
201 "\"origin_address\" must be defined for ${target_name}.")
Andrew Walbrande33f082018-12-07 14:10:11 +0000202 assert(defined(invoker.heap_pages),
203 "\"heap_pages\" must be defined for ${target_name}.")
Andrew Scull23e93a82018-10-26 14:56:04 +0100204 assert(defined(invoker.max_cpus),
205 "\"max_cpus\" must be defined for ${target_name}.")
206 assert(defined(invoker.max_vms),
207 "\"max_vms\" must be defined for ${target_name}.")
Alfredo Mazzinghi880f5b22019-02-07 15:42:41 +0000208 assert(defined(invoker.platform_name),
209 "\"platform_name\" must be defined for ${target_name}.")
Andrew Scull23e93a82018-10-26 14:56:04 +0100210
211 defines = ""
212 cflags = "-fno-stack-protector -fno-builtin -ffreestanding -fpic"
213 ldflags = "--defsym=ORIGIN_ADDRESS=${invoker.origin_address}"
214 if (defined(invoker.extra_defines)) {
215 defines += " ${invoker.extra_defines}"
216 }
217 if (defined(invoker.extra_cflags)) {
218 cflags += " ${invoker.extra_cflags}"
219 }
220 if (defined(invoker.extra_ldflags)) {
221 ldflags += " ${invoker.extra_ldflags}"
222 }
223
224 embedded_clang_toolchain("${target_name}_clang") {
225 target = invoker.target
226 tool_prefix = invoker.tool_prefix
227 extra_defines = defines
228 extra_cflags = cflags
229 extra_ldflags = ldflags
230 toolchain_args = {
Andrew Scullb401ba32018-11-09 10:30:54 +0000231 use_platform = true
Alfredo Mazzinghi880f5b22019-02-07 15:42:41 +0000232 plat_name = invoker.platform_name
233 plat_arch = invoker.arch
234 plat_heap_pages = invoker.heap_pages
235 plat_max_cpus = invoker.max_cpus
236 plat_max_vms = invoker.max_vms
237 if (defined(invoker.toolchain_args)) {
238 forward_variables_from(invoker.toolchain_args, "*")
239 }
240 }
241 }
242
243 embedded_clang_bfd_toolchain("${target_name}_clang_bfd") {
244 target = invoker.target
245 tool_prefix = invoker.tool_prefix
246 extra_defines = defines
247 extra_cflags = cflags
248 extra_ldflags = ldflags
249 toolchain_args = {
250 use_platform = true
251 plat_name = invoker.platform_name
Andrew Scullb401ba32018-11-09 10:30:54 +0000252 plat_arch = invoker.arch
Andrew Walbrande33f082018-12-07 14:10:11 +0000253 plat_heap_pages = invoker.heap_pages
Andrew Scullb401ba32018-11-09 10:30:54 +0000254 plat_max_cpus = invoker.max_cpus
255 plat_max_vms = invoker.max_vms
Andrew Scull23e93a82018-10-26 14:56:04 +0100256 if (defined(invoker.toolchain_args)) {
257 forward_variables_from(invoker.toolchain_args, "*")
258 }
259 }
260 }
261
262 embedded_gcc_toolchain("${target_name}_gcc") {
263 tool_prefix = invoker.tool_prefix
264 extra_defines = defines
265 extra_cflags = cflags
266 extra_ldflags = ldflags
267 toolchain_args = {
Andrew Scullb401ba32018-11-09 10:30:54 +0000268 use_platform = true
Alfredo Mazzinghi880f5b22019-02-07 15:42:41 +0000269 plat_name = invoker.platform_name
Andrew Scullb401ba32018-11-09 10:30:54 +0000270 plat_arch = invoker.arch
Andrew Walbrande33f082018-12-07 14:10:11 +0000271 plat_heap_pages = invoker.heap_pages
Andrew Scullb401ba32018-11-09 10:30:54 +0000272 plat_max_cpus = invoker.max_cpus
273 plat_max_vms = invoker.max_vms
Andrew Scull23e93a82018-10-26 14:56:04 +0100274 if (defined(invoker.toolchain_args)) {
275 forward_variables_from(invoker.toolchain_args, "*")
276 }
277 }
278 }
279}
280
281# Specialize for different architectures.
282
Alfredo Mazzinghi880f5b22019-02-07 15:42:41 +0000283template("aarch64_common_toolchain") {
Andrew Scull23e93a82018-10-26 14:56:04 +0100284 assert(defined(invoker.cpu), "\"cpu\" must be defiend for ${target_name}.")
Alfredo Mazzinghi880f5b22019-02-07 15:42:41 +0000285 assert(defined(invoker.target),
286 "\"target\" must be defined for ${target_name}")
287 assert(defined(invoker.tool_prefix),
288 "\"tool_prefix\" must be defined for ${target_name}")
Andrew Scull23e93a82018-10-26 14:56:04 +0100289 assert(defined(invoker.origin_address),
290 "\"origin_address\" must be defined for ${target_name}.")
291 assert(defined(invoker.use_pl011),
292 "\"use_pl011\" must be defined for ${target_name}.")
Andrew Walbrande33f082018-12-07 14:10:11 +0000293 assert(defined(invoker.heap_pages),
294 "\"heap_pages\" must be defined for ${target_name}.")
Andrew Scull23e93a82018-10-26 14:56:04 +0100295 assert(defined(invoker.max_cpus),
296 "\"max_cpus\" must be defined for ${target_name}.")
297 assert(defined(invoker.max_vms),
298 "\"max_vms\" must be defined for ${target_name}.")
Andrew Walbran53f38762018-12-07 15:21:29 +0000299 if (invoker.gic_version == 3 || invoker.gic_version == 4) {
300 assert(defined(invoker.gicd_base_address),
301 "\"gicd_base_address\" must be defined for ${target_name}.")
302 assert(defined(invoker.gicr_base_address),
303 "\"gicr_base_address\" must be defined for ${target_name}.")
304 }
Alfredo Mazzinghi880f5b22019-02-07 15:42:41 +0000305 assert(defined(invoker.platform_name),
306 "\"platform_name\" must be defined for ${target_name}.")
Andrew Scull23e93a82018-10-26 14:56:04 +0100307
308 embedded_platform_toolchain(target_name) {
309 forward_variables_from(invoker,
310 [
311 "origin_address",
Andrew Walbrande33f082018-12-07 14:10:11 +0000312 "heap_pages",
Andrew Scull23e93a82018-10-26 14:56:04 +0100313 "max_cpus",
314 "max_vms",
Alfredo Mazzinghi880f5b22019-02-07 15:42:41 +0000315 "platform_name",
316 "extra_defines",
317 "extra_ldflags",
Andrew Scull23e93a82018-10-26 14:56:04 +0100318 ])
319 arch = "aarch64"
Alfredo Mazzinghi880f5b22019-02-07 15:42:41 +0000320 target = invoker.target
321 tool_prefix = invoker.tool_prefix
Andrew Scull23e93a82018-10-26 14:56:04 +0100322 extra_cflags = "-mcpu=${invoker.cpu} -mstrict-align"
Alfredo Mazzinghi880f5b22019-02-07 15:42:41 +0000323 if (defined(invoker.extra_cflags)) {
324 extra_cflags += " ${invoker.extra_cflags}"
325 }
Andrew Scull23e93a82018-10-26 14:56:04 +0100326
Andrew Walbran53f38762018-12-07 15:21:29 +0000327 extra_defines = ""
Andrew Scull23e93a82018-10-26 14:56:04 +0100328 if (invoker.use_pl011) {
329 assert(defined(invoker.pl011_base_address),
330 "\"pl011_base_address\" must be defined for ${target_name}.")
Andrew Walbran53f38762018-12-07 15:21:29 +0000331 extra_defines += " -DPL011_BASE=${invoker.pl011_base_address}"
332 }
333 if (invoker.gic_version > 0) {
334 extra_defines += " -DGIC_VERSION=${invoker.gic_version}"
335 }
336 if (invoker.gic_version == 3 || invoker.gic_version == 4) {
337 extra_defines += " -DGICD_BASE=${invoker.gicd_base_address} -DGICR_BASE=${invoker.gicr_base_address}"
Andrew Scull23e93a82018-10-26 14:56:04 +0100338 }
339
340 toolchain_args = {
341 arch_aarch64_use_pl011 = invoker.use_pl011
342 }
343 }
344}
Alfredo Mazzinghi880f5b22019-02-07 15:42:41 +0000345
346template("aarch64_toolchain") {
347 aarch64_common_toolchain("${target_name}") {
348 forward_variables_from(invoker, "*")
349 target = "aarch64-none-eabi"
350 tool_prefix = "aarch64-linux-gnu-" # TODO: this isn't right for bare metal but it works.
351 platform_name = target_name
352 }
353}