# Copyright 2023 The Pigweed Authors # # Licensed under the Apache License, Version 2.0 (the "License"); you may not # use this file except in compliance with the License. You may obtain a copy of # the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations under # the License. """Utilities for declaring Rust toolchains that are compatible with Arm gcc.""" load("@rules_rust//rust:toolchain.bzl", "rust_analyzer_toolchain", "rust_toolchain") load("//pw_env_setup/bazel/cipd_setup:cipd_rules.bzl", "cipd_repository") HOSTS = [ { "cipd_arch": "arm64", "cpu": "aarch64", "dylib_ext": ".so", "os": "linux", "triple": "aarch64-unknown-linux-gnu", }, { "cipd_arch": "amd64", "cpu": "x86_64", "dylib_ext": ".so", "os": "linux", "triple": "x86_64-unknown-linux-gnu", }, { "cipd_arch": "arm64", "cpu": "aarch64", "dylib_ext": ".dylib", "os": "macos", "triple": "aarch64-apple-darwin", }, { "cipd_arch": "amd64", "cpu": "x86_64", "dylib_ext": ".dylib", "os": "macos", "triple": "x86_64-apple-darwin", }, ] EXTRA_TARGETS = [ { "cpu": "armv6-m", "triple": "thumbv6m-none-eabi", }, { "cpu": "armv7-m", "triple": "thumbv7m-none-eabi", }, { "cpu": "armv7e-m", "triple": "thumbv7m-none-eabi", }, ] CHANNELS = [ { "extra_rustc_flags": ["-Dwarnings", "-Zmacro-backtrace"], "name": "nightly", "target_settings": ["@rules_rust//rust/toolchain/channel:nightly"], }, { # In order to approximate a stable toolchain with our nightly one, we # disable experimental features with the exception of `proc_macro_span` # because the `proc-marcro2` automatically detects the toolchain # as nightly and dynamically uses this feature. "extra_rustc_flags": ["-Dwarnings", "-Zallow-features=proc_macro_span"], "name": "stable", "target_settings": ["@rules_rust//rust/toolchain/channel:stable"], }, ] # buildifier: disable=unnamed-macro def pw_rust_register_toolchain_and_target_repos(cipd_tag, pigweed_repo_name = "@pigweed"): """Declare and register CIPD repos for Rust toolchain and target rupport. Args: cipd_tag: Tag with which to select specific package versions. pigweed_repo_name: The name of the pigweed used to reference build files for the registered repositories. Defaults to "@pigweed". """ for host in HOSTS: cipd_os = host["os"] if cipd_os == "macos": cipd_os = "mac" cipd_repository( name = "rust_toolchain_host_{}_{}".format(host["os"], host["cpu"]), build_file = "{}//pw_toolchain/rust:rust_toolchain.BUILD".format(pigweed_repo_name), path = "fuchsia/third_party/rust/host/{}-{}".format(cipd_os, host["cipd_arch"]), tag = cipd_tag, ) cipd_repository( name = "rust_toolchain_target_{}".format(host["triple"]), build_file = "{}//pw_toolchain/rust:rust_stdlib.BUILD".format(pigweed_repo_name), path = "fuchsia/third_party/rust/target/{}".format(host["triple"]), tag = cipd_tag, ) for target in EXTRA_TARGETS: cipd_repository( name = "rust_toolchain_target_{}".format(target["triple"]), build_file = "{}//pw_toolchain/rust:rust_stdlib.BUILD".format(pigweed_repo_name), path = "fuchsia/third_party/rust/target/{}".format(target["triple"]), tag = cipd_tag, ) # buildifier: disable=unnamed-macro def pw_rust_register_toolchains(): """Register Rust Toolchains For this registration to be valid one must 1. Call `pw_rust_register_toolchain_and_target_repos(tag)` pervisouly in the WORKSPACE file. 2. Call `pw_rust_declare_toolchain_targets()` from `//pw_toolchain/rust/BUILD.bazel`. """ for channel in CHANNELS: for host in HOSTS: native.register_toolchains( "//pw_toolchain/rust:host_rust_toolchain_{}_{}_{}".format(host["os"], host["cpu"], channel["name"]), "//pw_toolchain/rust:host_rust_analyzer_toolchain_{}_{}_{}".format(host["os"], host["cpu"], channel["name"]), ) for target in EXTRA_TARGETS: native.register_toolchains( "//pw_toolchain/rust:{}_{}_rust_toolchain_{}_{}_{}".format(host["os"], host["cpu"], target["triple"], target["cpu"], channel["name"]), ) # buildifier: disable=unnamed-macro def pw_rust_declare_toolchain_targets(): """Declare rust toolchain targets""" for channel in CHANNELS: for host in HOSTS: _pw_rust_host_toolchain( name = "host_rust_toolchain_{}_{}_{}".format(host["os"], host["cpu"], channel["name"]), analyzer_toolchain_name = "host_rust_analyzer_toolchain_{}_{}_{}".format(host["os"], host["cpu"], channel["name"]), compatible_with = [ "@platforms//cpu:{}".format(host["cpu"]), "@platforms//os:{}".format(host["os"]), ], target_settings = channel["target_settings"], dylib_ext = host["dylib_ext"], target_repo = "@rust_toolchain_target_{}".format(host["triple"]), toolchain_repo = "@rust_toolchain_host_{}_{}".format(host["os"], host["cpu"]), triple = host["triple"], extra_rustc_flags = channel["extra_rustc_flags"], ) for target in EXTRA_TARGETS: _pw_rust_toolchain( name = "{}_{}_rust_toolchain_{}_{}_{}".format(host["os"], host["cpu"], target["triple"], target["cpu"], channel["name"]), exec_triple = host["triple"], target_triple = target["triple"], target_repo = "@rust_toolchain_target_{}".format(target["triple"]), toolchain_repo = "@rust_toolchain_host_{}_{}".format(host["os"], host["cpu"]), dylib_ext = "*.so", exec_compatible_with = [ "@platforms//cpu:{}".format(host["cpu"]), "@platforms//os:{}".format(host["os"]), ], target_compatible_with = [ "@platforms//cpu:{}".format(target["cpu"]), ], target_settings = channel["target_settings"], extra_rustc_flags = channel["extra_rustc_flags"], ) def _pw_rust_toolchain( name, exec_triple, target_triple, toolchain_repo, target_repo, dylib_ext, exec_compatible_with, target_compatible_with, target_settings, extra_rustc_flags): rust_toolchain( name = "{}_rust_toolchain".format(name), binary_ext = "", default_edition = "2021", dylib_ext = dylib_ext, exec_compatible_with = exec_compatible_with, exec_triple = exec_triple, rust_doc = "{}//:bin/rustdoc".format(toolchain_repo), rust_std = "{}//:rust_std".format(target_repo), rustc = "{}//:bin/rustc".format(toolchain_repo), rustc_lib = "{}//:rustc_lib".format(toolchain_repo), staticlib_ext = ".a", stdlib_linkflags = [], target_compatible_with = target_compatible_with, target_triple = target_triple, extra_rustc_flags = extra_rustc_flags, extra_exec_rustc_flags = extra_rustc_flags, # TODO: https://pwbug.dev/342695883 - Works around confusing # target_compatible_with semantics in rust_toolchain. Figure out how to # do better. tags = ["manual"], ) native.toolchain( name = name, exec_compatible_with = exec_compatible_with, target_compatible_with = target_compatible_with, target_settings = target_settings, toolchain = ":{}_rust_toolchain".format(name), toolchain_type = "@rules_rust//rust:toolchain", ) def _pw_rust_host_toolchain( name, analyzer_toolchain_name, triple, toolchain_repo, target_repo, dylib_ext, compatible_with, target_settings, extra_rustc_flags): _pw_rust_toolchain( name = name, exec_triple = triple, target_triple = triple, toolchain_repo = toolchain_repo, target_repo = target_repo, dylib_ext = dylib_ext, exec_compatible_with = compatible_with, target_compatible_with = compatible_with, target_settings = target_settings, extra_rustc_flags = extra_rustc_flags, ) rust_analyzer_toolchain( name = "{}_rust_analyzer_toolchain".format(analyzer_toolchain_name), exec_compatible_with = compatible_with, proc_macro_srv = "{}//:libexec/rust-analyzer-proc-macro-srv".format(toolchain_repo), rustc = "{}//:bin/rustc".format(toolchain_repo), rustc_srcs = "{}//:rustc_srcs".format(toolchain_repo), target_compatible_with = compatible_with, visibility = ["//visibility:public"], ) native.toolchain( name = analyzer_toolchain_name, exec_compatible_with = compatible_with, target_compatible_with = compatible_with, target_settings = target_settings, toolchain = ":{}_rust_analyzer_toolchain".format(analyzer_toolchain_name), toolchain_type = "@rules_rust//rust/rust_analyzer:toolchain_type", )