10 May 2017

Creating config header files using qmake

In case you are using qmake as tool to build your Qt based application, you might sometimes jealously look over to other build systems like cmake for their support of configuration header files (or more generally “configuration” files at all, as this is not limited to C/C++ headers in the end). So what’s the background? There are several files where you need the content to reflect something that is usually only known to the build system. This could be

  • Information about (optional) build dependencies of your app or library.
  • User provided configuration options, e.g. installation target locations for use with make install.

In a lot of cases you just might get away by passing certain stuff through to the compile process as defines (using qmake’s DEFINES variable). However, there are cases where this is not the case. Probably the most prominent example would be .desktop files in Linux, where the file needs to point to the installation location of your application. However, you even will find situations where using DEFINES is not sufficient (admittedly, this is when stretching qmake’s capabilities a bit, but hey…).

In these cases, what you actually want to create is configured files on disk, which are fed into further steps of the build or installation process later on. Long story short: While other tools have their way to create such files well documented, qmake is hiding this a bit (at least I was not able to find information about it in the official docs). But nevertheless, such a function exists: Enter, QMAKE_SUBSTITUTES!

QMAKE_SUBSTITUTES is a variable you can append to template files (e.g. config.h.inMyCoolApp.desktop.in), that are stored in your source directory. qmake will configure these files and write the result to appropriate files without the *.in suffix into the build directory. Configuring in this case means that any references of the form $$SOME_VARIABLE will be replaced by the respective content of that variable known to qmake. A very simple example: You could use this to create a header file containing the version number of your app. In your project files, you would have something like this:

# ...
VERSION = 1.2.3
QMAKE_SUBSTITUTES += config.h.in
# ...

The content of the config.h.in file could look like this:

#ifndef MYAPP_CONFIG_H
#define MYAPP_CONFIG_H

#define MYAPP_VERSION '"$$VERSION"'

#endif // MYAPP_CONFIG_H

And finally, you could pull in this file into your source and header files as required:

#include 

#include "config.h"

int main(int argc, char** argv) {
    std::cout << "MyApp version " << MYAPP_VERSION << std::endl;
    return 0;
}
Thank You For Reading
Martin Hoeher

I am a software/firmware developer, working in Dresden, Germany. In my free time, I spent some time on developing apps, presenting some interesting findings here in my blog.

Comments
Your comment has been filed

We'll review it and it will appear here as soon as we're done.

Sorry, something went wrong...

Your comment could not be posted.

Regarding your personal information...
  • The name you enter will be shown next to your comment. You may enter your real name or whatever you like.
  • Your e-mail will be used to show an image representing you next to your comment. We do not store nor show your address somewhere. Instead, an ID will be calculated from it and stored. This ID is then used to retrieve an image from Gravatar.