mpyne added a comment.

  In https://phabricator.kde.org/D9334#180881, @kossebau wrote:
  
  > In https://phabricator.kde.org/D9334#180830, @mpyne wrote:
  >
  > > In fact this appears to force files containing `K_PLUGIN_FACTORY*` into 
being evaluated by CMake's AUTOMOC (other warning fixes removed files from 
consideration by CMake AUTOMOC).
  > >
  > > CMake itself appears to have had an interface change for AUTOMOC between 
3.8 and 3.9+.
  > >
  > > In particular, 
https://cmake.org/cmake/help/v3.8/manual/cmake-qt.7.html#automoc
  > >
  > > > If the macro is found in a C++ implementation file, the moc output will 
be put into a file named according to <basename>.moc, following the Qt 
conventions. The moc file may be included by the user in the C++ implementation 
file with a preprocessor #include. If it is not so included, it will be added 
to a separate file which is compiled into the target.
  > >
  > > vs. https://cmake.org/cmake/help/v3.9/manual/cmake-qt.7.html#automoc
  > >
  > > > If the macro is found in a C++ implementation file, the moc output will 
be put into a file named according to <basename>.moc, following the Qt 
conventions. The <basename>.moc must be included by the user in the C++ 
implementation file with a preprocessor #include.
  >
  >
  > Not sure if this is a behavioural change, or rather a fix in the docu.
  
  
  It's definitely at least a behavior change.  Before, CMake's AUTOMOC would 
generate a separate `moc_foo.cpp` and automatically add it to the project being 
built, unless the user manually added an `#include "foo.moc"` within the 
appropriate .cpp file.  So the user could allow moc to generate a separate file 
and then have it compiled and linked separately, or include it directly in the 
.cpp file as used to be mandatory.  From CMake 3.9 on, that is no longer true, 
and user code for moc files generated by AUTOMOC from classes found in a *.cpp* 
file now *must* be manually `#include`'d into that .cpp file.
  
  There may be reasons for this, I'm not sure, but the separate-compilation 
model for moc has worked fine in CMake up to 3.9, even for classes being moc'd 
that were defined in a .cpp.
  
  > unless I missed something, the code in the moc file has to see (or rather 
the compiler compiling it) the declaration of the class with the Q_OBJECT 
macro, as the code consists of the definitions of those declarations done by 
the Q_OBJECT macro.
  
  Yes, moc has to see the class that is using Q_OBJECT and, of course, generate 
the member function implementations for the methods added by the Q_OBJECT 
macro.  So
  
  > And if the macro is used for a declaration in a cpp file, the moc file 
cannot include the cpp file (otherwise the cpp definition content would be 
compiled 2x), so it has to be rather the cpp file which explicitely includes 
the moc file (after the code with the class with the Q_OBJECT declaration).
  
  Compiling the same file twice is certainly less efficient but it's not 
actually a C++ violation due to the one-definition rule (ODR).  The linker gets 
to figure out what happens with duplicate symbols.  Of course if the common 
subset of code in the foo.cpp compiles *differently* somehow when compiled as 
part of a moc_foo.cpp then that means we've introduced undefined behavior.  So 
this is much more brittle method of use.
  
  All the same, in code meeting our quality standards, separate moc compilation 
of classes defined in a .cpp *should* be nothing but a missed opportunity for 
optimization, not something that is impossible to make work.
  
  Given that this did catch an error in kwinscripts, it sounds like it may be a 
worthy behavior change, but I still think it's a behavior change, even in code 
that was not technically broken.

REPOSITORY
  R244 KCoreAddons

REVISION DETAIL
  https://phabricator.kde.org/D9334

To: mlaurent, dfaure
Cc: kossebau, mpyne, ngraham, #frameworks

Reply via email to