Packaging of wkhtmltopdf releases
Switch branches/tags
Nothing to show
Clone or download

Packaging wkhtmltopdf releases

Packaging wkhtmltopdf is a challenge because of the need for using a patched Qt to provide additional functionality and the cross-platform targets. Especially for Linux, the approach for packaging has changed multiple times, so it is best to decouple it from the releases itself.

This will allow creation of packages as per latest best practices, using the latest dependent libraries in static builds and for targets to be added long after the release has been made.

All targets are built in a separate container or VM to ensure that nothing from the build machine leaks into the output package and it can be reproduced by anyone.


The software requirements on the build machine are:

  • git and p7zip
  • python and PyYAML
  • docker >= 17.05 (for linux targets)
    • build-time args in FROM were introduced in this version
  • Linux kernel >= 4.8 (for linux targets -- foreign archs only)
    • for seamless foreign arch emulation via qemu-user-static
  • vagrant with virtualbox (for non-linux targets)

On Ubuntu 18.04, this can be installed via a single command:

sudo apt install -y python-yaml vagrant virtualbox p7zip-full

Build System

Just call ./build or python build from the top-level folder, you will see all available commands. The build.yml file contains the configuration for all targets -- it includes documentation on the syntax to use.

The source folder which contains wkhtmltopdf (along with Qt) is always required as an argument; the version number is automatically generated based on the latest commit in git. In case you are rebuilding a tagged release, you can optionally specify an --iteration which is included in the filename, so that different filenames are generated if packaging scripts are different.

Before a release build, it is recommended to run docker system prune -af to ensure that the latest images are pulled.


The docker images are published to Docker Hub, so you don't need to build them everytime. In case you are building for a new target, you can run the command ./build docker-images <target> to generate a local image.

For building, just use the ./build package-docker command and it will generate a package in the targets folder. If you don't specify --clean, it will also keep the complete build folder.


The base VM images are pulled and provisioned on-the-fly, so a lot of time and bandwidth would possibly be required before the build actually starts. The source code is pushed to the VM via rsync and the target package is pulled to the targets folder.

As the build steps could be varying across targets, for each VM a "plugin" needs to be defined which has the prepare_build and package_build functions defined and do the necessary steps specific to the target.

For building, just use the ./build vagrant command and it will bring up the VM, rsync the code into it, build dependent libraries via conan and compile Qt along with wkhtmltopdf, package it and copy the package into the output folder.


It's best if you can get the distribution/OS to support wkhtmltopdf with patched Qt, as it would enable using the native package management tools.

Failing this, please open an issue for adding support for a differnt target. In case your target also requires patches to Qt, make sure to submit and get them merged before opening a PR for packaging the target.


You can build a native distro package if fpm supports it directly. If fpm doesn't support your distro format, build a tarball which can then be used by extracting it manually.

  • If you're building for 64-bit linux, find the appropriate docker image and provision it with the required tools/libraries in a custom Dockerfile present in the docker/ folder.
  • If you're building for other architectures, if there is a docker image then you can use emulation via qemu to use it directly -- but please note that it will be very slow -- it is not uncommon for builds to take 8+ hours on a recent machine.
  • If you're building for other architectures and cross-compilation toolchain is available along with dependent libraries (either built statically or extracted from image), then provision everything in a Dockerfile and then specify a cross-compilation prefix.

Please look at the existing definitions and use them as a base to making a working package. In case you get stuck, please discuss it on the related issue.


This requires having a base box available on Vagrant Cloud. See the existing definitions and use them as a base to making a working package. In case you get stuck, please discuss it on the related issue.