Skip to content

Commit

Permalink
WIP on new approach to building python-poppler-qt5 wheels
Browse files Browse the repository at this point in the history
  • Loading branch information
jeanas committed Aug 9, 2023
1 parent 238e0dd commit 6096ae4
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 1 deletion.
11 changes: 11 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
on: [push, pull_request]

jobs:
build_wheels_linux:
name: Build wheels for Linux
runs-on: ubuntu-latest
container: quay.io/pypa/manylinux2014_x86_64
steps:
- uses: actions/checkout@v3
- name: Build python-poppler-qt5 wheels
run: ./ci-build.sh
102 changes: 102 additions & 0 deletions ci-build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
#!/bin/sh -eu

# These compiler flags add an RPATH entry with value $ORIGIN (literally),
# to make the built shared libraries search for Qt and Poppler in the
# same directory instead of using the system ones. --disable-new-dtags
# is to generate an RPATH and not a RUNPATH; the latter doesn't apply
# to transitive dependencies.
RPATH_OPTION="-Wl,-rpath,'\$ORIGIN',--disable-new-dtags"
# Shell quoting madness to survive through qmake and make ...
RPATH_OPTION_2="-Wl,-rpath,'\\'\\\$\\\$ORIGIN\\'',--disable-new-dtags"

# Sync with pyproject.toml. POPPLER_VERSION is for the download of Poppler and may contain
# leading zeroes, while PYTHON_POPPLER_QT5_VERSION does not.
POPPLER_VERSION="21.03.0"
PYTHON_POPPLER_QT5_VERSION="21.3.0"

# We build Poppler from source because there is no reason for a distro
# to package the exact version we want, and by having control over the
# compilation flags, we can disable many features, reducing the number
# of shared libraries to package, which alleviates some headaches.


# Download and extract the Poppler source code

POPPLER=poppler-$POPPLER_VERSION
##wget https://poppler.freedesktop.org/$POPPLER.tar.xz
cp ../$POPPLER.tar.xz . ## TEMP
tar -xf $POPPLER.tar.xz

pushd $POPPLER

# Construct build options

CMAKE_OPTIONS=
# We don't need the Qt6, GLib (GTK) and C++ wrappers, only the Qt5 one.
CMAKE_OPTIONS+="-DENABLE_QT5=ON"
CMAKE_OPTIONS+=" -DENABLE_QT6=OFF"
CMAKE_OPTIONS+=" -DENABLE_GLIB=OFF"
CMAKE_OPTIONS+=" -DENABLE_CPP=OFF"
# We don't need the command line utilities (pdfimages, pdfattach, etc.)
CMAKE_OPTIONS+=" -DENABLE_UTILS=OFF"
# We don't (?) need libpng or libtiff. Apparently, only they're used in pdfimages.
# However, the build is not smart enough to avoid searching them if the utilities
# aren't built.
CMAKE_OPTIONS+=" -DWITH_PNG=OFF"
CMAKE_OPTIONS+=" -DWITH_TIFF=OFF"
# Disable network stuff that's apparently used to validate signatures and the like.
# We don't need this.
CMAKE_OPTIONS+=" -DWITH_NSS3=OFF"
CMAKE_OPTIONS+=" -DENABLE_LIBCURL=OFF"
# Disable the use of Little CMS. (TODO: maybe this would actually be useful? Investigate.)
CMAKE_OPTIONS+=" -DENABLE_CMS=none"
# Disable Cairo backend, it's (famously) not supported in the Qt5 wrapper anyway.
CMAKE_OPTIONS+=" -DWITH_Cairo=OFF"

# Install locally
CMAKE_OPTIONS+=" -DCMAKE_INSTALL_PREFIX==../../../installed-poppler"

# Build Poppler (Ninja is faster than Make and just saner).
LDFLAGS=$RPATH_OPTION cmake -G Ninja -S . -B build $CMAKE_OPTIONS
pushd build
ninja
ninja install
popd

popd


# Make sip find our locally built poppler-qt5
export PKG_CONFIG_PATH=installed-poppler/lib64/pkgconfig

# Now build python-poppler-qt5. Add a RUNPATH just like for poppler;
# this is done in project.py, to which we communicate that we
# are doing a CI build using the PYTHON_POPPLER_QT5_CI variable.
sip-wheel --verbose --qmake=$(which qmake-qt5) --link-args=$RPATH_OPTION_2 --build-dir=build


# Unpack wheel to tinker with it
WHEEL=(python_poppler_qt5*.whl)
wheel unpack $WHEEL
pushd python_poppler_qt5-$PYTHON_POPPLER_QT5_VERSION
# Move popplerqt5.cpython-...-x86_64-linux-gnu.so under PyQt5. This
# is the simplest way to ensure that it will use PyQt5 from the Python
# environment instead of from the system, without tinkering with
# RUNPATH, etc.
PYTHON_POPPLER_QT5_LIB=(popplerqt5*.so)
PYTHON_POPPLER_QT5_LIB_DEST=PyQt5/Qt5/lib/
mkdir -p $PYTHON_POPPLER_QT5_LIB_DEST
mv $PYTHON_POPPLER_QT5_LIB $PYTHON_POPPLER_QT5_LIB_DEST/$PYTHON_POPPLER_QT5_LIB
cp /lib64/libjpeg.so* /lib64/libopenjp2.so* $PYTHON_POPPLER_QT5_LIB_DEST
# Add popplerqt5.py wrapper to import popplerqt5 from PyQt5/
cat > popplerqt5.py <<EOF
# TODO: this should verify the installation. FIXME
from PyQt5.Qt5.lib.popplerqt5 import *
EOF
# Add the poppler libraries
cp ../installed-poppler/lib64/*.so* $PYTHON_POPPLER_QT5_LIB_DEST

# Repack the wheel
popd
mkdir fixed-wheel
wheel pack --dest-dir=fixed-wheel python_poppler_qt5-$PYTHON_POPPLER_QT5_VERSION
9 changes: 9 additions & 0 deletions project.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ def get_options(self):
Option('poppler_version',
help='version of the poppler library',
metavar='VERSION'))
options.append(
Option('link_args',
help='linker arguments',
metavar='ARGS'))
return options

@staticmethod
Expand Down Expand Up @@ -86,3 +90,8 @@ def apply_user_defaults(self, tool):
tag = 'POPPLER_V0_20_0'
self.tags.append(tag)
super().apply_user_defaults(tool)


# Allow passing linker arguments, needed for RUNPATH
# in the CI build.
self.extra_link_args = self.link_args.split()
7 changes: 6 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ build-backend = "sipbuild.api"

[tool.sip.metadata]
name = "python-poppler-qt5"
# Sync with ci-build.sh
version = "21.3.0"
summary = "A Python binding to Poppler-Qt5"
description-file = "README.rst"
Expand All @@ -21,7 +22,11 @@ classifier = [
"Programming Language :: Python :: 3",
"Topic :: Multimedia :: Graphics :: Viewers"
]
requires-dist = "PyQt5"
requires-dist = [
"PyQt5==5.15.9; sys_platform=='linux'",
"PyQt5; sys_platform=='darwin'",
"PyQt5; sys_platform=='win32'",
]

[tool.sip.project]
sip-files-dir = "."
Expand Down

0 comments on commit 6096ae4

Please sign in to comment.