On Monday 31 October 2011 21:47:31 Alexander Neundorf wrote:
On Monday 31 October 2011, David Faure wrote:
This is a typical (kde) case where the .cpp incudes the .moc, for the
object defined in the .h.
Shouldn't it include moc_kauthactionwatcher.cpp ?
No, that's for the case where the qobject is in the .cpp file.
Is this really a typical case, i.e. is that done in many places ?
Yes. Just grep for moc includes in kde...
I thought the rule is that if there is a include foo.moc, the Q_OBJECT is
in the same cpp file.
No, it's the other way around, in KDE.
$ grep Q_OBJECT kautosavefile.*
kautosavefile.h: Q_OBJECT
$ grep moc kautosavefile.cpp
#include "kautosavefile.moc"
If it did additionally other things, this was more or less accidentially.
But it was the way kdesupport/automoc always worked, on purpose, not
accidentally.
OK, more precisely: it didn't care what the name of the included moc file
was, what mattered was, where is Q_OBJECT being used.
As the kde4automoc.cpp code says: when parsing the .cpp file:
// If the moc include is of the moc_foo.cpp style we expect the Q_OBJECT
class // declaration in a header file.
// If the moc include is of the foo.moc style we need to look for a
Q_OBJECT // macro in the current source file, if it contains the macro we
generate the // moc file from the source file, else from the header.
The logic which is currently implemented is:
1. if foo.cpp includes foo.moc, run moc on foo.cpp and generate foo.moc
That should depend on if foo.cpp actually says Q_OBJECT or not. Otherwise
this .moc should be created from the header file. Not much point in running
moc over a .cpp that doesn't define a Q_OBJECT :)
2. run moc on all header files bar.h which contain "Q_OBJECT" and
generate moc_bar.cpp from them
That could be moc_bar.cpp or bar.moc depending on which one is included.
(which in detail means:
2.1 for every included moc_xyz.cpp (no matter in which file), search for
a corresponsing xyz.h/hxx/hpp file and run moc on it
2.2 for every bar.cpp file, check whether there is a corresponding
bar.h/hpp/hxx file and collect it
2.3 check for a Q_OBJECT macro in all collected header files and all
header files listed explicitely as a source for the target, and run moc
on them. If the resulting moc_xyz.cpp file has not been included in any
source file, include it in<targetname>_automoc.cpp, which is built as
part of the target )
Step 2.2 already involves guessing, which I don't like.
Beside that, IMO these are clear rules, which are easy to understand.
With the old behaviour it was actually ambigous:
foo.h:
class Foo
{
Q_OBJECT
};
foo.cpp:
Foo::Foo() {}
#include "foo.moc"
#include "moc_foo.cpp"
This would have generated twice the same moc file, I think. IMO this is
really confusing.
Well there is no reason to include both, unless you have Q_OBJECT in the
.cpp file too :-)
Now it is simple: foo.moc from foo.cpp, moc_foo.cpp from foo.h.
If this is really done in many places in KDE, I'll add some workaround,
but I think the default behaviour should stay as it is now in cmake git.
How does qmake handle such cases ?
Checking....
Indeed qmake expects moc_foo.cpp for the standard case (Q_OBJECT in
header). This is why kde4automoc was made to support both moc filenames,
so that it could be compatible with the kde way of doing it (foo.moc) and
with the qmake way of doing it (moc_foo.cpp).
Oh well, if you want to stick to that we'll change all of KDE, for the
benefit of a clearer future indeed... At least it won't be an source
incompatible change for app developers since they will have to enable
CMAKE_AUTOMOC to get into this situation. Merely upgrading cmake or KDE
(even to frameworks 5) won't trigger it. OK not exactly,
find_package(kde4) will stop working so they will -have- to port to
CMAKE_AUTOMOC, it will be the only solution available...