I have a puzzling issue when trying to apply the Qt meta-object compiler (moc) to a header file in a Qt project. I am using Visual Studio 2013, and performing the moc step using a Custom Build Tool which was orignally auto-generated using the Qt Visual Studio add-in.
First, some tedious but highly relevant background. My project involves streaming data from a camera, which may be any one of a number of different types, into a GUI. Some classes are only relevant if certain camera SDKs are available on the particular tool where I am compiling the code; some classes are relevant if any one of a number of possible camera SDKs are available, but should not be compiled if no SDKs are. To handle this, I have a universal header called "Support.h" which currently consists of the following code:
#if defined(PTGREY_SUPPORT) || defined(SVS_VISTEK_SUPPORT)
#define CAMERA_SUPPORT
#endif
#ifdef CAMERA_SUPPORT
#pragma message ("Support for at least one camera is available")
#else
#pragma message ("No support is available for any camera on this machine")
#endif
Every affected .h file and .cpp file then has the structure
#include "Support.h"
#ifdef CAMERA_SUPPORT
... the whole file contents
#endif
In general, this works a treat: if I have a suitable camera SDK present and I compile a single .cpp in isolation, then everything compiles cleanly and I see "Support for at least one camera is available" messages thrown out in all the right places.
However, if I try to build the whole project then I get a bunch of linking errors because none of the meta-object functions required for Qt signals and slots are being generated. On further investigation, I find that although the .h files are being moc'ed just like they should be, the moc compiler is outputting the error message "Note: No relevant classes found. No output generated." each time and the moc_[class name].cpp files, although they are all being generated, are empty!
Going back to the header files and manually replacing '#include "Support.h"' with '#define CAMERA_SUPPORT' solves the problem at a stroke, but utterly defeats the object of what I am trying to achieve.
It seems that what's happening is this:
- When a .cpp file is compiled, the preprocessor parses the contents of "Support.h", defines CAMERA_SUPPORT, and thereafter all the relevant blocks of code are seen and compiled correctly.
- However, when a .h file is moc'ed, "Support.h" is ignored and CAMERA_SUPPORT remains undefined. However, the preprocessor still strips out everything between the '#ifdef CAMERA_SUPPORT' and the '#endif' so what the moc actually sees is an empty file.
So, in one line, here is my question: why, when the file is moc'ed, is the preprocessor being invoked to check whether CAMERA_SUPPORT is defined, but not to check whether CAMERA_SUPPORT should be defined?
[N.B. I have also tried replacing the line '#include "Support.h"' with the contents of Support.h, and it makes no difference. Therefore it seems that the problem during moc'ing is that the "#if defined(..." line is not being executed, not that it is failing to include Support.h.]