Building legacy PySide 1.2 for new versions of Python

Recently, I found myself in a situation where I needed to use the good old PySide 1.2, which, unfortunately, doesn't appear to be maintained anymore, and I didn't want to use a deprecated version of Python. Building it in a recent environment is not quite as simple as a pip install, but it's not that hard, either. Read on to find out how to go about it.

To start off, you'll need to have a full build environment installed in your system, as well as a version of Qt 4 including all the development headers, and, of course, Python 3 with headers. Personally, I run Gentoo, so I usually have all of that installed by default; on Ubuntu, you'd typically need packages like build-essential, cmake, qt4-default, and python3-dev. Adjust accordingly for whatever distribution you're using.

Now, let's move on to the installation itself. We start by creating a virtualenv with our target version of Python – it won't actually contain much, but I generally don't keep pip installed in my global system Python environment, I only run it from within virtualenvs. We will, however, need to install wheel in there (so we might as well just upgrade pip and setuptools to their latest versions). We then use pip to fetch the latest tarball of PySide, and unpack the source:

python3 -m venv env-pyside-build
. env-pyside-build/bin/activate
pip install -U pip setuptools wheel
pip download pyside
tar xzf PySide-1.2.4.tar.gz
cd PySide-1.2.4

In a perfect world, all we'd have to do would be to build a wheel, but PySide is not aging particularly well, so it needs a few manual adjustments. First, the included checks that the version of Python you're running is listed in the trove classifiers, otherwise it refuses to run. Since there hasn't been an update to PySide since Python 3.4 times, we have to add our desired Python version to the classifiers.

A second issue I've encountered is that the build system attempts to build bindings for QGtkStyle, which has rotted away already, so the build fails. It doesn't appear to be a very important class, though, so we just remove all mentions of this binding.

I've prepared a handy diff file for you to download, and apply to the PySide source tree, which does both of these tasks:

patch -p1 <pyside-modern.diff

It might happen that you're reading this far enough in the future that a higher version of Python has been released than 3.7; in that case, you'll have to add it to manually.

Now, finally, we can get to the building part. You'll have to tell the build system where to look for the Qt 4 version of qmake; on Gentoo, that would be /usr/lib/qt4/bin/qmake, on Ubuntu, it'd probably be something like /usr/bin/qmake-qt4. You'll also have to decide whether you want to bundle the Qt 4 libraries inside the PySide wheel, in that case, use the --standalone switch, otherwise, just leave it out, and it will just use whatever Qt libraries are installed system-wide.

Another thing to consider is that the build takes a while, so if you have multiple CPU cores, you might want to parallelize it – to the best of my knowledge, there's no official simple way of passing the number of parallel processes to make through Python setuptools, but at least with the standard GNU make, you can hack around this with the MAKEFLAGS environment variable. You basically tell make to spawn as many processes as it wants by passing -j to it without any number, until the system load reaches a certain value which you specify with -l<number>; then it tries to maintain that level of load. You'd set this number to roughly the number of cores, and it has a somewhat similar effect to -j<number>. The downside is that there's a chance that it will spawn too many processes in the beginning, until the load reaches a high enough value (remember, system load is averaged over the last minute, so it takes a moment to reflect momentary load), so maybe set it a bit lower if you don't have enough RAM to accommodate the initial spike of several dozen compiler processes.

So, putting everything together, the magical incantation that I used on my system was:

MAKEFLAGS='-j -l10' python bdist_wheel --qmake=/usr/lib/qt4/bin/qmake --standalone

Now, just sit back for a couple-five minutes, and once it's done, voilà, in a new dist subdirectory, you have a new wheel of PySide for your version of Python that you can simply install with pip.


Comments powered by Disqus