WineHQ

Pop! os: Difference between revisions

(Created page with "= Building Wine in Pop!_OS = While Pop!_OS, like Ubuntu, has support for multi-arch libraries, some i386 packages that are required to build a 32-bit version of Wine may conf...")
(No difference)

Revision as of 00:44, 30 March 2023

Building Wine in Pop!_OS

While Pop!_OS, like Ubuntu, has support for multi-arch libraries, some i386 packages that are required to build a 32-bit version of Wine may conflict with pre-installed system packages, so you won't be able to install them.

For this reason, in this tutorial we will use LXD to create a 64-bit Ubuntu LXC container were we will install the required packages, build Wine with WoW64 support, and then use it to our host system.

We start by creating a working directory:

mkdir $HOME/wine-dir
cd $HOME/wine-dir

Setting up an LXC container

This Section is based on the official Pop!_OS documentation on containers.

We use LXD to create the Ubuntu container.

Install LXD through snap:

$ sudo apt install snapd
$ snap install lxd

Add your current user to the lxd group so that it has the correct permissions to use the application:

$ sudo usermod -aG lxd $USER
$ reboot # to apply permissions.

Initialize LXD:

$ lxd init

If you don't want containers to automatically start on boot:

$ lxc profile set default boot.autostart false

Launch an Ubuntu container:

$ lxc launch ubuntu:20.04 wine-container

Start the container:

$ lxc list
$ lxc start wine-container

and update:

$ lxc exec wine-container -- apt update

To enter container, use the following command:

$ lxc exec wine-container -- /bin/bash

In order to share files between the host and the container, we have two options:

  • (a) Setup a shared host directory inside the LXC container in read-write mode.
  • (b) Pull and push directories every time we need to.

Option (a) is probably the most comfortable in the long run, if you need to compile wine many times, but it requires special permissions and a longer setup.

We will use Option (a) in this tutorial. For Option (b) see #Pushing and pulling files from the container without a shared directory.


Setup a shared host directory inside the LXC container

This Section is based on a tutorial from nixCraft.

Allow remaping the user ID in the host

First, we need to know our user id in the host, for that purpose we can use the id command:

$ id

This is an example output:

uid=1000(alice) gid=1000(alice) groups=1000(alice),4(adm),27(sudo),121(lpadmin),999(lxd)

We see that our user (alice in this example) has user id (uid) 1000, and group id (gid) 1000.

Now, we need to give permission to the root user (and thus, the LXD daemon) to remap the user id and the group id.

We do that by adding new lines to the /etc/subuid and /etc/subgid files, respectively:

$ echo "root:1000:1" | sudo tee -a /etc/subuid
$ echo "root:1000:1" | sudo tee -a /etc/subgid

where we need to replace the 1000 with our uid in the first line, and to replace the 1000 with our gid in the second line.

Remap user ID inside the container

The next step is to remap the user ID inside the container, so we need to enter it, with the aforementioned command:

$ lxc exec wine-container -- /bin/bash

After entering the container, we need to know if our user is already present inside:

# grep '^alice' /etc/passwd

If no line appears, we need to create it:

# adduser alice

We now need the uid and gid our user inside the container:

# id alice

This is an example output:

uid=1001(alice) gid=1001(alice) groups=1001(alice)

in this case the uid and the gid are 1001.

Now we go back to the host, and map both the uid and gid from our user in the host to our user in the container:

$ lxc config set wine-container raw.idmap "both 1000 1001"

where we replace the 1000 and 1001 accordingly.

And we restart the container:

$ lxc restart wine-container

Finally, we can mount the directory:

$ lxc config device add wine-container wine-dir disk source=$HOME/wine-dir path=/root/wine-dir

Download the wine source code

We clone the wine repo inside the wine-dir directory, in the host system:

$ cd $HOME/wine-dir
$ git clone https://gitlab.winehq.org/wine/wine.git wine-source

We can then select a specific branch or tag:

$ cd wine-source
$ git checkout stable

Install wine dependencies in the container

We need access to the source code repositories inside the container, so we enter the container again:

$ lxc exec wine-container -- /bin/bash

Uncomment all deb-src lines after uncommented dev lines in /etc/apt/sources.list using nano or vim:

# nano /etc/apt/sources.list

Also, add the i386 arch, and update:

# dpkg --add-architecture i386
# apt update

Install both x86-64 and i386 wine dependencies

# apt-cache depends wine # Just lists distro's wine package dependencies.
# apt build-dep wine64
# apt build-dep wine32:i386
# apt install gcc-multilib g++-multilib
# apt install libx11-dev:i386 libfreetype-dev:i386 libgnutls28-dev:i386 ocl-icd-opencl-dev:i386 libvulkan-dev:i386
# apt install gcc-mingw-w64

You may need more, check the Building Wine page.

This is a list of packages that works at the time of writing:

# apt install libgl-dev libpulse-dev libdbus-1-dev libfontconfig-dev libxrender-dev gettext libxcursor-dev libxi-dev libxrandr-dev libxfixes-dev libxinerama-dev libxcomposite-dev libosmesa6-dev libpcap-dev libsane-dev libusb-1.0-0-dev libv4l-dev libgphoto2-dev libgphoto2-dev libudev-dev libsdl2-dev libcapi20-dev libkrb5-dev libopenal-dev libldap-dev libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-good1.0-dev libpng-dev libjpeg-dev libtiff-dev

and their i386 versions:

