Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CMake : detect "Q_OBJECT" in a file and add it to a list of file to treat by MOC

Tags:

cmake

qt

qt4

Currently, I use a variable MYPROJECT_CURRENT_HEADERS in CMake to list all the headers. As I use Qt, my CMakeLists.txt contains :

QT4_WRAP_CPP(MYPROJECT_CURRENT_MOC ${MYPROJECT_CURRENT_HEADERS})

The problem is that all headers are treated by moc, even those that don't have a Q_OBJECT : so it generates many empty file.

Is there a solution to "grep"/detect if the file contains the string Q_OBJECT and if it's the case, add it to MYPROJECT_CURRENT_MOC ?

Thank you

like image 417
Vincent Avatar asked Aug 20 '11 09:08

Vincent


2 Answers

There's a new target property in the soon-to-be-released CMake 2.8.6 called "AUTOMOC" that may help you out.

The test for this feature (which you can use as a guide or example) is found here:

http://cmake.org/gitweb?p=cmake.git;a=tree;f=Tests/QtAutomoc;h=7dae3b16a54dc0b2f63bbfa5c218c48b9bbf34a9;hb=nightly-master

The very simple CMakeLists.txt file is here:

http://cmake.org/gitweb?p=cmake.git;a=blob;f=Tests/QtAutomoc/CMakeLists.txt;h=4a5ff1099ba5249a6f22eea745a031b76e6f440f;hb=nightly-master

If you use this feature, cmake will scan the headers for Q_OBJECT and automatically run moc for you.

If you'd like to try it out before the final release of CMake 2.8.6, you can download one of the release candidates here:

http://cmake.org/files/v2.8/?C=M;O=D

The "-rc2" files do include the AUTOMOC property.

Here's the help text from running "cmake --help-property AUTOMOC":

cmake version 2.8.6-rc2
  AUTOMOC
       Should the target be processed with automoc (for Qt projects).

       AUTOMOC is a boolean specifying whether CMake will handle the Qt moc
       preprocessor automatically, i.e.  without having to use the
       QT4_WRAP_CPP() macro.  Currently Qt4 is supported.  When this property
       is set to TRUE, CMake will scan the source files at build time and
       invoke moc accordingly.  If an #include statement like #include
       "moc_foo.cpp" is found, the Q_OBJECT class declaration is expected in
       the header, and moc is run on the header file.  If an #include
       statement like #include "foo.moc" is found, then a Q_OBJECT is
       expected in the current source file and moc is run on the file itself.
       Additionally, all header files are parsed for Q_OBJECT macros, and if
       found, moc is also executed on those files.  The resulting moc files,
       which are not included as shown above in any of the source files are
       included in a generated _automoc.cpp file, which is
       compiled as part of the target.This property is initialized by the
       value of the variable CMAKE_AUTOMOC if it is set when a target is
       created.
like image 169
DLRdave Avatar answered Nov 02 '22 22:11

DLRdave


I don't know a simple command to pick headers having a string from the list but you can always make a loop to find all such headers:

set(HEADERS_HAVING_Q_OBJECT)
foreach(header ${MYPROJECT_CURRENT_HEADERS})
    file(STRINGS "${header}" lines REGEX "Q_OBJECT")
    if(lines)
        list(APPEND HEADERS_HAVING_Q_OBJECT "${header}")
    endif()
endforeach()

But this solution has its own drawback: if you add a Q_OBJECT into one of the filtered out files you need to rerun cmake manually. Otherwise moc code for new file will not be automatically generated during the build process.

like image 5
Andrey Kamaev Avatar answered Nov 03 '22 00:11

Andrey Kamaev