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