# apt install libgl-dev:i386 libpulse-dev:i386 libdbus-1-dev:i386 libfontconfig-dev:i386 libxrender-dev:i386 gettext:i386 libxcursor-dev:i386 libxi-dev:i386 libxrandr-dev:i386 libxfixes-dev:i386 libxinerama-dev:i386 libxcomposite-dev:i386 libosmesa6-dev:i386 libpcap-dev:i386 libsane-dev:i386 libusb-1.0-0-dev:i386 libv4l-dev:i386 libgphoto2-dev:i386 libgphoto2-dev:i386 libudev-dev:i386 libsdl2-dev:i386 libcapi20-dev:i386 libkrb5-dev:i386 libopenal-dev:i386 libldap-dev:i386 libgstreamer1.0-dev:i386 libgstreamer-plugins-base1.0-dev:i386 libgstreamer-plugins-good1.0-dev:i386 libpng-dev:i386 libjpeg-dev:i386 libtiff-dev:i386

We can also install ccache to lower our build times in case we need to build Wine many times:

# apt install ccache

And other packages that you may want, such as valgrind:i386.

Building 64-bit wine

Let's start by building a 64-bit version of Wine inside the container.

# cd /root/wine-dir
# mkdir wine64
# cd wine64
# ../wine-source/configure --enable-win64 CC="ccache gcc" CROSSCC="ccache x86_64-w64-mingw32-gcc"

Where the CROSSCC option allows cross compiling modules as PE.

If you don't use ccache, remove ccache in both arguments.

Read the configure script output. If you need more libraries, install them as in the previous step, otherwise continue.

Run:

# make -j8 # or as many CPU threads you have available.

Building 32-bit wine-tools

Now we need to build a 32-bit version of Wine and inject it into our 64-bit Wine build to turn it into a WoW64 Wine, so that it supports 32-bit Windows applications, since most of them indeed are 32-bit.

Before we build a 32-bit wine, we need the 32-bit wine-tools, so we make a provisional 32-bit version of Wine:

# cd /root/wine-dir
# mkdir wine32-tools
# cd wine32-tools
# ../wine-source/configure CC="ccache gcc" CROSSCC="ccache i686-w64-mingw32-gcc"
# make -j8 # or as many CPU threads you have available.

If you don't use ccache, remove ccache from the options.

Building 32-bit wine

# cd /root/wine-dir
# mkdir wine32
# cd wine32

Configure and make:

# ../wine-source/configure --with-wine64=../wine64 --with-wine-tools=../wine32-tools CC="ccache gcc" CROSSCC="ccache i686-w64-mingw32-gcc"
# make -j8 # or as many threads you have available.

Again, if you don't use ccache, remove ccache from the options.

Fixing symbolic links

Some links may have absolute paths for within the container. These need to be fixed.

We can inspect all the symbolic links:

$ cd $HOME/wine-dir
$ find wine32 wine64 wine32-tools -type l -ls

In particular the offending ones:

$ find wine32 wine64 wine32-tools -type l -ls | grep '-> /root/'

At the moment of writing, there are two links that need to be changed, the ones that the 64-bit build uses to refer to the 32-bit build:

... wine64/loader/wine -> /root/wine-dir/wine32/loader/wine
... wine64/loader/wine-preloader -> /root/wine-dir/wine32/loader/wine-preloader

We change them inside the container:

# cd /root/wine-dir
# rm wine64/loader/wine wine64/loader/wine-preloader
# ln -s ../../wine32/loader/wine wine64/loader/wine
# ln -s ../../wine32/loader/wine-preloader wine64/loader/wine-preloader

Install runtime dependencies in the host system

Wine requires access to some dynamic system libraries to run.

As mentioned in the Building_Wine#Runtime_Dependencies section of the Building Wine page, the easiest way to achieve this is to install the wine package provided by the distribution in the host system:

$ apt install wine

Keep in mind that the wine command will execute the version of wine that this package installs, and not the one you build.

You may also want to install optional runtime dependencies such as:

$ apt install corefonts

Run wine

You should be able to run wine from your build now, remember to use it with a prefix.

$ PREFIX=$HOME/wine-dir/wine-prefix $HOME/wine-dir/wine64/wine --version

We can stop the container now

lxc stop wine-container

Pushing and pulling files from the container without a shared directory

If you don't want to set up a shared directory between the host and the container, an alternative is to use the lxc file push and lxc file pull commands to send and retireve files from the container.

The syntax is:

lxc file push -r <host-src-directory> wine-container/root/<container-dst-directory>
lxc file pull -r wine-container/root/<container-dst-directory> <host-dst-directory>

Keep in mind that symbolic links end up invalid in the host system after pulling, because lxc file pull makes their paths absolute and respective to the container filesystem. Check the symbolic links using:

$ find <pulled-directory> -type l -ls

We can fix them running the following link_fixer.sh script in the same folder we pulled the directory.

#!/bin/bash

PULLED_DIRECTORIES="$@"

find $PULLED_DIRECTORIES -type l | while read symlink; do
    if [ ! -e "$symlink" ]; then
        old_path=$(readlink "$symlink")
        # Remove the '/root/' prefix and change it with the current path ${PWD}
        new_path=${old_path/\/root\//${PWD}\/}
        new_path=$(realpath --relative-to="$(dirname "$symlink")" "$new_path")
        ( set -x; ln -f -s "$new_path" "$symlink")
    fi
done
$ bash link_fixer.sh <host-dst-directory>
This page was last edited on 30 March 2023, at 00:44.