Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Qt, CMake, Visual Studio and Q_OBJECT in cpp files

I'm developing a large project using Qt 4.6, CMake 2.8 and Visual Studio 2008 for the Windows platform.

As far the build system goes, it's all standard stuff: I'm using CMake's QT4_WRAP_CPP macro to generate moc files from header files, which are then linked into the final executable in the add_executable command. Everything is working as expected.

The only restriction with this setup is that I can't define widgets or helper using Q_OBJECT in .cpp files. This would be very convenient for small, context-specific helpers classes that should appear right next to where they're used.

I tried to pass the whole list of source files (both .h and .cpp) to QT4_WRAP_CPP, instead of just the header files, but that doesn't work (linking fails because some moc-related symbols are undefined).

I think the problem is that, for a given pair of files foo.h and foo.cpp, the QT4_WRAP_CPP macro will generate the same moc file (moc_foo.cxx) in the same directory, and obviously that means the first file will be overwritten by the second one, and as a result symbols will be missing at link-time.

Is there a way to fix or work around that problem? For instance, I tried to add a specific rule for foo.cpp of the form

QT4_GENERATE_MOC(directory/foo.cpp directory/foo.moc)

and then add

#include "foo.moc"

at the end of foo.cpp. I think this ought to work, but alas Visual Studio only allows one build rule per file, and .cpp files already have a build rule (compilation to object file), so this approach doesn't work, at least with Visual Studio.

Another idea that I had was to create a new macro, say QT4_WRAP_CPP_WITH_PREFIX, based on QT4_WRAP_CPP (which is defined in share/cmake-2.8/Modules/Qt4Macros.cmake), that would take an additional prefix argument and would add this prefix to the generated moc files. That way, I would call QT4_WRAP_CPP_WITH_PREFIX twice, once for .h files and once for .cpp files, with different prefixes. What I just dislike about this approach is that I'd be messing with the internals of CMake's Qt support, instead of using the public API.

Any better idea?

Cheerz, Franz

like image 909
François Beaune Avatar asked Sep 06 '10 09:09

François Beaune


1 Answers

Recent versions of CMake have "automoc" which worked like a charm for me: http://blogs.kde.org/2011/11/01/cool-new-stuff-cmake-286-automoc

Simply add in the CMakeLists.txt:

set(CMAKE_AUTOMOC TRUE)

and then in the cpp (e.g. example.cpp) file:

#include "example.moc"

(the *.moc must match the cpp file's name).

like image 198
David Doria Avatar answered Sep 18 '22 22:09

David Doria