Compile a mixed 32 bit/64 bit wine for Debian

The Wine 🍷 wiki has instructions for building a shared WoW64 WineΒ : this needs two out of source builds. The issue is that some developement packages are not multiarch co-installable. Another wiki page for Ubuntu recommends setting up a 32-bit LXC. Here is how I did it without a 32-bit container on Debian πŸ₯ testing.

Warning

The resulting binary might be broken if some .h files do not match with the expected configuration. If something is not configured correctly, the 32-bit build might end up using some 64-bit only header files (such as /usr/lib/x86_64-linux-gnu/glib-2.0/include/glibconfig.h) resulting in breakage.

git clone git://source.winehq.org/git/wine.git
cd wine

die() {
  echo "$@" >&2
  exit 1
}

setup() {
  RELEASE="$1"
  PREFIX=/opt/"$RELEASE"
  git checkout "$RELEASE"
}

check_state() {
  test -d dlls && test -f configure || die "Not in wine base directory"
  test -n "$RELEASE" || die "No RELEASE variable"
  test -n "$PREFIX" || die "No PREFIX variable"
}

setup wine-1.7.34

Update 2015-04-29: There is a SONAME issue which prevents wine to build against the debian version of gnutls (which uses libgnutls-deb0.so.XX as a SONAME). In order to avoid this you need to apply the debian-gnutls.patch from the debian source package. A simple fix is to use:

sed -i 's/NEEDED\.\*libgnutls/NEEDED.*libgnutls-deb0/ ' ./configure

Update 2018-02-18: added CPATH environment variable.

Compilation for 64 bit

This one is easy (once the needed packages are installed):

compile64() {
    (
    check_state
    mkdir wine64 &&
    cd wine64 &&
    ../configure --prefix=$PREFIX --enable-win64 &&
    make
    )
}

Compilation for 32 bit

Setup some missing environment

The issue is that some -dev packages are currently not multiarch-coinstallable. We'll install them in a local directory and fix some things:

  • the symlinks of the .so files;

  • the paths in the .pc files.

packages="
  libfontconfig1-dev:i386
  libfreetype6-dev:i386
  libglib2.0-dev:i386
  libglu1-mesa-dev:i386
  libgnutls28-dev:i386
  libgstreamer0.10-dev:i386
  libgstreamer-plugins-base0.10-dev:i386
  libosmesa6-dev:i386
  libxcomposite-dev:i386
  libxi-dev:i386
"

prepare_env() {
    (
    check_state

    mkdir helpers && cd helpers || die "Could not create helper directory"

    # Get the packages:
    apt-get download $packages || die "Could not get packages"

    # Extract the packages here:
    for p in *.deb; do dpkg -x "$p" . ; done

    # Fix the path fo the .pc files:
    sep="|"
    sed -i "s${sep}^prefix=/usr*${sep}prefix=$(pwd)/usr${sep}" $(find usr | grep \.pc$)

    # Fix the symlinks:
    cd usr/lib/i386-linux-gnu || die ":/"
    for f in *.so ; do
    link="$(readlink "$f")" || die "Could not read link for $f"
    rm "$f" && ln -s /usr/lib/i386-linux-gnu/"$link" "$f" || die "Coule not fix $f, too bad"
    done
    # This one is somewhere else:
    rm libglib-2.0.so && ln -s /lib/i386-linux-gnu/libglib-2.0.so.0.4200.1 libglib-2.0.so || die "Could not setup glob symlink"
    )
}

Update 2018-02-18: this time I used packages="ocl-icd-opencl-dev:i386 libdbus-1-dev:i386 libgnutls28-dev:i386 libgstreamer1.0-dev:i386 libxml2-dev:i386 libxslt1-dev:i386".

Compilation

We use this environment to build the 32 bit version:

compile32() {
    (
    check_state

    export PATH="$(pwd)/helpers/usr/bin:$PATH"
    export CPATH="$(pwd)/helpers/usr/include/i386-linux-gnu:$(pwd)/helpers/usr/include:$CPATH"
    export LDFLAGS="-L$(pwd)/helpers/usr/lib/i386-linux-gnu"
    export LD_LIBRARY_PATH="$(pwd)/helpers/usr/lib/i386-linux-gnu"
    export LD_RUN_PATH="$(pwd)/helpers/usr/lib/i386-linux-gnu"
    export PKG_CONFIG_PATH="$(pwd)/helpers/usr/lib/i386-linux-gnu/pkgconfig/"

    mkdir wine32
    cd wine32

    ../configure --with-wine64=../wine64 --prefix="$PREFIX" &&
    make
    )
}

Installation

Install 32 bit first and 64 bit next:

do_install() {
    check_state
    (cd wine32 && sudo make install) &&
    (cd wine64 && sudo make install)
}