README.md

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 linaro/wine-arm64 wine-arm64 --version
docker run -it --rm 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 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 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 --rm -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix linaro/wine-arm64 wine-arm64 gui_program.exe

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
Конвейеры
0 успешных
0 с ошибкой