1# Copyright 2023 The Pigweed Authors 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); you may not 4# use this file except in compliance with the License. You may obtain a copy of 5# the License at 6# 7# https://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, WITHOUT 11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12# License for the specific language governing permissions and limitations under 13# the License. 14"""Utilities for declaring Rust toolchains that are compatible with Arm gcc.""" 15 16load("@rules_rust//rust:toolchain.bzl", "rust_analyzer_toolchain", "rust_toolchain") 17load("//pw_env_setup/bazel/cipd_setup:cipd_rules.bzl", "cipd_repository") 18 19HOSTS = [ 20 { 21 "cipd_arch": "arm64", 22 "cpu": "aarch64", 23 "dylib_ext": ".so", 24 "os": "linux", 25 "triple": "aarch64-unknown-linux-gnu", 26 }, 27 { 28 "cipd_arch": "amd64", 29 "cpu": "x86_64", 30 "dylib_ext": ".so", 31 "os": "linux", 32 "triple": "x86_64-unknown-linux-gnu", 33 }, 34 { 35 "cipd_arch": "arm64", 36 "cpu": "aarch64", 37 "dylib_ext": ".dylib", 38 "os": "macos", 39 "triple": "aarch64-apple-darwin", 40 }, 41 { 42 "cipd_arch": "amd64", 43 "cpu": "x86_64", 44 "dylib_ext": ".dylib", 45 "os": "macos", 46 "triple": "x86_64-apple-darwin", 47 }, 48] 49 50EXTRA_TARGETS = [ 51 { 52 "cpu": "armv6-m", 53 "triple": "thumbv6m-none-eabi", 54 }, 55 { 56 "cpu": "armv7-m", 57 "triple": "thumbv7m-none-eabi", 58 }, 59 { 60 "cpu": "armv7e-m", 61 "triple": "thumbv7m-none-eabi", 62 }, 63] 64 65CHANNELS = [ 66 { 67 "extra_rustc_flags": ["-Dwarnings", "-Zmacro-backtrace"], 68 "name": "nightly", 69 "target_settings": ["@rules_rust//rust/toolchain/channel:nightly"], 70 }, 71 { 72 # In order to approximate a stable toolchain with our nightly one, we 73 # disable experimental features with the exception of `proc_macro_span` 74 # because the `proc-marcro2` automatically detects the toolchain 75 # as nightly and dynamically uses this feature. 76 "extra_rustc_flags": ["-Dwarnings", "-Zallow-features=proc_macro_span"], 77 "name": "stable", 78 "target_settings": ["@rules_rust//rust/toolchain/channel:stable"], 79 }, 80] 81 82# buildifier: disable=unnamed-macro 83def pw_rust_register_toolchain_and_target_repos(cipd_tag, pigweed_repo_name = "@pigweed"): 84 """Declare and register CIPD repos for Rust toolchain and target rupport. 85 86 Args: 87 cipd_tag: Tag with which to select specific package versions. 88 pigweed_repo_name: The name of the pigweed used to reference build files 89 for the registered repositories. Defaults to "@pigweed". 90 """ 91 for host in HOSTS: 92 cipd_os = host["os"] 93 if cipd_os == "macos": 94 cipd_os = "mac" 95 96 cipd_repository( 97 name = "rust_toolchain_host_{}_{}".format(host["os"], host["cpu"]), 98 build_file = "{}//pw_toolchain/rust:rust_toolchain.BUILD".format(pigweed_repo_name), 99 path = "fuchsia/third_party/rust/host/{}-{}".format(cipd_os, host["cipd_arch"]), 100 tag = cipd_tag, 101 ) 102 103 cipd_repository( 104 name = "rust_toolchain_target_{}".format(host["triple"]), 105 build_file = "{}//pw_toolchain/rust:rust_stdlib.BUILD".format(pigweed_repo_name), 106 path = "fuchsia/third_party/rust/target/{}".format(host["triple"]), 107 tag = cipd_tag, 108 ) 109 110 for target in EXTRA_TARGETS: 111 cipd_repository( 112 name = "rust_toolchain_target_{}".format(target["triple"]), 113 build_file = "{}//pw_toolchain/rust:rust_stdlib.BUILD".format(pigweed_repo_name), 114 path = "fuchsia/third_party/rust/target/{}".format(target["triple"]), 115 tag = cipd_tag, 116 ) 117 118# buildifier: disable=unnamed-macro 119def pw_rust_register_toolchains(): 120 """Register Rust Toolchains 121 122 For this registration to be valid one must 123 1. Call `pw_rust_register_toolchain_and_target_repos(tag)` pervisouly in the 124 WORKSPACE file. 125 2. Call `pw_rust_declare_toolchain_targets()` from 126 `//pw_toolchain/rust/BUILD.bazel`. 127 """ 128 for channel in CHANNELS: 129 for host in HOSTS: 130 native.register_toolchains( 131 "//pw_toolchain/rust:host_rust_toolchain_{}_{}_{}".format(host["os"], host["cpu"], channel["name"]), 132 "//pw_toolchain/rust:host_rust_analyzer_toolchain_{}_{}_{}".format(host["os"], host["cpu"], channel["name"]), 133 ) 134 for target in EXTRA_TARGETS: 135 native.register_toolchains( 136 "//pw_toolchain/rust:{}_{}_rust_toolchain_{}_{}_{}".format(host["os"], host["cpu"], target["triple"], target["cpu"], channel["name"]), 137 ) 138 139# buildifier: disable=unnamed-macro 140def pw_rust_declare_toolchain_targets(): 141 """Declare rust toolchain targets""" 142 for channel in CHANNELS: 143 for host in HOSTS: 144 _pw_rust_host_toolchain( 145 name = "host_rust_toolchain_{}_{}_{}".format(host["os"], host["cpu"], channel["name"]), 146 analyzer_toolchain_name = "host_rust_analyzer_toolchain_{}_{}_{}".format(host["os"], host["cpu"], channel["name"]), 147 compatible_with = [ 148 "@platforms//cpu:{}".format(host["cpu"]), 149 "@platforms//os:{}".format(host["os"]), 150 ], 151 target_settings = channel["target_settings"], 152 dylib_ext = host["dylib_ext"], 153 target_repo = "@rust_toolchain_target_{}".format(host["triple"]), 154 toolchain_repo = "@rust_toolchain_host_{}_{}".format(host["os"], host["cpu"]), 155 triple = host["triple"], 156 extra_rustc_flags = channel["extra_rustc_flags"], 157 ) 158 for target in EXTRA_TARGETS: 159 _pw_rust_toolchain( 160 name = "{}_{}_rust_toolchain_{}_{}_{}".format(host["os"], host["cpu"], target["triple"], target["cpu"], channel["name"]), 161 exec_triple = host["triple"], 162 target_triple = target["triple"], 163 target_repo = "@rust_toolchain_target_{}".format(target["triple"]), 164 toolchain_repo = "@rust_toolchain_host_{}_{}".format(host["os"], host["cpu"]), 165 dylib_ext = "*.so", 166 exec_compatible_with = [ 167 "@platforms//cpu:{}".format(host["cpu"]), 168 "@platforms//os:{}".format(host["os"]), 169 ], 170 target_compatible_with = [ 171 "@platforms//cpu:{}".format(target["cpu"]), 172 ], 173 target_settings = channel["target_settings"], 174 extra_rustc_flags = channel["extra_rustc_flags"], 175 ) 176 177def _pw_rust_toolchain( 178 name, 179 exec_triple, 180 target_triple, 181 toolchain_repo, 182 target_repo, 183 dylib_ext, 184 exec_compatible_with, 185 target_compatible_with, 186 target_settings, 187 extra_rustc_flags): 188 rust_toolchain( 189 name = "{}_rust_toolchain".format(name), 190 binary_ext = "", 191 default_edition = "2021", 192 dylib_ext = dylib_ext, 193 exec_compatible_with = exec_compatible_with, 194 exec_triple = exec_triple, 195 rust_doc = "{}//:bin/rustdoc".format(toolchain_repo), 196 rust_std = "{}//:rust_std".format(target_repo), 197 rustc = "{}//:bin/rustc".format(toolchain_repo), 198 rustc_lib = "{}//:rustc_lib".format(toolchain_repo), 199 staticlib_ext = ".a", 200 stdlib_linkflags = [], 201 target_compatible_with = target_compatible_with, 202 target_triple = target_triple, 203 extra_rustc_flags = extra_rustc_flags, 204 extra_exec_rustc_flags = extra_rustc_flags, 205 # TODO: https://pwbug.dev/342695883 - Works around confusing 206 # target_compatible_with semantics in rust_toolchain. Figure out how to 207 # do better. 208 tags = ["manual"], 209 ) 210 native.toolchain( 211 name = name, 212 exec_compatible_with = exec_compatible_with, 213 target_compatible_with = target_compatible_with, 214 target_settings = target_settings, 215 toolchain = ":{}_rust_toolchain".format(name), 216 toolchain_type = "@rules_rust//rust:toolchain", 217 ) 218 219def _pw_rust_host_toolchain( 220 name, 221 analyzer_toolchain_name, 222 triple, 223 toolchain_repo, 224 target_repo, 225 dylib_ext, 226 compatible_with, 227 target_settings, 228 extra_rustc_flags): 229 _pw_rust_toolchain( 230 name = name, 231 exec_triple = triple, 232 target_triple = triple, 233 toolchain_repo = toolchain_repo, 234 target_repo = target_repo, 235 dylib_ext = dylib_ext, 236 exec_compatible_with = compatible_with, 237 target_compatible_with = compatible_with, 238 target_settings = target_settings, 239 extra_rustc_flags = extra_rustc_flags, 240 ) 241 242 rust_analyzer_toolchain( 243 name = "{}_rust_analyzer_toolchain".format(analyzer_toolchain_name), 244 exec_compatible_with = compatible_with, 245 proc_macro_srv = "{}//:libexec/rust-analyzer-proc-macro-srv".format(toolchain_repo), 246 rustc = "{}//:bin/rustc".format(toolchain_repo), 247 rustc_srcs = "{}//:rustc_srcs".format(toolchain_repo), 248 target_compatible_with = compatible_with, 249 visibility = ["//visibility:public"], 250 ) 251 252 native.toolchain( 253 name = analyzer_toolchain_name, 254 exec_compatible_with = compatible_with, 255 target_compatible_with = compatible_with, 256 target_settings = target_settings, 257 toolchain = ":{}_rust_analyzer_toolchain".format(analyzer_toolchain_name), 258 toolchain_type = "@rules_rust//rust/rust_analyzer:toolchain_type", 259 ) 260