Batteries included, MULTIPLE times! ๐๐๐โกโก
"Bro, unreal!! Latest Wine, latest Mesa, latest everything!" โ Gandalf, a famous ๐ง
"See, eh, now Little Tony can finally enjoy all his games, eh, yeah." โ the Mob ๐ฎ๐น
TL;DR Does it even work?! Yes, absolutely. But it shouldn't, really. ๐คก๐คก
Welcome to the Docker recipe for building a statically linked 32-bit
Wine for x86_64 targets. The build supports most
Wine features. The motivation for this bizarre experiment is to avoid having
to install hundreds of :i386
dependencies in order to run Wine but it might
be useful beyond that as well, i.e. to get an extremely optimized and
performant Wine. Just do a sudo apt install wine32
on a freshly
installed Ubuntu and see what burden people have to struggle with every day just
to run their favorite Deus Ex and System Shock 2. Never again lose your temper
over unavailable packages which you'll never need anyhow! Gentoo users, no
need to thank me, I'm just doing my job *tips hat* ! The recipe should
be straightforward to adapt for targets other than x86.
Actually, in retrospect, just compiling the (dynamic) Wine dependencies and bundling them should be enough to make people happy but where's the fun in that? It's much better to have libz statically linked 20+ times. Also, static linking allows us to go berserk with treats like link time optimization (LTO).
All dependencies except for critical stuff like libc, libstdc++, libm,
libresolv, libdl, librt, libpthread are statically linked in
Wine's .so
and .dll
modules. This includes graphics drivers, scanner
drivers, multimedia codecs etc. The graphics drivers are
Mesa's. They're awesome if you have Intel or AMD
hardware. For Nvidia you'll be stuck with nouveau which is probably not what
you want. Vendor provided drivers are NOT supported. Why are you even
wasting your time with Linux if you're gonna use black box software operating
at kernel level?
The project uses a modified version of Wine available at
https://github.com/MIvanchev/wine/tree/static-dependencies which I
continuously update to the latest Wine release. The changes are
only intended to make Wine compatible with statically linked dependencies as is
clearly visible in the diff.
Basically I just removed the dynamic loading of libraries and replaced the
function pointers that Wine dlsym
s with the actual library symbols. This
removes one level of indirection. There are a couple of hacks like win32u.so
loading OpenGL symbols from winex11.so
to avoid statically linking Mesa two
times.
This Wine build is very unorthodox. I cannot stress on this enough. Several libraries were patched (although lightly) to pull this off. Are you really gonna trust something like that? Also, using statically compiled software is in general a bad idea if you don't know what you're doing and comes with significant dangers. Use at your own risk and discretion. I assume no responsibility for any damage resulting from using this project. I do use it myself all the time to play GoG games and use some Windows programs and I've never had any issues.
Please report any bugs and problems. I really greatly appreciate your feedback even if it's an angry rant about reformatted hard drive. Let's make static-wine32 better together and liberate ourselves from the dynamic oppression. Feel free to share your ideas and contributions as well.
Before you begin building and installing you need to be aware that to run
a statically compiled Wine you need 32-bit libc and libstdc++ along with a
couple of other closely related libraries like libm, librt, libphread etc. If
you're on Ubuntu, start with apt install libc6:i386 libstdc++6:i386
. That
might be all you'll have to do. For other distros you'll have to figure it out
but most likely it's something similar.
Statically linked Wine will also probably crash if you have an "official"
32-bit Wine installation at a well-known location or if you've preinstalled
32-bit versions of some of the Wine dependencies like libX11, SDL, GStreamer,
LLVM, GnuTLS etc. If you experience crashes remove the official 32-bit Wine,
all :i386
dependencies and start over. You won't be needing them anyhow.
Consult the troubleshooting section when in trouble.
You'll also need to install Docker in order to build static-wine32 but actually running it does not require Docker. This is because the build downloads and compiles a lot of dependencies and I thought this is best done as an image recipe. Once the image is created, you can copy the Wine build out of it.
The steps are as follows:
Clone this repository. Let's call the absolute path to the downloaded
directory <static-wine-dir>
.
Run cd <static-wine-dir>
and execute
DOCKER_BUILDKIT=0 docker build --build-arg PLATFORM=<your CPU's architecture> --build-arg PREFIX=$HOME/.local -t static-wine32:latest . 2>&1 | tee build.log
The value of the PLATFORM
argument is used to optimize static-wine32 for your
machine. Find a suitable value from the possible values of the -march
option
of GCC here https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html, i.e.
broadwell
if you have the i7-5600U CPU.
The PREFIX
argument denotes the directory to which
you'll later install Wine, most likely $HOME/.local
or /usr/local
.
Additionally you can pass the following arguments:
--build-arg BUILD_WITH_LTO=n
: disables the link time optimizations.
--build-arg BUILD_JOBS=1|2|3|4|...
: set to number of parallel build jobs
you'd like. By default it's set to 8. ๐ถ It's gettin' hot in here ๐ถ
If you encounter errors during the build the recipes for the affected packages
in Dockerfile
will have to be fixed. This usually happens when moving to
newer or older versions of the dependencies. What I usually do is to build an
image that works and then try out new recipes within it. Sometimes this takes
days.
The image also contains statically contained glxgears
and vkcube
in
/usr/local/bin
in case you want debug something.
Copy the Wine build from /root/wine-build.tar.gz
in the image to your
computer, there are many ways to do this but I use a temporary container
which is deleted immediately afterwards.
docker cp $(docker create --name foo static-wine32):/root/wine-build.tar.gz . && docker rm foo
Extract the Wine build to the installation directory.
tar xvf wine-build.tar.gz -C "$HOME/.local"
Enjoy Wine!
Depends on the context. Not per se. Installing thousands of shared libraries with sketchy interdependencies is not better IMHO if you only want to run Wine. However static compilation requires some knowledge of what's going on under the hood.
To name just one example, the virtual memory of your Wine process will
now contain N copies of some dependency, say libz, where it would usually
contain only one. This multiplication could quickly cause a catastrophy if you
let copy <x>
handle data originating from copy <y>
assuming that <x>
is <y>
which with a dynamic library will indeed be the case. Here's where
Wine's architecture really shines. It's so well decoupled that assumptions
like that seem to have been avoided entirely but be on your guard at all times.
Static linking also allows us to perform whole program optimization which could potentially result in significant performance increases.
For now only x64 Linux.
No and there won't be. With static linkage of so many dependencies the licensing situation becomes impossible to resolve. The build process is however not that complicated so give it a go! If you're stuck contact me and I'll guide you through it.
No. The project features a statically compiled Mesa with the open-source video drivers you're likely to need but there's no way to use dynamic libraries supplied by your hardware's vendor (i.e. Nvidia). If you have an Nvidia card static-wine32 might not be for you.
Yes it is! Intel, AMD and software rendering drivers are included, Nvidia users are out of luck. The Zink OpenGL driver is also included if Mesa provides no OpenGL driver for your hardware.
Vulkan employs a dynamic loading architecture for drivers and layers that wasn't easy to hack away but everything seems to be running OK. However, I'm still working on preincluding the Mesa layers, it shouldn't be long now. Please let me know if you have issues.
I don't use winetricks so I don't know but most of it should, yes. Please let me know if you try it out.
Yes it is! DXVK runs perfectly fine with static-wine32. In fact it should be your first choice if you intend to run Direct3D software and your GPU supports Vulkan. If you're running software using Direct3D versions earlier than Direct3D 9 you should consider using dgVoodoo with DXVK.
Not yet but currently working on it with high priority.
Try building only the graphics drivers that you actually need. Open
Dockerfile and find the lines where the Mesa drivers are
configured, something like
-Dgallium-drivers=swrast,zink,i915,iris,crocus,nouveau,r300,r600,radeonsi
and -Dvulkan-drivers=intel,intel_hasvk,amd,swrast
. Change these to include
only what you need, e.g. -Dgallium-drivers=iris
and -Dvulkan-drivers=intel
.
With enough luck you might be able to remove the LLVM dependency completely
and get a very slim build.
I haven't benchmarked. Per default static-wine32 is compiled with link time optimizations (LTO) so the speed up might be significant. There are rumors on the web that Mesa runs 15-20% faster when compiled with LTO.
Among others the GOG versions of System Shock 2, Deus Ex, Hidden and Dangerous 2, Sid Meyer's Alpha Centauri, Hotline Miami, Hitman: Codename 47, Supreme Commander Gold Edition (sound doesn't work but seems to be a Wine issue), Total Annihilation: Commander Pack; Max Payne, Rainbow Six: Rogue Spear, Fightcade, Microsoft Office 2007, TeamViewer, Winamp Classic.
Make sure you haven't installed a 32-bit Wine through your distro's package manager. If you have, remove it because it'll likely interfere with the static build. I haven't researched it well but I think it's because the static build will load modules of the offical version.
Next, check whether you have any official :i386
libraries which Wine loads
but shouldn't. Libraries like libc, libstdc++, librt, libpthread, libm are
fine, but anything else shouldn't be.
A good way to see what libraries Wine is loading at runtime is
cat /proc/<id>/maps
where <id>
is the process ID of one of Wine's processes.
If nothing else helps you could dedicate a week to build Wine without optimizations and with full debug symbols. You'll deeply regret it so just jump to official Wine while you still can.
I've experienced this on one of my machines but have no I idea what causes it.
I patched numerous libraries to make them compile statically. All the patches are available in the patches directory or in Dockerfile.
Thanks to my friends and their friends for compilation hardware, testing and general support.
Thanks to everybody on the #dri-devel IRC channel for Mesa-related questions.
Thanks to everybody on the #winehackers IRC channel for Wine-related questions, especially nsivov, zf and stefand.
Thanks to all the OSS devs for their hard work.
This project, i.e. the recipe for building a statically linked Wine, is licensed under the 3-Clause BSD License. See the license file for the full text.
Both Wine and my fork with the necessary adjustments are licensed under the GNU Lesser General Public License, version 2.1.
However I can't say what license the end product, i.e. the statically linked Wine itself, would fall under. You should probably limit yourself to personal non-profit use only.