xref: /aosp_15_r20/bootable/libbootloader/gbl/toolchain/BUILD (revision 5225e6b173e52d2efc6bcf950c27374fd72adabc)
1# Copyright (C) 2023 The Android Open Source Project
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#     http://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
15load("@bazel_skylib//rules:common_settings.bzl", "bool_setting")
16load(
17    "@gbl_llvm_prebuilts//:info.bzl",
18    "LINUX_SYSROOT_INCLUDES",
19    "LLVM_PREBUILTS_CPP_INCLUDE",
20    "LLVM_PREBUILTS_C_INCLUDE",
21    "gbl_llvm_tool_path",
22)
23load("@rules_rust//bindgen:defs.bzl", "rust_bindgen_toolchain")
24load(
25    "@rules_rust//rust:toolchain.bzl",
26    "rust_stdlib_filegroup",
27    "rust_toolchain",
28    "rustfmt_toolchain",
29)
30load(
31    ":gbl_toolchain.bzl",
32    "build_with_no_rust_sysroot",
33    "gbl_clang_cc_toolchain",
34    "prebuilt_binary",
35)
36
37package(
38    default_visibility = ["//visibility:public"],
39)
40
41# The following constraint/settings will be used in our newly defined
42# toolchains, so that they only get selected by bazel when we configure
43# to build GBL.
44constraint_setting(name = "firmware_image_type")
45
46constraint_value(
47    name = "uefi",
48    constraint_setting = ":firmware_image_type",
49)
50
51constraint_value(
52    name = "elf",
53    constraint_setting = ":firmware_image_type",
54)
55
56host_x86_64_constraint_values = [
57    "@platforms//os:linux",
58    "@platforms//cpu:x86_64",
59]
60
61uefi_x86_64_constraint_values = [
62    ":uefi",
63    "@platforms//os:none",
64    "@platforms//cpu:x86_64",
65]
66
67uefi_x86_32_constraint_values = [
68    ":uefi",
69    "@platforms//os:none",
70    "@platforms//cpu:x86_32",
71]
72
73uefi_aarch64_constraint_values = [
74    ":uefi",
75    "@platforms//os:none",
76    "@platforms//cpu:aarch64",
77]
78
79elf_riscv64_constraint_values = [
80    ":elf",
81    "@platforms//os:none",
82    "@platforms//cpu:riscv64",
83]
84
85config_setting(
86    name = "gbl_rust_host_x86_64",
87    constraint_values = host_x86_64_constraint_values,
88)
89
90config_setting(
91    name = "gbl_rust_uefi_x86_64",
92    constraint_values = uefi_x86_64_constraint_values,
93)
94
95config_setting(
96    name = "gbl_rust_uefi_x86_32",
97    constraint_values = uefi_x86_32_constraint_values,
98)
99
100config_setting(
101    name = "gbl_rust_uefi_aarch64",
102    constraint_values = uefi_aarch64_constraint_values,
103)
104
105config_setting(
106    name = "gbl_rust_elf_riscv64",
107    constraint_values = elf_riscv64_constraint_values,
108)
109
110# The following will be passed to "bazel build --platform=<>" argument to
111# configure building for specific architecture and image type.
112platform(
113    name = "gbl_uefi_x86_64",
114    constraint_values = uefi_x86_64_constraint_values,
115)
116
117platform(
118    name = "gbl_uefi_x86_32",
119    constraint_values = uefi_x86_32_constraint_values,
120)
121
122platform(
123    name = "gbl_uefi_aarch64",
124    constraint_values = uefi_aarch64_constraint_values,
125)
126
127platform(
128    name = "gbl_elf_riscv64",
129    constraint_values = elf_riscv64_constraint_values,
130)
131
132bool_setting(
133    name = "rust_no_sysroot",
134    build_setting_default = False,
135    visibility = ["//visibility:public"],
136)
137
138config_setting(
139    name = "rust_no_sysroot_true",
140    flag_values = {":rust_no_sysroot": "True"},
141)
142
143# Linux host LLVM toolchain.
144# The toolchain is mainly used for building/linking host tools, i.e. bindgen pre-processing
145gbl_clang_cc_toolchain(
146    name = "x86_64-unknown-linux-gnu",
147    # Host LLVM toolchain has additional C++ stdlib.
148    builtin_includes = [
149        LLVM_PREBUILTS_CPP_INCLUDE,  # C++ headers must come first.
150        LLVM_PREBUILTS_C_INCLUDE,
151    ] + LINUX_SYSROOT_INCLUDES,
152    ld_flags = [
153        "-stdlib=libc++",
154        "-static-libstdc++",
155    ],
156    target_cpu = "x86_64",
157    target_system_triple = "x86_64-unknown-linux-gnu",
158)
159
160toolchain(
161    name = "x86_64-unknown-linux-gnu_toolchain",
162    exec_compatible_with = ["@platforms//os:linux"],
163    target_compatible_with = [
164        "@platforms//os:linux",
165        "@platforms//cpu:x86_64",
166    ],
167    toolchain = ":x86_64-unknown-linux-gnu",
168    toolchain_type = "@bazel_tools//tools/cpp:toolchain_type",
169)
170
171# The following defines LLVM C++ toolchains for UEFI/ELF targets. They are mostly used for the
172# final step of linking Rust executables, but may also be used for compiling mixed C/C++ code.
173
174cc_flags_common = [
175    "-ffreestanding",
176    "-fno-common",
177    "-fno-exceptions",
178    "-fno-rtti",
179    # Enable optimization otherwise software AVB hash will be too slow.
180    "-O3",
181]
182
183# x86_64 UEFI targets
184gbl_clang_cc_toolchain(
185    name = "x86_64_uefi_clang_cc_toolchain",
186    cc_flags = cc_flags_common,
187    target_cpu = "x86_64",
188    target_system_triple = "x86_64-unknown-windows-msvc",
189)
190
191toolchain(
192    name = "x86_64_uefi_clang",
193    exec_compatible_with = ["@platforms//os:linux"],
194    target_compatible_with = uefi_x86_64_constraint_values,
195    toolchain = ":x86_64_uefi_clang_cc_toolchain",
196    toolchain_type = "@bazel_tools//tools/cpp:toolchain_type",
197)
198
199# x86_32 UEFI targets
200gbl_clang_cc_toolchain(
201    name = "x86_32_uefi_clang_cc_toolchain",
202    cc_flags = cc_flags_common + [
203        "-m32",
204        # Adding this prevents the compiler from generating mmx, sse instructions such as
205        # "movsd (%esp),%xmm0" which likely isn't enabled during the bootloader stage and causes
206        # crash as a result.
207        "-march=i686",
208    ],
209    # Safe Exception Handlers is not applicable to EFI systems.
210    ld_flags = ["/SAFESEH:no"],
211    target_cpu = "x86_32",
212    target_system_triple = "i686-unknown-windows-gnu",
213)
214
215toolchain(
216    name = "x86_32_uefi_clang",
217    exec_compatible_with = ["@platforms//os:linux"],
218    target_compatible_with = uefi_x86_32_constraint_values,
219    toolchain = ":x86_32_uefi_clang_cc_toolchain",
220    toolchain_type = "@bazel_tools//tools/cpp:toolchain_type",
221)
222
223# aarch64 UEFI targets
224gbl_clang_cc_toolchain(
225    name = "aarch64_uefi_clang_cc_toolchain",
226    cc_flags = cc_flags_common,
227    target_cpu = "aarch64",
228    target_system_triple = "aarch64-windows-msvc",
229)
230
231toolchain(
232    name = "aarch64_uefi_clang",
233    exec_compatible_with = ["@platforms//os:linux"],
234    target_compatible_with = uefi_aarch64_constraint_values,
235    toolchain = ":aarch64_uefi_clang_cc_toolchain",
236    toolchain_type = "@bazel_tools//tools/cpp:toolchain_type",
237)
238
239# riscv64 ELF targets
240gbl_clang_cc_toolchain(
241    name = "riscv64_elf_clang_cc_toolchain",
242    cc_flags = cc_flags_common + ["-fpie"],
243    target_cpu = "riscv64",
244    target_system_triple = "riscv64-unknown-linux",
245)
246
247toolchain(
248    name = "riscv64_elf_clang",
249    exec_compatible_with = ["@platforms//os:linux"],
250    target_compatible_with = elf_riscv64_constraint_values,
251    toolchain = ":riscv64_elf_clang_cc_toolchain",
252    toolchain_type = "@bazel_tools//tools/cpp:toolchain_type",
253)
254
255# Rust toolchains
256
257# An empty rust std file group used as placeholder when building rust sysroot.
258rust_stdlib_filegroup(
259    name = "rust_stdlib_empty",
260    srcs = [],
261)
262
263# A rule for building sysroot from source.
264build_with_no_rust_sysroot(
265    name = "rust_sysroot_source_build",
266    deps = [
267        "@rust_prebuilts//:liballoc",
268        "@rust_prebuilts//:libcompiler_builtins",
269        "@rust_prebuilts//:libcore",
270    ],
271)
272
273rust_stdlib_filegroup(
274    name = "rust_std_source_build",
275    srcs = [":rust_sysroot_source_build"],
276)
277
278common_lint_opts = [
279    "-A",
280    "deprecated",
281    # external/rust/crates/spin doesn't pass this lint check and there is not a way to make an
282    # exemption. Disable it until upstream is fixed or we figure out a workaround.
283    #"-D",
284    #"unsafe_op_in_unsafe_fn",
285    "-D",
286    "warnings",
287    "-D",
288    "clippy::undocumented_unsafe_blocks",
289    "-D",
290    "clippy::too-many-arguments",
291]
292
293# Linux x86_64 Host toolchain
294rust_toolchain(
295    name = "x86_64_unknown_linux_gnu",
296    allocator_library = None,
297    binary_ext = "",
298    default_edition = "2021",
299    dylib_ext = ".so",
300    exec_triple = "x86_64-unknown-linux-gnu",
301    global_allocator_library = None,
302    rust_doc = "@rust_prebuilts//:bin/rustdoc",
303    rust_std = "@rust_prebuilts//:prebuilt_stdlibs",
304    rustc = "@rust_prebuilts//:bin/rustc",
305    staticlib_ext = ".a",
306    stdlib_linkflags = [],
307    target_triple = "x86_64-unknown-linux-gnu",
308)
309
310toolchain(
311    name = "x86_64_unknown_linux_gnu_toolchain",
312    exec_compatible_with = ["@platforms//os:linux"],
313    target_settings = [":gbl_rust_host_x86_64"],
314    toolchain = ":x86_64_unknown_linux_gnu",
315    toolchain_type = "@rules_rust//rust:toolchain",
316)
317
318# x86_64 UEFI toolchain
319rust_toolchain(
320    name = "x86_64-unknown-uefi",
321    allocator_library = None,
322    binary_ext = ".efi",
323    default_edition = "2021",
324    dylib_ext = ".so",
325    exec_triple = "x86_64-unknown-linux-gnu",
326    extra_rustc_flags = common_lint_opts + [
327        # The linker options generated by rustc assumes `lld` as the linker. For windows platforms,
328        # the lld args style is different than that of clang++, i.e. for library search path, lld
329        # uses "/L<path>" while clang++ uses "-L<path>". Thus we need to use lld directly instead
330        # of `clang++`.
331        "--codegen=linker={}".format(gbl_llvm_tool_path("lld")),
332        # Disable default sysroot. We'll pass sysroot explicitly via the `rust_std` field below.
333        "--sysroot",
334        "/dev/null",
335    ],
336    global_allocator_library = None,
337    rust_doc = "@rust_prebuilts//:bin/rustdoc",
338    rust_std = "@rust_prebuilts//:x86_64-unknown-uefi_prebuilt_stdlibs",
339    rustc = "@rust_prebuilts//:bin/rustc",
340    staticlib_ext = ".a",
341    stdlib_linkflags = [],
342    target_triple = "x86_64-unknown-uefi",
343)
344
345toolchain(
346    name = "x86_64-unknown-uefi_toolchain",
347    exec_compatible_with = ["@platforms//os:linux"],
348    target_settings = [":gbl_rust_uefi_x86_64"],
349    toolchain = ":x86_64-unknown-uefi",
350    toolchain_type = "@rules_rust//rust:toolchain",
351)
352
353# i686 UEFI toolchain
354rust_toolchain(
355    name = "i686-unknown-uefi",
356    allocator_library = None,
357    binary_ext = ".efi",
358    default_edition = "2021",
359    dylib_ext = ".so",
360    exec_triple = "x86_64-unknown-linux-gnu",
361    extra_rustc_flags = common_lint_opts + [
362        "--codegen=linker={}".format(gbl_llvm_tool_path("lld")),
363        # Disable default sysroot. We'll pass sysroot explicitly via the `rust_std` field below.
364        "--sysroot",
365        "/dev/null",
366    ],
367    global_allocator_library = None,
368    rust_doc = "@rust_prebuilts//:bin/rustdoc",
369    # Need to use our own sysroot because we have a custom patch that needs to be applied for std
370    # in order to enable compiler builtin for chkstk(), alloca(). Once the fix is upstreamed, we
371    # can use the prebuilt.
372    rust_std = select({
373        ":rust_no_sysroot_true": ":rust_stdlib_empty",
374        "//conditions:default": ":rust_std_source_build",
375    }),
376    #rust_std = "@rust_prebuilts//:i686-unknown-uefi_prebuilt_stdlibs",
377    rustc = "@rust_prebuilts//:bin/rustc",
378    staticlib_ext = ".a",
379    stdlib_linkflags = [],
380    target_triple = "i686-unknown-uefi",
381)
382
383toolchain(
384    name = "i686-unknown-uefi_toolchain",
385    exec_compatible_with = ["@platforms//os:linux"],
386    target_settings = [":gbl_rust_uefi_x86_32"],
387    toolchain = ":i686-unknown-uefi",
388    toolchain_type = "@rules_rust//rust:toolchain",
389)
390
391# aarch64 UEFI toolchain
392rust_toolchain(
393    name = "aarch64-unknown-uefi",
394    allocator_library = None,
395    binary_ext = ".efi",
396    default_edition = "2021",
397    dylib_ext = ".so",
398    exec_triple = "x86_64-unknown-linux-gnu",
399    extra_rustc_flags = common_lint_opts + [
400        "--codegen=linker={}".format(gbl_llvm_tool_path("lld")),
401        # Disable default sysroot. We'll pass sysroot explicitly via the `rust_std` field below.
402        "--sysroot",
403        "/dev/null",
404    ],
405    global_allocator_library = None,
406    rust_doc = "@rust_prebuilts//:bin/rustdoc",
407    rust_std = "@rust_prebuilts//:aarch64-unknown-uefi_prebuilt_stdlibs",
408    rustc = "@rust_prebuilts//:bin/rustc",
409    staticlib_ext = ".a",
410    stdlib_linkflags = [],
411    target_triple = "aarch64-unknown-uefi",
412)
413
414toolchain(
415    name = "aarch64-unknown-uefi_toolchain",
416    exec_compatible_with = ["@platforms//os:linux"],
417    target_settings = [":gbl_rust_uefi_aarch64"],
418    toolchain = ":aarch64-unknown-uefi",
419    toolchain_type = "@rules_rust//rust:toolchain",
420)
421
422# riscv64 PIE ELF toolchain
423rust_toolchain(
424    name = "riscv64gc-unknown-none-pie_elf",
425    allocator_library = None,
426    binary_ext = "",
427    default_edition = "2021",
428    dylib_ext = ".so",
429    exec_triple = "x86_64-unknown-linux-gnu",
430    extra_rustc_flags = common_lint_opts + [
431        "--codegen=linker={}".format(gbl_llvm_tool_path("lld")),
432        # Disable default sysroot. We'll pass sysroot explicitly via the `rust_std` field below.
433        "--sysroot",
434        "/dev/null",
435    ],
436    global_allocator_library = None,
437    rust_doc = "@rust_prebuilts//:bin/rustdoc",
438    # Need to use our own built sysroot because we are using a custom spec below.
439    rust_std = select({
440        ":rust_no_sysroot_true": ":rust_stdlib_empty",
441        "//conditions:default": ":rust_std_source_build",
442    }),
443    rustc = "@rust_prebuilts//:bin/rustc",
444    staticlib_ext = ".a",
445    stdlib_linkflags = [],
446    # The custom spec is based on builtin target "riscv64gc-unknown-none-elf" but with the
447    # following changes for enabling PIE:
448    #
449    #   1. "relocation-model" config entry changed from "static" to "pic".
450    #   2. Added "position-independent-executables": true.
451    #
452    # The original spec can be obtained by:
453    #
454    #   rustc +nightly -Z unstable-options --print target-spec-json \
455    #     --target riscv64gc-unknown-none-elf
456    target_json = """
457                {
458                    "arch": "riscv64",
459                    "code-model": "medium",
460                    "cpu": "generic-rv64",
461                    "data-layout": "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128",
462                    "eh-frame-header": false,
463                    "emit-debug-gdb-scripts": false,
464                    "features": "+m,+a,+f,+d,+c",
465                    "is-builtin": false,
466                    "linker": "rust-lld",
467                    "linker-flavor": "ld.lld",
468                    "llvm-abiname": "lp64d",
469                    "llvm-target": "riscv64-unknown-linux",
470                    "max-atomic-width": 64,
471                    "os": "none",
472                    "panic-strategy": "abort",
473                    "relocation-model": "pic",
474                    "position-independent-executables": true,
475                    "supported-sanitizers": [
476                        "kernel-address"
477                    ],
478                    "target-pointer-width": "64"
479                }
480""",
481)
482
483toolchain(
484    name = "riscv64gc-unknown-none-pie_elf_toolchain",
485    exec_compatible_with = ["@platforms//os:linux"],
486    target_settings = ["@gbl//toolchain:gbl_rust_elf_riscv64"],
487    toolchain = ":riscv64gc-unknown-none-pie_elf",
488    toolchain_type = "@rules_rust//rust:toolchain",
489)
490
491# rustfmt toolchain
492rustfmt_toolchain(
493    name = "rustfmt",
494    rustfmt = "@rust_prebuilts//:bin/rustfmt",
495)
496
497toolchain(
498    name = "rustfmt_toolchain",
499    exec_compatible_with = ["@platforms//os:linux"],
500    toolchain = ":rustfmt",
501    toolchain_type = "@rules_rust//rust/rustfmt:toolchain_type",
502)
503
504# Rust bindgen toolchain
505
506prebuilt_binary(
507    name = "bindgen_prebuilt",
508    bin = "@bindgen//:bindgen",
509)
510
511rust_bindgen_toolchain(
512    name = "bindgen_toolchain_impl",
513    bindgen = ":bindgen_prebuilt",
514    clang = "@gbl_llvm_prebuilts//:clang-bin",
515    libclang = "@gbl_llvm_prebuilts//:libclang",
516    libstdcxx = "@gbl_llvm_prebuilts//:libc++",
517)
518
519toolchain(
520    name = "bindgen_toolchain",
521    toolchain = "bindgen_toolchain_impl",
522    toolchain_type = "@rules_rust//bindgen:toolchain_type",
523)
524