Using python-poppler-qt5 on Windows

172 Views Asked by At

Using python-poppler-qt5 on Windows I am working on a project that involves qpageview, which is a library that extends PyQt5, and depends on python-poppler-qt5, the Python bindings for poppler-qt5. Poppler is a C++ library which easy to use on Linux, but difficult to use on Windows. A quick web search will indicate that many people have made various distributions for poppler on Windows, but unfortunately, none of these solve my problem. I have tried various environments on Windows, including MSYS, Cygwin, Anaconda, and the default Windows Python distribution with the MS Build Tools, and I believe that the furthest I have got is to use Cygwin, so this post will focus on that approach. I am just looking for someone to help point me in the right direction to getting this to work, as I have experience with Python, but much less with C/C++. This works fine in WSL, but I would like to make it work Windows natively too. First, to ensure that my various previous attempts will not cause problems, I created an entirely new Windows 10 installation in VirtualBox. Inside of VirtualBox, I only installed Cygwin (and Git Bash, so I could clone my repository to get my code in the virtual machine). Over the course of my various attempts, I have installed many packages to ensure that all the dependencies are installed in my Cygwin distribution. When I open up the Cygwin terminal, I use git to clone the repository. My minimal reproducible example program to run to prove qpageview works. This works fine in Ubuntu Linux on WSL:

from PyQt5.QtWidgets import QApplication
import qpageview

app = QApplication([])

v = qpageview.View()
v.resize(900, 500)
v.show()
v.loadPdf("../pyqt.pdf")
app.exec()

The Cygwin packages I have installed: https://pastebin.com/bL13jqic

Other information regarding my Cygwin environment:

me@system ~/python-poppler-qt5
$ pip freeze #this is run within cygwin, but outside of any virtual environment
Babel @ file:///pub/devel/python/python-babel/python-babel-2.12.1-1.noarch/build/dist/Babel-2.12.1-py3-none-any.whl
cffi @ file:///pub/devel/python/python-cffi/python-cffi-1.15.1-1.x86_64/build/dist/cffi-1.15.1-cp39-cp39-cygwin_3_4_6_x86_64.whl
chardet @ file:///pub/devel/python/python-chardet/python-chardet-4.0.0-2.noarch/build/dist/chardet-4.0.0-py2.py3-none-any.whl
Cython @ file:///pub/devel/python/python-cython/python-cython-0.29.33-1.x86_64/build/dist/Cython-0.29.33-cp39-cp39-cygwin_3_4_6_x86_64.whl
dbus-python @ file:///pub/devel/python/python-dbus/python-dbus-1.2.18-1.x86_64/build/dist/dbus_python-1.2.18-cp39-cp39-cygwin_3_3_3_x86_64.whl
distlib @ file:///pub/devel/python/python-distlib/python-distlib-0.3.6-1.noarch/build/dist/distlib-0.3.6-py2.py3-none-any.whl
docutils @ file:///pub/devel/python/python-docutils/python-docutils-0.18.1-1.noarch/build/dist/docutils-0.18.1-py2.py3-none-any.whl
filelock @ file:///pub/devel/python/python-filelock/python-filelock-3.9.0-1.noarch/build/dist/filelock-3.9.0-py3-none-any.whl
idna @ file:///pub/devel/python/python-idna/python-idna-3.3-1.noarch/build/dist/idna-3.3-py3-none-any.whl
imagesize @ file:///pub/devel/python/python-imagesize/python-imagesize-1.3.0-1.noarch/build/dist/imagesize-1.3.0-py2.py3-none-any.whl
iniconfig @ file:///pub/devel/python/python-iniconfig/python-iniconfig-2.0.0-1.noarch/build/dist/iniconfig-2.0.0-py3-none-any.whl
Jinja2 @ file:///pub/devel/python/python-jinja2/python-jinja2-3.1.2-1.noarch/build/dist/Jinja2-3.1.2-py3-none-any.whl
MarkupSafe @ file:///pub/devel/python/python-markupsafe/python-markupsafe-2.1.2-1.x86_64/build/dist/MarkupSafe-2.1.2-cp39-cp39-cygwin_3_4_6_x86_64.whl
olefile @ file:///pub/devel/python/python-olefile/python-olefile-0.46-3.noarch/build/dist/olefile-0.46-py2.py3-none-any.whl
packaging @ file:///pub/devel/python/python-packaging/python-packaging-21.3-1.noarch/build/dist/packaging-21.3-py3-none-any.whl
Pillow @ file:///home/Hamis/python-imaging/python-imaging-8.4.0-1.x86_64/build/dist/Pillow-8.4.0-cp39-cp39-cygwin_3_3_3_x86_64.whl
platformdirs @ file:///pub/devel/python/python-platformdirs/python-platformdirs-3.1.1-1.noarch/build/dist/platformdirs-3.1.1-py3-none-any.whl
pluggy @ file:///pub/devel/python/python-pluggy/python-pluggy-1.0.0-1.noarch/build/dist/pluggy-1.0.0-py2.py3-none-any.whl
ply==3.11
pycairo @ file:///pub/devel/python/python-cairo/python-cairo-1.20.1-1.x86_64/build/dist/pycairo-1.20.1-cp39-cp39-cygwin_3_3_3_x86_64.whl
pycparser @ file:///pub/devel/python/python-pycparser/python-pycparser-2.21-1.noarch/build/dist/pycparser-2.21-py2.py3-none-any.whl
PyCygwin==0.1
Pygments @ file:///pub/devel/python/python-pygments/python-pygments-2.10.0-1.noarch/build/dist/Pygments-2.10.0-py3-none-any.whl
PyGObject @ file:///cygdrive/d/a/scallywag/python-gi/python-gi-3.36.1-3.x86_64/build/dist/PyGObject-3.36.1-cp39-cp39-cygwin_3_4_5_x86_64.whl
pyparsing @ file:///pub/devel/python/python-pyparsing/python-pyparsing-3.0.6-1.noarch/build/dist/pyparsing-3.0.6-py3-none-any.whl
PyQt-builder==1.15.1
PyQt5==5.15.6
pytest @ file:///pub/devel/python/python-pytest/python-pytest-7.3.0-1.noarch/build/dist/pytest-7.3.0-py3-none-any.whl
requests @ file:///pub/devel/python/python-requests/python-requests-2.27.1-1.noarch/build/dist/requests-2.27.1-py2.py3-none-any.whl
sip==6.7.9
six @ file:///pub/devel/python/python-six/python-six-1.16.0-1.noarch/build/dist/six-1.16.0-py2.py3-none-any.whl
snowballstemmer @ file:///pub/devel/python/python-snowballstemmer/python-snowballstemmer-2.2.0-1.noarch/build/dist/snowballstemmer-2.2.0-py2.py3-none-any.whl
Sphinx @ file:///pub/devel/python/python-sphinx/python-sphinx-4.4.0-1.noarch/build/dist/Sphinx-4.4.0-py3-none-any.whl
sphinxcontrib-serializinghtml @ file:///pub/devel/python/python-sphinxcontrib-serializinghtml/python-sphinxcontrib-serializinghtml-1.1.5-1.noarch/build/dist/sphinxcontrib_serializinghtml-1.1.5-py2.py3-none-any.whl
toml @ file:///pub/devel/python/python-toml/python-toml-0.10.2-2.noarch/build/dist/toml-0.10.2-py2.py3-none-any.whl
tomli==2.0.1
urllib3 @ file:///pub/devel/python/python-urllib3/python-urllib3-1.26.7-1.noarch/build/dist/urllib3-1.26.7-py2.py3-none-any.whl
virtualenv @ file:///pub/devel/python/python-virtualenv/python-virtualenv-20.21.0-1.noarch/build/dist/virtualenv-20.21.0-py3-none-any.whl

