Cool new stuff in CMake 2.8.6: automoc
Starting with version 2.8.6 CMake supports what is known as automoc, i.e. automatic handling of moc when using Qt4.
As you know, when adding signals and slots to a class using Qt, this source code (typically the header) has to be processed by the moc preprocessor. This invocation of moc during the build is what we are talking about.
When using plain CMake, you had to use the macro
qt4_wrapp_cpp(srcsVar ${filesToBeMocced}).
Several years ago, actually I can't remember when it was, I guess it must have been at KDE 2.x times, we wanted to make life easier for our KDE developers and added automoc to our (back then) autotools-based KDE buildsystem. This means all source files for a target and also the corresponding header files are scanned automatically for code which requires moc, i.e. code which contains the Q_OBJECT macro. If such files were found, rules for running moc on these files were added to the Makefiles (or Makefile.am or .in ? I don't know).
This behaviour was later on adopted by qmake, so you didn't have to care anymore about running moc when using qmake.
When we switched for KDE4 to CMake, this functionality was kept, but it had to be done in a different way. For CMake we, well Matthias Kretz mainly, created a tool called automoc4, which lived in kdesupport (and internally used QtCore). This automoc4 tool is used in the current KDE macros kde4_add_executable(), kde4_add_library(), kde4_add_plugin() etc., so when using these macros to create executables etc., you automatically got automoc and didn't have to list the files to be moc'ed explicitely.
Although automoc4 is completely independent from KDE, many developers told me that they would really like to have automoc-functionality directly in CMake, because automoc4 still is an additional dependency for a Qt-only program.
So, now with CMake 2.8.6, automoc is supported directly by CMake. The work to achieve this was done in two parts, Gregory Schlomoff ported automoc4 away from QtCore to plain STL, which is a required for integration into CMake, during the Platform 11 sprint in Randa, and I then finally integrated it into CMake during this years Desktop Summit in Berlin.
So, how do you use it ?
Simple way:
set(CMAKE_AUTOMOC TRUE)
and then CMake will automoc all targets.
If you don't want to have automoc for all targets (while the scanning is fast, it still takes some time), you can also enable it just for some targets by setting the AUTOMOC target property to TRUE for these targets:
set_target_properties(Foo PROPERTIES AUTOMOC TRUE)
What exactly does it do:
- if a source file contains an #include "foo.moc", the Q_OBJECT is expected in the source file itself and moc is executed accordingly.
- if a source file contains an #include "moc_foo.cpp", the Q_OBJECT is expected in the corresponding header file foo.h, and moc is run on the header
- additionally all header files are parsed, and if a Q_OBJECT is found, and there is not yet a rule for running moc on this file, a rule for running moc is added and the resulting moc file is included in a
_automoc.cpp file, which is then compiled as part of the target.
So, this way you don't have to care abotu moc anymore. The only time when you actually have to do something is, as noted above, if the Q_OBJECT is in the cpp-file, then add
#include "thisfile.moc"
to that file, somewhere after the class declaration.
Alex