Files
wz-phone/scripts/Dockerfile.windows-builder
Siavash Sameni 48d2bd4f65
Some checks failed
Mirror to GitHub / mirror (push) Failing after 39s
Build Release Binaries / build-amd64 (push) Failing after 3m40s
fix(windows): bake SSE patch into docker image instead of runtime
2026-04-10 12:55:48 +04:00

117 lines
5.4 KiB
Docker

# =============================================================================
# WZ Phone — Windows (x86_64-pc-windows-msvc) cross-compile image
#
# Cross-compiles the Tauri desktop binary for Windows from a Linux host via
# `cargo xwin`, which auto-downloads the Microsoft CRT + Windows SDK at build
# time. This image pre-warms that cache so the cross-compile is as close as
# possible to a native Linux build on rebuild (~3 min warm vs ~20 min cold).
#
# Build:
# docker build -t wzp-windows-builder -f Dockerfile.windows-builder .
#
# Run: driven by scripts/build-windows-docker.sh (see that file).
# =============================================================================
FROM debian:bookworm
ARG RUST_TARGET=x86_64-pc-windows-msvc
ENV DEBIAN_FRONTEND=noninteractive
# ── System packages ──────────────────────────────────────────────────────────
# - build-essential + pkg-config + libssl-dev: baseline cargo build toolchain
# - cmake + ninja-build: audiopus_sys (libopus) uses cmake and expects Ninja
# as the generator for the windows target; without ninja-build the cmake
# build fails with "CMake was unable to find a build program corresponding
# to Ninja" partway through.
# - llvm + clang + lld: cargo-xwin uses clang + lld-link for PE/COFF output.
# - nasm: ring / rustls assembly for Windows needs NASM on non-Windows hosts.
# - curl, git, ca-certificates, unzip: obvious plumbing.
# - xz-utils: some Microsoft installer archives are xz-compressed.
RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential \
cmake \
ninja-build \
curl \
git \
pkg-config \
libssl-dev \
ca-certificates \
llvm \
clang \
lld \
nasm \
unzip \
xz-utils \
file \
&& rm -rf /var/lib/apt/lists/*
# ── Node.js 20 LTS (required by Tauri for frontend build) ────────────────────
RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \
&& apt-get install -y --no-install-recommends nodejs \
&& rm -rf /var/lib/apt/lists/* \
&& node --version \
&& npm --version
# ── Builder user (1000:1000) — matches host bind-mount UID for the cache
# volumes so cargo-registry / target survive across runs without perms
# gymnastics.
RUN groupadd -g 1000 builder \
&& useradd -m -u 1000 -g 1000 -s /bin/bash builder
USER builder
WORKDIR /home/builder
# ── Rust toolchain + Windows target + cargo-xwin ────────────────────────────
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs \
| sh -s -- -y --default-toolchain stable \
&& . $HOME/.cargo/env \
&& rustup target add ${RUST_TARGET} \
&& cargo install cargo-xwin --locked
ENV PATH="/home/builder/.cargo/bin:$PATH" \
XWIN_ACCEPT_LICENSE=1 \
RUST_TARGET_WIN=${RUST_TARGET}
# ── Pre-warm the xwin cache ─────────────────────────────────────────────────
# cargo-xwin downloads the Microsoft CRT + Windows SDK (~1.5-2 GB) into
# ~/.cache/cargo-xwin the first time it runs. Baking that into an image
# layer saves ~4 minutes off every subsequent cold run.
#
# We do this by creating a throwaway Rust project, building it with
# cargo-xwin against the Windows target, then deleting the project but
# keeping the xwin cache.
RUN set -eux; \
mkdir -p /tmp/xwin-warmup && cd /tmp/xwin-warmup && \
. $HOME/.cargo/env && \
cargo new --bin xwin-warmup --quiet && \
cd xwin-warmup && \
cargo xwin build --release --target ${RUST_TARGET} 2>&1 | tail -5 && \
cd / && rm -rf /tmp/xwin-warmup && \
du -sh $HOME/.cache/cargo-xwin
# ── Patch the cargo-xwin clang-cl toolchain to add SSE4.1 / SSSE3 ─────────
# libopus (via audiopus_sys) uses per-file COMPILE_FLAGS "-msse4.1" on
# its opus/silk/x86/*_sse4_1.c sources, but clang-cl silently drops the
# bare -m flags (it expects /clang:-m… instead). The per-file
# intrinsics functions then fail to compile because the surrounding
# function isn't marked with the target feature. We fix this by
# inserting /clang:-msse4.1 / /clang:-mssse3 directly into the
# COMPILE_FLAGS list in the cargo-xwin-generated cmake toolchain so
# EVERY C file in every cmake-driven subbuild gets the feature flags.
# All x86_64 Windows CPUs shipped since 2008 have these, safe on target.
#
# We do the patch inside the image (not at container run time) so
# (a) it persists across container restarts without bash/awk/sed
# escaping games inside docker-bash-c, and (b) it becomes part of
# the shared image layer cache.
RUN set -eux; \
TOOLCHAIN=$HOME/.cache/cargo-xwin/cmake/clang-cl/x86_64-pc-windows-msvc-toolchain.cmake; \
test -f "$TOOLCHAIN"; \
grep -q WZP_SSE_PATCH "$TOOLCHAIN" || \
awk '/\/imsvc .*\/winrt\)/ {sub(/\)/, "", $0); print $0; print " /clang:-msse4.1"; print " /clang:-mssse3"; print " /clang:-msse3"; print " /clang:-msse2"; print " # WZP_SSE_PATCH"; print " )"; next} {print}' "$TOOLCHAIN" > "$TOOLCHAIN.new" && \
mv "$TOOLCHAIN.new" "$TOOLCHAIN"; \
echo "=== Patched toolchain ==="; \
grep -A 15 "set(COMPILE_FLAGS" "$TOOLCHAIN" | head -20
WORKDIR /build/source