blob: d21c77ad7344043fc3895b0330115272898103e0 [file] [log] [blame]
Tim Windelschmidt223609c2024-01-12 22:59:20 +01001From d20698e4802b801807d0474f1d1d003b13c78277 Mon Sep 17 00:00:00 2001
2From: Tim Windelschmidt <tim@monogon.tech>
3Date: Fri, 12 Jan 2024 15:44:41 +0100
4Subject: [PATCH] Improve reproducibility
5
Serge Bazanski4f00f902023-12-19 13:54:04 +01006Fixes a few issues with rules_rust/rustc reproducibility when the same code is
7being built in slightly different BuildConfigurations.
8
9Even if BuildConfigurations differ only by insignificant (to rules_rust)
10configuration flags, the resulting output directory will be different (keyed by
11an 'ST-hash' which is generated from the configuration).
12
13Unfortunately, rust/rules_rust really likes to embed bazel-out/<dir>/bin paths
14into the binaries by default, thus embedding the ST-hash, thus leading to
15different bit-for-bit binaries when built across two slightly different
16configs.
17
18We fix this by doing two changes:
19
20 1. We override the codegen metadata hash suffix to not depend on the ST-hash
21 directory name. Otherwise, built rlibs will have a numeric .XXX suffix that
22 changes depending on the ST-hash. We have to do this separately for prost
23 codegen, too.
24 2. We add a remap path option to rustc that replaces bazel-out/<dir>/bin/ with
25 bin/.
Tim Windelschmidt223609c2024-01-12 22:59:20 +010026---
27 proto/prost/private/prost.bzl | 4 +++-
28 proto/protobuf/proto.bzl | 2 +-
29 rust/private/clippy.bzl | 2 +-
30 rust/private/rust.bzl | 6 +++---
31 rust/private/rustc.bzl | 4 ++++
32 rust/private/utils.bzl | 7 +++++--
33 6 files changed, 17 insertions(+), 8 deletions(-)
Serge Bazanski4f00f902023-12-19 13:54:04 +010034
35diff --git a/proto/prost/private/prost.bzl b/proto/prost/private/prost.bzl
Tim Windelschmidt223609c2024-01-12 22:59:20 +010036index e3e5e382..b91123f3 100644
Serge Bazanski4f00f902023-12-19 13:54:04 +010037--- a/proto/prost/private/prost.bzl
38+++ b/proto/prost/private/prost.bzl
Tim Windelschmidt223609c2024-01-12 22:59:20 +010039@@ -125,7 +125,9 @@ def _compile_rust(ctx, attr, crate_name, src, deps, edition):
Serge Bazanski4f00f902023-12-19 13:54:04 +010040 A DepVariantInfo provider.
41 """
42 toolchain = ctx.toolchains["@rules_rust//rust:toolchain_type"]
43- output_hash = repr(hash(src.path + ".prost"))
44+ src_path = src.path.replace(ctx.bin_dir.path, 'bin')
45+ print(src.path, src_path)
46+ output_hash = repr(hash(src_path + ".prost"))
Tim Windelschmidt223609c2024-01-12 22:59:20 +010047
Serge Bazanski4f00f902023-12-19 13:54:04 +010048 lib_name = "{prefix}{name}-{lib_hash}{extension}".format(
49 prefix = "lib",
50diff --git a/proto/protobuf/proto.bzl b/proto/protobuf/proto.bzl
Tim Windelschmidt223609c2024-01-12 22:59:20 +010051index 7b254305..d61a1cbc 100644
Serge Bazanski4f00f902023-12-19 13:54:04 +010052--- a/proto/protobuf/proto.bzl
53+++ b/proto/protobuf/proto.bzl
Tim Windelschmidt223609c2024-01-12 22:59:20 +010054@@ -187,7 +187,7 @@ def _rust_proto_compile(protos, descriptor_sets, imports, crate_name, ctx, is_gr
Serge Bazanski4f00f902023-12-19 13:54:04 +010055 srcs.append(lib_rs)
Tim Windelschmidt223609c2024-01-12 22:59:20 +010056
Serge Bazanski4f00f902023-12-19 13:54:04 +010057 # And simulate rust_library behavior
58- output_hash = determine_output_hash(lib_rs, ctx.label)
59+ output_hash = determine_output_hash(ctx.bin_dir, lib_rs, ctx.label)
60 rust_lib = ctx.actions.declare_file("%s/lib%s-%s.rlib" % (
61 output_dir,
62 crate_name,
63diff --git a/rust/private/clippy.bzl b/rust/private/clippy.bzl
Tim Windelschmidt223609c2024-01-12 22:59:20 +010064index 9fd9842c..54a0547c 100644
Serge Bazanski4f00f902023-12-19 13:54:04 +010065--- a/rust/private/clippy.bzl
66+++ b/rust/private/clippy.bzl
67@@ -120,7 +120,7 @@ def _clippy_aspect_impl(target, ctx):
68 dep_info = dep_info,
69 linkstamp_outs = linkstamp_outs,
70 ambiguous_libs = ambiguous_libs,
71- output_hash = determine_output_hash(crate_info.root, ctx.label),
72+ output_hash = determine_output_hash(ctx.bin_dir, crate_info.root, ctx.label),
73 rust_flags = [],
74 out_dir = out_dir,
75 build_env_files = build_env_files,
76diff --git a/rust/private/rust.bzl b/rust/private/rust.bzl
Tim Windelschmidt223609c2024-01-12 22:59:20 +010077index 7727febb..217f1059 100644
Serge Bazanski4f00f902023-12-19 13:54:04 +010078--- a/rust/private/rust.bzl
79+++ b/rust/private/rust.bzl
Tim Windelschmidt223609c2024-01-12 22:59:20 +010080@@ -159,7 +159,7 @@ def _rust_library_common(ctx, crate_type):
Serge Bazanski4f00f902023-12-19 13:54:04 +010081 if crate_type in ["cdylib", "staticlib"]:
82 output_hash = None
83 else:
84- output_hash = determine_output_hash(crate_root, ctx.label)
85+ output_hash = determine_output_hash(ctx.bin_dir, crate_root, ctx.label)
Tim Windelschmidt223609c2024-01-12 22:59:20 +010086
87 rust_lib_name = determine_lib_name(
88 crate_name,
89@@ -310,7 +310,7 @@ def _rust_test_impl(ctx):
Serge Bazanski4f00f902023-12-19 13:54:04 +010090 # Target is building the crate in `test` config
91 crate = ctx.attr.crate[rust_common.crate_info] if rust_common.crate_info in ctx.attr.crate else ctx.attr.crate[rust_common.test_crate_info].crate
Tim Windelschmidt223609c2024-01-12 22:59:20 +010092
Serge Bazanski4f00f902023-12-19 13:54:04 +010093- output_hash = determine_output_hash(crate.root, ctx.label)
94+ output_hash = determine_output_hash(ctx.bin_dir, crate.root, ctx.label)
95 output = ctx.actions.declare_file(
96 "test-%s/%s%s" % (
97 output_hash,
Tim Windelschmidt223609c2024-01-12 22:59:20 +010098@@ -369,7 +369,7 @@ def _rust_test_impl(ctx):
Serge Bazanski4f00f902023-12-19 13:54:04 +010099 crate_root = crate_root_src(ctx.attr.name, ctx.files.srcs, crate_root_type)
Tim Windelschmidt223609c2024-01-12 22:59:20 +0100100 srcs, crate_root = transform_sources(ctx, ctx.files.srcs, crate_root)
101
Serge Bazanski4f00f902023-12-19 13:54:04 +0100102- output_hash = determine_output_hash(crate_root, ctx.label)
103+ output_hash = determine_output_hash(ctx.bin_dir, crate_root, ctx.label)
104 output = ctx.actions.declare_file(
105 "test-%s/%s%s" % (
106 output_hash,
107diff --git a/rust/private/rustc.bzl b/rust/private/rustc.bzl
Tim Windelschmidt223609c2024-01-12 22:59:20 +0100108index ef3479e5..06c94574 100644
Serge Bazanski4f00f902023-12-19 13:54:04 +0100109--- a/rust/private/rustc.bzl
110+++ b/rust/private/rustc.bzl
Tim Windelschmidt223609c2024-01-12 22:59:20 +0100111@@ -966,6 +966,10 @@ def construct_arguments(
Serge Bazanski4f00f902023-12-19 13:54:04 +0100112 if remap_path_prefix != None:
113 rustc_flags.add("--remap-path-prefix=${{pwd}}={}".format(remap_path_prefix))
Tim Windelschmidt223609c2024-01-12 22:59:20 +0100114
Serge Bazanski4f00f902023-12-19 13:54:04 +0100115+ # Replace unstable bindir path (based on ST-hash which is in turn based on
116+ # build configuration) with a stable bin/ path.
117+ rustc_flags.add("--remap-path-prefix={}=bin".format(ctx.bin_dir.path))
118+
119 if emit:
120 rustc_flags.add_joined(emit_with_paths, format_joined = "--emit=%s", join_with = ",")
121 if error_format != "json":
122diff --git a/rust/private/utils.bzl b/rust/private/utils.bzl
Tim Windelschmidt223609c2024-01-12 22:59:20 +0100123index 4e9b4b79..82317359 100644
Serge Bazanski4f00f902023-12-19 13:54:04 +0100124--- a/rust/private/utils.bzl
125+++ b/rust/private/utils.bzl
Tim Windelschmidt223609c2024-01-12 22:59:20 +0100126@@ -182,7 +182,7 @@ def abs(value):
Serge Bazanski4f00f902023-12-19 13:54:04 +0100127 return -value
128 return value
Tim Windelschmidt223609c2024-01-12 22:59:20 +0100129
Serge Bazanski4f00f902023-12-19 13:54:04 +0100130-def determine_output_hash(crate_root, label):
131+def determine_output_hash(bin_dir, crate_root, label):
132 """Generates a hash of the crate root file's path.
Tim Windelschmidt223609c2024-01-12 22:59:20 +0100133
Serge Bazanski4f00f902023-12-19 13:54:04 +0100134 Args:
Tim Windelschmidt223609c2024-01-12 22:59:20 +0100135@@ -193,8 +193,11 @@ def determine_output_hash(crate_root, label):
Serge Bazanski4f00f902023-12-19 13:54:04 +0100136 str: A string representation of the hash.
137 """
Tim Windelschmidt223609c2024-01-12 22:59:20 +0100138
Serge Bazanski4f00f902023-12-19 13:54:04 +0100139+ # Remove any unstable BuildConfiguration derived dir fragments to unify
140+ # hashes between different configs.
141+ crate_root_path = crate_root.path.replace(bin_dir.path, 'bin')
142 # Take the absolute value of hash() since it could be negative.
143- h = abs(hash(crate_root.path) + hash(repr(label)))
144+ h = abs(hash(crate_root_path) + hash(repr(label)))
145 return repr(h)
Tim Windelschmidt223609c2024-01-12 22:59:20 +0100146
Serge Bazanski4f00f902023-12-19 13:54:04 +0100147 def get_preferred_artifact(library_to_link, use_pic):
Tim Windelschmidt223609c2024-01-12 22:59:20 +0100148--
1492.42.0
150