Skip to content

Building

tej edited this page Jun 2, 2026 · 2 revisions

Building

TL;DR

make build          # -> bin/podman-api, with the required build tags
make test           # unit tests
make test-integration   # unit + integration; needs a real podman socket

Always prefer the Makefile targets — they carry the build tags described below. A plain go build ./... fails on a clean machine.

Why the tags are mandatory

The podman v5 bindings transitively pull in the container storage graph drivers (btrfs, devicemapper) and gpgme, all of which are CGO and need system -dev headers. Without the right tags you get:

# go.podman.io/storage/drivers/btrfs
fatal error: btrfs/version.h: No such file or directory
# github.com/proglottis/gpgme
Package gpgme was not found in the pkg-config search path.

podman-api only uses the remote libpod client, so it never needs those drivers. We exclude them and swap gpgme for a pure-Go OpenPGP implementation with three build tags:

containers_image_openpgp exclude_graphdriver_btrfs exclude_graphdriver_devicemapper

The Makefile defines them once as TAGS and the CI workflow mirrors them as GO_TAGSkeep the two in sync.

Note: go test -tags cannot mix space- and comma-separated tags. Because TAGS is space-separated, append integration with a space ("$(TAGS) integration"), not a comma.

Static / no-CGO build

With the tags, no system headers are needed at all — you can build a fully static binary:

CGO_ENABLED=0 go build \
  -tags "containers_image_openpgp exclude_graphdriver_btrfs exclude_graphdriver_devicemapper" \
  -o podman-api ./cmd/podman-api

Cross-compiling for a Linux server

GOOS=linux GOARCH=amd64 go build \
  -tags "containers_image_openpgp exclude_graphdriver_btrfs exclude_graphdriver_devicemapper" \
  -o podman-api ./cmd/podman-api

CI

.forgejo/workflows/ci.yaml runs two jobs on the self-hosted runner:

  • lint, test, buildgo vet / gofmt -l / go test -race / go build, all with GO_TAGS, inside golang:1.26-bookworm. nodejs is installed before actions/checkout because the JS-based actions need a node binary the golang image doesn't ship.
  • integration (podman-in-podman) — runs rootful podman nested inside a privileged quay.io/podman/stable container and runs the -tags=integration suite against it.

See Troubleshooting if either job fails.

Related

Clone this wiki locally