On Wed, Feb 04, 2026 at 01:42:03PM +0100, kpcyrd wrote: > hello, Yo,
> I joined as co-maintainer for syft after the recent todo item[1] and
> modernized the PKGBUILD.
>
> Based on the repro-get package[2] (which did reproduce successfully) I've
> changed the syft build instructions to this:
>
> ```
> export CGO_CPPFLAGS="${CPPFLAGS}"
> export CGO_CFLAGS="${CFLAGS}"
> export CGO_CXXFLAGS="${CXXFLAGS}"
> export CGO_LDFLAGS="${LDFLAGS}"
> export CGO_REQUIRED="1"
>
> mkdir -p build
> go build \
> -o build/ \
> -buildmode=pie \
> -mod=readonly \
> -ldflags "-compressdwarf=false -linkmode=external -X
> main.version=${pkgver}" \
> ./...
> ```
>
> This did not reproduce in our verification system however:
>
> [SNIP]
>
> From what I understand both build IDs are hashes over other parts of the
> binary. Since they are the only difference though, the problem is likely in
> the debug symbols that get detached after the compile (and also after this
> hashing is done), but before diffoscope is executed on the final release
> artifact.
You've already figured out the issue but I'll explain it in detail for the
benefit of the list.
The issue here is that you didn't include `option=(!lto)` in the package file.
Go produces a BUILD_ID by hashing all the object files during building and
stamping them in the final build. This is reproducible for the Go compiler and
works just fine. However we are enabling the `cgo` compiler backend.
Go has two compilers and two linkers you can use and mix-match. The `go` backend
is a full Go compiler, and the `cgo` backend produces C code which calls `gcc`.
You then have the internal linker which is a Go program, and the external linker
which is the usual `ldd`.
The fundamental problem we have here is that we want `checksec` to pass with all
hardening options, which the Go compiler with the internal linker simply does
not do for us.
This means we are explicitly enabling `cgo` and the external linker to give all
Go binaries the hardening features we want in our distro. This makes building Go
complicated, because `cgo` is complicated.
The reason why `lto` needs to be disabled is because there is a `gcc` bug in the
LTO streamer backend where bare `#line` macros get prepended a temporary
directory which does not get stripped by the `prefix-strip` flag. I tried to
propose a patch to the go compiler, and to gcc, but all of this has stalled.
https://gcc.gnu.org/pipermail/gcc-patches/2024-March/647303.html
https://github.com/golang/go/pull/53528
I've spent several weekends working through all the this and I'm generally
unhappy about the state of things.
If we decide that we just follow the Go compiler and ignore `checksec`, all of
this would be a lot simpler for us. I'm also unsure how much all the binary
hardening options actually matter for the Go compiler considering we have a
GC-runtime in play here.
Note that the upstream does not give any reproducible builds guarantees for the
`cgo` compiler setup, so I assume something is going to regress in the future.
I have several patches in the Go compiler to resolve `cgo` issues already.
> Our guidelines for Go[3] mention the -trimpath option (which I forgot to
> add, but also wasn't necessary for repro-get), but since we have normalized
> paths in our build containers I'm not sure if the claim about Reproducible
> Builds applies to non-AUR packages?
Correct, I have been lazy and not updated the guidelines to remove this option.
I have largely been waiting for the Developer handbook before doing a refresh of
the package guidelines.
Note that including `-trimpath` also breaks debug packages for Go packages.
> [SNIP]
>
> Maybe we could have something like /etc/makepkg.conf.d/rust.conf but for Go?
Yes, I have been waiting on drop-in support for makepkg. Jelle started working
out something, and I think we need this for the ports RFC anyway. I have simply
not followed up on this.
I still don't think it would solve a lot as the interplay between `GOFLAGS` and
`go build` CLI flags do not play nicely with each other. So the packager would
need to understand the interplay here, sadly.
For the sake of progress; I plan on writing up a new revision of the Go package
guidelines into the new handbook. And then I'll get to the `go` makepkg
configurations at some point.
--
Morten Linderud
PGP: 9C02FF419FECBE16
signature.asc
Description: PGP signature
