wxpython provides some prebuilt wheels for linux, with both gtk2 and gtk3 bindings; however, those wheels only support a limited subset of linux environments; if your linux environment is not one of those then you will be out of luck; for example, these are the linux environments currently supported by the gtk2 binding:

  • centos-7
  • debian-8
  • debian-9
  • fedora-23
  • fedora-24
  • fedora-26
  • ubuntu-14.04
  • ubuntu-16.04
  • ubuntu-18.04

obviously, fedora-26 is old; people using a newer version of fedora must help themselves; in this article i will describe how i helped myself, and possibly you; specifically, i shall demonstrate how to build a wheel for wxpython with gtk2 binding on fedora-29; the build environment is python 3.7.2 on a x86_64 machine;

quickstart

the version i am building is wxPython-4.0.4, the latest stable version; it is recommended to read its readme, carefully; it is a lengthy readme, but has some important notices and steps we must follow;

get source

a build process starts with fetching the source code; normally, we can either download a source tarball, or checkout a git repo; however, in this case, it is strongly recommended to use a source tarball, because it contains the complete source code; you can download it here: wxPython-4.0.4.tar.gz; if the link becomes invalid, you can search on its pypi;

if you still prefer fetching from its git repo, dont forget to also fetch its submodules with --recurse-submodules:

git clone --branch wxPython-4.0.4 --recurse-submodules https://github.com/wxWidgets/Phoenix.git

build

in addition to the normal setup.py, wxpython provides a script build.py; you may run this script, but dont run it as ./build.py because its shebang may not be the python version you want; instead, execute it using a known correct python version like this:

$ python3.7 build.py --help

its readme says, build.py and setup.py depend on each other, but build.py gives greater control over the build process; so we will be using build.py in our build process;

some build commands have strange names: dox, etg, sip and build; dont care about what they are; to make a build, you need only 4 commands in total, and the first 3 run reasonably fast; note that these commands must be run in order; however, once a command succeeds, it doesnt have to be run again unless you have changed something for that command to process;

so lets start the build:

$ python3.7 build.py dox etg --nodoc sip build --gtk2 -j 4

after several minutes, it should fail with:

/usr/bin/ld: cannot find -lwx_gtk2u_webview-3.0
collect2: error: ld returned 1 exit status

our journey just begins;

debug

the error info shows we are missing a shared library; so this command should give nothing:

$ ldconfig -p | grep wx_gtk2u_webview-3.0

indeed; but lets relax it a little bit:

$ ldconfig -p | grep wx_gtk

this time there are some interesting results:

...
libwx_gtk3u_webview-3.0.so (libc6,x86-64) => /lib64/libwx_gtk3u_webview-3.0.so
...

in this case i am lucky: i have similar packages installed on my system which helped me debug this; you may not get the same result if you dont have these packages; but lets continue with my story;

dnf provides told me this shared library libwx_gtk3u_webview-3.0.so comes from wxGTK3-devel package; so i installed wxGTK and wxGTK-devel packages, hoping for some gtk2 port of the same thing; but no, they dont have it;

then i found i was an idiot; wxpython source code comes with wxwidgets, and wxgtk is a port of wxwidgets (using the gtk+ library); so i should debug the wxwidgets library shipped with the wxpython source code, not looking for one among my system libraries;

now let us dig into wxwidgets itself to find out what is happening; the readme says wxwidgets is located at ext/wxWidgets; so i entered its dir and tried to compile it separately;

check its configure options:

$ ./configure --help
...
--enable-webview        use wxWebView library
...
--with-gtk[=VERSION]    use GTK+, VERSION can be 3, 2 (default), 1 or "any"
...

looks relevant; lets configure:

$ ./configure --enable-webview --with-gtk=2
...
checking for WEBKIT... configure: WARNING: webkitgtk not found.
configure: WARNING: WebKit not available, disabling wxWebView
...

now the problem is clear: i dont have webkitgtk installed on my system; i tried to install this package with dnf, but there is no such package; in fact, it has been retired since fedora 27 due to security vulnerabilities (link1, link2);

after some research, i grabbed a webkitgtk source rpm from fedora 26 and threw it on copr; nope, it didnt build; failed and failed again; the build takes long long time, and logs are not very helpful; anyway, it is usually hopeless when a package gets obsoleted by a distro; the build script is no longer maintained;

solution 0

the solution i came up with was very simple: drop webview support from wxpython; in fact, webview needs to link libwebkitgtk-1.0.so at run time; if this shared library is not available then it cannot be used even if the build is successful;

wxpython uses the waf build system; i opened its wscript file and removed all code sections containing WXWEBVIEW; then i rebuilt with the same command as above:

$ python3.7 build.py dox etg --nodoc sip build --gtk2 -j 4

wow, it worked; both wxwidgets and wxpython were successfully built; packaging is easy:

$ python3.7 build.py sdist
$ python3.7 build.py bdist_wheel

now i have a source tarball and a wheel in the dist directory:

$ ls dist/
wxPython-4.0.4-cp37-cp37m-linux_x86_64.whl  wxPython-4.0.4.tar.gz

