Dockerfile.cross 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. # Cross-compile Wails v3 apps to any platform
  2. #
  3. # Darwin: Zig + macOS SDK
  4. # Linux: Native GCC when host matches target, Zig for cross-arch
  5. # Windows: Zig + bundled mingw
  6. #
  7. # Usage:
  8. # docker build -t wails-cross -f Dockerfile.cross .
  9. # docker run --rm -v $(pwd):/app wails-cross darwin arm64
  10. # docker run --rm -v $(pwd):/app wails-cross darwin amd64
  11. # docker run --rm -v $(pwd):/app wails-cross linux amd64
  12. # docker run --rm -v $(pwd):/app wails-cross linux arm64
  13. # docker run --rm -v $(pwd):/app wails-cross windows amd64
  14. # docker run --rm -v $(pwd):/app wails-cross windows arm64
  15. # Debian 13 provides the GTK >= 4.14 API baseline used by the default Linux backend.
  16. FROM golang:1.26-trixie
  17. ARG TARGETARCH
  18. ARG GARBLE_VERSION=v0.16.0
  19. # Install base tools, GCC, and GTK/WebKit dev packages
  20. RUN apt-get update && apt-get install -y --no-install-recommends \
  21. curl xz-utils python3 nodejs npm pkg-config gcc libc6-dev \
  22. libgtk-3-dev libwebkit2gtk-4.1-dev \
  23. libgtk-4-dev libwebkitgtk-6.0-dev \
  24. && pkg-config --atleast-version=4.14 gtk4 \
  25. && pkg-config --exists webkitgtk-6.0 \
  26. && pkg-config --exists gtk+-3.0 \
  27. && pkg-config --exists webkit2gtk-4.1 \
  28. && rm -rf /var/lib/apt/lists/*
  29. RUN go install mvdan.cc/garble@${GARBLE_VERSION}
  30. # Install Zig - automatically selects correct binary for host architecture.
  31. # The SHA-256 is fetched from Zig's official download manifest and verified
  32. # before extraction to protect against MITM or corrupted downloads.
  33. ARG ZIG_VERSION=0.14.0
  34. RUN ZIG_ARCH=$(case "${TARGETARCH}" in arm64) echo "aarch64" ;; *) echo "x86_64" ;; esac) && \
  35. ZIG_FILE="zig-linux-${ZIG_ARCH}-${ZIG_VERSION}.tar.xz" && \
  36. curl -fSL "https://ziglang.org/download/${ZIG_VERSION}/${ZIG_FILE}" -o "/tmp/${ZIG_FILE}" && \
  37. EXPECTED=$(curl -fsSL "https://ziglang.org/download/index.json" | \
  38. python3 -c "import json,sys; d=json.load(sys.stdin); print(d[sys.argv[1]][sys.argv[2]+'-linux']['shasum'])" \
  39. "${ZIG_VERSION}" "${ZIG_ARCH}") && \
  40. echo "${EXPECTED} /tmp/${ZIG_FILE}" | sha256sum -c - && \
  41. tar -xJ -f "/tmp/${ZIG_FILE}" -C /opt && \
  42. rm "/tmp/${ZIG_FILE}" && \
  43. ln -s /opt/zig-linux-${ZIG_ARCH}-${ZIG_VERSION}/zig /usr/local/bin/zig
  44. # Download macOS SDK (required for darwin targets)
  45. ARG MACOS_SDK_VERSION=14.5
  46. RUN curl -L "https://github.com/joseluisq/macosx-sdks/releases/download/${MACOS_SDK_VERSION}/MacOSX${MACOS_SDK_VERSION}.sdk.tar.xz" \
  47. | tar -xJ -C /opt \
  48. && mv /opt/MacOSX${MACOS_SDK_VERSION}.sdk /opt/macos-sdk
  49. ENV MACOS_SDK_PATH=/opt/macos-sdk
  50. # Create Zig CC wrappers for cross-compilation targets
  51. # Darwin and Windows use Zig; Linux uses native GCC (run with --platform for cross-arch)
  52. # Darwin arm64
  53. COPY <<'ZIGWRAP' /usr/local/bin/zcc-darwin-arm64
  54. #!/bin/sh
  55. ARGS=""
  56. SKIP_NEXT=0
  57. for arg in "$@"; do
  58. if [ $SKIP_NEXT -eq 1 ]; then
  59. SKIP_NEXT=0
  60. continue
  61. fi
  62. case "$arg" in
  63. -target) SKIP_NEXT=1 ;;
  64. -mmacosx-version-min=*) ;;
  65. *) ARGS="$ARGS $arg" ;;
  66. esac
  67. done
  68. 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
  69. ZIGWRAP
  70. RUN chmod +x /usr/local/bin/zcc-darwin-arm64
  71. # Darwin amd64
  72. COPY <<'ZIGWRAP' /usr/local/bin/zcc-darwin-amd64
  73. #!/bin/sh
  74. ARGS=""
  75. SKIP_NEXT=0
  76. for arg in "$@"; do
  77. if [ $SKIP_NEXT -eq 1 ]; then
  78. SKIP_NEXT=0
  79. continue
  80. fi
  81. case "$arg" in
  82. -target) SKIP_NEXT=1 ;;
  83. -mmacosx-version-min=*) ;;
  84. *) ARGS="$ARGS $arg" ;;
  85. esac
  86. done
  87. 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
  88. ZIGWRAP
  89. RUN chmod +x /usr/local/bin/zcc-darwin-amd64
  90. # Windows amd64 - uses Zig's bundled mingw
  91. COPY <<'ZIGWRAP' /usr/local/bin/zcc-windows-amd64
  92. #!/bin/sh
  93. ARGS=""
  94. SKIP_NEXT=0
  95. for arg in "$@"; do
  96. if [ $SKIP_NEXT -eq 1 ]; then
  97. SKIP_NEXT=0
  98. continue
  99. fi
  100. case "$arg" in
  101. -target) SKIP_NEXT=1 ;;
  102. -Wl,*) ;;
  103. *) ARGS="$ARGS $arg" ;;
  104. esac
  105. done
  106. exec zig cc -target x86_64-windows-gnu $ARGS
  107. ZIGWRAP
  108. RUN chmod +x /usr/local/bin/zcc-windows-amd64
  109. # Windows arm64 - uses Zig's bundled mingw
  110. COPY <<'ZIGWRAP' /usr/local/bin/zcc-windows-arm64
  111. #!/bin/sh
  112. ARGS=""
  113. SKIP_NEXT=0
  114. for arg in "$@"; do
  115. if [ $SKIP_NEXT -eq 1 ]; then
  116. SKIP_NEXT=0
  117. continue
  118. fi
  119. case "$arg" in
  120. -target) SKIP_NEXT=1 ;;
  121. -Wl,*) ;;
  122. *) ARGS="$ARGS $arg" ;;
  123. esac
  124. done
  125. exec zig cc -target aarch64-windows-gnu $ARGS
  126. ZIGWRAP
  127. RUN chmod +x /usr/local/bin/zcc-windows-arm64
  128. # Build script
  129. COPY <<'SCRIPT' /usr/local/bin/build.sh
  130. #!/bin/sh
  131. set -e
  132. OS=${1:-darwin}
  133. ARCH=${2:-arm64}
  134. case "${OS}-${ARCH}" in
  135. darwin-arm64|darwin-aarch64)
  136. export CC=zcc-darwin-arm64
  137. export GOARCH=arm64
  138. export GOOS=darwin
  139. ;;
  140. darwin-amd64|darwin-x86_64)
  141. export CC=zcc-darwin-amd64
  142. export GOARCH=amd64
  143. export GOOS=darwin
  144. ;;
  145. linux-arm64|linux-aarch64)
  146. export CC=gcc
  147. export GOARCH=arm64
  148. export GOOS=linux
  149. ;;
  150. linux-amd64|linux-x86_64)
  151. export CC=gcc
  152. export GOARCH=amd64
  153. export GOOS=linux
  154. ;;
  155. windows-arm64|windows-aarch64)
  156. export CC=zcc-windows-arm64
  157. export GOARCH=arm64
  158. export GOOS=windows
  159. ;;
  160. windows-amd64|windows-x86_64)
  161. export CC=zcc-windows-amd64
  162. export GOARCH=amd64
  163. export GOOS=windows
  164. ;;
  165. *)
  166. echo "Usage: <os> <arch>"
  167. echo " os: darwin, linux, windows"
  168. echo " arch: amd64, arm64"
  169. exit 1
  170. ;;
  171. esac
  172. export CGO_ENABLED=1
  173. export CGO_CFLAGS="-w"
  174. # Build frontend if exists and not already built (host may have built it)
  175. if [ -d "frontend" ] && [ -f "frontend/package.json" ] && [ ! -d "frontend/dist" ]; then
  176. (cd frontend && npm install --silent && npm run build --silent)
  177. fi
  178. # Build
  179. APP=${APP_NAME:-$(basename $(pwd))}
  180. mkdir -p bin
  181. EXT=""
  182. LDFLAGS="-s -w"
  183. if [ "$GOOS" = "windows" ]; then
  184. EXT=".exe"
  185. LDFLAGS="-s -w -H windowsgui"
  186. fi
  187. TAGS="production"
  188. if [ -n "$EXTRA_TAGS" ]; then
  189. TAGS="${TAGS},${EXTRA_TAGS}"
  190. fi
  191. COMPILER="go build"
  192. if [ "$OBFUSCATED" = "true" ]; then
  193. COMPILER="garble ${GARBLE_ARGS} build"
  194. TAGS="${TAGS},wails_obfuscated"
  195. fi
  196. ${COMPILER} -tags "$TAGS" -trimpath -buildvcs=false -ldflags="$LDFLAGS" -o bin/${APP}-${GOOS}-${GOARCH}${EXT} .
  197. echo "Built: bin/${APP}-${GOOS}-${GOARCH}${EXT}"
  198. SCRIPT
  199. RUN chmod +x /usr/local/bin/build.sh
  200. WORKDIR /app
  201. ENTRYPOINT ["/usr/local/bin/build.sh"]
  202. CMD ["darwin", "arm64"]