# Go package guidelines

From ArchWiki
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

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.

Note: The package name should be entirely lowercase.

## Building

### Dependencies

Go 1.11 introduced the initial support for go modules. This allows Go upstream code to declare dependencies and pin them to the given project version. Currently our packaging efforts utilize this to vendor dependencies.

### 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_CPPFLAGS="${CPPFLAGS}"
    export CGO_CFLAGS="${CFLAGS}"
    export CGO_CXXFLAGS="${CXXFLAGS}"
    export CGO_LDFLAGS="${LDFLAGS}"
    export GOFLAGS="-buildmode=pie -trimpath -ldflags=-linkmode=external -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 "-linkmode external -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.

Warning: It is up to the packager to verify the build flags are passed correctly to the compiler. Read the `Makefile` if there is one.

### Output 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_CPPFLAGS="${CPPFLAGS}"
      export CGO_CFLAGS="${CFLAGS}"
      export CGO_CXXFLAGS="${CXXFLAGS}"
      export CGO_LDFLAGS="${LDFLAGS}"
      export GOFLAGS="-buildmode=pie -trimpath -ldflags=-linkmode=external -mod=readonly -modcacherw"
      go build -o build ./cmd/...
    }

    check() {
      cd "$pkgname-$pkgver"
      go test ./...
    }

    package() {
      cd "$pkgname-$pkgver"
      install -Dm755 build/$pkgname "$pkgdir"/usr/bin/$pkgname
    }

## Example packages

- podman
- k9s
- helm

Category:

- Arch package guidelines