finally, i installed the wheel with pip; everything i tested (except wx.html2) was working;

github

i forked wxpython repo on github and added a tag wxPython-4.0.4-GTK2; if you also need to build for gtk2, then you can check it out and build with:

git submodule update --init --recursive
python build.py dox etg --nodoc sip build --gtk2 -j 4
python build.py sdist
python build.py bdist_wheel

replace python with the correct python version you are using; the build should have everything but wx.html2;

solution 1

i made a success later on: i patched the buggy webkitgtk source rpm (following this issue) and threw it on copr again; after 4-hour build, a success finally came;

all rpms and source rpms are available here:

so we got a webkitgtk source rpm which works on fedora-29; this is really not bad; i installed the built rpms and libwebkitgtk-1.0.so became available;

$ ldconfig -p | grep libwebkitgtk

...
libwebkitgtk-1.0.so.0 (libc6,x86-64) => /lib64/libwebkitgtk-1.0.so.0
libwebkitgtk-1.0.so (libc6,x86-64) => /lib64/libwebkitgtk-1.0.so
...

then i made a clean build of wxpython again, this time building at the original wxPython-4.0.4 tag without any modification:

git submodule update --init --recursive
python build.py cleanall
python build.py dox etg --nodoc sip build --gtk2 -j 4
python build.py sdist
python build.py bdist_wheel

the build process is smooth; no link error; no webkit warning; pip install the wheel and test with this program:

#!/usr/bin/env python3

import wx
import wx.html2

class MyBrowser(wx.Dialog):
    def __init__(self, *args, **kwds):
        wx.Dialog.__init__(self, *args, **kwds)
        sizer = wx.BoxSizer(wx.VERTICAL)
        self.browser = wx.html2.WebView.New(self)
        sizer.Add(self.browser, 1, wx.EXPAND, 10)
        self.SetSizer(sizer)
        self.SetSize((700, 700))

if __name__ == '__main__':
    app = wx.App()
    dialog = MyBrowser(None, -1)
    dialog.browser.LoadURL("http://www.google.com")
    dialog.Show()
    app.MainLoop()

a gui window poped up showing the search engine; hooray;

the wheel can be installed and used even if you dont have packages webkitgtk and webkitgtk-devel; i am almost sure everything will be working, except when you try to import wx.html2 you will get an error like this:

Traceback (most recent call last):
...
ImportError: libwebkitgtk-1.0.so.0: cannot open shared object file: No such file or directory

if you install webkitgtk and webkitgtk-devel:

sudo dnf --repo=cykerway-webkitgtk install webkitgtk webkitgtk-devel

then the error goes away and everything works again;

finally, if you dont need webview, then it is recommended not to install these 2 packages because they have security issues; and that is why they were obsoleted;

update: build on fedora 34

there is an official package python-wxpython4 on fedora 34, which has gtk3 binding; with a little modification we can change this into gtk2 binding and throw it on copr; the modification involves only 2 lines in its spec file as shown by this patch:

35c35
< BuildRequires:  wxGTK3-devel
---
> BuildRequires:  compat-wxGTK3-gtk2-devel
133c133
< DOXYGEN=%{_bindir}/doxygen WAF=%{_bindir}/waf %{__python3} -u build.py dox touch etg --nodoc sip build_py --use_syswx --gtk3
---
> DOXYGEN=%{_bindir}/doxygen WAF=%{_bindir}/waf %{__python3} -u build.py dox touch etg --nodoc sip build_py --use_syswx --gtk2

the build takes about half an hour; the built rpms and srpms are available here:

note that webview may not work in this build; i did not spend time figuring out how to make it work, as i do not need it at the moment;

update: build on fedora 35

the official package python-wxpython4 remains on fedora 35; however, fedora 35 comes with python 3.10, which, even the latest wxpython does not support yet; we can do nothing but wait for wxpython developers fixing compat issues incurred by this new version of python;

at the same time, though, we can build a wxpython wheel on fedora 34 for use on python 3.9; this way we can use this wheel on fedora 35 too;

the latest version of wxpython on fedora 34 is 4.0.7; this version has a bug in its setup.py that raises exception when bdist_wheel; the issue is here and the fix is here; include the fix patch in srpm and add bdist_wheel in spec file %build section to build a wheel on copr; here are the build results:

install the “wheel” rpm package and it puts a wxpython 4.0.7 (gtk2) (cp39) wheel in /usr/share/python-wheels; install this wheel with pip then you can remove this rpm package; its sole purpose is to ship a wheel;

it is worth mentioning that wxpython built on copr is using system wxwidgets; if you want to use wxwidgets bundled in wxpython, you can clone wxpython repo to build without --use_syswx; this is doable using python 3.9 on fedora 35; to make life easier, there is a tag wxPython-4.0.7-GTK2 in my repo that includes a successful build script; see its tag message for details;

update: build on fedora 36

the official package python-wxpython4 remains on fedora 36; now it comes with patches to work with python 3.10; so we use the same “wheel” rpm package trick: