The "Warf" Way: Seamless Windows Testing on Linux using MinGW & Wine

In the world of language development, even a "toy" language needs a solid foundation. My project, warfLang, isn't trying to replace C++ or Rust. It’s an LL(1) parser written in C++ that generates an Abstract Syntax Tree (AST)—essentially a glorified calculator that supports variable definitions.
But even a calculator needs to count correctly on every platform. To ensure warfLang remains truly cross-platform, I needed a CI/CD pipeline that could verify its logic on Windows without the overhead of actually owning a Windows machine.
The Problem: Cross-Platform Logic is Tricky
Even for a high-level parser, moving from Linux to Windows introduces subtle behavioral risks and differences especially when you are compiling acros different compilers like CL, Clang, and GCC or different libC implementations.
Inspired by Gianni Milanesi’s post, I realized I didn't need a native Windows environment to find out. I just needed a containerized "Build Appliance."
Note this post will not be the promised part 5 of the Cross-Compiling series since we are using mingw-w64 and not clang.
The "Warf" Solution: Dockerizing the Toolchain
Instead of manually managing cross-compilers, I use a custom Dockerfile Dockerfile.mingw-cross. This encapsulates the entire MinGW-w64 suite, ensuring that the environment where I build warfLang today is the exact same one I'll use six months from now.
Why Docker makes it easy:
Zero Setup: A new contributor doesn't need to install
binutils-mingw-w64. They just run the container.Consistency: It's a container, it always the works the same thats the point.
The "Magic" Compiler: We get instant access to
x86_64-w64-mingw32-gcc, which treats our C++ code as a native Windows project.
FROM ubuntu:latest
# Install MinGW for building and Wine for testing
RUN apt-get update && apt-get install -y \
mingw-w64 \
cmake \
wine \
&& rm -rf /var/lib/apt/lists/\*
...
RUN cmake -S . -B build \
-GNinja -DCMAKE\_BUILD\_TYPE=Release \
-DCMAKE\_C\_COMPILER=x86\_64-w64-mingw32-gcc-posix \
-DCMAKE\_CXX\_COMPILER=x86\_64-w64-mingw32-g++-posix \
-DBuildTest=TRUE \
-DCMAKE\_SYSTEM\_NAME=Windows -DCMAKE\_CROSS\_COMPILING=TRUE
Bundling Wine: Testing the Calculator
The real value of the "Warf" way is the inclusion of Wine. For a project like warfLang , testing is straightforward: I feed the parser an expression (like x = 5; x * 2;), and I expect a specific AST output. By bundling Wine in the Docker image, I can run the Windows version immediately after compiling it without having to context switch to a new device. This works the same on my local dev machines as well as in the CI.
Why this is vital for a "Toy" Language:
- It isn't: but it is fun 😂!
- Headless Validation: The real reason I did this no context switching for testing cross plat. Using
wine ./warf_tests.exein a headless Docker container gives me instant feedback if something works on windows without having to have a dedicated windows device.
Leveraging GitHub Actions
By using this crossPlat builder approach, my GitHub Actions workflow is faster and cheaper (see runner pricing). I pull a single Linux-based image, build the Windows .exe file, and run the test suite through Wine.
When I see the "Green Checkmark" now it proves that the "calculator" works on Windows, even though it was born and raised on Linux.
Conclusion
Whether you're building a massive compiler or a glorified calculator like warfLang , the "Warf" way combining Docker, MinGW, and Wine provides a professional, reproducible, and verifiable way to ship to Windows users without ever leaving the comfort of Linux.
Check out the implementation and play with the parser in the WarfLang WASM demo.
First published 4/19/26 on blog.farzon.org



