Is GOFLAGS respected when building via build.go?

Trying to make the syncthing package on Arch Linux reproducible.

I’m trying to figure why the build id is still random even with -buildid= in the ldflags.

Here is the relevant snippet:

export GOFLAGS="-buildmode=pie -trimpath '-ldflags=-linkmode=external -buildid=' -mod=readonly -modcacherw"
go run build.go -no-upgrade -version v${pkgver} build
go run build.go -no-upgrade -version v${pkgver} build strelaysrv
go run build.go -no-upgrade -version v${pkgver} build stdiscosrv

I don’t see why this wouldn’t work, except maybe if GOFLAGS or the ldflags within aren’t respected.

So, is the GOFLAGS environment variable respected when building (through build.go)?

Might be related

Only seems to be related in the way that both are trying to get reproducible builds.

I know why it’s not reproducible. It’s because of the build ID that the Go linker adds. I figured that out from diffoscope.

So I attempted to set -buildid= in ldflags in GOFLAGS to set the build ID to a blank string to improve reproducibility, but the thing is, it’s still using a random build ID that’s different on every build.

Using EXTRA_LDFLAGS instead of GOFLAGS seems to have gotten rid of the Go build ID or at least have made it reproducible.

1 Like

Did you also have to set SOURCE_DATE_EPOCH?

I wonder if I had this added for nothing as already found a fallback mechanism to determine from git state in build.go?

@marbens Thanks for the tip! :slight_smile: . I’ve found that also made the “libsyncthingnative.so” builds reproducible so F-Droid is happy.

export "EXTRA_LDFLAGS=-buildid="

ref: build-syncthing.py: Remove GO BUILDID (fixes #1383) · Catfriend1/syncthing-android@64986fe · GitHub

Not manually, because makerepropkg sets it for me. But the timestamps would be different if it wasn’t set, so yes.

1 Like

My impression is that buildid should be entirely deterministic and hence reproducible by default…

I don’t see why blanking the build ID helped out Catfriend1, but in my case it was just a red herring/domino effect. It was the unique temporary file paths created by Go that were stored in syncthing.debug that were the problem.

You might think what I’m saying conflicts with this:

But “it” here means the build ID, not the entire build.

Here is the relevant diffoscope output of comparing the build in extra-debug to a build I made myself:

│ │ │  String dump of section '.debug_line_str':
│ │ │ -  [     0]  ../../../../../../../tmp/go-build2698637364/b060
│ │ │ -  [    31]  ../../../../../../../tmp/go-build2698637364/b105
│ │ │ +  [     0]  ../../../../../../../tmp/go-build3466362441/b060
│ │ │ +  [    31]  ../../../../../../../tmp/go-build3466362441/b105

The go-build2698637364 folder name part is not reproducible.

I saw a change in the .gnu_debuglink in the non-debug package, and at first I thought it was another copy of the build ID was in there, but no, it was a CRC of the syncthing.debug file. See also loqs’ comment.

A workaround to make the entire build reproducible is to add to -s -buildid= to the ldflags, but that has the disadvantage of rendering the debug (syncthing-debug) package useless.