User:Foxboron/Go packaging guidelines
32-bit – CLR – CMake – Cross – DKMS – Eclipse – Electron – Font – Free Pascal – GNOME – Go – Haskell – Java – KDE – Kernel modules – Lisp – Meson – MinGW – Node.js – Nonfree – OCaml – Perl – PHP – Python – R – Ruby – Rust - Security – Shell – VCS – Web – Wine
This document covers standards and guidelines on writing PKGBUILDs for Go.
General guidelines
Package naming
For Go library modules, use golang-modulename
. Also use the prefix if the package provides a program that is strongly coupled to the Go ecosystem. For other applications, use only the program name.
Building
Flags and build options
Most Makefiles written for go applications do not respect the build flags provided by build systems along with overwriting GOFLAGS
, this causes Go binaries to not be compiled with RELRO as we need CGO_CFLAGS
and CGO_LDFLAGS
to be set for the compiler. This needs to be patched into the Makefile, or the Makefile should be omitted.
export CGO_LDFLAGS="${LDFLAGS}" export CGO_CFLAGS="${CFLAGS}" export CGO_CPPFLAGS="${CPPFLAGS}" export CGO_CXXFLAGS="${CXXFLAGS}" export GOFLAGS="-buildmode=pie -trimpath -mod=readonly -modcacherw" # or alternatively you can define some of these flags from the CLI options go build \ -trimpath \ -buildmode=pie \ -mod=readonly \ -modcacherw \ -ldflags "-extldflags ${LDFLAGS}" \ .
Flag Meaning:
-buildmode=pie
enables PIE compilation for binary harderning.-trimpath
important for reproducible builds so full build paths and module paths are not embedded.-mod=readonly
ensure the module files are not updated in any go actions.-modcacherw
is not important, but it ensures that go modules creates a write-able path. Default is read-only.
Makefile
if there is oneOutput directory
There are currently a few ways to build all go binaries in a project.
build(){ cd "$pkgname-$pkgver" go build -o output-binary . }
...
is a shorthand for the compiler to recursively descend into the directory and find all binaries. It can be used in conjunction with a output directory to build everything.
prepare(){ cd "$pkgname-$pkgver" mkdir -p build } build(){ cd "$pkgname-$pkgver" go build -o build ./cmd/... }
Sample PKGBUILD
pkgname=foo pkgver=0.0.1 pkgrel=1 pkgdesc='Go PKGBUILD Example' arch=('x86_64') url="https://example.org/$pkgname" license=('GPL') makedepends=('go') source=("$url/$pkgname-$pkgver.tar.gz") sha256sums=('1337deadbeef') prepare(){ cd "$pkgname-$pkgver" mkdir -p build/ } build() { cd "$pkgname-$pkgver" export CGO_LDFLAGS="${LDFLAGS}" export CGO_CFLAGS="${CFLAGS}" export CGO_CPPFLAGS="${CPPFLAGS}" export CGO_CXXFLAGS="${CXXFLAGS}" export GOFLAGS="-buildmode=pie -trimpath -modcacherw" go build -o build ./cmd/... } check() { cd "$pkgname-$pkgver" go test ./... } package() { cd "$pkgname-$pkgver" install -Dm755 build/$pkgname "$pkgdir"/usr/bin/$pkgname }