| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225 |
- # Cross-compile Wails v3 apps to any platform
- #
- # Darwin: Zig + macOS SDK
- # Linux: Native GCC when host matches target, Zig for cross-arch
- # Windows: Zig + bundled mingw
- #
- # Usage:
- # docker build -t wails-cross -f Dockerfile.cross .
- # docker run --rm -v $(pwd):/app wails-cross darwin arm64
- # docker run --rm -v $(pwd):/app wails-cross darwin amd64
- # docker run --rm -v $(pwd):/app wails-cross linux amd64
- # docker run --rm -v $(pwd):/app wails-cross linux arm64
- # docker run --rm -v $(pwd):/app wails-cross windows amd64
- # docker run --rm -v $(pwd):/app wails-cross windows arm64
- # Debian 13 provides the GTK >= 4.14 API baseline used by the default Linux backend.
- FROM golang:1.26-trixie
- ARG TARGETARCH
- ARG GARBLE_VERSION=v0.16.0
- # Install base tools, GCC, and GTK/WebKit dev packages
- RUN apt-get update && apt-get install -y --no-install-recommends \
- curl xz-utils python3 nodejs npm pkg-config gcc libc6-dev \
- libgtk-3-dev libwebkit2gtk-4.1-dev \
- libgtk-4-dev libwebkitgtk-6.0-dev \
- && pkg-config --atleast-version=4.14 gtk4 \
- && pkg-config --exists webkitgtk-6.0 \
- && pkg-config --exists gtk+-3.0 \
- && pkg-config --exists webkit2gtk-4.1 \
- && rm -rf /var/lib/apt/lists/*
- RUN go install mvdan.cc/garble@${GARBLE_VERSION}
- # Install Zig - automatically selects correct binary for host architecture.
- # The SHA-256 is fetched from Zig's official download manifest and verified
- # before extraction to protect against MITM or corrupted downloads.
- ARG ZIG_VERSION=0.14.0
- RUN ZIG_ARCH=$(case "${TARGETARCH}" in arm64) echo "aarch64" ;; *) echo "x86_64" ;; esac) && \
- ZIG_FILE="zig-linux-${ZIG_ARCH}-${ZIG_VERSION}.tar.xz" && \
- curl -fSL "https://ziglang.org/download/${ZIG_VERSION}/${ZIG_FILE}" -o "/tmp/${ZIG_FILE}" && \
- EXPECTED=$(curl -fsSL "https://ziglang.org/download/index.json" | \
- python3 -c "import json,sys; d=json.load(sys.stdin); print(d[sys.argv[1]][sys.argv[2]+'-linux']['shasum'])" \
- "${ZIG_VERSION}" "${ZIG_ARCH}") && \
- echo "${EXPECTED} /tmp/${ZIG_FILE}" | sha256sum -c - && \
- tar -xJ -f "/tmp/${ZIG_FILE}" -C /opt && \
- rm "/tmp/${ZIG_FILE}" && \
- ln -s /opt/zig-linux-${ZIG_ARCH}-${ZIG_VERSION}/zig /usr/local/bin/zig
- # Download macOS SDK (required for darwin targets)
- ARG MACOS_SDK_VERSION=14.5
- RUN curl -L "https://github.com/joseluisq/macosx-sdks/releases/download/${MACOS_SDK_VERSION}/MacOSX${MACOS_SDK_VERSION}.sdk.tar.xz" \
- | tar -xJ -C /opt \
- && mv /opt/MacOSX${MACOS_SDK_VERSION}.sdk /opt/macos-sdk
- ENV MACOS_SDK_PATH=/opt/macos-sdk
- # Create Zig CC wrappers for cross-compilation targets
- # Darwin and Windows use Zig; Linux uses native GCC (run with --platform for cross-arch)
- # Darwin arm64
- COPY <<'ZIGWRAP' /usr/local/bin/zcc-darwin-arm64
- #!/bin/sh
- ARGS=""
- SKIP_NEXT=0
- for arg in "$@"; do
- if [ $SKIP_NEXT -eq 1 ]; then
- SKIP_NEXT=0
- continue
- fi
- case "$arg" in
- -target) SKIP_NEXT=1 ;;
- -mmacosx-version-min=*) ;;
- *) ARGS="$ARGS $arg" ;;
- esac
- done
- exec zig cc -fno-sanitize=all -target aarch64-macos-none -isysroot /opt/macos-sdk -I/opt/macos-sdk/usr/include -L/opt/macos-sdk/usr/lib -F/opt/macos-sdk/System/Library/Frameworks -w $ARGS
- ZIGWRAP
- RUN chmod +x /usr/local/bin/zcc-darwin-arm64
- # Darwin amd64
- COPY <<'ZIGWRAP' /usr/local/bin/zcc-darwin-amd64
- #!/bin/sh
- ARGS=""
- SKIP_NEXT=0
- for arg in "$@"; do
- if [ $SKIP_NEXT -eq 1 ]; then
- SKIP_NEXT=0
- continue
- fi
- case "$arg" in
- -target) SKIP_NEXT=1 ;;
- -mmacosx-version-min=*) ;;
- *) ARGS="$ARGS $arg" ;;
- esac
- done
- exec zig cc -fno-sanitize=all -target x86_64-macos-none -isysroot /opt/macos-sdk -I/opt/macos-sdk/usr/include -L/opt/macos-sdk/usr/lib -F/opt/macos-sdk/System/Library/Frameworks -w $ARGS
- ZIGWRAP
- RUN chmod +x /usr/local/bin/zcc-darwin-amd64
- # Windows amd64 - uses Zig's bundled mingw
- COPY <<'ZIGWRAP' /usr/local/bin/zcc-windows-amd64
- #!/bin/sh
- ARGS=""
- SKIP_NEXT=0
- for arg in "$@"; do
- if [ $SKIP_NEXT -eq 1 ]; then
- SKIP_NEXT=0
- continue
- fi
- case "$arg" in
- -target) SKIP_NEXT=1 ;;
- -Wl,*) ;;
- *) ARGS="$ARGS $arg" ;;
- esac
- done
- exec zig cc -target x86_64-windows-gnu $ARGS
- ZIGWRAP
- RUN chmod +x /usr/local/bin/zcc-windows-amd64
- # Windows arm64 - uses Zig's bundled mingw
- COPY <<'ZIGWRAP' /usr/local/bin/zcc-windows-arm64
- #!/bin/sh
- ARGS=""
- SKIP_NEXT=0
- for arg in "$@"; do
- if [ $SKIP_NEXT -eq 1 ]; then
- SKIP_NEXT=0
- continue
- fi
- case "$arg" in
- -target) SKIP_NEXT=1 ;;
- -Wl,*) ;;
- *) ARGS="$ARGS $arg" ;;
- esac
- done
- exec zig cc -target aarch64-windows-gnu $ARGS
- ZIGWRAP
- RUN chmod +x /usr/local/bin/zcc-windows-arm64
- # Build script
- COPY <<'SCRIPT' /usr/local/bin/build.sh
- #!/bin/sh
- set -e
- OS=${1:-darwin}
- ARCH=${2:-arm64}
- case "${OS}-${ARCH}" in
- darwin-arm64|darwin-aarch64)
- export CC=zcc-darwin-arm64
- export GOARCH=arm64
- export GOOS=darwin
- ;;
- darwin-amd64|darwin-x86_64)
- export CC=zcc-darwin-amd64
- export GOARCH=amd64
- export GOOS=darwin
- ;;
- linux-arm64|linux-aarch64)
- export CC=gcc
- export GOARCH=arm64
- export GOOS=linux
- ;;
- linux-amd64|linux-x86_64)
- export CC=gcc
- export GOARCH=amd64
- export GOOS=linux
- ;;
- windows-arm64|windows-aarch64)
- export CC=zcc-windows-arm64
- export GOARCH=arm64
- export GOOS=windows
- ;;
- windows-amd64|windows-x86_64)
- export CC=zcc-windows-amd64
- export GOARCH=amd64
- export GOOS=windows
- ;;
- *)
- echo "Usage: <os> <arch>"
- echo " os: darwin, linux, windows"
- echo " arch: amd64, arm64"
- exit 1
- ;;
- esac
- export CGO_ENABLED=1
- export CGO_CFLAGS="-w"
- # Build frontend if exists and not already built (host may have built it)
- if [ -d "frontend" ] && [ -f "frontend/package.json" ] && [ ! -d "frontend/dist" ]; then
- (cd frontend && npm install --silent && npm run build --silent)
- fi
- # Build
- APP=${APP_NAME:-$(basename $(pwd))}
- mkdir -p bin
- EXT=""
- LDFLAGS="-s -w"
- if [ "$GOOS" = "windows" ]; then
- EXT=".exe"
- LDFLAGS="-s -w -H windowsgui"
- fi
- TAGS="production"
- if [ -n "$EXTRA_TAGS" ]; then
- TAGS="${TAGS},${EXTRA_TAGS}"
- fi
- COMPILER="go build"
- if [ "$OBFUSCATED" = "true" ]; then
- COMPILER="garble ${GARBLE_ARGS} build"
- TAGS="${TAGS},wails_obfuscated"
- fi
- ${COMPILER} -tags "$TAGS" -trimpath -buildvcs=false -ldflags="$LDFLAGS" -o bin/${APP}-${GOOS}-${GOARCH}${EXT} .
- echo "Built: bin/${APP}-${GOOS}-${GOARCH}${EXT}"
- SCRIPT
- RUN chmod +x /usr/local/bin/build.sh
- WORKDIR /app
- ENTRYPOINT ["/usr/local/bin/build.sh"]
- CMD ["darwin", "arm64"]
|