File
Blob: build/deps/formatters/rustfmt_repository.bzl
| 1 | """ |
| 2 | Repository rule that downloads a standalone rustfmt binary along with the rustc |
| 3 | shared libraries it depends on. |
| 4 | |
| 5 | This avoids needing `bazel run @rules_rust//:rustfmt`, which triggers C++ toolchain |
| 6 | resolution and (in edgeworker) the V8 build cache download — a multi-GB fetch that |
| 7 | is unnecessary for code formatting. |
| 8 | """ |
| 9 | |
| 10 | load("@@//:build/http_proxy_config.bzl", "PROXY_URL") |
| 11 | |
| 12 | _URL_TEMPLATE = "https://static.rust-lang.org/dist/{iso_date}/{component}-nightly-{triple}.tar.xz" |
| 13 | |
| 14 | def _rustfmt_standalone_repository_impl(repository_ctx): |
| 15 | triple = repository_ctx.attr.triple |
| 16 | iso_date = repository_ctx.attr.iso_date |
| 17 | proxy = PROXY_URL |
| 18 | |
| 19 | # Download the rustfmt component (contains bin/rustfmt and bin/cargo-fmt). |
| 20 | rustfmt_url = proxy + _URL_TEMPLATE.format( |
| 21 | iso_date = iso_date, |
| 22 | component = "rustfmt", |
| 23 | triple = triple, |
| 24 | ) |
| 25 | repository_ctx.download_and_extract( |
| 26 | url = rustfmt_url, |
| 27 | sha256 = repository_ctx.attr.rustfmt_sha256, |
| 28 | stripPrefix = "rustfmt-nightly-{}/rustfmt-preview".format(triple), |
| 29 | ) |
| 30 | |
| 31 | # Download the rustc component (contains shared libraries that rustfmt |
| 32 | # dynamically links against, e.g. librustc_driver-*.so / .dylib). |
| 33 | rustc_url = proxy + _URL_TEMPLATE.format( |
| 34 | iso_date = iso_date, |
| 35 | component = "rustc", |
| 36 | triple = triple, |
| 37 | ) |
| 38 | repository_ctx.download_and_extract( |
| 39 | url = rustc_url, |
| 40 | sha256 = repository_ctx.attr.rustc_sha256, |
| 41 | stripPrefix = "rustc-nightly-{}/rustc".format(triple), |
| 42 | ) |
| 43 | |
| 44 | # Create a wrapper script that sets the library path so the dynamically-linked |
| 45 | # rustfmt binary can find its libraries. We embed absolute paths because the |
| 46 | # wrapper may be copied to bazel-bin by native_binary. |
| 47 | repo_dir = str(repository_ctx.path("")) |
| 48 | is_macos = "apple-darwin" in triple |
| 49 | if is_macos: |
| 50 | wrapper = """\ |
| 51 | #!/bin/bash |
| 52 | DYLD_LIBRARY_PATH="{lib_dir}:${{DYLD_LIBRARY_PATH:-}}" exec "{rustfmt_bin}" "$@" |
| 53 | """ |
| 54 | else: |
| 55 | wrapper = """\ |
| 56 | #!/bin/bash |
| 57 | LD_LIBRARY_PATH="{lib_dir}:${{LD_LIBRARY_PATH:-}}" exec "{rustfmt_bin}" "$@" |
| 58 | """ |
| 59 | repository_ctx.file("rustfmt", content = wrapper.format( |
| 60 | lib_dir = repo_dir + "/lib", |
| 61 | rustfmt_bin = repo_dir + "/bin/rustfmt", |
| 62 | ), executable = True) |
| 63 | |
| 64 | repository_ctx.file("BUILD.bazel", 'exports_files(["rustfmt"])\n') |
| 65 | |
| 66 | rustfmt_standalone_repository = repository_rule( |
| 67 | doc = "Downloads a standalone rustfmt binary and the rustc shared libraries it needs.", |
| 68 | attrs = { |
| 69 | "triple": attr.string(mandatory = True, doc = "Rust target triple, e.g. x86_64-unknown-linux-gnu"), |
| 70 | "iso_date": attr.string(mandatory = True, doc = "Nightly date, e.g. 2026-02-12"), |
| 71 | "rustfmt_sha256": attr.string(mandatory = True, doc = "SHA-256 of the rustfmt component tarball"), |
| 72 | "rustc_sha256": attr.string(mandatory = True, doc = "SHA-256 of the rustc component tarball"), |
| 73 | }, |
| 74 | implementation = _rustfmt_standalone_repository_impl, |
| 75 | ) |
| 76 | |
| 77 | # -- Module extension -- |
| 78 | |
| 79 | def _rustfmt_standalone_ext_impl(module_ctx): |
| 80 | for mod in module_ctx.modules: |
| 81 | for repo in mod.tags.repo: |
| 82 | rustfmt_standalone_repository( |
| 83 | name = repo.name, |
| 84 | triple = repo.triple, |
| 85 | iso_date = repo.iso_date, |
| 86 | rustfmt_sha256 = repo.rustfmt_sha256, |
| 87 | rustc_sha256 = repo.rustc_sha256, |
| 88 | ) |
| 89 | return module_ctx.extension_metadata( |
| 90 | root_module_direct_deps = "all", |
| 91 | root_module_direct_dev_deps = [], |
| 92 | ) |
| 93 | |
| 94 | _repo_tag = tag_class(attrs = { |
| 95 | "name": attr.string(mandatory = True), |
| 96 | "triple": attr.string(mandatory = True), |
| 97 | "iso_date": attr.string(mandatory = True), |
| 98 | "rustfmt_sha256": attr.string(mandatory = True), |
| 99 | "rustc_sha256": attr.string(mandatory = True), |
| 100 | }) |
| 101 | |
| 102 | rustfmt_standalone = module_extension( |
| 103 | implementation = _rustfmt_standalone_ext_impl, |
| 104 | tag_classes = {"repo": _repo_tag}, |
| 105 | ) |