blob: 4ff6852f1437f7e9c111db026190c50697945881 [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 = ""
Alfredo Mazzinghi8aa8c622019-01-18 17:40:58 +000018
19 # Enable link time optimizations
20 use_lto = true
Andrew Scull23e93a82018-10-26 14:56:04 +010021}
22
23# Template for embedded toolchains; there is no support for C++ or libraries.
24# Instead, use source_set to group source together.
25template("embedded_cc_toolchain") {
26 toolchain(target_name) {
27 assert(defined(invoker.cc), "\"cc\" must be defined for ${target_name}.")
28 assert(defined(invoker.ld), "\"ld\" must be defined for ${target_name}.")
29
30 # Collect extra flags from the toolchain.
31 extra_defines = ""
Alfredo Mazzinghi8aa8c622019-01-18 17:40:58 +000032 extra_cflags = "-ffunction-sections -fdata-sections"
33 if (use_lto) {
34 extra_cflags += " -flto"
35 }
36 extra_ldflags = "-pie --gc-sections"
37
Andrew Scull23e93a82018-10-26 14:56:04 +010038 if (defined(invoker.extra_defines)) {
39 extra_defines += " ${invoker.extra_defines}"
40 }
41 if (defined(invoker.extra_cflags)) {
42 extra_cflags += " ${invoker.extra_cflags}"
43 }
44 if (defined(invoker.extra_ldflags)) {
45 extra_ldflags += " ${invoker.extra_ldflags}"
46 }
47
48 # Define the tools.
49 tool("cc") {
50 depfile = "{{output}}.d"
51 command = "${invoker.cc} -MMD -MF $depfile ${extra_defines} {{defines}} {{include_dirs}} ${extra_cflags} {{cflags}} {{cflags_c}} -c {{source}} -o {{output}}"
52 depsformat = "gcc"
53 description = "CC {{output}}"
54 outputs = [
55 "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o",
56 ]
57 }
58
59 tool("asm") {
60 depfile = "{{output}}.d"
Alfredo Mazzinghi880f5b22019-02-07 15:42:41 +000061 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 +010062 depsformat = "gcc"
63 description = "ASM {{output}}"
64 outputs = [
65 "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o",
66 ]
67 }
68
69 tool("link") {
70 outfile = "{{output_dir}}/{{target_output_name}}{{output_extension}}"
71 rspfile = "$outfile.rsp"
72 command = "${invoker.ld} ${extra_ldflags} {{ldflags}} -o $outfile --start-group @$rspfile --end-group"
73 description = "LINK $outfile"
74 default_output_dir = "{{root_out_dir}}"
75 rspfile_content = "{{inputs}}"
76 outputs = [
77 outfile,
78 ]
79 }
80
81 tool("stamp") {
82 command = "touch {{output}}"
83 description = "STAMP {{output}}"
84 }
85
86 tool("copy") {
87 command = "cp -af {{source}} {{output}}"
88 description = "COPY {{source}} {{output}}"
89 }
90
91 toolchain_args = {
92 forward_variables_from(invoker.toolchain_args, "*")
93 }
94 }
95}
96
97# Specialize for clang.
98template("embedded_clang_toolchain") {
99 assert(defined(invoker.target),
100 "\"target\" must be defined for ${target_name}.")
101 assert(defined(invoker.tool_prefix),
102 "\"tool_prefix\" must be defined for ${target_name}.")
Alfredo Mazzinghi880f5b22019-02-07 15:42:41 +0000103 assert(defined(invoker.extra_defines),
104 "\"extra_defines\" must be defined for ${target_name}")
105 assert(defined(invoker.extra_cflags),
106 "\"extra_cflags\" must be defined for ${target_name}")
107 assert(defined(invoker.extra_ldflags),
108 "\"extra_ldflags\" must be defined for ${target_name}")
Andrew Scull23e93a82018-10-26 14:56:04 +0100109
110 embedded_cc_toolchain(target_name) {
Alfredo Mazzinghi880f5b22019-02-07 15:42:41 +0000111 cc = "clang"
112 ld = "ld.lld"
Andrew Scull23e93a82018-10-26 14:56:04 +0100113
Alfredo Mazzinghi880f5b22019-02-07 15:42:41 +0000114 forward_variables_from(invoker,
115 [
116 "extra_defines",
117 "extra_cflags",
118 "extra_ldflags",
119 ])
120 extra_cflags += " -target ${invoker.target} -fcolor-diagnostics"
121 extra_ldflags +=
122 " -O2 -lto-O2 --icf=all --fatal-warnings --color-diagnostics"
123
124 toolchain_args = {
125 tool_prefix = invoker.tool_prefix
126 if (defined(invoker.toolchain_args)) {
127 forward_variables_from(invoker.toolchain_args, "*")
128 }
Andrew Scull23e93a82018-10-26 14:56:04 +0100129 }
Alfredo Mazzinghi880f5b22019-02-07 15:42:41 +0000130 }
131}
132
133# Specialize for mixed toolchain with clang and bfd linker.
134template("embedded_clang_bfd_toolchain") {
135 assert(defined(invoker.target),
136 "\"target\" must be defined for ${target_name}.")
137 assert(defined(invoker.tool_prefix),
138 "\"tool_prefix\" must be defined for ${target_name}.")
139 assert(defined(invoker.extra_defines),
140 "\"extra_defines\" must be defined for ${target_name}")
141 assert(defined(invoker.extra_cflags),
142 "\"extra_cflags\" must be defined for ${target_name}")
143 assert(defined(invoker.extra_ldflags),
144 "\"extra_ldflags\" must be defined for ${target_name}")
145
146 embedded_cc_toolchain(target_name) {
147 cc = "clang"
148 ld = "${invoker.tool_prefix}ld.bfd"
149
150 forward_variables_from(invoker,
151 [
152 "extra_defines",
153 "extra_cflags",
154 "extra_ldflags",
155 ])
156 extra_cflags += " -target ${invoker.target} -fcolor-diagnostics"
Alfredo Mazzinghi8aa8c622019-01-18 17:40:58 +0000157 extra_ldflags += " --fatal-warnings"
158 if (use_lto) {
159 extra_ldflags += " -O2 -lto-O2 --icf=all"
160 }
Andrew Scull23e93a82018-10-26 14:56:04 +0100161
162 toolchain_args = {
163 tool_prefix = invoker.tool_prefix
164 if (defined(invoker.toolchain_args)) {
165 forward_variables_from(invoker.toolchain_args, "*")
166 }
167 }
168 }
169}
170
171# Specialize for gcc.
172template("embedded_gcc_toolchain") {
173 assert(defined(invoker.tool_prefix),
174 "\"tool_prefix\" must be defined for ${target_name}.")
Alfredo Mazzinghi880f5b22019-02-07 15:42:41 +0000175 assert(defined(invoker.extra_defines),
176 "\"extra_defines\" must be defined for ${target_name}.")
177 assert(defined(invoker.extra_cflags),
178 "\"extra_cflags\" must be defined for ${target_name}.")
179 assert(defined(invoker.extra_ldflags),
180 "\"extra_ldflags\" must be defined for ${target_name}.")
Andrew Scull23e93a82018-10-26 14:56:04 +0100181
182 embedded_cc_toolchain(target_name) {
Alfredo Mazzinghi880f5b22019-02-07 15:42:41 +0000183 cc = "${invoker.tool_prefix}gcc"
Andrew Scull23e93a82018-10-26 14:56:04 +0100184 ld = "${invoker.tool_prefix}ld"
185
Alfredo Mazzinghi880f5b22019-02-07 15:42:41 +0000186 forward_variables_from(invoker,
187 [
188 "extra_defines",
189 "extra_cflags",
190 "extra_ldflags",
191 ])
192
193 extra_cflags += " -fdiagnostics-color=always"
Andrew Scull23e93a82018-10-26 14:56:04 +0100194
195 toolchain_args = {
196 tool_prefix = invoker.tool_prefix
197 if (defined(invoker.toolchain_args)) {
198 forward_variables_from(invoker.toolchain_args, "*")
199 }
200 }
201 }
202}
203
204# Expand to clang and gcc variants.
205template("embedded_platform_toolchain") {
206 assert(defined(invoker.arch), "\"arch\" must be defined for ${target_name}.")
207 assert(defined(invoker.target),
208 "\"target\" must be defined for ${target_name}.")
209 assert(defined(invoker.tool_prefix),
210 "\"tool_prefix\" must be defined for ${target_name}.")
211 assert(defined(invoker.origin_address),
212 "\"origin_address\" must be defined for ${target_name}.")
Andrew Walbrande33f082018-12-07 14:10:11 +0000213 assert(defined(invoker.heap_pages),
214 "\"heap_pages\" must be defined for ${target_name}.")
Andrew Scull23e93a82018-10-26 14:56:04 +0100215 assert(defined(invoker.max_cpus),
216 "\"max_cpus\" must be defined for ${target_name}.")
217 assert(defined(invoker.max_vms),
218 "\"max_vms\" must be defined for ${target_name}.")
Alfredo Mazzinghi880f5b22019-02-07 15:42:41 +0000219 assert(defined(invoker.platform_name),
220 "\"platform_name\" must be defined for ${target_name}.")
Andrew Scull23e93a82018-10-26 14:56:04 +0100221
222 defines = ""
223 cflags = "-fno-stack-protector -fno-builtin -ffreestanding -fpic"
224 ldflags = "--defsym=ORIGIN_ADDRESS=${invoker.origin_address}"
225 if (defined(invoker.extra_defines)) {
226 defines += " ${invoker.extra_defines}"
227 }
228 if (defined(invoker.extra_cflags)) {
229 cflags += " ${invoker.extra_cflags}"
230 }
231 if (defined(invoker.extra_ldflags)) {
232 ldflags += " ${invoker.extra_ldflags}"
233 }
234
235 embedded_clang_toolchain("${target_name}_clang") {
236 target = invoker.target
237 tool_prefix = invoker.tool_prefix
238 extra_defines = defines
239 extra_cflags = cflags
240 extra_ldflags = ldflags
241 toolchain_args = {
Andrew Scullb401ba32018-11-09 10:30:54 +0000242 use_platform = true
Alfredo Mazzinghi880f5b22019-02-07 15:42:41 +0000243 plat_name = invoker.platform_name
244 plat_arch = invoker.arch
245 plat_heap_pages = invoker.heap_pages
246 plat_max_cpus = invoker.max_cpus
247 plat_max_vms = invoker.max_vms
248 if (defined(invoker.toolchain_args)) {
249 forward_variables_from(invoker.toolchain_args, "*")
250 }
251 }
252 }
253
254 embedded_clang_bfd_toolchain("${target_name}_clang_bfd") {
255 target = invoker.target
256 tool_prefix = invoker.tool_prefix
257 extra_defines = defines
258 extra_cflags = cflags
259 extra_ldflags = ldflags
260 toolchain_args = {
261 use_platform = true
262 plat_name = invoker.platform_name
Andrew Scullb401ba32018-11-09 10:30:54 +0000263 plat_arch = invoker.arch
Andrew Walbrande33f082018-12-07 14:10:11 +0000264 plat_heap_pages = invoker.heap_pages
Andrew Scullb401ba32018-11-09 10:30:54 +0000265 plat_max_cpus = invoker.max_cpus
266 plat_max_vms = invoker.max_vms
Andrew Scull23e93a82018-10-26 14:56:04 +0100267 if (defined(invoker.toolchain_args)) {
268 forward_variables_from(invoker.toolchain_args, "*")
269 }
270 }
271 }
272
273 embedded_gcc_toolchain("${target_name}_gcc") {
274 tool_prefix = invoker.tool_prefix
275 extra_defines = defines
276 extra_cflags = cflags
277 extra_ldflags = ldflags
278 toolchain_args = {
Andrew Scullb401ba32018-11-09 10:30:54 +0000279 use_platform = true
Alfredo Mazzinghi880f5b22019-02-07 15:42:41 +0000280 plat_name = invoker.platform_name
Andrew Scullb401ba32018-11-09 10:30:54 +0000281 plat_arch = invoker.arch
Andrew Walbrande33f082018-12-07 14:10:11 +0000282 plat_heap_pages = invoker.heap_pages
Andrew Scullb401ba32018-11-09 10:30:54 +0000283 plat_max_cpus = invoker.max_cpus
284 plat_max_vms = invoker.max_vms
Andrew Scull23e93a82018-10-26 14:56:04 +0100285 if (defined(invoker.toolchain_args)) {
286 forward_variables_from(invoker.toolchain_args, "*")
287 }
288 }
289 }
290}
291
292# Specialize for different architectures.
293
Alfredo Mazzinghi880f5b22019-02-07 15:42:41 +0000294template("aarch64_common_toolchain") {
Andrew Scull23e93a82018-10-26 14:56:04 +0100295 assert(defined(invoker.cpu), "\"cpu\" must be defiend for ${target_name}.")
Alfredo Mazzinghi880f5b22019-02-07 15:42:41 +0000296 assert(defined(invoker.target),
297 "\"target\" must be defined for ${target_name}")
298 assert(defined(invoker.tool_prefix),
299 "\"tool_prefix\" must be defined for ${target_name}")
Andrew Scull23e93a82018-10-26 14:56:04 +0100300 assert(defined(invoker.origin_address),
301 "\"origin_address\" must be defined for ${target_name}.")
302 assert(defined(invoker.use_pl011),
303 "\"use_pl011\" must be defined for ${target_name}.")
Andrew Walbrande33f082018-12-07 14:10:11 +0000304 assert(defined(invoker.heap_pages),
305 "\"heap_pages\" must be defined for ${target_name}.")
Andrew Scull23e93a82018-10-26 14:56:04 +0100306 assert(defined(invoker.max_cpus),
307 "\"max_cpus\" must be defined for ${target_name}.")
308 assert(defined(invoker.max_vms),
309 "\"max_vms\" must be defined for ${target_name}.")
Andrew Walbran53f38762018-12-07 15:21:29 +0000310 if (invoker.gic_version == 3 || invoker.gic_version == 4) {
311 assert(defined(invoker.gicd_base_address),
312 "\"gicd_base_address\" must be defined for ${target_name}.")
313 assert(defined(invoker.gicr_base_address),
314 "\"gicr_base_address\" must be defined for ${target_name}.")
315 }
Alfredo Mazzinghi880f5b22019-02-07 15:42:41 +0000316 assert(defined(invoker.platform_name),
317 "\"platform_name\" must be defined for ${target_name}.")
Andrew Scull23e93a82018-10-26 14:56:04 +0100318
319 embedded_platform_toolchain(target_name) {
320 forward_variables_from(invoker,
321 [
322 "origin_address",
Andrew Walbrande33f082018-12-07 14:10:11 +0000323 "heap_pages",
Andrew Scull23e93a82018-10-26 14:56:04 +0100324 "max_cpus",
325 "max_vms",
Alfredo Mazzinghi880f5b22019-02-07 15:42:41 +0000326 "platform_name",
327 "extra_defines",
328 "extra_ldflags",
Andrew Scull23e93a82018-10-26 14:56:04 +0100329 ])
330 arch = "aarch64"
Alfredo Mazzinghi880f5b22019-02-07 15:42:41 +0000331 target = invoker.target
332 tool_prefix = invoker.tool_prefix
Andrew Scull23e93a82018-10-26 14:56:04 +0100333 extra_cflags = "-mcpu=${invoker.cpu} -mstrict-align"
Alfredo Mazzinghi880f5b22019-02-07 15:42:41 +0000334 if (defined(invoker.extra_cflags)) {
335 extra_cflags += " ${invoker.extra_cflags}"
336 }
Andrew Scull23e93a82018-10-26 14:56:04 +0100337
Andrew Walbran53f38762018-12-07 15:21:29 +0000338 extra_defines = ""
Andrew Scull23e93a82018-10-26 14:56:04 +0100339 if (invoker.use_pl011) {
340 assert(defined(invoker.pl011_base_address),
341 "\"pl011_base_address\" must be defined for ${target_name}.")
Andrew Walbran53f38762018-12-07 15:21:29 +0000342 extra_defines += " -DPL011_BASE=${invoker.pl011_base_address}"
343 }
344 if (invoker.gic_version > 0) {
345 extra_defines += " -DGIC_VERSION=${invoker.gic_version}"
346 }
347 if (invoker.gic_version == 3 || invoker.gic_version == 4) {
348 extra_defines += " -DGICD_BASE=${invoker.gicd_base_address} -DGICR_BASE=${invoker.gicr_base_address}"
Andrew Scull23e93a82018-10-26 14:56:04 +0100349 }
350
351 toolchain_args = {
352 arch_aarch64_use_pl011 = invoker.use_pl011
353 }
354 }
355}
Alfredo Mazzinghi880f5b22019-02-07 15:42:41 +0000356
357template("aarch64_toolchain") {
358 aarch64_common_toolchain("${target_name}") {
359 forward_variables_from(invoker, "*")
360 target = "aarch64-none-eabi"
361 tool_prefix = "aarch64-linux-gnu-" # TODO: this isn't right for bare metal but it works.
362 platform_name = target_name
363 }
364}