From ca19a4e555487380b8a885c84e8133b7cfcf659b Mon Sep 17 00:00:00 2001 From: Travis Downs Date: Thu, 14 May 2026 18:53:25 -0400 Subject: [PATCH] bazel/avro: make avrogen header include guard deterministic The generated header's include guard was suffixed with the output of a `boost::mt19937` seeded from `::time(nullptr)` (`avrogencpp.cc:796`), producing a different guard on every avrogen invocation: #ifndef BAZEL_OUT_..._MANIFEST_FILE_AVROGEN_H_3350718792_H #ifndef BAZEL_OUT_..._MANIFEST_FILE_AVROGEN_H_2362587291_H That made every consumer of the generated header (e.g. manifest_list_avro.cc) see a different input digest on each build, so bazel's remote cache was broken for the entire downstream dependency chain even on byte-identical schemas. `headerFile_` is already a unique-per-output path; dropping the random suffix leaves a stable, still-unique guard. Identified via two-output-base hermetic builds of `//tools:redpanda_package_for_pgo` as one of the two roots that infect that target. Tracks CORE-16317. --- MODULE.bazel.lock | 5 ++-- bazel/repositories.bzl | 1 + .../avrogen-stable-include-guard.patch | 28 +++++++++++++++++++ 3 files changed, 32 insertions(+), 2 deletions(-) create mode 100644 bazel/thirdparty/avrogen-stable-include-guard.patch diff --git a/MODULE.bazel.lock b/MODULE.bazel.lock index 19eb08dcf8d39..a9373b65b1cec 100644 --- a/MODULE.bazel.lock +++ b/MODULE.bazel.lock @@ -352,7 +352,7 @@ "moduleExtensions": { "//bazel:extensions.bzl%non_module_dependencies": { "general": { - "bzlTransitiveDigest": "yZROfZgIs0LcoLF6ANflyVgdZWDFiY86XvceRey/k1U=", + "bzlTransitiveDigest": "sEIE/cj3N8I1IHROjK3AdXZTTBeDOkBtEX1mgrcGJas=", "usagesDigest": "FEiDyZe9eAU6yEqnarZf0XMEUk+prUyYClvq1RU1J98=", "recordedInputs": [ "REPO_MAPPING:,bazel_tools bazel_tools" @@ -375,7 +375,8 @@ "url": "https://github.com/redpanda-data/avro/archive/46fe1e36f680d75219cba46368de38321f1810ed.tar.gz", "patches": [ "@@//bazel/thirdparty:avro-snappy-includes.patch", - "@@//bazel/thirdparty:avro-fmt-const.patch" + "@@//bazel/thirdparty:avro-fmt-const.patch", + "@@//bazel/thirdparty:avrogen-stable-include-guard.patch" ], "patch_args": [ "-p1" diff --git a/bazel/repositories.bzl b/bazel/repositories.bzl index 5688007aaa6da..a3677afe5cf04 100644 --- a/bazel/repositories.bzl +++ b/bazel/repositories.bzl @@ -28,6 +28,7 @@ def data_dependency(): patches = [ "//bazel/thirdparty:avro-snappy-includes.patch", "//bazel/thirdparty:avro-fmt-const.patch", + "//bazel/thirdparty:avrogen-stable-include-guard.patch", ], patch_args = ["-p1"], ) diff --git a/bazel/thirdparty/avrogen-stable-include-guard.patch b/bazel/thirdparty/avrogen-stable-include-guard.patch new file mode 100644 index 0000000000000..1fa74b4b1f35f --- /dev/null +++ b/bazel/thirdparty/avrogen-stable-include-guard.patch @@ -0,0 +1,28 @@ +From: Travis Downs +Subject: [PATCH] avrogencpp: use deterministic include guard + +The generated header's include guard was suffixed with the output of a +`boost::mt19937` seeded from `::time(nullptr)`, which produced a different +guard on every avrogen invocation. That made every consumer of the generated +header (e.g. `manifest_list_avro.cc`) see a different input digest on each +build, breaking Bazel's remote cache for the entire dependency chain even +on byte-identical schemas. + +`headerFile_` is already a unique-per-output path; `makeCanonical(h, true)` +canonicalizes it into a valid identifier ending in `_H` (from the `.h` +extension). Dropping the random number leaves a stable, still-unique guard. + +Tracks CORE-16317. + +diff --git a/lang/c++/impl/avrogencpp.cc b/lang/c++/impl/avrogencpp.cc +--- a/lang/c++/impl/avrogencpp.cc ++++ b/lang/c++/impl/avrogencpp.cc +@@ -793,7 +793,7 @@ + string CodeGen::guard() { + string h = headerFile_; + makeCanonical(h, true); +- return h + "_" + lexical_cast(random_()) + "_H"; ++ return h + "_H"; + } + + void CodeGen::generate(const ValidSchema &schema) {