Have an awesome Windows application that you want to use on Linux? And it works in Wine? Awesome, let’s create a snap for it!
This thread puts all the info about creating Wine snaps in one place. There’s a bunch of people doing cool stuff with Wine in snaps, so let’s gather what we learned here to make it easier. This is currently mostly a collection of useful info but if you want to create a full-on tutorial, go ahead! If you post it here, I can include it.
Honorable mention to Winepak, a similar initiative making it easy to put a Windows application inside a Flatpak.
- Why do I need a snap? I can use Wine!
- How do I create a WineSnap?
- Tips and tricks
- What are the components of a WineSnap?
- Installing Wine
- Installing and running the application with
- Figuring out what dependencies and config are needed
- Showing loading screens and menus with
- How can we make WineSnapping easier?
(Anyone has any idea how I can create a table of contents with hyperlinks?)
Why do I need a snap? I can use Wine!
Some advantages of using Wine in a snap vs using it directly on your machine:
- Easy to install. No more messing around tweaking Wine, installing dependencies, and Windows libraries. Just a few clicks and the application is installed.
- Available in the Ubuntu Software store. While PlayOnLinux and Lutris also offer easy installation of Windows applications, each of these applications has a separate store. Having to search through multiple stores to find a game depending on whether it’s a native Linux application, it runs on Wine or another emulator is a hassle. It’s easier to have a single place for all applications so users get the habit of searching the software store when they want to install an application.
- Sandboxed. Windows applications running in Wine normally have full access to your operating system, so when an application crashes, does stupid things, or is infected, it can mess up your operating system. Snaps only have limited access to your host operating system so your computer is a lot better protected from buggy Windows applications and buggy Wine.
- All dependencies included. Snaps contain all the dependencies that an application needs, so you don’t have to install additional libraries or mess with your system in order to install a single application.
- Snap once, run anywhere*, anytime**. Once an application is snapped, you can install it on a large number of Linux distributions and it will keep working for a very long time. It should be noted, however, that *not all distributions are supported as well as Ubuntu and ** snapd might change in a backward-incompatible way in the distant future.
How do I create a WineSnap?
Roughly speaking, there are two kinds of Wine snaps. Either the snap includes the application preinstalled, or the snap downloads and installs the application and dependencies during the first run. Preinstalled snaps have a better user experience, but know that it might not be legal to distribute the application or the libraries it depends on.
These are some examples of good, working snaps. I recommend you start from one of these examples, clone/fork the repo and change the code to install the application you want.
- PhotoScape [first-run install]
- SteamForWindows [first-run install]
- Track Mania Nations Forever [first-run install]
- Foobar2000 [preinstalled]
- Notepad++ [preinstalled]
- Command and Conquer: Tiberian Sun [first-run install]
The SteamForWindows snap has a list of things to do when you create a new snap based on it. Below is a thorough explanation of all the components of a WineSnap and what you should consider when creating one.
Tips and Tricks
SNAPCRAFT_CONTAINER_BUILDS=1 snapcraft. This builds your snap inside a 16.04 container just like
cleanbuild, but it doesn’t throw away the container. It reuses the container for all next builds so that you get the isolation of a container, but the speed of a local build. Other commands like
SNAPCRAFT_CONTAINER_BUILDS=1 snapcraft clean <part>clean that part inside the container.
set -ein your bash scripts to show debugging output.
snap remove <name>to remove all data including the Wine namespace if you want to simulate a clean install of a snap.
What are the components of a WineSnap?
This part explains all the components of a WineSnap, how everything works, and all the things that I tripped over, so you can refer back to this info when you’re creating your snap.
The first thing we need is Wine itself installed in the snap. Because 64-bit wine is very buggy, we’re using 32-bit wine, even though most computers run 64-bit Linux.
The snapcraft.yaml file describes how wine is installed.
enable-i386part makes it possible to include 32-bit packages in a snap
winedownloads and installs your preferred wine version directly from the packages provided by winehq itself.
wine-runtimeincludes all the dependencies of wine.
You can specify a specific wine version by changing the variables in the
override-build section of the
WINE_REL="wine-staging" WINE_ARCH="i386" WINE_VER="3.10.0"
Note that all the
stage-packages end with
:i386. This tells
apt to install the 32-bit version of the library instead of the 64-bit version of the library. This is because 32-bit programs like the 32-bit version of wine can only use 32-bit libraries. Check out Debian’s multiarch howto for more information about how to install and use 32-bit libraries in a 64-bit Debian-based distribution.
Since we’re only using 32-bit libraries, the snap can run on both 32-bit and 64-bit systems. However, it needs to be built on 64-bit. (I don’t know why. If you do, please let me know.)
architectures: - build-on: amd64 run-on: [amd64, i386]
This is also the reason why we can’t use the snapcraft-desktop-helpers since those are 64-bit only. https://github.com/ubuntu/snapcraft-desktop-helpers/issues/126
Installing and running the application with
Sommelier is a helper script in
scripts/sommelier to install and start applications inside of wine in a snap. It originally comes from the
SteamForWindows snap. The script has some modularity and customization built-in but you’ll probably have to change some parts of the script. If you’re interested in making
sommelier more modular so all wine snaps can use the same script, go ahead and let us know your progress.
Sommelier first sets up loads and loads of environment variables to make both Wine and
yad work inside of the snap. At the end of the script, it either installs the application or starts it if it’s already installed.
winetricks is used for the installation of dependencies and configuration of the wine environment. Winetricks is a (not-snap-specific) helper script to work around issues in Wine. It can install Windows libraries on demand and it has a number of automatic profiles tailored to certain applications. It’s basically a lightweight command-line version of PlayOnLinux. Winetricks is a single script. You can get the latest version from their Github repo. It’s best not to change Winetricks yourself.
To install additional libraries or configure wine using winetricks, you set the
TRICKS environment variable in the
apps part of the snapcraft.yaml file.
TRICKSis a space-separated list of winetricks commands to execute. These can be library names, application names or
<key>=<value>settings. Each will be executed by sommelier during the install phase.
DLLOVERRIDESspecifies which library the application should use first. The native one (
n; provided by Wine), or the builtin one; (
b; provided by the application, taken from windows or installed by winetricks). This functionality is the same as setting a DLL override in the winecfg utility. More info
environment: WINEPREFIX: "$SNAP_USER_COMMON/.wine" DLLOVERRIDES: "mscoree,mshtml=;gdiplus=n,b" # "mscoree,mshtml=" Prevents pop-ups asking to install Wine Mono and Wine Gecko. TRICKS: "fontsmooth=rgb gdiplus vcrun2008" LC_ALL: "C.UTF-8"
Figuring out what dependencies and config are needed
The SteamForWindows snap and any based on it contain three extra CLI tools useful for debugging and trying out what dependencies are needed.
winecfgis a GUI to configure the Windows version, library overrides, graphics, desktop integration, and more.
winetricksis winetricks. Running it will run the winetricks command in the wine namespace of the app.
winebootsimulates a windows OS reboot.
You can use these tools to get the application installed and running manually, and then update the snap to do all that stuff by default.
To run the tools, prefix them with the name of the snap. For example, the following command will run the Wine config GUI in the namespace of the PhotoScape snap.
Showing loading screens and menus with
yad is a command-line tool to show menus, loading screens, and other GUI’s. This is an easy way to show a GUI from a bash script. It’s API compatible with
Zenity, but it has a lot fewer dependencies and it’s easier to package in a snap. The file in
scripts/Zenity is a wrapper for yad to mimic
zenity, so applications that use Zenity like winetricks still work in the snap.
Note that there is currently a bug where it takes ~1 minute for the first yad window to appear after a clean install of the snap. I don’t know why this is, I think GTK is rebuilding font caches or something. If anyone knows how to fix this, let me know. A band-aid solution is to create a notification using
notify-send right after your application starts to let the user know that it has indeed started and us doing stuff in the background.
yad is very useful to show a loading screen while the application is installing or to show a menu screen to select different game modes for example.
Example yad loading screen
The loading screen in PhotoScape is made with yad.
install_app | tee /dev/stderr | yad --progress --width 350 --pulsate --text "Installing the application, this might take a few minutes." --title "Installing application" --auto-close
progress window of yad displays each line on
stdin that starts with a
# as the text above the loading bar.
install_app is a bash function that prints status messages starting with a
#. Its output is first duplicated to
stderr so that you can still see all the output if you run it from the command-line. This will greatly help debugging. (yad captures all
Example yad menu
The menu screen in Command and Conquer: Tiberian Sun is made with yad.
action=$(yad --width 400 --entry --title "C&C Tiberian Sun" \ --center \ --width=400 \ --button="Install:0" --button="Exit:1" \ --text "Select Game Version Type:" \ --entry-text \ "Full Game (Singleplayer + Multiplayer)" "Multiplayer") ret=$? [[ $ret -eq 1 ]] && exit 0 case $action in Full*) cmd=$(install_ts) ;; Multi*) cmd=$(install_cnc) ;; *) exit 1 ;; esac eval exec $cmd
More yad examples
yad is API compatible with
zenity, you can use the docs for both tools.
How can we make WineSnapping easier?
Are there ways we can make it easier to create these snaps?
- Many of the wine snaps include copy-pasted boilerplate code. It would be useful if we could figure out a way to use more common parts. Would it be possible to create a remote part to install wine and sommelier? Is anyone interested in hacking on this? Winepak has an interesting approach; they have a platform snap that provides wine and they use extensions for different wine versions.
- The Phoenicis (PlayOnLinux successor) people are trying to create a snap package for it, but they seemed to have hit a brick wall ~december. Anyone with experience with snapping a Java GUI application that can help them out?
- The Lutris guys have extensive knowledge of Wine and wrapping installers. They’re currently looking into Flatpak, but they’re open for contributions for snap support. This seems interesting both for lutris-in-a-snap and lutris-installing-a-snap. Lutris itself can be a classic snap that calls the
snapCLI on the host to install wine games.