-
Notifications
You must be signed in to change notification settings - Fork 18k
cmd/go: Build information embedded by Go 1.18 impairs build reproducibility with cgo flags #52372
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
what was the env / command used to build the binary? |
This is roughly the command (split into multiple lines):
Regarding |
Minimal example:
|
I don't think it would make sense to modify CGO flags before storing them since the toolchain would end up storing an incorrect representation of the build. It would be better to avoid storing the flags altogether. Making reproducible binaries with CGO is fundamentally tricky/fraught, but there are some some existing workarounds:
Potential toolchain modifications:
Both (4) and (5) risk disappointing users since some things are outside the control of the toolchain and it may not be possible to reproduce the original build. Fundamentally, builds using CGO will require the same or a very similar environment to reproduce binaries (library versions, build options,...). This effectively requires (1) to guarantee reproducibility with CGO, or (3) to remove CGO from the equation. Perhaps the best option is for users desiring reproducible builds to use Reproducible builds are hard but desirable. Perhaps the answer is documentation? It would help if the project maintained docs higlhighting best practices. |
AFAIK our (OpenWrt) CGO binaries had been reproducible before 1.18.
This only removes VCS information, not build information. (See #50501 for some background.)
As it stands currently, using |
Yes, I was referring to reproducible builds in general - there are many things that can break them. Reproducible builds are possible, but environments need to be tightly controlled (I agree this is now harder than before). For reference, Restic is an example of a project that provides specific instructions on how to reproduce their builds (including specific paths). It would be useful for the toolchain to make this easier where reasonably practical. I expect this will be a somewhat never-ending process with the inherent complexity in C/C++ environments (beyond the regression here).
If CGO is disabled the
Ah, thanks. I misremembered about |
That is essentially what Perhaps we can do something more nuanced in the future — like stamping only the non-path portions of those flags — but that would require that we know exactly which flags may contain paths. (And that seems like a whole can of worms!) The point of stamping the cgo settings is to allow someone with a cgo-enabled binary to reproduce the build, but that's already not the case to begin with: we don't record the C compiler version, and we also don't stamp the versions of the headers in the user's C |
@gopherbot, please backport to Go 1.18. This is an unexpected side-effect of a change in Go 1.18, and interferes with build reproducibility. |
Backport issue(s) opened: #53119 (for 1.18). Remember to create the cherry-pick CL(s) as soon as the patch is submitted to master, according to https://go.dev/wiki/MinorReleases. |
Change https://go.dev/cl/409174 mentions this issue: |
Minimal example with
|
Change https://go.dev/cl/414794 mentions this issue: |
…system paths when -trimpath is set CGO flag variables often include system paths for header files and compiled libraries. The point of -trimpath is to avoid dependending on system paths, so stamping these variables is counterproductive. Moreover, the point of stamping build information is to improve reproducibility. Since we don't also stamp the versions of C compilers, headers, and libraries used in a cgo build, only the most trivial cgo programs can be faithfully reproduced from the stamped information. Likewise, the -ldflags flag may include system-specific paths, particularly if external linking is in use. For now, we omit -ldflags entirely; however, in the future we may instead want to parse and redact the individual flags. Updates #52372. Fixes #53119. Change-Id: I73318a01cce4371d66955b3261fc7ee58d4b33dd Reviewed-on: https://go-review.googlesource.com/c/go/+/409174 TryBot-Result: Gopher Robot <[email protected]> Auto-Submit: Bryan Mills <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]> Run-TryBot: Bryan Mills <[email protected]> (cherry picked from commit a6e5be0) Reviewed-on: https://go-review.googlesource.com/c/go/+/414794 Reviewed-by: Nooras Saba <[email protected]>
…ath is set CGO flag variables often include system paths for header files and compiled libraries. The point of -trimpath is to avoid dependending on system paths, so stamping these variables is counterproductive. Moreover, the point of stamping build information is to improve reproducibility. Since we don't also stamp the versions of C compilers, headers, and libraries used in a cgo build, only the most trivial cgo programs can be faithfully reproduced from the stamped information. Likewise, the -ldflags flag may include system-specific paths, particularly if external linking is in use. For now, we omit -ldflags entirely; however, in the future we may instead want to parse and redact the individual flags. Fixes golang#52372. Change-Id: I73318a01cce4371d66955b3261fc7ee58d4b33dd Reviewed-on: https://go-review.googlesource.com/c/go/+/409174 TryBot-Result: Gopher Robot <[email protected]> Auto-Submit: Bryan Mills <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]> Run-TryBot: Bryan Mills <[email protected]>
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
Yes
What operating system and processor architecture are you using (
go env
)?Not relevant
What did you do?
Reproducible builds is something OpenWrt, and many other Linux distributions, would like to achieve. We use
-trimpath
to remove build host-specific paths from binaries built by Go.We also set
-I
options inCGO_CPPFLAGS
, and-L
options in-ldflags
(passed to-extldflags
) andCGO_LDFLAGS
.What did you expect to see?
A way to either sanitize the embedded build information or omit it entirely.
What did you see instead?
There are build host-specific paths in
CGO_CPPFLAGS
(the-I
options),-ldflags
andCGO_LDFLAGS
(the-L
options). There is also a build host-specific path as part of-ffile-prefix-map
inCGO_CFLAGS
andCGO_CXXFLAGS
(I believe this is set as a result of.-trimpath
)go version -m
OutputThe text was updated successfully, but these errors were encountered: