Introduction
Go's CGO allows calling C code from Go, but cross-compiling CGO-enabled programs requires a C cross-compilation toolchain for the target platform. Without it, the linker fails with errors like "exec gcc not found" or "cannot find -lc".
This is common when building Docker images for different architectures or creating cross-platform binaries with native dependencies.
Symptoms
- go build fails with "exec gcc: not found" when cross-compiling
- Linker error "cannot find -lc" or "ld: library not found for -lSystem"
- Build works for GOOS/GOARCH matching the host but fails for other targets
Common Causes
- No C cross-compilation toolchain installed for the target platform
- CGO_ENABLED=1 is set but no cross-compiler is available
- Missing target-specific C libraries or headers
Step-by-Step Fix
- 1.Disable CGO for pure Go builds: If your code doesn't actually need CGO, disable it.
- 2.```bash
- 3.# Check if your code uses CGO:
- 4.go list -f '{{.CgoFiles}}' ./...
# If no CGO files, disable CGO for cross-compilation: CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -o myapp-linux-arm64
# Pure Go cross-compiles without any C toolchain ```
- 1.Install cross-compilation toolchain: Install the appropriate cross-compiler for the target.
- 2.```bash
- 3.# On Ubuntu/Debian for Linux ARM64:
- 4.sudo apt-get install -y gcc-aarch64-linux-gnu
# Then cross-compile: CC=aarch64-linux-gnu-gcc CGO_ENABLED=1 GOOS=linux GOARCH=arm64 go build
# For Windows from Linux: sudo apt-get install -y gcc-mingw-w64-x86-64 CC=x86_64-w64-mingw32-gcc CGO_ENABLED=1 GOOS=windows GOARCH=amd64 go build ```
- 1.Use Docker for cross-compilation: Build in a container with the target toolchain.
- 2.```dockerfile
- 3.FROM golang:1.22 AS builder
- 4.RUN apt-get update && apt-get install -y \
- 5.gcc-aarch64-linux-gnu \
- 6.gcc-x86-64-linux-gnu
ARG TARGETARCH RUN if [ "$TARGETARCH" = "arm64" ]; then \ export CC=aarch64-linux-gnu-gcc; \ fi && \ CGO_ENABLED=1 GOARCH=$TARGETARCH go build -o /app/myapp ./cmd/myapp ```
- 1.Use zig as a universal C compiler for cross-compilation: Zig ships with cross-compilation support built-in.
- 2.```bash
- 3.# Use zig as CC for any target:
- 4.CC="zig cc -target x86_64-linux" CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go build
- 5.CC="zig cc -target aarch64-linux" CGO_ENABLED=1 GOOS=linux GOARCH=arm64 go build
- 6.CC="zig cc -target x86_64-windows" CGO_ENABLED=1 GOOS=windows GOARCH=amd64 go build
- 7.
`
Prevention
- Prefer pure Go packages over CGO-dependent packages when possible
- Use Docker with buildx for reproducible cross-platform builds
- Document the required C toolchains for each target platform
- Consider using zig cc for reliable cross-compilation of C dependencies