Skip to content

cmd/loopvec-toolexec: give the same archive on every build - #15

Merged
thesyncim merged 4 commits into
masterfrom
toolexec-reproducible
Nov 1, 2026
Merged

thesyncim merged 4 commits into
masterfrom
toolexec-reproducible

Conversation

@thesyncim

@thesyncim thesyncim commented Oct 31, 2026 •

Copy link
Copy Markdown
Owner

Stacked on #4.

The wrapper wrote rewritten files to a fresh os.MkdirTemp directory under the go command's work directory. File names end up in the export data, and the go command only trims each compile's own object directory. So every build of a rewritten package gave a different archive, with a random absolute path in it.

That breaks builds where the go command compiles one package twice with the same inputs. With PGO, go test can compile a dependency once per test binary, then compile an importer against one copy and link the other. In goav1, whose cmd/qualitybench has a default.pgo, go test ./... failed with master's wrapper:

link: fingerprint mismatch: github.com/thesyncim/goav1 has 9bcecb47ca806e38, import from github.com/thesyncim/goav1/cmd/qualitybench expecting 224b81cee36e8b4e

The rewritten files now go in loopvec/ inside the object directory, next to the importcfg the go command writes there. That's still a separate place for each compile, and the -trimpath "$WORK/bNNN=>" that the go command always passes reduces it to loopvec/x.go. After this, the two archives in that build have the same content ID, and the test binary links.

toolexec_reproducible.txt builds a package with two empty caches and compares the archives. It fails without the change. -trimpath builds were already fine.

ubuntu-latest is now ubuntu-26.04, which has no qemu-user-static
package, so every run fails at the install step and skips the arm64
tsvc run, the golden check, fmt and lint. qemu-user ships the static
emulators there; link qemu-aarch64-static to it when the name is
missing, as the Makefile runs that name.
Go tip writes export data in iexport version 4, which encodes float
constants exactly. x/tools v0.51.0, and the v0.52.0 release, read only
up to version 3, so on tip go/packages fails for every package:

  cannot import "math" (unstable iexport format version 4, just rebuild
  compiler and std library), export data is newer version - update tool

and every script that runs loopvec fails in the tip job. x/tools master
reads version 4 (golang/tools@966056e2637c). Update to it until a release
includes it. The pinned toolchain is unaffected.
go1.27.3 is the latest 1.27 release. Its simd package is the same as
go1.27.1's, so the capability table only changes in its header, and
the -methods crash (golang/go#80657) is still there, as
flag_methods_ice.txt checks. go.mod keeps go 1.27.1: that is the first
release whose simd package loopvec's output compiles against
(go1.27.0's ShiftAllRight takes a uint8).
The wrapper wrote the rewritten files to a new os.MkdirTemp directory
under the go command's work directory. The compiler records file names
in the export data, and the go command trims only the compile's own
object directory, so every build of a rewritten package produced a
different archive, with a random absolute path in it.

That fails builds where the go command compiles a package twice with
the same inputs. With PGO, go test can compile a dependency once for
each test binary that needs it, then compile an importer against one
copy and link the other. In github.com/thesyncim/goav1, whose
cmd/qualitybench has a default.pgo, go test ./... fails with:

  link: fingerprint mismatch: github.com/thesyncim/goav1 has
  9bcecb47ca806e38, import from github.com/thesyncim/goav1/cmd/qualitybench
  expecting 224b81cee36e8b4e

The rewritten files now go in a loopvec directory inside the object
directory, next to the importcfg the go command writes there. That is
still a separate place for each compile, and the -trimpath the go
command passes reduces it to loopvec/x.go.
@thesyncim
thesyncim merged commit 53d9dee into master Nov 1, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant