automoc: dependencies added with AUTOGEN_TARGET_DEPENDS do not trigger moc re-run if Q_OBJECT is inside C++ preprocessor macro
Given a file DATA which is registered by AUTOGEN_TARGET_DEPENDS for a target, and given a source file which declares a QObject subclass by a C++ preprocessor macro, incl. the Q_OBJECT macro, then the Makefiles generated by cmake (at least 3.10.2) will not result in a re-run of moc on the sources if the file DATA is changed. It works, if the Q_OBJECT macro is used directly.
This affects at least a lot of KDE projects, where plugins typically are done setting the JSON metadata of the QObject plugin classes by a separate JSON file, which either is edited directly or created on-the-fly during the build from metadata in another format ("desktop" files). And the boilerplate code for defining the plugin entry classes is done via C++ preprocessor macros, which also define those QObject subclasses including Q_OBJECT macros.
I have no idea of the internals of automoc/cmake, so cannot point to anything sadly.
When autogen target dependencies change, moc is also re-run if the Q_OBJECT call is inside a C++ preprocessor macro (listed in CMAKE_AUTOMOC_MACRO_NAMES as used/needed elsewhere).
Place the following files in a new subdirectory, then do this in the subdir:
# preparation mkdir build cd build cmake .. make # trigger issue rm pluginA.json pluginF.json make
With both QObject metadata files removed, one would expect the buildsystem rules to first regenerate both and then also rerun moc and following the recompilation of the sources.
Though that only happens for the source file of pluginA, where the Q_OBJECT is not used as part of a macro. For pluginF moc seems not re-run (the timestamp of pluginF_autogen/include/pluginF.moc does not change):
[ 10%] Generating plugin metadata file pluginA.json [ 20%] Automatic MOC for target pluginA [ 20%] Built target pluginA_autogen Scanning dependencies of target pluginA [ 30%] Building CXX object CMakeFiles/pluginA.dir/pluginA.cpp.o [ 40%] Linking CXX shared module libpluginA.so [ 50%] Built target pluginA [ 60%] Generating plugin metadata file pluginF.json [ 70%] Automatic MOC for target pluginF [ 70%] Built target pluginF_autogen [100%] Built target pluginF
Things also do not change if adding
list(APPEND CMAKE_AUTOMOC_MACRO_NAMES OBJECT)
to the CMakeLists.txt (as one should do, forgot to add to the uploaded file).