This project aims to build and run binaries for Windows on Arm on Linux, using Docker, Wine and Qemu.
It can be used on a Linux arm64 or x64 system. The other architecture is emulated thanks to qemu-user
. This will be slow, but it works!
[[TOC]]
Prerequisites
To run prebuilt images, you only need docker
(or podman
).
To build any image, you need to have podman
(instead of docker
), and qemu-user-static
package installed on your system.
Unified docker image
Building wine (arm64) is long and requires qemu support for executing container.
Thus, we provide a way to build a unified x64 image, that contains prebuilt wine-arm64, plus a wrapper script to execute it using qemu-aarch64 (distributed in x64 image).
This is built thanks to a multi stage dockerfile, first by creating an arm64 image and copying this rootfs.
Based on latest debian stable. See containers/unified.Dockerfile for details.
Build and use unified image
# ./containers/build_unified_image.sh <wine-version> <image-name>
./containers/build_unified_image.sh 8.6 wine-arm64
# a wrapper script named wine-arm64 is available on PATH
docker run -it --rm wine-arm64 which wine-arm64
# -> /usr/bin/wine-arm64
docker run -it --rm wine-arm64 wine-arm64 cmd.exe /c 'echo hello world'
# hello world
Result image also contains some basic tools (wget, curl, rsync, git, unzip, …) preinstalled, for convenience.
We automatically build and publish those images for all wine versions (from 8.0) using gitlab CI. Images are available on https://hub.docker.com/r/linaro/wine-arm64.
docker run -it --rm docker.io/linaro/wine-arm64 wine-arm64 --version
docker run -it --rm docker.io/linaro/wine-arm64:8.5 wine-arm64 --version
Show wine debug
By default, WINEDEBUG
is set to -all, but you can override it. In case of a crash, you can set it to ‘default’ to start investigate what happens.
docker run -it --rm docker.io/linaro/wine-arm64 env WINEDEBUG=default wine-arm64 cmd.exe /c 'echo hello world'
# ...
# 0094:fixme:...
# ...
# hello world
Run without any emulator
In case you want to avoid running wine-arm64 through qemu-static included in image, you can set env variable WINE_NO_EMULATOR=1
.
This is needed if you run natively on linux-arm64 for instance, or if you have binfmt support for aarch64 already setup on your host.
Graphical programs (headless)
To run graphical programs (headless), you can use xvfb-run, which is included:
docker run -it --init --rm docker.io/linaro/wine-arm64 xvfb-run wine-arm64 gui_program.exe
# Note: --init is needed or xvfb-run hangs
Graphical programs
To run graphical programs on your host, you need to set DISPLAY
and mount /tmp/.X11-unix
:
docker run -it --init --rm -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix --ipc host docker.io/linaro/wine-arm64 wine-arm64 gui_program.exe
# ipc host is used to fix crash with X11 MIT-SHM extension
Build and run wine manually
Instead of building a unified docker image, it’s also possible to build wine directly, for arm64 or x64. This is what script run.sh
does.
run.sh
needs an architecture (x64 or arm64) and a command in parameter.
It will build a docker container and wine for this architecture. The executed container will map your user, and your HOME automatically.
NOTE: First time will be long, as it will clone + build wine. ccache is used to speed up next builds.
./run.sh x64 which wine
# .../build/wine-8.0-x64/src/wine
./run.sh arm64 which wine
# .../build/wine-8.0-arm64/src/wine
Build specific version
To build a specific wine version, use WINE_VERSION env var:
WINE_VERSION=8.3 ./run.sh x64 which wine
# .../build/wine-8.3-x64/src/wine
WINE_VERSION=master ./run.sh x64 which wine
# .../build/wine-master-x64/src/wine
You can see versions available here: https://github.com/wine-mirror/wine/tags
Silent wine
Wine can be pretty verbose sometimes, when reporting warnings or unimplemented functions. To silent it, define WINEDEBUG
env var inside container:
./run.sh x64 env WINEDEBUG=-all wine cmd.exe /c "echo hello && exit"
Files
- containers: scripts and dockerfile to create containers for x64 and arm64, and unified x64.
- wine: script to build and run wine
- get_msvc.sh: download msvc using https://github.com/mstorsjo/msvc-wine
- run.sh: builds wine, and run a container with it
Hello world example
# download msvc
./run.sh x64 ./get_msvc.sh
# create source file
echo '#include <stdio.h>' > hello_world.c
echo 'int main() {printf("Hello World\n");}' >> hello_world.c
# compile it for x64
./run.sh x64 ./build/msvc/bin/x64/cl hello_world.c
file hello_world.exe # x64
# execute the binary using wine
./run.sh x64 wine ./hello_world.exe
# compile it for arm64 (using x64 -> arm64 cl wrapper script from msvc-wine)
./run.sh x64 ./build/msvc/bin/arm64/cl hello_world.c
file hello_world.exe # now aarch64
# execute it using wine-arm64
./run.sh arm64 wine ./hello_world.exe