[Scons-users] Two limitations of Qt's Moc invocations

Olivier Renaud orenaud at coventor.com
Thu May 24 05:58:40 EDT 2018


Hi,

I am trying to compile some Qt code using SCons. I am not the author of 
this code. This is a public code 
(https://github.com/itay-grudev/SingleApplication) that does not use 
SCons, and that I want to integrate into my SCons-based project. I was 
able to compile it and to make it work, but I encountered two issues 
with SCons' Qt Moc invocation, and I'd like to share it with you.

Two important things to know about this project:
- There are 3 source files in the project: 1 cpp and 2 headers. The cpp 
includes both, and one of the header includes the other.
- This project declares a class SingleApplication that inherits from a 
base class. The base class can be QCoreApplication, QGuiApplication or 
QApplication, and this is abstracted away using a macro as the name of 
the base class (QAPPLICATION_CLASS).

My SConscript is basically:

     env.Append( CPPDEFINES = {'QAPPLICATION_CLASS' : 'QApplication'} )
     env.SharedLibrary('SingleApp', ['singleapplication.cpp'])

That is, I define the macro to select the base class I need, and I 
compile the cpp file. This triggers the Automoc feature of Scons.

My first problem is that moc does only a partial job. It generates a moc 
file only for one of the headers (moc_singleapplication.cc). This leads 
to a link error down the road. I would expect Automoc to discover both 
header files and to generate two files.

The workaround I found is to ask moc to run explicitly. My SConscript 
became:

     env.Append( CPPDEFINES = {'QAPPLICATION_CLASS' : 'QApplication'} )
     obj = env.Moc(['singleapplication_p.h'])
     lib = env.SharedLibrary('SingleApp', ['singleapplication.cpp', obj])

My second problem is that, at runtime, the following code fails:
     qobject_cast<QApplication*>(mySingleApp);

qobject_cast does not rely on RTTI, but instead it uses the information 
generated by moc to know the class hierarchy, and to check the validity 
of the cast. In my case, moc did not understand that SingleApplication 
inherits from QApplication. This is because the base class QApplication 
is hidden behind a macro, and that moc did not know about the value of 
this macro.

The workaround is to add an argument to the moc invocation, that defines 
the value of this macro.

     env.Append( CPPDEFINES = {'QAPPLICATION_CLASS' : 'QApplication'} )
     env.Append(QT_MOCFROMHFLAGS = '-DQAPPLICATION_CLASS=QApplication')
     obj = env.Moc(['singleapplication_p.h'])
     lib = env.SharedLibrary('SingleApp', ['singleapplication.cpp', obj])

In my opinion, the correct thing to do when SCons invokes moc is to 
forward all the macros defined in CPPDEFINES, so that moc has the same 
knowledge of the macros as the compiler.

I hit these issues with both SCons 2.x and 3.0.1, on Windows 7 using 
MSVC 2017. I am using Qt 5.9.0.

--Olivier Renaud


More information about the Scons-users mailing list