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 # Adding this prevents the compiler from generating mmx, sse instructions such as 188 # "movsd (%esp),%xmm0" which likely isn't enabled during the bootloader stage and causes 189 # crash as a result. 190 "-mgeneral-regs-only", 191 ], 192 target_cpu = "x86_64", 193 target_system_triple = "x86_64-unknown-windows-msvc", 194) 195 196toolchain( 197 name = "x86_64_uefi_clang", 198 exec_compatible_with = ["@platforms//os:linux"], 199 target_compatible_with = uefi_x86_64_constraint_values, 200 toolchain = ":x86_64_uefi_clang_cc_toolchain", 201 toolchain_type = "@bazel_tools//tools/cpp:toolchain_type", 202) 203 204# x86_32 UEFI targets 205gbl_clang_cc_toolchain( 206 name = "x86_32_uefi_clang_cc_toolchain", 207 cc_flags = cc_flags_common + [ 208 "-m32", 209 # Adding this prevents the compiler from generating mmx, sse instructions such as 210 # "movsd (%esp),%xmm0" which likely isn't enabled during the bootloader stage and causes 211 # crash as a result. 212 "-march=i686", 213 ], 214 # Safe Exception Handlers is not applicable to EFI systems. 215 ld_flags = ["/SAFESEH:no"], 216 target_cpu = "x86_32", 217 target_system_triple = "i686-unknown-windows-gnu", 218) 219 220toolchain( 221 name = "x86_32_uefi_clang", 222 exec_compatible_with = ["@platforms//os:linux"], 223 target_compatible_with = uefi_x86_32_constraint_values, 224 toolchain = ":x86_32_uefi_clang_cc_toolchain", 225 toolchain_type = "@bazel_tools//tools/cpp:toolchain_type", 226) 227 228# aarch64 UEFI targets 229gbl_clang_cc_toolchain( 230 name = "aarch64_uefi_clang_cc_toolchain", 231 cc_flags = cc_flags_common, 232 target_cpu = "aarch64", 233 target_system_triple = "aarch64-windows-msvc", 234) 235 236toolchain( 237 name = "aarch64_uefi_clang", 238 exec_compatible_with = ["@platforms//os:linux"], 239 target_compatible_with = uefi_aarch64_constraint_values, 240 toolchain = ":aarch64_uefi_clang_cc_toolchain", 241 toolchain_type = "@bazel_tools//tools/cpp:toolchain_type", 242) 243 244# riscv64 ELF targets 245gbl_clang_cc_toolchain( 246 name = "riscv64_elf_clang_cc_toolchain", 247 cc_flags = cc_flags_common + ["-fpie"], 248 target_cpu = "riscv64", 249 target_system_triple = "riscv64-unknown-linux", 250) 251 252toolchain( 253 name = "riscv64_elf_clang", 254 exec_compatible_with = ["@platforms//os:linux"], 255 target_compatible_with = elf_riscv64_constraint_values, 256 toolchain = ":riscv64_elf_clang_cc_toolchain", 257 toolchain_type = "@bazel_tools//tools/cpp:toolchain_type", 258) 259 260# Rust toolchains 261 262# An empty rust std file group used as placeholder when building rust sysroot. 263rust_stdlib_filegroup( 264 name = "rust_stdlib_empty", 265 srcs = [], 266) 267 268# A rule for building sysroot from source. 269build_with_no_rust_sysroot( 270 name = "rust_sysroot_source_build", 271 deps = [ 272 "@rust_prebuilts//:liballoc", 273 "@rust_prebuilts//:libcompiler_builtins", 274 "@rust_prebuilts//:libcore", 275 ], 276) 277 278rust_stdlib_filegroup( 279 name = "rust_std_source_build", 280 srcs = [":rust_sysroot_source_build"], 281) 282 283common_lint_opts = [ 284 "-A", 285 "deprecated", 286 # external/rust/crates/spin doesn't pass this lint check and there is not a way to make an 287 # exemption. Disable it until upstream is fixed or we figure out a workaround. 288 #"-D", 289 #"unsafe_op_in_unsafe_fn", 290 "-D", 291 "warnings", 292 "-D", 293 "clippy::undocumented_unsafe_blocks", 294 "-D", 295 "clippy::too-many-arguments", 296] 297 298# Linux x86_64 Host toolchain 299rust_toolchain( 300 name = "x86_64_unknown_linux_gnu", 301 allocator_library = None, 302 binary_ext = "", 303 default_edition = "2021", 304 dylib_ext = ".so", 305 exec_triple = "x86_64-unknown-linux-gnu", 306 global_allocator_library = None, 307 rust_doc = "@rust_prebuilts//:bin/rustdoc", 308 rust_std = "@rust_prebuilts//:prebuilt_stdlibs", 309 rustc = "@rust_prebuilts//:bin/rustc", 310 staticlib_ext = ".a", 311 stdlib_linkflags = [], 312 target_triple = "x86_64-unknown-linux-gnu", 313) 314 315toolchain( 316 name = "x86_64_unknown_linux_gnu_toolchain", 317 exec_compatible_with = ["@platforms//os:linux"], 318 target_settings = [":gbl_rust_host_x86_64"], 319 toolchain = ":x86_64_unknown_linux_gnu", 320 toolchain_type = "@rules_rust//rust:toolchain", 321) 322 323# x86_64 UEFI toolchain 324rust_toolchain( 325 name = "x86_64-unknown-uefi", 326 allocator_library = None, 327 binary_ext = ".efi", 328 default_edition = "2021", 329 dylib_ext = ".so", 330 exec_triple = "x86_64-unknown-linux-gnu", 331 extra_rustc_flags = common_lint_opts + [ 332 # The linker options generated by rustc assumes `lld` as the linker. For windows platforms, 333 # the lld args style is different than that of clang++, i.e. for library search path, lld 334 # uses "/L<path>" while clang++ uses "-L<path>". Thus we need to use lld directly instead 335 # of `clang++`. 336 "--codegen=linker={}".format(gbl_llvm_tool_path("lld")), 337 # Disable default sysroot. We'll pass sysroot explicitly via the `rust_std` field below. 338 "--sysroot", 339 "/dev/null", 340 ], 341 global_allocator_library = None, 342 rust_doc = "@rust_prebuilts//:bin/rustdoc", 343 rust_std = "@rust_prebuilts//:x86_64-unknown-uefi_prebuilt_stdlibs", 344 rustc = "@rust_prebuilts//:bin/rustc", 345 staticlib_ext = ".a", 346 stdlib_linkflags = [], 347 target_triple = "x86_64-unknown-uefi", 348) 349 350toolchain( 351 name = "x86_64-unknown-uefi_toolchain", 352 exec_compatible_with = ["@platforms//os:linux"], 353 target_settings = [":gbl_rust_uefi_x86_64"], 354 toolchain = ":x86_64-unknown-uefi", 355 toolchain_type = "@rules_rust//rust:toolchain", 356) 357 358# i686 UEFI toolchain 359rust_toolchain( 360 name = "i686-unknown-uefi", 361 allocator_library = None, 362 binary_ext = ".efi", 363 default_edition = "2021", 364 dylib_ext = ".so", 365 exec_triple = "x86_64-unknown-linux-gnu", 366 extra_rustc_flags = common_lint_opts + [ 367 "--codegen=linker={}".format(gbl_llvm_tool_path("lld")), 368 # Disable default sysroot. We'll pass sysroot explicitly via the `rust_std` field below. 369 "--sysroot", 370 "/dev/null", 371 ], 372 global_allocator_library = None, 373 rust_doc = "@rust_prebuilts//:bin/rustdoc", 374 # Need to use our own sysroot because we have a custom patch that needs to be applied for std 375 # in order to enable compiler builtin for chkstk(), alloca(). Once the fix is upstreamed, we 376 # can use the prebuilt. 377 rust_std = select({ 378 ":rust_no_sysroot_true": ":rust_stdlib_empty", 379 "//conditions:default": ":rust_std_source_build", 380 }), 381 #rust_std = "@rust_prebuilts//:i686-unknown-uefi_prebuilt_stdlibs", 382 rustc = "@rust_prebuilts//:bin/rustc", 383 staticlib_ext = ".a", 384 stdlib_linkflags = [], 385 target_triple = "i686-unknown-uefi", 386) 387 388toolchain( 389 name = "i686-unknown-uefi_toolchain", 390 exec_compatible_with = ["@platforms//os:linux"], 391 target_settings = [":gbl_rust_uefi_x86_32"], 392 toolchain = ":i686-unknown-uefi", 393 toolchain_type = "@rules_rust//rust:toolchain", 394) 395 396# aarch64 UEFI toolchain 397rust_toolchain( 398 name = "aarch64-unknown-uefi", 399 allocator_library = None, 400 binary_ext = ".efi", 401 default_edition = "2021", 402 dylib_ext = ".so", 403 exec_triple = "x86_64-unknown-linux-gnu", 404 extra_rustc_flags = common_lint_opts + [ 405 "--codegen=linker={}".format(gbl_llvm_tool_path("lld")), 406 # Disable default sysroot. We'll pass sysroot explicitly via the `rust_std` field below. 407 "--sysroot", 408 "/dev/null", 409 ], 410 global_allocator_library = None, 411 rust_doc = "@rust_prebuilts//:bin/rustdoc", 412 rust_std = "@rust_prebuilts//:aarch64-unknown-uefi_prebuilt_stdlibs", 413 rustc = "@rust_prebuilts//:bin/rustc", 414 staticlib_ext = ".a", 415 stdlib_linkflags = [], 416 target_triple = "aarch64-unknown-uefi", 417) 418 419toolchain( 420 name = "aarch64-unknown-uefi_toolchain", 421 exec_compatible_with = ["@platforms//os:linux"], 422 target_settings = [":gbl_rust_uefi_aarch64"], 423 toolchain = ":aarch64-unknown-uefi", 424 toolchain_type = "@rules_rust//rust:toolchain", 425) 426 427# riscv64 PIE ELF toolchain 428rust_toolchain( 429 name = "riscv64gc-unknown-none-pie_elf", 430 allocator_library = None, 431 binary_ext = "", 432 default_edition = "2021", 433 dylib_ext = ".so", 434 exec_triple = "x86_64-unknown-linux-gnu", 435 extra_rustc_flags = common_lint_opts + [ 436 "--codegen=linker={}".format(gbl_llvm_tool_path("lld")), 437 # Disable default sysroot. We'll pass sysroot explicitly via the `rust_std` field below. 438 "--sysroot", 439 "/dev/null", 440 ], 441 global_allocator_library = None, 442 rust_doc = "@rust_prebuilts//:bin/rustdoc", 443 # Need to use our own built sysroot because we are using a custom spec below. 444 rust_std = select({ 445 ":rust_no_sysroot_true": ":rust_stdlib_empty", 446 "//conditions:default": ":rust_std_source_build", 447 }), 448 rustc = "@rust_prebuilts//:bin/rustc", 449 staticlib_ext = ".a", 450 stdlib_linkflags = [], 451 # The custom spec is based on builtin target "riscv64gc-unknown-none-elf" but with the 452 # following changes for enabling PIE: 453 # 454 # 1. "relocation-model" config entry changed from "static" to "pic". 455 # 2. Added "position-independent-executables": true. 456 # 457 # The original spec can be obtained by: 458 # 459 # rustc +nightly -Z unstable-options --print target-spec-json \ 460 # --target riscv64gc-unknown-none-elf 461 target_json = """ 462 { 463 "arch": "riscv64", 464 "code-model": "medium", 465 "cpu": "generic-rv64", 466 "data-layout": "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128", 467 "eh-frame-header": false, 468 "emit-debug-gdb-scripts": false, 469 "features": "+m,+a,+f,+d,+c", 470 "is-builtin": false, 471 "linker": "rust-lld", 472 "linker-flavor": "ld.lld", 473 "llvm-abiname": "lp64d", 474 "llvm-target": "riscv64-unknown-linux", 475 "max-atomic-width": 64, 476 "os": "none", 477 "panic-strategy": "abort", 478 "relocation-model": "pic", 479 "position-independent-executables": true, 480 "supported-sanitizers": [ 481 "kernel-address" 482 ], 483 "target-pointer-width": "64" 484 } 485""", 486) 487 488toolchain( 489 name = "riscv64gc-unknown-none-pie_elf_toolchain", 490 exec_compatible_with = ["@platforms//os:linux"], 491 target_settings = ["@gbl//toolchain:gbl_rust_elf_riscv64"], 492 toolchain = ":riscv64gc-unknown-none-pie_elf", 493 toolchain_type = "@rules_rust//rust:toolchain", 494) 495 496# rustfmt toolchain 497rustfmt_toolchain( 498 name = "rustfmt", 499 rustfmt = "@rust_prebuilts//:bin/rustfmt", 500) 501 502toolchain( 503 name = "rustfmt_toolchain", 504 exec_compatible_with = ["@platforms//os:linux"], 505 toolchain = ":rustfmt", 506 toolchain_type = "@rules_rust//rust/rustfmt:toolchain_type", 507) 508 509# Rust bindgen toolchain 510 511prebuilt_binary( 512 name = "bindgen_prebuilt", 513 bin = "@bindgen//:bindgen", 514) 515 516rust_bindgen_toolchain( 517 name = "bindgen_toolchain_impl", 518 bindgen = ":bindgen_prebuilt", 519 clang = "@gbl_llvm_prebuilts//:clang-bin", 520 libclang = "@gbl_llvm_prebuilts//:libclang", 521 libstdcxx = "@gbl_llvm_prebuilts//:libc++", 522) 523 524toolchain( 525 name = "bindgen_toolchain", 526 toolchain = "bindgen_toolchain_impl", 527 toolchain_type = "@rules_rust//bindgen:toolchain_type", 528) 529