chore(wails): scaffold v3 project boilerplate

Wails v3 replaces the NPM-only dev entry point. This adds the Go module,
Taskfile, build metadata, and a minimal window shell without touching
frontend logic.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-29 22:20:21 -07:00
parent 5fc2b6ad65
commit f5feefe844
78 changed files with 7072 additions and 0 deletions
+220
View File
@@ -0,0 +1,220 @@
# 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
FROM golang:1.26-bookworm
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 \
&& 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"]
+67
View File
@@ -0,0 +1,67 @@
# Wails Server Mode Dockerfile
# Multi-stage build for a minimal image.
#
# Defaults produce a pure-Go, fully static binary on a distroless/static base:
# the smallest, most secure image, and correct for the default (CGO-free) app.
#
# If your app needs CGO, override the build args, e.g.:
# docker build --build-arg CGO_ENABLED=1 \
# --build-arg GO_IMAGE=golang:bookworm \
# --build-arg RUNTIME_IMAGE=gcr.io/distroless/base-debian12 \
# -f build/docker/Dockerfile.server .
# CGO needs a C toolchain in the builder and a libc in the runtime image; keep
# the builder and runtime libc compatible (a glibc builder -> a glibc runtime).
# The Taskfile passes these through: task build:docker CGO_ENABLED=1 GO_IMAGE=... RUNTIME_IMAGE=...
ARG GO_IMAGE=golang:alpine
ARG RUNTIME_IMAGE=gcr.io/distroless/static-debian12
ARG CGO_ENABLED=0
# Build stage
FROM ${GO_IMAGE} AS builder
ARG CGO_ENABLED
WORKDIR /app
# Install build dependencies: git always; a C compiler only when CGO is enabled.
# Supports both apk (alpine) and apt (debian/bookworm) base images.
RUN if command -v apk >/dev/null 2>&1; then \
apk add --no-cache git $([ "$CGO_ENABLED" = "1" ] && echo gcc musl-dev); \
else \
apt-get update && apt-get install -y --no-install-recommends git $([ "$CGO_ENABLED" = "1" ] && echo gcc libc6-dev) && rm -rf /var/lib/apt/lists/*; \
fi
# Copy source code
COPY . .
# Remove local replace directive if present (for production builds)
RUN sed -i '/^replace/d' go.mod || true
# Download dependencies
RUN go mod tidy
# Build the production server binary.
# - server,production tags: HTTP server mode with production code paths (no dev
# logger/asset middleware), matching the desktop production build.
# - CGO_ENABLED defaults to 0 for a fully static binary (distroless/static);
# override with --build-arg CGO_ENABLED=1 (see header) for CGO apps.
RUN CGO_ENABLED=${CGO_ENABLED} go build -tags server,production -trimpath -buildvcs=false -ldflags="-s -w" -o server .
# Runtime stage - minimal image
FROM ${RUNTIME_IMAGE}
# Copy the binary
COPY --from=builder /app/server /server
# Copy frontend assets
COPY --from=builder /app/frontend/dist /frontend/dist
# Expose the default port
EXPOSE 8080
# Bind to all interfaces (required for Docker)
# Can be overridden at runtime with -e WAILS_SERVER_HOST=...
ENV WAILS_SERVER_HOST=0.0.0.0
# Run the server
ENTRYPOINT ["/server"]