Cross Compile a Go Project With CGO Dependencies Using Zig
Cross compiling with Go is usually straighforward: set GOOS
and GOARCH
environement variables and then go build
.
Unfortunately for projects that uses CGO dependencies things can be harder.
Depending on the target architecture it requires to install a C compiler like gcc, clang or x86_64-w64-mingw64-gcc and configure additional environment variables like CC
along with the CGO_ENABLED=1
one.
In this post we’ll see how to cross-compile the Paw project for linux, macOS and Windows using Zig without the need to install additional complilers.
Paw is a cross platform application to manage passwords and identities securely, it is written in Go and uses Fyne toolkit for the GUI and golang.design/x/clipboard library for the CLI that have CGO dependencies.
Zig is a general-purpose programming language and toolchain that provides a zero-dependency, drop-in C/C++ compiler that supports cross-compilation out-of-the-box.
Requirements
- debian/ubuntu based distro
- go v1.18.0
- zig v0.9.1
Download the source code
git clone https://github.com/lucor/paw.git
Compile for target linux amd64
# install the GUI and CLI dependencies
apt-get update
apt-get install -y -q --no-install-recommends \
libgl-dev \
libx11-dev \
libxrandr-dev \
libxxf86vm-dev \
libxi-dev \
libxcursor-dev \
libxinerama-dev
# create dist dir
mkdir -p dist/linux-amd64
# build
CGO_ENABLED=1 \
GOOS=linux \
GOARCH=amd64 \
CC="zig cc -target x86_64-linux-gnu -isystem /usr/include -L/usr/lib/x86_64-linux-gnu" \
CXX="zig c++ -target x86_64-linux-gnu -isystem /usr/include -L/usr/lib/x86_64-linux-gnu" \
go build -trimpath -o dist/linux-amd64 ./cmd/...
Compile for target linux arm64
# install the GUI and CLI dependencies
dpkg --add-architecture arm64
apt-get update
apt-get install -y -q --no-install-recommends \
libgl-dev:arm64 \
libx11-dev:arm64 \
libxrandr-dev:arm64 \
libxxf86vm-dev:arm64 \
libxi-dev:arm64 \
libxcursor-dev:arm64 \
libxinerama-dev:arm64
# create dist dir
mkdir -p dist/linux-arm64
# build
CGO_ENABLED=1 \
GOOS=linux \
GOARCH=arm64 \
PKG_CONFIG_LIBDIR=/usr/lib/aarch64-linux-gnu/pkgconfig \
CC="zig cc -target aarch64-linux-gnu -isystem /usr/include -L/usr/lib/aarch64-linux-gnu" \
CXX="zig c++ -target aarch64-linux-gnu -isystem /usr/include -L/usr/lib/aarch64-linux-gnu" \
go build -trimpath -o dist/linux-arm64 ./cmd/...
Compile for target windows amd64
# create dist dir
mkdir -p dist/windows-amd64
# build
CGO_ENABLED=1 \
GOOS=windows \
GOARCH=amd64 \
CC="zig cc -target x86_64-windows-gnu" \
CXX="zig c++ -target x86_64-windows-gnu" \
go build -trimpath -ldflags='-H=windowsgui' -o dist/windows-amd64 ./cmd/...
Compile for target macOS amd64
export MACOS_MIN_VER=10.14
export MACOS_SDK_PATH="/path/to/macOS/sdk"
# create dist dir
mkdir -p dist/darwin-amd64
# build
CGO_ENABLED=1 \
GOOS=darwin \
GOARCH=amd64 \
CGO_LDFLAGS="-mmacosx-version-min=${MACOS_MIN_VER} --sysroot ${MACOS_SDK_PATH} -F/System/Library/Frameworks -L/usr/lib" \
CC="zig cc -mmacosx-version-min=${MACOS_MIN_VER} -target x86_64-macos-gnu -isysroot ${MACOS_SDK_PATH} -iwithsysroot /usr/include -iframeworkwithsysroot /System/Library/Frameworks" \
CXX="zig c++ -mmacosx-version-min=${MACOS_MIN_VER} -target x86_64-macos-gnu -isysroot ${MACOS_SDK_PATH} -iwithsysroot /usr/include -iframeworkwithsysroot /System/Library/Frameworks" \
go build -trimpath -buildmode=pie -o dist/darwin-amd64 ./cmd/...
Compile for target macOS arm64
export MACOS_MIN_VER=11.1
export MACOS_SDK_PATH="/path/to/macOS/sdk"
# create dist dir
mkdir -p dist/darwin-arm64
# build
CGO_ENABLED=1 \
GOOS=darwin \
GOARCH=arm64 \
CGO_LDFLAGS="-mmacosx-version-min=${MACOS_MIN_VER} --sysroot ${MACOS_SDK_PATH} -F/System/Library/Frameworks -L/usr/lib" \
CC="zig cc -mmacosx-version-min=${MACOS_MIN_VER} -target aarch64-macos-gnu -isysroot ${MACOS_SDK_PATH} -iwithsysroot /usr/include -iframeworkwithsysroot /System/Library/Frameworks" \
CXX="zig c++ -mmacosx-version-min=${MACOS_MIN_VER} -target aarch64-macos-gnu -isysroot ${MACOS_SDK_PATH} -iwithsysroot /usr/include -iframeworkwithsysroot /System/Library/Frameworks" \
go build -ldflags "-s -w" -buildmode=pie -trimpath -o dist/darwin-arm64 ./cmd/...
References: