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