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