PDA

View Full Version : How to get CMake to generate moc files that can be included in cpps



ghorwin
26th May 2018, 14:07
Hi there,

since it's been a while since my last post - hello to everyone!

In a library code I noticed that the moc-generated cpp files are included at the bottom of the cpp file that matches the respective header used to generate the moc_xxx.cpp. I understand that this speeds up compilation. But also, inside the cpp file there are private class declarations that are needed for the moc-generated code to compile.

Building with Qt-creator is no problem at all - it generates the moc_xxx.cpp files, they are included in the cpp-files, compiled and done. Also, qmake does not attempt to compile the moc_xxx.cpp files themselves!

When running the system through CMake using qt5_wrap_cpp() I get a problem. Example cmake-code:


# collect a list of all header files (to be used in MOC compiler)
file( GLOB LIB_HDRS ${PROJECT_SOURCE_DIR}/../../src/*.h )

# collect a list of all source files, these are also run through the moc compiler
file( GLOB LIB_SRCS ${PROJECT_SOURCE_DIR}/../../src/*.cpp )


# generate mocs from headers
qt5_wrap_cpp( LIB_MOC_SRCS ${LIB_HDRS})

# generate moc-cpps from sources
qt5_wrap_cpp( LIB_MOCCPP_SRCS ${LIB_SRCS})


# add build target for library and use all generated files as dependencies
add_library( ${PROJECT_NAME} STATIC
${LIB_SRCS}
${LIB_MOC_SRCS}
${LIB_MOCCPP_SRCS}
)


CMake will now generate build rules for all generated cpps, resulting in some code being compile twice (giving linker problems) and some moc_xxx.cpp files not being able to compile because the private declarations inside the cpp-files are not available.

Question: what's the best way to get tell cmake that the moc-generated cpps are already included in other cpps and do not need to be compiled?

The variant with handcrafting a custom build target for the mocs alone and adding this "custom target" as dependency to the lib appears to work, but is quite complex. Sure there is a simpler solution, or not?

Thanks,
Andreas

d_stranz
26th May 2018, 18:01
Google found the answer (https://cmake.org/cmake/help/v3.9/manual/cmake-qt.7.html#manual:cmake-qt(7)) more quickly than the time it probably took you to write this.

ghorwin
27th May 2018, 17:19
Unfortunately, the page you dug up does not give a solution to my problem (btw, reading the CMake docs was the first I tried, also googling the various solutions proposed therein). Let me re-phrase my question again:

How can I tell CMake to *exclude* the generated moc-cpp-files from the build because they are already included in other cpps. AUTOMOC will only be activated, when resulting moc-cpps are actually *built* in the project. If they are not part of the add_executable() or add_library() statement, moc won't be called in the first place.

Added after 22 minutes:

The CMake docs are unspecific at best:


AUTOMOC is a boolean specifying whether CMake will handle the Qt moc preprocessor automatically, i.e. without having to use the QT4_WRAP_CPP() or QT5_WRAP_CPP() macro.

It is not clear how automoc determines the respective files to parse and under which conditions it is run.

I attached a test project to try out a solution - the AUTOMOC property clearly does not work (despite the CMake documentation that this should run moc even without the use of qt5_wrap_cpp() ) macro.

ChristianEhrlicher
27th May 2018, 17:44
The command is 'set(CMAKE_AUTOMOC ON)' as correctly stated in the documentation.
And there you can also read how to exclude a file from automoc: 'Source C++ files can be excluded from AUTOMOC processing by enabling SKIP_AUTOMOC or the broader SKIP_AUTOGEN.'

ghorwin
27th May 2018, 18:23
Thanks, that works nicely.

d_stranz
27th May 2018, 21:32
Question: what's the best way to get tell cmake that the moc-generated cpps are already included in other cpps and do not need to be compiled?

I do not #include the moc-generated cpps in the corresponding class cpp files, but instead let them be built and linked as separate compilation and link targets, so I don't run into this issue. The .moc files will be re-generated and compiled as needed when the QObject-based class header file changes.