[ Post updated 2018-02-03, see new Build Steps section below. ]
wxPython Wheels for Linux?
Before reading further, you may want to check and see if there are already
some wxPython wheels available for your flavor of Linux. A few are built as
part of the release process and are available from one of wxPython's
servers. More details and some links are on the
download page.
If there are no existing wheels there for your distro, (or perhaps a close
relative,) then read on to find out why we can't just provide wheels for
all Linuxes, and what you need to build one for yourself.
The Problem
There have been some issues flowing into Phoenix's issue tracker since the
release of wxPython 4.0.0b1 related to installation issues on Linux using
pip, which have caused some overhead and soaked up unnecessary amounts of
time. So lets start with getting some of the basics out of the way. There
are a lot of flavors of linux. To name a few there's the Debian family,
Debian, Ubuntu, Kubuntu, Elementary, Mint, etc., Arch, Gentoo, RHEL and CentOS,
and so on. Each flavor has differences which can make binary distributions
incompatible across flavors.
Why does this affect wxPython you may ask? It's just a Python package, and
Python source is independent across operating systems after all, right?.
Well, not all Python packages are just Python. wxPython as an example
contains binary extension modules (compiled C or C++ code that is platform
and architecture dependent.) wxPython by default also contains a copy of
the compiled version of the wxWidgets library written in C++, which also
depends on other 3rd party libraries which need to not only be present at
runtime, but also have their development-related files present at
wxWidgets' and wxPython's compile time.
Pip in its infinite wisdom can detect this, and knows how to select the
appropriate binary wheel for the following criteria:
- OS (Windows, macOS, Linux)
- Architecture (i386, x86_64, etc)
- Python Version (2.7, 3.5, 3.6, etc)
See how pip doesn't care about the specific linux distribution? That's the
issue. The binary content and dependencies of wxPython can't be delivered
consistently via pip. There are some efforts to get around this (eg. PEP
513 a.k.a. manylinux1
) but
they don't quite work for wxPython yet. Packages that are able to fit into
the very narrow manylinux1
requirements can be hosted on PyPI and will
install with pip just as smoothly as pure-python packages do. Unfortunately
the manylinux1
spec does not include a version of GTK+ and its
dependencies that are new enough to be able to provide all the features
that wxWidgets requires.
The Fix
In order to deploy to linux systems wxPython4 (Phoenix) simply builds
itself from a source tarball as part of the pip setup process. All of the
code generated by wxPython's build system is already present in the
tarball, it merely needs to be compiled. This causes a very lengthy
installation times, but is a necessary evil. Because the build is just
that, a build, you will need all of wxWidgets and wxPython's binary
dependencies present at build time. wxWidgets' configure will be run, and
if it detects missing libraries the whole build, and therefore the pip
installation, will fail.
What You Need
You will need the following packages (please consult your distribution's
package list for the appropriate package names) and their dependencies:
- python-dev (for your version of python)
- gtk (preferably version 3, but depends on your needs)
- gstreamer
- gstreamer-plugins-base
- glut
- libwebkitgtk (matching your gtk version)
- libjpeg
- libpng
- libtiff
- libsdl
- libnotify
- libsm
on Debian based systems, or other systems that separate development
packages from standard packages, you will need the corresponding -dev
or
-devel
package in addition to the standard package.
Once the appropriate packages are present on your system then wxPython
should build with no problems, either with pip or from a source tree
extracted from the source tarball. If it still doesn't work for you then be
sure to look closely at the build log as there will likely be some clues
there that may point you in the right direction. For example, this:
checking for OpenGL headers... not found
checking for GL/gl.h... no
configure: error: OpenGL libraries not available
will tell you that the OpenGL libraries are missing. They are usually a
dependency of the glut or freeglut packages and should have been installed
along with that library, but perhaps your system's dependencies are
different and you'll need to do a little investigation to determine the
proper system packages that need to be installed.
Build Steps
Once you have installed the required depenency libraries, it should take
just a few steps to build a wxPython that will work on your system with
your Python. The steps shown here are just one option, but seems to be one
of the simpler approaches to take, and will require nothing extra to be
installed in your system Python. These instructions assume that you will be
using a 3.4+ version of Python and that the executable is called "python3".
If you are using 2.7 or the binary is called something else then adapt
accordingly.
Step 1: The first thing we'll do is create and activate a new virtual
environment for the build and the initial testing. This is optional, but
highly recommended as it will ensure that there is nothing left over from a
previous build that could trip things up. The last two commands shown here
are just so you can verify that the python and pip commands are now being
found in the new virtual environment instead of from the system or other
Python environment.
cd [some tmp folder]
python3 -m venv builder_py
source builder_py/bin/activate
which python
which pip
Step 2: Next, you'll want to update pip and add a few more packages.
pip install -U pip
pip install -U six wheel setuptools
Step 3: Use pip to download the latest source archive from PyPI.
pip download wxPython
Step 4: Use pip to build a wxPython wheel file. We'll also redirect the
build output to a file so you can review it later if needed. This step will
take a while to complete, as it will be compiling all the wxWidgets and
wxPython source code, but you'll be able to watch the build output to
monitor the progress. Be sure to use the actual name of the downloaded
source archive file, which may be different than the one shown here.
pip wheel -v wxPython-4.0.1.tar.gz 2>&1 | tee build.log
Step 5: If the build was successful then you should now have a wxPython
wheel file in the current working directory. If there was a problem then
review the build.log
file and see if you can spot any clues as to what
dependencies may be missing or out of date. (Build problems from wxPython
release sources are almost always due to missing dependencies.) Once you
think you have solved the problem go back to step 4 and try the build
again.
Step 6: The next step is to install the wheel file in the virtual
environment and give it a quick test run. (Use the actual name of the wheel
file you built, which may be different than the one shown here.)
pip install wxPython-4.0.1-cp35-cp35m-linux_x86_64.whl
python -c "import wx; a=wx.App(); wx.Frame(None,title='hello world').Show(); a.MainLoop();"
You should see a new window open with a "hello world" title bar, which will
indicate that this build was successful and this wxPython wheel can be used
on your system. You can now use pip to install the wheel file in other
Python environments or virtual environments that use the same base Python
executable that you used for this build.
Known Issues
wxPython's build tools on Linux assume that the Python being used was configured
with the --enable-shared
flag. That is usually true for Pythons installed from
the Linux distro's repositories, as well as for most known 3rd Party Python
distributions for Linux. However, that flag is not enabled by default. So if
your Python is one that you've configured and built yourself, then double-check
that you used the flag. If it wasn't then you'll likely see a configuration
error when the build gets to the wxPython portion (after it has built
wxWidgets).
Similarly, the pyenv does not use the
--enable-shared
flag when it builds a Python environment for you.
There is a note in the
pyenv wiki
that shows how to add the flag when it builds a new Python environment.
FAQ
Q1: "Why can't you just install the necessary packages as part of
wxPython's installation"
A1: Lots of good reasons, among them are: Pip is NOT your linux package
manager, Phoenix is not responsible for maintaining your system.
Q2: "I can install PyQt(4/5) just fine via pip! Why can't wxPython do the
same?"
A2: Qt does not depend on system provided libraries other than the low-
level basic libs. wxWidgets does, it's one of the defining differences of
the two toolkits. As such PyQt can deliver to all linuxes in the same
manner.