Hello Morten On Sun, Mar 15, 2020 at 5:38 AM Morten Linderud via arch-dev-public <arch-dev-public@archlinux.org> wrote:
# Introduction
To enable PIE compilation, we have relied on a patched version of the go compiler which has been distributed as `go-pie` since around 2017. However, full RELRO support for go binaries has been a bit back and forth the past years. With some thing working, and other things don't.
With the release of Go 1.11 there was support for a general `GOFLAGS` variable that lets us pass flags directly to the compiler. This email details what these flags should be going forward.
Big +1 for removing go-pie in favor of using GOFLAGS. It makes the go-based packages management more straightforward and cleaner.
# Flags
Expected environment variables in PKGBUILDs:
export CGO_LDFLAGS="$LDFLAGS" export GOFLAGS="-buildmode=pie -trimpath -mod=vendor -modcacherw"
Explanation:
* `CGO_LDFLAGS` passes the proper `LDFLAGS` to the linker. This should enable full RELRO when used in conjunction with `GOFLAGS`.
* `-buildmode=pie` is the proper way to enable PIE and replaces the `go-pie` patch.
* `-trimpath` this is to achieve reproducible builds and remove PWD from the binary.
* `-modcacherw` modules are downloaded to `$GOPATH/pkg/mod` and by default have the permissions 444 for god knows why. If we want to run `makepkg -c` or `git clean` we won't have the correct permissions. This is probably not a big problem for repository packages, but it's a nice addition so they work as expected.
Notice that `-mod=vendor` is also added to `GOFLAGS`.
Most of the Go projects do not vendorize their dependencies to avoid polluting the source tree. And there is no point to force vendorizing in the PKGBUILD neither. go modules are doing a great job with pinning dependencies to a specific version thus eliminating the main reason for vendor'ization existence (i.e. reproducible builds). Thus following YAGNI principle I propose to drop this "-mod=vendor" flag.
This will make sure we are using the vendored dependencies in the project. If they are not present, please ensure they are downloaded in the `prepare` function:
prepare(){ cd $pkgname-$pkgver go mod vendor }
If the project is *not* using Go 1.11 modules, missing `go.mod` and/or `go.sum` in the project root, then disable it with `export GO111MODULE=off` and continue with symlink hacks.
Some upstreams override these values for strange reasons in their `Makefile` and build systems. You *need* to read over them and ensure this does not happen!
# Pacman
Clearly we shouldn't have to specify this in every PKGBUILD, so I have been playing with a `pacman` patch that passes all of the variables. However I have been struggling with debug support and figuring out that part of the flags, so nothing have been upstreamed yet.
However this is only applicable to around 126 packages, so I guess it's fine? ¯\_(ツ)_/¯
# In conclusion...
If there are no objections to the New Way Of Doing Things™, I'll be updating the package guidelines within the next week or two and drop the `go-pie` package containing the patch. For the sake of compatibility, the `go` package will contain a `replaces=('go-pie')`. I also expect people packaging go packages to follow the guidelines!
-- Morten Linderud PGP: 9C02FF419FECBE16