| Fetch rustc the way buck can ship it, from what DotSlash already pins 8cf1b33 nandi 19d ago | 1 | # A Rust toolchain whose compiler is a dependency rather than a name. |
| 2 | # |
| 3 | # The prelude's system_rust_toolchain hands RustToolchainInfo |
| 4 | # `RunInfo(args = ["rustc"])` — a bare string. Nothing about the compiler is an |
| 5 | # input to any action, so nothing about it reaches the action's cache digest, |
| 6 | # and there is nothing for a remote worker to materialise. Both of this repo's |
| 7 | # problems come from that one line: a shared cache cannot tell two compilers |
| 8 | # apart, and remote execution has no compiler to run. |
| 9 | # |
| 10 | # Here the dist tarball is a dep. cmd_args carries the archive's directory into |
| 11 | # every rustc invocation, so buck knows the action depends on it. |
| 12 | load("@prelude//rust:rust_toolchain.bzl", "PanicRuntime", "RustToolchainInfo") |
| 13 | |
| 14 | def _hermetic_rust_toolchain_impl(ctx): |
| 15 | dist = ctx.attrs.dist[DefaultInfo].default_outputs[0] |
| 16 | |
| 17 | # The dist tarball keeps its components in sibling directories, so the |
| 18 | # compiler's default sysroot (rustc/) holds no libstd — it lives under |
| 19 | # rust-std-<triple>/. The same stitching scripts/rustc does by hand, said |
| 20 | # to buck instead. The compiler's own codegen libraries are found by rpath, |
| 21 | # relative to the binary, so only the sysroot has to be named. |
| 22 | # rustc goes through a wrapper because the sysroot cannot travel any other |
| 23 | # way: rustc_flags takes plain strings, so an artifact path cannot be put |
| 24 | # there, and putting --sysroot on the compiler unconditionally breaks |
| 25 | # buck's own rustc_cfg action, which passes an empty one. Both the wrapper |
| 26 | # and the tarball are inputs, which is the point. |
| 27 | wrapper = ctx.attrs.wrapper[DefaultInfo].default_outputs[0] |
| 28 | compiler = cmd_args(wrapper, dist, ctx.attrs.rustc_target_triple) |
| 29 | rustdoc = cmd_args(dist, format = "{}/rustc/bin/rustdoc") |
| 30 | |
| 31 | return [ |
| 32 | DefaultInfo(), |
| 33 | RustToolchainInfo( |
| 34 | allow_lints = ctx.attrs.allow_lints, |
| 35 | clippy_driver = RunInfo(args = cmd_args(dist, format = "{}/clippy/bin/clippy-driver")), |
| 36 | clippy_toml = None, |
| 37 | compiler = RunInfo(args = compiler), |
| 38 | default_edition = ctx.attrs.default_edition, |
| 39 | panic_runtime = PanicRuntime("unwind"), |
| 40 | deny_lints = ctx.attrs.deny_lints, |
| 41 | doctests = ctx.attrs.doctests, |
| 42 | nightly_features = ctx.attrs.nightly_features, |
| 43 | report_unused_deps = ctx.attrs.report_unused_deps, |
| 44 | rustc_binary_flags = ctx.attrs.rustc_binary_flags, |
| 45 | rustc_flags = ctx.attrs.rustc_flags, |
| 46 | rustc_target_triple = ctx.attrs.rustc_target_triple, |
| 47 | rustc_test_flags = ctx.attrs.rustc_test_flags, |
| 48 | rustdoc = RunInfo(args = rustdoc), |
| 49 | rustdoc_flags = ctx.attrs.rustdoc_flags, |
| 50 | warn_lints = ctx.attrs.warn_lints, |
| 51 | ), |
| 52 | ] |
| 53 | |
| 54 | hermetic_rust_toolchain = rule( |
| 55 | impl = _hermetic_rust_toolchain_impl, |
| 56 | attrs = { |
| 57 | "allow_lints": attrs.list(attrs.string(), default = []), |
| 58 | "default_edition": attrs.option(attrs.string(), default = None), |
| 59 | "deny_lints": attrs.list(attrs.string(), default = []), |
| 60 | "dist": attrs.dep(providers = [DefaultInfo]), |
| 61 | "wrapper": attrs.dep(providers = [DefaultInfo]), |
| 62 | "doctests": attrs.bool(default = False), |
| 63 | "nightly_features": attrs.bool(default = True), |
| 64 | "report_unused_deps": attrs.bool(default = False), |
| 65 | "rustc_binary_flags": attrs.list(attrs.arg(), default = []), |
| 66 | "rustc_flags": attrs.list(attrs.arg(), default = []), |
| 67 | "rustc_target_triple": attrs.string(), |
| 68 | "rustc_test_flags": attrs.list(attrs.arg(), default = []), |
| 69 | "rustdoc_flags": attrs.list(attrs.arg(), default = []), |
| 70 | "warn_lints": attrs.list(attrs.string(), default = []), |
| 71 | }, |
| 72 | is_toolchain_rule = True, |
| 73 | ) |