CMake support for Qt5's external resources

Sun, 03 May 2015 :: #cmake :: #qt5

When writing a Qt5 application there is often a need to include graphical resources inside the application binary. As Qt is a portable framework, it doesn't use platform-specific solutions for resource storage like the Resource section in PE files on Windows systems. Qt has its own mechanism which is possible for use with the help of the rcc tool.

Normally the rcc tool will generate c++ source files which contain selected resources as simple arrays, together with some control structs. Your build system takes this autogenerated source file, compiles it to a normal object file with your C++ compiler, and links it into the final executable. CMake supports that without any problem.

The problem started when I wanted to create an application which loads a plugin. I wanted the plugin to use Qt5 code, but also I wanted to put some resources into the plugin itself, not to the host application that loads the plugin. This resulted in a problem, because the resources linked to the plugin shared object are not registered to the Qt Resource subsystem, which results in inability to load them through normal loading mechanisms, like QPixmap(":/resource.jpg").

Fortunately Qt's rcc tool also supports external resources, which are compiled binaries, that are meant to be put in an external *.rcc file instead of linked into the application binary. It's possible to generate this kind of resources by adding the -binary option to rcc:

$ rcc res.qrc -o res.rcc -binary
$ file res.rcc
res.rcc:       Qt Binary Resource file

Normally I am using a combo of CMake and Ninja to manage the build process, and unfortunately CMake doesn't support generation of external resource files. CMake seems to support qt5_add_resources function, but it's designed to generate source files that are later linked into the application. Even if forcing this function to pass the -binary option to rcc tool, which is possible, the result is that the linker tries to link also these binary resource files, which obviously is not a good idea.

However, I've managed to create a small CMake script that should add support for this. My function is based on original qt5_add_resources in the sense that it tries to parse the qrc file to extract the external file references. These file references are added to a list of dependencies, so CMake knows that it has to rebuild the rcc file if any of the referenced resource files will change. It rebuilds the rcc file also when the qrc file will change.

The function works in both make and ninja generators. It has been tested on gcc only, and I have no idea if it will work on Visual Studio or not.

You can use this support in your projects by checking out this repository on GitHub:

This repository contains a small example application that will help you understand how the CMake function should be called and how to load an external resource from your application.