me@system ~/python-poppler-qt5
$ which gcc
/usr/bin/gcc

me@system ~/python-poppler-qt5
$ which g++
/usr/bin/g++

me@system ~/python-poppler-qt5
$ which python
/usr/bin/python

me@system ~/python-poppler-qt5
$ which sip-build
/usr/local/bin/sip-build

me@system ~/python-poppler-qt5
$ which sip-install
/usr/local/bin/sip-install

me@system ~/python-poppler-qt5
$ python --version
Python 3.9.16

me@system ~/python-poppler-qt5
$ gcc --version
gcc (GCC) 11.4.0
Copyright (C) 2021 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.


me@ system ~/python-poppler-qt5
$ g++ --version
g++ (GCC) 11.4.0
Copyright (C) 2021 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.


me@system ~/python-poppler-qt5
$ sip-build --version
6.7.9

me@system ~/python-poppler-qt5
$ sip-install --version
6.7.9

me@system ~/python-poppler-qt5
$ which ld
/usr/bin/ld

me@system ~/python-poppler-qt5
$ ld --version
GNU ld (GNU Binutils) 2.40
Copyright (C) 2023 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms of
the GNU General Public License version 3 or (at your option) a later version.
This program has absolutely no warranty.

In order to build it, I simply run sip-install –verbose. This same command is run when you install python-poppler-qt5 with pip, but this allows you to actually see the compiler output for debugging.

The problem is that the build scripts exclude the necessary g++ compiler flag -lpython3.9. Since I do not know how to make sip add that to the Makefile it generates, I made an incredibly hacky solution:

import os

while(True):
    tmpdir = os.listdir("/tmp")
    for i in tmpdir:
        f = i.replace("/", "")
        if os.path.isdir("/tmp/" + f):
            os.system("cp Makefile /tmp/" + f + "/popplerqt5/Makefile")

I run this script in a separate terminal window before running the install, and let it run until the install finishes. It continuously copies the correct Makefile into the build directory, overwriting sip's erroneous Makefile.

The Makefile I am using is the same as the one sip generates, with one line changed:

LIBS          = $(SUBLIBS) -lpoppler-qt5 -lQt5Gui -lQt5Xml -lQt5Core -lGL -lpthread  -lpython3.9

Does anyone know of a better fix for this than making a script that overwrites the makefile?

0

There are 0 best solutions below