| From 544ee8b571a006a8e03eb4401f6644bb8bf6628f Mon Sep 17 00:00:00 2001 |
| From: Serge Bazanski <serge@monogon.tech> |
| Date: Wed, 25 Sep 2024 02:38:50 +0200 |
| Subject: [PATCH] Improve reproducibility |
| |
| Fixes a few issues with rules_rust/rustc reproducibility when the same code is |
| being built in slightly different BuildConfigurations. |
| |
| Even if BuildConfigurations differ only by insignificant (to rules_rust) |
| configuration flags, the resulting output directory will be different (keyed by |
| an 'ST-hash' which is generated from the configuration). |
| |
| Unfortunately, rust/rules_rust really likes to embed bazel-out/<dir>/bin paths |
| into the binaries by default, thus embedding the ST-hash, thus leading to |
| different bit-for-bit binaries when built across two slightly different |
| configs. |
| |
| We fix this by doing two changes: |
| |
| 1. We override the codegen metadata hash suffix to not depend on the ST-hash |
| directory name. Otherwise, built rlibs will have a numeric .XXX suffix that |
| changes depending on the ST-hash. We have to do this separately for prost |
| codegen, too. |
| 2. We add a remap path option to rustc that replaces bazel-out/<dir>/bin/ with |
| bin/. |
| --- |
| proto/prost/private/prost.bzl | 3 ++- |
| proto/protobuf/proto.bzl | 2 +- |
| rust/private/clippy.bzl | 2 +- |
| rust/private/rust.bzl | 6 +++--- |
| rust/private/rustc.bzl | 4 ++++ |
| rust/private/utils.bzl | 7 +++++-- |
| 6 files changed, 16 insertions(+), 8 deletions(-) |
| |
| diff --git a/proto/prost/private/prost.bzl b/proto/prost/private/prost.bzl |
| index 20814500..45b283d9 100644 |
| --- a/proto/prost/private/prost.bzl |
| +++ b/proto/prost/private/prost.bzl |
| @@ -132,7 +132,8 @@ def _compile_rust(ctx, attr, crate_name, src, deps, edition): |
| A DepVariantInfo provider. |
| """ |
| toolchain = ctx.toolchains["@rules_rust//rust:toolchain_type"] |
| - output_hash = repr(hash(src.path + ".prost")) |
| + src_path = src.path.replace(ctx.bin_dir.path, 'bin') |
| + output_hash = repr(hash(src_path + ".prost")) |
| |
| lib_name = "{prefix}{name}-{lib_hash}{extension}".format( |
| prefix = "lib", |
| diff --git a/proto/protobuf/proto.bzl b/proto/protobuf/proto.bzl |
| index 959d0c1c..00dff5d0 100644 |
| --- a/proto/protobuf/proto.bzl |
| +++ b/proto/protobuf/proto.bzl |
| @@ -187,7 +187,7 @@ def _rust_proto_compile(protos, descriptor_sets, imports, crate_name, ctx, is_gr |
| srcs.append(lib_rs) |
| |
| # And simulate rust_library behavior |
| - output_hash = determine_output_hash(lib_rs, ctx.label) |
| + output_hash = determine_output_hash(ctx.bin_dir, lib_rs, ctx.label) |
| rust_lib = ctx.actions.declare_file("%s/lib%s-%s.rlib" % ( |
| output_dir, |
| crate_name, |
| diff --git a/rust/private/clippy.bzl b/rust/private/clippy.bzl |
| index 748f33a0..772b39ad 100644 |
| --- a/rust/private/clippy.bzl |
| +++ b/rust/private/clippy.bzl |
| @@ -131,7 +131,7 @@ def _clippy_aspect_impl(target, ctx): |
| dep_info = dep_info, |
| linkstamp_outs = linkstamp_outs, |
| ambiguous_libs = ambiguous_libs, |
| - output_hash = determine_output_hash(crate_info.root, ctx.label), |
| + output_hash = determine_output_hash(ctx.bin_dir, crate_info.root, ctx.label), |
| rust_flags = [], |
| out_dir = out_dir, |
| build_env_files = build_env_files, |
| diff --git a/rust/private/rust.bzl b/rust/private/rust.bzl |
| index 21881729..24792e99 100644 |
| --- a/rust/private/rust.bzl |
| +++ b/rust/private/rust.bzl |
| @@ -159,7 +159,7 @@ def _rust_library_common(ctx, crate_type): |
| if crate_type in ["cdylib", "staticlib"]: |
| output_hash = None |
| else: |
| - output_hash = determine_output_hash(crate_root, ctx.label) |
| + output_hash = determine_output_hash(ctx.bin_dir, crate_root, ctx.label) |
| |
| rust_lib_name = determine_lib_name( |
| crate_name, |
| @@ -316,7 +316,7 @@ def _rust_test_impl(ctx): |
| ) |
| else: |
| crate_name = crate.name |
| - output_hash = determine_output_hash(crate.root, ctx.label) |
| + output_hash = determine_output_hash(ctx.bin_dir, crate.root, ctx.label) |
| output = ctx.actions.declare_file( |
| "test-%s/%s%s" % ( |
| output_hash, |
| @@ -380,7 +380,7 @@ def _rust_test_impl(ctx): |
| ctx.label.name + toolchain.binary_ext, |
| ) |
| else: |
| - output_hash = determine_output_hash(crate_root, ctx.label) |
| + output_hash = determine_output_hash(ctx.bin_dir, crate_root, ctx.label) |
| output = ctx.actions.declare_file( |
| "test-%s/%s%s" % ( |
| output_hash, |
| diff --git a/rust/private/rustc.bzl b/rust/private/rustc.bzl |
| index c82c236b..576de4e3 100644 |
| --- a/rust/private/rustc.bzl |
| +++ b/rust/private/rustc.bzl |
| @@ -973,6 +973,10 @@ def construct_arguments( |
| if remap_path_prefix != None: |
| rustc_flags.add("--remap-path-prefix=${{pwd}}={}".format(remap_path_prefix)) |
| |
| + # Replace unstable bindir path (based on ST-hash which is in turn based on |
| + # build configuration) with a stable bin/ path. |
| + rustc_flags.add("--remap-path-prefix={}=bin".format(ctx.bin_dir.path)) |
| + |
| emit_without_paths = [] |
| for kind in emit: |
| if kind == "link" and crate_info.type == "bin" and crate_info.output != None: |
| diff --git a/rust/private/utils.bzl b/rust/private/utils.bzl |
| index a0fda352..ff45a149 100644 |
| --- a/rust/private/utils.bzl |
| +++ b/rust/private/utils.bzl |
| @@ -188,7 +188,7 @@ def abs(value): |
| return -value |
| return value |
| |
| -def determine_output_hash(crate_root, label): |
| +def determine_output_hash(bin_dir, crate_root, label): |
| """Generates a hash of the crate root file's path. |
| |
| Args: |
| @@ -199,8 +199,11 @@ def determine_output_hash(crate_root, label): |
| str: A string representation of the hash. |
| """ |
| |
| + # Remove any unstable BuildConfiguration derived dir fragments to unify |
| + # hashes between different configs. |
| + crate_root_path = crate_root.path.replace(bin_dir.path, 'bin') |
| # Take the absolute value of hash() since it could be negative. |
| - h = abs(hash(crate_root.path) + hash(repr(label))) |
| + h = abs(hash(crate_root_path) + hash(repr(label))) |
| return repr(h) |
| |
| def get_preferred_artifact(library_to_link, use_pic): |
| -- |
| 2.44.1 |
| |