build wxpython with gtk2
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:
- webkitgtk-2.4.11-5.fc29.src.rpm (mirror)
- webkitgtk-2.4.11-5.fc29.x86_64.rpm (mirror)
- webkitgtk-devel-2.4.11-5.fc29.x86_64.rpm (mirror)
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:
- python3-wxpython4-4.0.7-16.fc34.x86_64.rpm
- python-wxpython4-4.0.7-16.fc34.src.rpm
- python-wxpython4-wheel-4.0.7-16.fc34.x86_64.rpm
- …
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: