1"""Repository rules for defining Rust dependencies and toolchains""" 2 3load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") 4load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe") 5load("//rust/platform:triple.bzl", "get_host_triple", "triple") 6load("//rust/platform:triple_mappings.bzl", "triple_to_constraint_set") 7load("//rust/private:common.bzl", "DEFAULT_NIGHTLY_ISO_DATE", "rust_common") 8load( 9 "//rust/private:repository_utils.bzl", 10 "BUILD_for_rust_analyzer_proc_macro_srv", 11 "BUILD_for_rust_analyzer_toolchain", 12 "BUILD_for_rust_toolchain", 13 "BUILD_for_rustfmt_toolchain", 14 "BUILD_for_toolchain", 15 "DEFAULT_EXTRA_TARGET_TRIPLES", 16 "DEFAULT_NIGHTLY_VERSION", 17 "DEFAULT_STATIC_RUST_URL_TEMPLATES", 18 "TINYJSON_KWARGS", 19 "check_version_valid", 20 "includes_rust_analyzer_proc_macro_srv", 21 "load_cargo", 22 "load_clippy", 23 "load_llvm_tools", 24 "load_rust_compiler", 25 "load_rust_src", 26 "load_rust_stdlib", 27 "load_rustc_dev_nightly", 28 "load_rustfmt", 29 "select_rust_version", 30 "toolchain_repository_hub", 31 _load_arbitrary_tool = "load_arbitrary_tool", 32) 33 34# Reexport `load_arbitrary_tool` as it's currently in use in https://github.com/google/cargo-raze 35load_arbitrary_tool = _load_arbitrary_tool 36 37# Note: Code in `.github/workflows/crate_universe.yaml` looks for this line, if you remove it or change its format, you will also need to update that code. 38DEFAULT_TOOLCHAIN_TRIPLES = { 39 "aarch64-apple-darwin": "rust_darwin_aarch64", 40 "aarch64-pc-windows-msvc": "rust_windows_aarch64", 41 "aarch64-unknown-linux-gnu": "rust_linux_aarch64", 42 "x86_64-apple-darwin": "rust_darwin_x86_64", 43 "x86_64-pc-windows-msvc": "rust_windows_x86_64", 44 "x86_64-unknown-freebsd": "rust_freebsd_x86_64", 45 "x86_64-unknown-linux-gnu": "rust_linux_x86_64", 46} 47 48def rules_rust_dependencies(): 49 """Dependencies used in the implementation of `rules_rust`.""" 50 51 maybe( 52 http_archive, 53 name = "platforms", 54 urls = [ 55 "https://mirror.bazel.build/github.com/bazelbuild/platforms/releases/download/0.0.8/platforms-0.0.8.tar.gz", 56 "https://github.com/bazelbuild/platforms/releases/download/0.0.8/platforms-0.0.8.tar.gz", 57 ], 58 sha256 = "8150406605389ececb6da07cbcb509d5637a3ab9a24bc69b1101531367d89d74", 59 ) 60 maybe( 61 http_archive, 62 name = "rules_cc", 63 urls = ["https://github.com/bazelbuild/rules_cc/releases/download/0.0.9/rules_cc-0.0.9.tar.gz"], 64 sha256 = "2037875b9a4456dce4a79d112a8ae885bbc4aad968e6587dca6e64f3a0900cdf", 65 strip_prefix = "rules_cc-0.0.9", 66 ) 67 maybe( 68 http_archive, 69 name = "rules_license", 70 urls = [ 71 "https://mirror.bazel.build/github.com/bazelbuild/rules_license/releases/download/0.0.8/rules_license-0.0.8.tar.gz", 72 "https://github.com/bazelbuild/rules_license/releases/download/0.0.8/rules_license-0.0.8.tar.gz", 73 ], 74 sha256 = "241b06f3097fd186ff468832150d6cc142247dc42a32aaefb56d0099895fd229", 75 ) 76 77 maybe( 78 http_archive, 79 name = "bazel_skylib", 80 sha256 = "cd55a062e763b9349921f0f5db8c3933288dc8ba4f76dd9416aac68acee3cb94", 81 urls = [ 82 "https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.5.0/bazel-skylib-1.5.0.tar.gz", 83 "https://github.com/bazelbuild/bazel-skylib/releases/download/1.5.0/bazel-skylib-1.5.0.tar.gz", 84 ], 85 ) 86 87 # Make the iOS simulator constraint available, which is referenced in abi_to_constraints() 88 # rules_rust does not require this dependency; it is just imported as a convenience for users. 89 maybe( 90 http_archive, 91 name = "build_bazel_apple_support", 92 sha256 = "1c4031e72b456a048d8177f59a5581808c07585fa9e255c6f5fefb8752af7e40", 93 url = "https://github.com/bazelbuild/apple_support/releases/download/1.13.0/apple_support.1.13.0.tar.gz", 94 ) 95 96 # process_wrapper needs a low-dependency way to process json. 97 maybe( 98 http_archive, 99 **TINYJSON_KWARGS 100 ) 101 102_RUST_TOOLCHAIN_VERSIONS = [ 103 rust_common.default_version, 104 DEFAULT_NIGHTLY_VERSION, 105] 106 107# buildifier: disable=unnamed-macro 108def rust_register_toolchains( 109 dev_components = False, 110 edition = None, 111 allocator_library = None, 112 global_allocator_library = None, 113 iso_date = None, 114 register_toolchains = True, 115 rustfmt_version = DEFAULT_NIGHTLY_VERSION, 116 rust_analyzer_version = None, 117 sha256s = None, 118 extra_target_triples = DEFAULT_EXTRA_TARGET_TRIPLES, 119 extra_rustc_flags = None, 120 extra_exec_rustc_flags = None, 121 urls = DEFAULT_STATIC_RUST_URL_TEMPLATES, 122 version = None, 123 versions = []): 124 """Emits a default set of toolchains for Linux, MacOS, and Freebsd 125 126 Skip this macro and call the `rust_repository_set` macros directly if you need a compiler for \ 127 other hosts or for additional target triples. 128 129 The `sha256` attribute represents a dict associating tool subdirectories to sha256 hashes. As an example: 130 ```python 131 { 132 "rust-1.46.0-x86_64-unknown-linux-gnu": "e3b98bc3440fe92817881933f9564389eccb396f5f431f33d48b979fa2fbdcf5", 133 "rustfmt-1.4.12-x86_64-unknown-linux-gnu": "1894e76913303d66bf40885a601462844eec15fca9e76a6d13c390d7000d64b0", 134 "rust-std-1.46.0-x86_64-unknown-linux-gnu": "ac04aef80423f612c0079829b504902de27a6997214eb58ab0765d02f7ec1dbc", 135 } 136 ``` 137 This would match for `exec_triple = "x86_64-unknown-linux-gnu"`. If not specified, rules_rust pulls from a non-exhaustive \ 138 list of known checksums.. 139 140 See `load_arbitrary_tool` in `@rules_rust//rust:repositories.bzl` for more details. 141 142 Args: 143 dev_components (bool, optional): Whether to download the rustc-dev components (defaults to False). Requires version to be "nightly". 144 edition (str, optional): The rust edition to be used by default (2015, 2018, or 2021). If absent, every target is required to specify its `edition` attribute. 145 allocator_library (str, optional): Target that provides allocator functions when rust_library targets are embedded in a cc_binary. 146 global_allocator_library (str, optional): Target that provides allocator functions when global allocator is used with cc_common.link. 147 iso_date (str, optional): **Deprecated**: Use `versions` instead. 148 register_toolchains (bool): If true, repositories will be generated to produce and register `rust_toolchain` targets. 149 rustfmt_version (str, optional): The version of rustfmt. 150 rust_analyzer_version (str, optional): The version of Rustc to pair with rust-analyzer. 151 sha256s (str, optional): A dict associating tool subdirectories to sha256 hashes. 152 extra_target_triples (list, optional): Additional rust-style targets that rust toolchains should support. 153 extra_rustc_flags (dict, list, optional): Dictionary of target triples to list of extra flags to pass to rustc in non-exec configuration. 154 extra_exec_rustc_flags (list, optional): Extra flags to pass to rustc in exec configuration. 155 urls (list, optional): A list of mirror urls containing the tools from the Rust-lang static file server. These must contain the '{}' used to substitute the tool being fetched (using .format). 156 version (str, optional): **Deprecated**: Use `versions` instead. 157 versions (list, optional): A list of toolchain versions to download. This paramter only accepts one versions 158 per channel. E.g. `["1.65.0", "nightly/2022-11-02", "beta/2020-12-30"]`. 159 """ 160 if version: 161 # buildifier: disable=print 162 print("`rust_register.toolchains.version` is deprecated. Please use `versions` instead: https://bazelbuild.github.io/rules_rust/flatten.html#rust_register_toolchains-versions") 163 164 if iso_date: 165 # buildifier: disable=print 166 print("`rust_register.toolchains.iso_date` is deprecated. Please use `versions` instead: https://bazelbuild.github.io/rules_rust/flatten.html#rust_register_toolchains-versions") 167 168 if rustfmt_version in ("nightly", "beta"): 169 # buildifier: disable=print 170 print("`rust_register.toolchains.rustfmt_version` now requires iso date to be included in the string. E.g. `nightly/2022-12-15`. This version will be assumed until this value is updated") 171 rustfmt_version = "{}/{}".format(rustfmt_version, DEFAULT_NIGHTLY_ISO_DATE) 172 173 if not versions: 174 if version: 175 versions = [version] 176 else: 177 versions = _RUST_TOOLCHAIN_VERSIONS 178 179 if dev_components: 180 has_nightly = False 181 for ver in versions: 182 if ver.startswith("nightly"): 183 has_nightly = True 184 break 185 if not has_nightly: 186 fail("rustc-dev components were requested but no \"nightly\" is being registered. Please update `versions` to include a nightly version.") 187 188 if not rust_analyzer_version: 189 rust_analyzer_version = select_rust_version(versions) 190 191 rust_analyzer_repo_name = "rust_analyzer_{}".format(rust_analyzer_version.replace("/", "-")) 192 rust_analyzer_iso_date = None 193 if rust_analyzer_version.startswith(("beta", "nightly")): 194 rust_analyzer_version, _, rust_analyzer_iso_date = rustfmt_version.partition("/") 195 196 toolchain_names = [] 197 toolchain_labels = {} 198 toolchain_types = {} 199 exec_compatible_with_by_toolchain = {} 200 target_compatible_with_by_toolchain = {} 201 202 maybe( 203 rust_analyzer_toolchain_repository, 204 name = rust_analyzer_repo_name, 205 version = rust_analyzer_version, 206 urls = urls, 207 sha256s = sha256s, 208 iso_date = rust_analyzer_iso_date, 209 ) 210 211 toolchain_names.append(rust_analyzer_repo_name) 212 toolchain_labels[rust_analyzer_repo_name] = "@{}_tools//:rust_analyzer_toolchain".format( 213 rust_analyzer_repo_name, 214 ) 215 exec_compatible_with_by_toolchain[rust_analyzer_repo_name] = [] 216 target_compatible_with_by_toolchain[rust_analyzer_repo_name] = [] 217 toolchain_types[rust_analyzer_repo_name] = "@rules_rust//rust/rust_analyzer:toolchain_type" 218 219 if register_toolchains: 220 native.register_toolchains("@{}//:toolchain".format( 221 rust_analyzer_repo_name, 222 )) 223 224 rustfmt_iso_date = None 225 rustfmt_version_or_channel = rustfmt_version 226 if rustfmt_version.startswith(("beta", "nightly")): 227 rustfmt_version_or_channel, _, rustfmt_iso_date = rustfmt_version.partition("/") 228 229 for exec_triple, name in DEFAULT_TOOLCHAIN_TRIPLES.items(): 230 maybe( 231 rust_repository_set, 232 name = name, 233 dev_components = dev_components, 234 edition = edition, 235 exec_triple = exec_triple, 236 extra_target_triples = extra_target_triples, 237 allocator_library = allocator_library, 238 global_allocator_library = global_allocator_library, 239 iso_date = iso_date, 240 register_toolchain = register_toolchains, 241 rustfmt_version = rustfmt_version, 242 extra_rustc_flags = extra_rustc_flags, 243 extra_exec_rustc_flags = extra_exec_rustc_flags, 244 sha256s = sha256s, 245 urls = urls, 246 version = version, 247 versions = versions, 248 ) 249 250 rustfmt_repo_name = "rustfmt_{}__{}".format(rustfmt_version.replace("/", "-"), exec_triple) 251 252 maybe( 253 rustfmt_toolchain_repository, 254 name = rustfmt_repo_name, 255 version = rustfmt_version_or_channel, 256 urls = urls, 257 sha256s = sha256s, 258 iso_date = rustfmt_iso_date, 259 exec_triple = exec_triple, 260 ) 261 262 if register_toolchains: 263 native.register_toolchains("@{}//:toolchain".format( 264 rustfmt_repo_name, 265 )) 266 267 for toolchain in _get_toolchain_repositories(name, exec_triple, extra_target_triples, versions, iso_date): 268 toolchain_names.append(toolchain.name) 269 toolchain_labels[toolchain.name] = "@{}//:{}".format(toolchain.name + "_tools", "rust_toolchain") 270 exec_compatible_with_by_toolchain[toolchain.name] = triple_to_constraint_set(exec_triple) 271 target_compatible_with_by_toolchain[toolchain.name] = triple_to_constraint_set(toolchain.target_triple) 272 toolchain_types[toolchain.name] = "@rules_rust//rust:toolchain" 273 274 toolchain_names.append(rustfmt_repo_name) 275 toolchain_labels[rustfmt_repo_name] = "@{}_tools//:rustfmt_toolchain".format(rustfmt_repo_name) 276 exec_compatible_with_by_toolchain[rustfmt_repo_name] = triple_to_constraint_set(exec_triple) 277 target_compatible_with_by_toolchain[rustfmt_repo_name] = [] 278 toolchain_types[rustfmt_repo_name] = "@rules_rust//rust/rustfmt:toolchain_type" 279 280 toolchain_repository_hub( 281 name = "rust_toolchains", 282 toolchain_names = toolchain_names, 283 toolchain_labels = toolchain_labels, 284 toolchain_types = toolchain_types, 285 exec_compatible_with = exec_compatible_with_by_toolchain, 286 target_compatible_with = target_compatible_with_by_toolchain, 287 ) 288 289# buildifier: disable=unnamed-macro 290def rust_repositories(**kwargs): 291 """**Deprecated**: Use [rules_rust_dependencies](#rules_rust_dependencies) \ 292 and [rust_register_toolchains](#rust_register_toolchains) directly. 293 294 Args: 295 **kwargs (dict): Keyword arguments for the `rust_register_toolchains` macro. 296 """ 297 rules_rust_dependencies() 298 299 rust_register_toolchains(**kwargs) 300 301def _rust_toolchain_tools_repository_impl(ctx): 302 """The implementation of the rust toolchain tools repository rule.""" 303 304 check_version_valid(ctx.attr.version, ctx.attr.iso_date) 305 306 exec_triple = triple(ctx.attr.exec_triple) 307 308 build_components = [ 309 load_rust_compiler( 310 ctx = ctx, 311 iso_date = ctx.attr.iso_date, 312 target_triple = exec_triple, 313 version = ctx.attr.version, 314 ), 315 load_clippy( 316 ctx = ctx, 317 iso_date = ctx.attr.iso_date, 318 target_triple = exec_triple, 319 version = ctx.attr.version, 320 ), 321 load_cargo( 322 ctx = ctx, 323 iso_date = ctx.attr.iso_date, 324 target_triple = exec_triple, 325 version = ctx.attr.version, 326 ), 327 ] 328 329 if ctx.attr.rustfmt_version: 330 rustfmt_version = ctx.attr.rustfmt_version 331 rustfmt_iso_date = None 332 if rustfmt_version in ("nightly", "beta"): 333 if ctx.attr.iso_date: 334 rustfmt_iso_date = ctx.attr.iso_date 335 else: 336 fail("`rustfmt_version` does not include an iso_date. The following reposiotry should either set `iso_date` or update `rustfmt_version` to include an iso_date suffix: {}".format( 337 ctx.name, 338 )) 339 elif rustfmt_version.startswith(("nightly", "beta")): 340 rustfmt_version, _, rustfmt_iso_date = rustfmt_version.partition("/") 341 build_components.append(load_rustfmt( 342 ctx = ctx, 343 target_triple = triple(ctx.attr.exec_triple), 344 version = rustfmt_version, 345 iso_date = rustfmt_iso_date, 346 )) 347 348 # Rust 1.45.0 and nightly builds after 2020-05-22 need the llvm-tools gzip to get the libLLVM dylib 349 include_llvm_tools = ctx.attr.version >= "1.45.0" or (ctx.attr.version == "nightly" and ctx.attr.iso_date > "2020-05-22") 350 if include_llvm_tools: 351 build_components.append(load_llvm_tools( 352 ctx = ctx, 353 target_triple = exec_triple, 354 )) 355 356 target_triple = triple(ctx.attr.target_triple) 357 build_components.append(load_rust_stdlib( 358 ctx = ctx, 359 target_triple = target_triple, 360 )) 361 362 stdlib_linkflags = None 363 if "BAZEL_RUST_STDLIB_LINKFLAGS" in ctx.os.environ: 364 stdlib_linkflags = ctx.os.environ["BAZEL_RUST_STDLIB_LINKFLAGS"].split(":") 365 366 build_components.append(BUILD_for_rust_toolchain( 367 name = "rust_toolchain", 368 exec_triple = exec_triple, 369 allocator_library = ctx.attr.allocator_library, 370 global_allocator_library = ctx.attr.global_allocator_library, 371 target_triple = target_triple, 372 stdlib_linkflags = stdlib_linkflags, 373 default_edition = ctx.attr.edition, 374 include_rustfmt = not (not ctx.attr.rustfmt_version), 375 include_llvm_tools = include_llvm_tools, 376 extra_rustc_flags = ctx.attr.extra_rustc_flags, 377 extra_exec_rustc_flags = ctx.attr.extra_exec_rustc_flags, 378 opt_level = ctx.attr.opt_level if ctx.attr.opt_level else None, 379 )) 380 381 # Not all target triples are expected to have dev components 382 if ctx.attr.dev_components: 383 load_rustc_dev_nightly(ctx, target_triple) 384 385 ctx.file("WORKSPACE.bazel", "") 386 ctx.file("BUILD.bazel", "\n".join(build_components)) 387 388rust_toolchain_tools_repository = repository_rule( 389 doc = ( 390 "Composes a single workspace containing the toolchain components for compiling on a given " + 391 "platform to a series of target platforms.\n" + 392 "\n" + 393 "A given instance of this rule should be accompanied by a toolchain_repository_proxy " + 394 "invocation to declare its toolchains to Bazel; the indirection allows separating toolchain " + 395 "selection from toolchain fetching." 396 ), 397 attrs = { 398 "allocator_library": attr.string( 399 doc = "Target that provides allocator functions when rust_library targets are embedded in a cc_binary.", 400 default = "@rules_rust//ffi/cc/allocator_library", 401 ), 402 "auth": attr.string_dict( 403 doc = ( 404 "Auth object compatible with repository_ctx.download to use when downloading files. " + 405 "See [repository_ctx.download](https://docs.bazel.build/versions/main/skylark/lib/repository_ctx.html#download) for more details." 406 ), 407 ), 408 "dev_components": attr.bool( 409 doc = "Whether to download the rustc-dev components (defaults to False). Requires version to be \"nightly\".", 410 default = False, 411 ), 412 "edition": attr.string( 413 doc = ( 414 "The rust edition to be used by default (2015, 2018, or 2021). " + 415 "If absent, every rule is required to specify its `edition` attribute." 416 ), 417 ), 418 "exec_triple": attr.string( 419 doc = "The Rust-style target that this compiler runs on", 420 mandatory = True, 421 ), 422 "extra_exec_rustc_flags": attr.string_list( 423 doc = "Extra flags to pass to rustc in exec configuration", 424 ), 425 "extra_rustc_flags": attr.string_list( 426 doc = "Extra flags to pass to rustc in non-exec configuration", 427 ), 428 "global_allocator_library": attr.string( 429 doc = "Target that provides allocator functions when a global allocator is used with cc_common.link.", 430 default = "@rules_rust//ffi/cc/global_allocator_library", 431 ), 432 "iso_date": attr.string( 433 doc = "The date of the tool (or None, if the version is a specific version).", 434 ), 435 "opt_level": attr.string_dict( 436 doc = "Rustc optimization levels. For more details see the documentation for `rust_toolchain.opt_level`.", 437 ), 438 "rustfmt_version": attr.string( 439 doc = "The version of the tool among \"nightly\", \"beta\", or an exact version.", 440 ), 441 "sha256s": attr.string_dict( 442 doc = "A dict associating tool subdirectories to sha256 hashes. See [rust_repositories](#rust_repositories) for more details.", 443 ), 444 "target_triple": attr.string( 445 doc = "The Rust-style target that this compiler builds for.", 446 mandatory = True, 447 ), 448 "urls": attr.string_list( 449 doc = "A list of mirror urls containing the tools from the Rust-lang static file server. These must contain the '{}' used to substitute the tool being fetched (using .format).", 450 default = DEFAULT_STATIC_RUST_URL_TEMPLATES, 451 ), 452 "version": attr.string( 453 doc = "The version of the tool among \"nightly\", \"beta\", or an exact version.", 454 mandatory = True, 455 ), 456 }, 457 implementation = _rust_toolchain_tools_repository_impl, 458) 459 460def _toolchain_repository_proxy_impl(repository_ctx): 461 repository_ctx.file("WORKSPACE.bazel", """workspace(name = "{}")""".format( 462 repository_ctx.name, 463 )) 464 465 repository_ctx.file("BUILD.bazel", BUILD_for_toolchain( 466 name = "toolchain", 467 toolchain = repository_ctx.attr.toolchain, 468 target_settings = repository_ctx.attr.target_settings, 469 toolchain_type = repository_ctx.attr.toolchain_type, 470 target_compatible_with = repository_ctx.attr.target_compatible_with, 471 exec_compatible_with = repository_ctx.attr.exec_compatible_with, 472 )) 473 474toolchain_repository_proxy = repository_rule( 475 doc = ( 476 "Generates a toolchain-bearing repository that declares the toolchains from some other " + 477 "rust_toolchain_repository." 478 ), 479 attrs = { 480 "exec_compatible_with": attr.string_list( 481 doc = "A list of constraints for the execution platform for this toolchain.", 482 ), 483 "target_compatible_with": attr.string_list( 484 doc = "A list of constraints for the target platform for this toolchain.", 485 ), 486 "target_settings": attr.string_list( 487 doc = "A list of config_settings that must be satisfied by the target configuration in order for this toolchain to be selected during toolchain resolution.", 488 ), 489 "toolchain": attr.string( 490 doc = "The name of the toolchain implementation target.", 491 mandatory = True, 492 ), 493 "toolchain_type": attr.string( 494 doc = "The toolchain type of the toolchain to declare", 495 mandatory = True, 496 ), 497 }, 498 implementation = _toolchain_repository_proxy_impl, 499) 500 501# For legacy support 502rust_toolchain_repository_proxy = toolchain_repository_proxy 503 504# N.B. A "proxy repository" is needed to allow for registering the toolchain (with constraints) 505# without actually downloading the toolchain. 506def rust_toolchain_repository( 507 name, 508 version, 509 exec_triple, 510 target_triple, 511 exec_compatible_with = None, 512 target_compatible_with = None, 513 target_settings = [], 514 channel = None, 515 allocator_library = None, 516 global_allocator_library = None, 517 iso_date = None, 518 rustfmt_version = None, 519 edition = None, 520 dev_components = False, 521 extra_rustc_flags = None, 522 extra_exec_rustc_flags = None, 523 opt_level = None, 524 sha256s = None, 525 urls = DEFAULT_STATIC_RUST_URL_TEMPLATES, 526 auth = None): 527 """Assembles a remote repository for the given toolchain params, produces a proxy repository \ 528 to contain the toolchain declaration, and registers the toolchains. 529 530 Args: 531 name (str): The name of the generated repository 532 version (str): The version of the tool among "nightly", "beta", or an exact version. 533 exec_triple (str): The Rust-style target that this compiler runs on. 534 target_triple (str): The Rust-style target to build for. 535 channel (str, optional): The channel of the Rust toolchain. 536 exec_compatible_with (list, optional): A list of constraints for the execution platform for this toolchain. 537 target_compatible_with (list, optional): A list of constraints for the target platform for this toolchain. 538 target_settings (list, optional): A list of config_settings that must be satisfied by the target configuration in order for this toolchain to be selected during toolchain resolution. 539 allocator_library (str, optional): Target that provides allocator functions when rust_library targets are embedded in a cc_binary. 540 global_allocator_library (str, optional): Target that provides allocator functions when a global allocator is used with cc_common.link. 541 iso_date (str, optional): The date of the tool. 542 rustfmt_version (str, optional): The version of rustfmt to be associated with the 543 toolchain. 544 edition (str, optional): The rust edition to be used by default (2015, 2018, or 2021). If absent, every rule is required to specify its `edition` attribute. 545 dev_components (bool, optional): Whether to download the rustc-dev components. 546 Requires version to be "nightly". Defaults to False. 547 extra_rustc_flags (list, optional): Extra flags to pass to rustc in non-exec configuration. 548 extra_exec_rustc_flags (list, optional): Extra flags to pass to rustc in exec configuration. 549 opt_level (dict, optional): Optimization level config for this toolchain. 550 sha256s (str, optional): A dict associating tool subdirectories to sha256 hashes. See 551 [rust_repositories](#rust_repositories) for more details. 552 urls (list, optional): A list of mirror urls containing the tools from the Rust-lang static file server. These must contain the '{}' used to substitute the tool being fetched (using .format). Defaults to ['https://static.rust-lang.org/dist/{}.tar.xz'] 553 auth (dict): Auth object compatible with repository_ctx.download to use when downloading files. 554 See [repository_ctx.download](https://docs.bazel.build/versions/main/skylark/lib/repository_ctx.html#download) for more details. 555 556 Returns: 557 str: The name of the registerable toolchain created by this rule. 558 """ 559 560 if rustfmt_version in ("nightly", "beta"): 561 # buildifier: disable=print 562 print("`rust_toolchain_repository.rustfmt_version` now requires iso date to be included in the string. E.g. `nightly/2022-12-15`. This version will be assumed until this value is updated") 563 rustfmt_version = "{}/{}".format(rustfmt_version, DEFAULT_NIGHTLY_ISO_DATE) 564 565 if exec_compatible_with == None: 566 exec_compatible_with = triple_to_constraint_set(exec_triple) 567 568 if target_compatible_with == None: 569 target_compatible_with = triple_to_constraint_set(target_triple) 570 571 tools_repo_name = "{}_tools".format(name) 572 573 rust_toolchain_tools_repository( 574 name = tools_repo_name, 575 exec_triple = exec_triple, 576 allocator_library = allocator_library, 577 global_allocator_library = global_allocator_library, 578 target_triple = target_triple, 579 iso_date = iso_date, 580 version = version, 581 rustfmt_version = rustfmt_version, 582 edition = edition, 583 dev_components = dev_components, 584 extra_rustc_flags = extra_rustc_flags, 585 extra_exec_rustc_flags = extra_exec_rustc_flags, 586 opt_level = opt_level, 587 sha256s = sha256s, 588 urls = urls, 589 auth = auth, 590 ) 591 592 channel_target_settings = ["@rules_rust//rust/toolchain/channel:{}".format(channel)] if channel else [] 593 594 toolchain_repository_proxy( 595 name = name, 596 toolchain = "@{}//:rust_toolchain".format(tools_repo_name), 597 target_settings = channel_target_settings + target_settings, 598 toolchain_type = "@rules_rust//rust:toolchain", 599 exec_compatible_with = exec_compatible_with, 600 target_compatible_with = target_compatible_with, 601 ) 602 603 return "@{name}//:toolchain".format( 604 name = name, 605 ) 606 607def _rust_analyzer_toolchain_tools_repository_impl(repository_ctx): 608 load_rust_src( 609 ctx = repository_ctx, 610 iso_date = repository_ctx.attr.iso_date, 611 version = repository_ctx.attr.version, 612 ) 613 614 repository_ctx.file("WORKSPACE.bazel", """workspace(name = "{}")""".format( 615 repository_ctx.name, 616 )) 617 618 host_triple = get_host_triple(repository_ctx) 619 build_contents = [ 620 load_rust_compiler( 621 ctx = repository_ctx, 622 iso_date = repository_ctx.attr.iso_date, 623 target_triple = host_triple, 624 version = repository_ctx.attr.version, 625 ), 626 ] 627 rustc = "//:rustc" 628 629 proc_macro_srv = None 630 if includes_rust_analyzer_proc_macro_srv(repository_ctx.attr.version, repository_ctx.attr.iso_date): 631 build_contents.append(BUILD_for_rust_analyzer_proc_macro_srv(host_triple)) 632 proc_macro_srv = "//:rust_analyzer_proc_macro_srv" 633 634 build_contents.append(BUILD_for_rust_analyzer_toolchain( 635 name = "rust_analyzer_toolchain", 636 rustc = rustc, 637 proc_macro_srv = proc_macro_srv, 638 )) 639 640 repository_ctx.file("BUILD.bazel", "\n".join(build_contents)) 641 repository_ctx.file("WORKSPACE.bazel", """workspace(name = "{}")""".format( 642 repository_ctx.name, 643 )) 644 645rust_analyzer_toolchain_tools_repository = repository_rule( 646 doc = "A repository rule for defining a rust_analyzer_toolchain with a `rust-src` artifact.", 647 attrs = { 648 "auth": attr.string_dict( 649 doc = ( 650 "Auth object compatible with repository_ctx.download to use when downloading files. " + 651 "See [repository_ctx.download](https://docs.bazel.build/versions/main/skylark/lib/repository_ctx.html#download) for more details." 652 ), 653 ), 654 "iso_date": attr.string( 655 doc = "The date of the tool (or None, if the version is a specific version).", 656 ), 657 "sha256s": attr.string_dict( 658 doc = "A dict associating tool subdirectories to sha256 hashes. See [rust_repositories](#rust_repositories) for more details.", 659 ), 660 "urls": attr.string_list( 661 doc = "A list of mirror urls containing the tools from the Rust-lang static file server. These must contain the '{}' used to substitute the tool being fetched (using .format).", 662 default = DEFAULT_STATIC_RUST_URL_TEMPLATES, 663 ), 664 "version": attr.string( 665 doc = "The version of the tool among \"nightly\", \"beta\", or an exact version.", 666 mandatory = True, 667 ), 668 }, 669 implementation = _rust_analyzer_toolchain_tools_repository_impl, 670) 671 672def rust_analyzer_toolchain_repository( 673 name, 674 version, 675 exec_compatible_with = [], 676 target_compatible_with = [], 677 iso_date = None, 678 sha256s = None, 679 urls = None, 680 auth = None): 681 """Assemble a remote rust_analyzer_toolchain target based on the given params. 682 683 Args: 684 name (str): The name of the toolchain proxy repository contianing the registerable toolchain. 685 version (str): The version of the tool among "nightly", "beta', or an exact version. 686 exec_compatible_with (list, optional): A list of constraints for the execution platform for this toolchain. 687 target_compatible_with (list, optional): A list of constraints for the target platform for this toolchain. 688 iso_date (str, optional): The date of the tool. 689 sha256s (str, optional): A dict associating tool subdirectories to sha256 hashes. See 690 [rust_repositories](#rust_repositories) for more details. 691 urls (list, optional): A list of mirror urls containing the tools from the Rust-lang static file server. These must contain the '{}' used to substitute the tool being fetched (using .format). Defaults to ['https://static.rust-lang.org/dist/{}.tar.xz'] 692 auth (dict): Auth object compatible with repository_ctx.download to use when downloading files. 693 See [repository_ctx.download](https://docs.bazel.build/versions/main/skylark/lib/repository_ctx.html#download) for more details. 694 695 Returns: 696 str: The name of a registerable rust_analyzer_toolchain. 697 """ 698 rust_analyzer_toolchain_tools_repository( 699 name = name + "_tools", 700 version = version, 701 iso_date = iso_date, 702 sha256s = sha256s, 703 urls = urls, 704 auth = auth, 705 ) 706 707 toolchain_repository_proxy( 708 name = name, 709 toolchain = "@{}//:{}".format(name + "_tools", "rust_analyzer_toolchain"), 710 toolchain_type = "@rules_rust//rust/rust_analyzer:toolchain_type", 711 exec_compatible_with = exec_compatible_with, 712 target_compatible_with = target_compatible_with, 713 ) 714 715 return "@{}//:toolchain".format( 716 name, 717 ) 718 719def _rustfmt_toolchain_tools_repository_impl(repository_ctx): 720 repository_ctx.file("WORKSPACE.bazel", """workspace(name = "{}")""".format( 721 repository_ctx.name, 722 )) 723 724 rustfmt = "//:rustfmt_bin" 725 rustc = "//:rustc" 726 rustc_lib = "//:rustc_lib" 727 728 exec_triple = triple(repository_ctx.attr.exec_triple) 729 730 build_contents = [ 731 load_rust_compiler( 732 ctx = repository_ctx, 733 iso_date = repository_ctx.attr.iso_date, 734 target_triple = exec_triple, 735 version = repository_ctx.attr.version, 736 ), 737 load_rustfmt( 738 ctx = repository_ctx, 739 iso_date = repository_ctx.attr.iso_date, 740 target_triple = exec_triple, 741 version = repository_ctx.attr.version, 742 ), 743 BUILD_for_rustfmt_toolchain( 744 name = "rustfmt_toolchain", 745 rustfmt = rustfmt, 746 rustc = rustc, 747 rustc_lib = rustc_lib, 748 ), 749 ] 750 751 repository_ctx.file("BUILD.bazel", "\n".join(build_contents)) 752 repository_ctx.file("WORKSPACE.bazel", """workspace(name = "{}")""".format( 753 repository_ctx.name, 754 )) 755 756rustfmt_toolchain_tools_repository = repository_rule( 757 doc = "A repository rule for defining a rustfmt_toolchain.", 758 attrs = { 759 "auth": attr.string_dict( 760 doc = ( 761 "Auth object compatible with repository_ctx.download to use when downloading files. " + 762 "See [repository_ctx.download](https://docs.bazel.build/versions/main/skylark/lib/repository_ctx.html#download) for more details." 763 ), 764 ), 765 "exec_triple": attr.string( 766 doc = "The Rust-style triple Rustfmt is expected to run on.", 767 mandatory = True, 768 ), 769 "iso_date": attr.string( 770 doc = "The date of the tool (or None, if the version is a specific version).", 771 ), 772 "sha256s": attr.string_dict( 773 doc = "A dict associating tool subdirectories to sha256 hashes. See [rust_repositories](#rust_repositories) for more details.", 774 ), 775 "urls": attr.string_list( 776 doc = "A list of mirror urls containing the tools from the Rust-lang static file server. These must contain the '{}' used to substitute the tool being fetched (using .format).", 777 default = DEFAULT_STATIC_RUST_URL_TEMPLATES, 778 ), 779 "version": attr.string( 780 doc = "The version of the tool among \"nightly\", \"beta\", or an exact version.", 781 mandatory = True, 782 ), 783 }, 784 implementation = _rustfmt_toolchain_tools_repository_impl, 785) 786 787def rustfmt_toolchain_repository( 788 name, 789 version, 790 exec_triple, 791 exec_compatible_with = None, 792 target_compatible_with = None, 793 iso_date = None, 794 channel = None, 795 sha256s = None, 796 urls = None, 797 auth = None): 798 """Assemble a remote rustfmt_toolchain target based on the given params. 799 800 Args: 801 name (str): The name of the toolchain proxy repository contianing the registerable toolchain. 802 version (str): The version of the tool among "nightly", "beta', or an exact version. 803 exec_triple (str): The platform triple Rustfmt is expected to run on. 804 exec_compatible_with (list, optional): A list of constraints for the execution platform for this toolchain. 805 target_compatible_with (list, optional): A list of constraints for the target platform for this toolchain. 806 iso_date (str, optional): The date of the tool. 807 channel (str, optional): The channel value to with which to constrain the toolchain. 808 sha256s (str, optional): A dict associating tool subdirectories to sha256 hashes. See 809 [rust_repositories](#rust_repositories) for more details. 810 urls (list, optional): A list of mirror urls containing the tools from the Rust-lang static file server. These must contain the '{}' used to substitute the tool being fetched (using .format). Defaults to ['https://static.rust-lang.org/dist/{}.tar.xz'] 811 auth (dict): Auth object compatible with repository_ctx.download to use when downloading files. 812 See [repository_ctx.download](https://docs.bazel.build/versions/main/skylark/lib/repository_ctx.html#download) for more details. 813 814 Returns: 815 str: The name of a registerable rustfmt_toolchain. 816 """ 817 if exec_compatible_with == None: 818 exec_compatible_with = triple_to_constraint_set(exec_triple) 819 820 rustfmt_toolchain_tools_repository( 821 name = name + "_tools", 822 version = version, 823 iso_date = iso_date, 824 sha256s = sha256s, 825 urls = urls, 826 auth = auth, 827 exec_triple = exec_triple, 828 ) 829 830 toolchain_repository_proxy( 831 name = name, 832 toolchain = "@{}//:{}".format(name + "_tools", "rustfmt_toolchain"), 833 toolchain_type = "@rules_rust//rust/rustfmt:toolchain_type", 834 target_settings = ["@rules_rust//rust/toolchain/channel:{}".format(channel)] if channel else None, 835 exec_compatible_with = exec_compatible_with, 836 target_compatible_with = target_compatible_with, 837 ) 838 839 return "@{}//:toolchain".format( 840 name, 841 ) 842 843def _rust_toolchain_set_repository_impl(repository_ctx): 844 repository_ctx.file("WORKSPACE.bazel", """workspace(name = "{}")""".format( 845 repository_ctx.name, 846 )) 847 848 repository_ctx.file("BUILD.bazel", """exports_files(["defs.bzl"])""") 849 repository_ctx.file("defs.bzl", "ALL_TOOLCHAINS = {}\n".format( 850 json.encode_indent(repository_ctx.attr.toolchains, indent = " " * 4), 851 )) 852 853rust_toolchain_set_repository = repository_rule( 854 doc = ( 855 "Generates a toolchain-bearing repository that declares the toolchains from some other " + 856 "rust_toolchain_repository." 857 ), 858 attrs = { 859 "toolchains": attr.string_list( 860 doc = "The list of all toolchains created by the current `rust_toolchain_set`", 861 mandatory = True, 862 ), 863 }, 864 implementation = _rust_toolchain_set_repository_impl, 865) 866 867def _get_toolchain_repositories(name, exec_triple, extra_target_triples, versions, iso_date): 868 toolchain_repos = [] 869 870 for target_triple in depset([exec_triple] + extra_target_triples).to_list(): 871 # Parse all provided versions while checking for duplicates 872 channels = {} 873 for version in versions: 874 if version.startswith(("beta", "nightly")): 875 channel, _, date = version.partition("/") 876 ver = channel 877 else: 878 channel = "stable" 879 date = iso_date 880 ver = version 881 882 if channel in channels: 883 fail("Duplicate {} channels provided for {}: {}".format(channel, name, versions)) 884 885 channels.update({channel: struct( 886 name = channel, 887 iso_date = date, 888 version = ver, 889 )}) 890 891 # Define toolchains for each requested version 892 for channel in channels.values(): 893 toolchain_repos.append(struct( 894 name = "{}__{}__{}".format(name, target_triple, channel.name), 895 target_triple = target_triple, 896 channel = channel, 897 )) 898 899 return toolchain_repos 900 901def rust_repository_set( 902 name, 903 exec_triple, 904 target_settings = [], 905 version = None, 906 versions = [], 907 allocator_library = None, 908 global_allocator_library = None, 909 extra_target_triples = {}, 910 iso_date = None, 911 rustfmt_version = None, 912 edition = None, 913 dev_components = False, 914 extra_rustc_flags = None, 915 extra_exec_rustc_flags = None, 916 opt_level = None, 917 sha256s = None, 918 urls = DEFAULT_STATIC_RUST_URL_TEMPLATES, 919 auth = None, 920 register_toolchain = True, 921 exec_compatible_with = None, 922 default_target_compatible_with = None): 923 """Assembles a remote repository for the given toolchain params, produces a proxy repository \ 924 to contain the toolchain declaration, and registers the toolchains. 925 926 Args: 927 name (str): The name of the generated repository 928 exec_triple (str): The Rust-style target that this compiler runs on 929 target_settings (list, optional): A list of config_settings that must be satisfied by the target configuration in order for this set of toolchains to be selected during toolchain resolution. 930 version (str): The version of the tool among "nightly", "beta', or an exact version. 931 versions (list, optional): A list of toolchain versions to download. This paramter only accepts one versions 932 per channel. E.g. `["1.65.0", "nightly/2022-11-02", "beta/2020-12-30"]`. 933 allocator_library (str, optional): Target that provides allocator functions when rust_library targets are 934 embedded in a cc_binary. 935 global_allocator_library (str, optional): Target that provides allocator functions a global allocator is used with cc_common.link. 936 extra_target_triples (list or map, optional): Additional rust-style targets that this set of 937 toolchains should support. If a map, values should be (optional) target_compatible_with lists for that particular target triple. 938 iso_date (str, optional): The date of the tool. 939 rustfmt_version (str, optional): The version of rustfmt to be associated with the 940 toolchain. 941 edition (str, optional): The rust edition to be used by default (2015, 2018, or 2021). If absent, every rule is 942 required to specify its `edition` attribute. 943 dev_components (bool, optional): Whether to download the rustc-dev components. 944 Requires version to be "nightly". 945 extra_rustc_flags (dict, list, optional): Dictionary of target triples to list of extra flags to pass to rustc in non-exec configuration. 946 extra_exec_rustc_flags (list, optional): Extra flags to pass to rustc in exec configuration. 947 opt_level (dict, dict, optional): Dictionary of target triples to optimiztion config. 948 sha256s (str, optional): A dict associating tool subdirectories to sha256 hashes. See 949 [rust_repositories](#rust_repositories) for more details. 950 urls (list, optional): A list of mirror urls containing the tools from the Rust-lang static file server. These 951 must contain the '{}' used to substitute the tool being fetched (using .format). 952 auth (dict): Auth object compatible with repository_ctx.download to use when downloading files. 953 See [repository_ctx.download](https://docs.bazel.build/versions/main/skylark/lib/repository_ctx.html#download) for more details. 954 register_toolchain (bool): If True, the generated `rust_toolchain` target will become a registered toolchain. 955 exec_compatible_with (list, optional): A list of constraints for the execution platform for this toolchain. 956 default_target_compatible_with (list, optional): A list of constraints for the target platform for this toolchain when the exec platform is the same as the target platform. 957 """ 958 959 if version and versions: 960 fail("`version` and `versions` attributes are mutually exclusive. Update {} to use one".format( 961 name, 962 )) 963 964 if not version and not versions: 965 fail("`version` or `versions` attributes are required. Update {} to use one".format( 966 name, 967 )) 968 969 if version: 970 # buildifier: disable=print 971 print("`rust_repository_set.version` is deprecated. Instead use `rust_repository_set.versions`") 972 973 if version and not versions: 974 versions = [version] 975 976 # extra_target_triples may be a dict or list - make a list we can pass to _get_toolchain_repositories 977 extra_target_triples_list = [] 978 for extra_target_triple in extra_target_triples: 979 extra_target_triples_list.append(extra_target_triple) 980 981 all_toolchain_names = [] 982 for toolchain in _get_toolchain_repositories(name, exec_triple, extra_target_triples_list, versions, iso_date): 983 target_compatible_with = None 984 if toolchain.target_triple == exec_triple: 985 # The exec triple implicitly gets a toolchain with itself as a target - use default_target_compatible_with for it 986 target_compatible_with = default_target_compatible_with 987 elif type(extra_target_triples) == "dict": 988 target_compatible_with = extra_target_triples.get(toolchain.target_triple) 989 990 all_toolchain_names.append(rust_toolchain_repository( 991 name = toolchain.name, 992 allocator_library = allocator_library, 993 global_allocator_library = global_allocator_library, 994 auth = auth, 995 channel = toolchain.channel.name, 996 dev_components = dev_components, 997 edition = edition, 998 exec_triple = exec_triple, 999 extra_exec_rustc_flags = extra_exec_rustc_flags, 1000 extra_rustc_flags = extra_rustc_flags.get(toolchain.target_triple) if extra_rustc_flags != None else None, 1001 opt_level = opt_level.get(toolchain.target_triple) if opt_level != None else None, 1002 target_settings = target_settings, 1003 iso_date = toolchain.channel.iso_date, 1004 rustfmt_version = rustfmt_version, 1005 sha256s = sha256s, 1006 target_triple = toolchain.target_triple, 1007 urls = urls, 1008 version = toolchain.channel.version, 1009 exec_compatible_with = exec_compatible_with, 1010 target_compatible_with = target_compatible_with, 1011 )) 1012 1013 # This repository exists to allow `rust_repository_set` to work with the `maybe` wrapper. 1014 rust_toolchain_set_repository( 1015 name = name, 1016 toolchains = all_toolchain_names, 1017 ) 1018 1019 # Register toolchains 1020 if register_toolchain: 1021 native.register_toolchains(*all_toolchain_names) 1022 native.register_toolchains(str(Label("//rust/private/dummy_cc_toolchain:dummy_cc_wasm32_toolchain"))) 1023