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") 18load(":toolchains.bzl", "CHANNELS", "EXTRA_TARGETS", "HOSTS") 19 20_rust_toolchain_repo_template = """\ 21load("{pigweed_repo_name}//pw_toolchain/rust:defs.bzl", "pw_rust_declare_toolchain_targets") 22 23package(default_visibility = ["//visibility:public"]) 24 25licenses(["notice"]) 26 27pw_rust_declare_toolchain_targets() 28""" 29 30def _rust_toolchain_repo_impl(ctx): 31 ctx.file("BUILD", _rust_toolchain_repo_template.format(pigweed_repo_name = ctx.attr.pigweed_repo_name)) 32 pass 33 34_rust_toolchain_repo = repository_rule( 35 _rust_toolchain_repo_impl, 36 attrs = { 37 "pigweed_repo_name": attr.string( 38 doc = "The name of the pigweed used to reference build files for the registered repositories.", 39 ), 40 }, 41) 42 43# buildifier: disable=unnamed-macro 44def pw_rust_register_toolchain_and_target_repos(cipd_tag, pigweed_repo_name = "@pigweed"): 45 """Declare and register CIPD repos for Rust toolchain and target rupport. 46 47 Args: 48 cipd_tag: Tag with which to select specific package versions. 49 pigweed_repo_name: The name of the pigweed used to reference build files 50 for the registered repositories. Defaults to "@pigweed". 51 """ 52 toolchain_repo_name = "{}_rust_toolchain_repo".format(pigweed_repo_name).lstrip("@") 53 _rust_toolchain_repo(name = toolchain_repo_name, pigweed_repo_name = pigweed_repo_name) 54 for host in HOSTS: 55 cipd_os = host["os"] 56 if cipd_os == "macos": 57 cipd_os = "mac" 58 59 cipd_repository( 60 name = "rust_toolchain_host_{}_{}".format(host["os"], host["cpu"]), 61 build_file = "{}//pw_toolchain/rust:rust_toolchain.BUILD".format(pigweed_repo_name), 62 path = "fuchsia/third_party/rust/host/{}-{}".format(cipd_os, host["cipd_arch"]), 63 tag = cipd_tag, 64 ) 65 66 cipd_repository( 67 name = "rust_toolchain_target_{}".format(host["triple"]), 68 build_file = "{}//pw_toolchain/rust:rust_stdlib.BUILD".format(pigweed_repo_name), 69 path = "fuchsia/third_party/rust/target/{}".format(host["triple"]), 70 tag = cipd_tag, 71 ) 72 73 for target in EXTRA_TARGETS: 74 cipd_repository( 75 name = "rust_toolchain_target_{}".format(target["triple"]), 76 build_file = "{}//pw_toolchain/rust:rust_stdlib.BUILD".format(pigweed_repo_name), 77 path = "fuchsia/third_party/rust/target/{}".format(target["triple"]), 78 tag = cipd_tag, 79 ) 80 81# buildifier: disable=unnamed-macro 82def pw_rust_register_toolchains(pigweed_repo_name = "@pigweed"): 83 """Register Rust Toolchains 84 85 Args: 86 pigweed_repo_name: The name of the pigweed used to reference build files 87 for the registered repositories. Defaults to "@pigweed". 88 89 For this registration to be valid one must 90 1. Call `pw_rust_register_toolchain_and_target_repos(tag)` pervisouly in the 91 WORKSPACE file. 92 2. Call `pw_rust_declare_toolchain_targets()` from 93 `//pw_toolchain/rust/BUILD.bazel`. 94 """ 95 96 toolchain_repo = "{}_rust_toolchain_repo".format(pigweed_repo_name) 97 98 for channel in CHANNELS: 99 for host in HOSTS: 100 native.register_toolchains( 101 "{}//:host_rust_toolchain_{}_{}_{}".format(toolchain_repo, host["os"], host["cpu"], channel["name"]), 102 "{}//:host_rust_analyzer_toolchain_{}_{}_{}".format(toolchain_repo, host["os"], host["cpu"], channel["name"]), 103 ) 104 for target in EXTRA_TARGETS: 105 native.register_toolchains( 106 "{}//:{}_{}_rust_toolchain_{}_{}_{}".format(toolchain_repo, host["os"], host["cpu"], target["triple"], target["cpu"], channel["name"]), 107 ) 108 109# buildifier: disable=unnamed-macro 110def pw_rust_declare_toolchain_targets(): 111 """Declare rust toolchain targets""" 112 for channel in CHANNELS: 113 for host in HOSTS: 114 _pw_rust_host_toolchain( 115 name = "host_rust_toolchain_{}_{}_{}".format(host["os"], host["cpu"], channel["name"]), 116 analyzer_toolchain_name = "host_rust_analyzer_toolchain_{}_{}_{}".format(host["os"], host["cpu"], channel["name"]), 117 compatible_with = [ 118 "@platforms//cpu:{}".format(host["cpu"]), 119 "@platforms//os:{}".format(host["os"]), 120 ], 121 target_settings = channel["target_settings"], 122 dylib_ext = host["dylib_ext"], 123 target_repo = "@rust_toolchain_target_{}".format(host["triple"]), 124 toolchain_repo = "@rust_toolchain_host_{}_{}".format(host["os"], host["cpu"]), 125 triple = host["triple"], 126 extra_rustc_flags = channel["extra_rustc_flags"], 127 ) 128 for target in EXTRA_TARGETS: 129 _pw_rust_toolchain( 130 name = "{}_{}_rust_toolchain_{}_{}_{}".format(host["os"], host["cpu"], target["triple"], target["cpu"], channel["name"]), 131 exec_triple = host["triple"], 132 target_triple = target["triple"], 133 target_repo = "@rust_toolchain_target_{}".format(target["triple"]), 134 toolchain_repo = "@rust_toolchain_host_{}_{}".format(host["os"], host["cpu"]), 135 dylib_ext = "*.so", 136 exec_compatible_with = [ 137 "@platforms//cpu:{}".format(host["cpu"]), 138 "@platforms//os:{}".format(host["os"]), 139 ], 140 target_compatible_with = [ 141 "@platforms//cpu:{}".format(target["cpu"]), 142 ], 143 target_settings = channel["target_settings"], 144 extra_rustc_flags = channel["extra_rustc_flags"], 145 ) 146 147def _pw_rust_toolchain( 148 name, 149 exec_triple, 150 target_triple, 151 toolchain_repo, 152 target_repo, 153 dylib_ext, 154 exec_compatible_with, 155 target_compatible_with, 156 target_settings, 157 extra_rustc_flags): 158 rust_toolchain( 159 name = "{}_rust_toolchain".format(name), 160 binary_ext = "", 161 clippy_driver = "{}//:bin/clippy-driver".format(toolchain_repo), 162 default_edition = "2021", 163 dylib_ext = dylib_ext, 164 exec_compatible_with = exec_compatible_with, 165 exec_triple = exec_triple, 166 rust_doc = "{}//:bin/rustdoc".format(toolchain_repo), 167 rust_std = "{}//:rust_std".format(target_repo), 168 rustc = "{}//:bin/rustc".format(toolchain_repo), 169 rustc_lib = "{}//:rustc_lib".format(toolchain_repo), 170 staticlib_ext = ".a", 171 stdlib_linkflags = [], 172 target_compatible_with = target_compatible_with, 173 target_triple = target_triple, 174 extra_rustc_flags = extra_rustc_flags, 175 extra_exec_rustc_flags = extra_rustc_flags, 176 # TODO: https://pwbug.dev/342695883 - Works around confusing 177 # target_compatible_with semantics in rust_toolchain. Figure out how to 178 # do better. 179 tags = ["manual"], 180 ) 181 native.toolchain( 182 name = name, 183 exec_compatible_with = exec_compatible_with, 184 target_compatible_with = target_compatible_with, 185 target_settings = target_settings, 186 toolchain = ":{}_rust_toolchain".format(name), 187 toolchain_type = "@rules_rust//rust:toolchain", 188 ) 189 190def _pw_rust_host_toolchain( 191 name, 192 analyzer_toolchain_name, 193 triple, 194 toolchain_repo, 195 target_repo, 196 dylib_ext, 197 compatible_with, 198 target_settings, 199 extra_rustc_flags): 200 _pw_rust_toolchain( 201 name = name, 202 exec_triple = triple, 203 target_triple = triple, 204 toolchain_repo = toolchain_repo, 205 target_repo = target_repo, 206 dylib_ext = dylib_ext, 207 exec_compatible_with = compatible_with, 208 target_compatible_with = compatible_with, 209 target_settings = target_settings, 210 extra_rustc_flags = extra_rustc_flags, 211 ) 212 213 rust_analyzer_toolchain( 214 name = "{}_rust_analyzer_toolchain".format(analyzer_toolchain_name), 215 exec_compatible_with = compatible_with, 216 proc_macro_srv = "{}//:libexec/rust-analyzer-proc-macro-srv".format(toolchain_repo), 217 rustc = "{}//:bin/rustc".format(toolchain_repo), 218 rustc_srcs = "{}//:rustc_srcs".format(toolchain_repo), 219 target_compatible_with = compatible_with, 220 visibility = ["//visibility:public"], 221 ) 222 223 native.toolchain( 224 name = analyzer_toolchain_name, 225 exec_compatible_with = compatible_with, 226 target_compatible_with = compatible_with, 227 target_settings = target_settings, 228 toolchain = ":{}_rust_analyzer_toolchain".format(analyzer_toolchain_name), 229 toolchain_type = "@rules_rust//rust/rust_analyzer:toolchain_type", 230 ) 231