[CMake] Qt4 moc and uic macros

Patrick Noffke Patrick.Noffke at adpro.com.au
Thu Jun 8 05:52:58 EDT 2006


All,

I've written the following macros (the first one based on the existing QT4_AUTOMOC macro) to improve the handling of moc and uic generated files with Qt4.  The "qmake way" is to generate moc_xxx.cpp files for headers that contain Q_OBJECT, and automatically include them as part of the build.  The QT4_AUTOMOC2 macro below does this.  An example usage of the macro would be as follows:

SET(foo_SRCS
  Class1.cpp
  Class2.cpp
  some_dir/Class3.cpp
)

SET(foo_MOC_HDRS
  Class1.h
  Class2.h
  some_dir/Class3.h
)

# Returns the moc_xxx.cpp files in the foo_MOC_SRCS variable
QT4_AUTOMOC2(foo_MOC_SRCS ${axiom_setup_MOC_HDRS})

ADD_EXECUTABLE(foo ${foo_SRCS} ${foo_MOC_SRCS})


The QT4_AUTOUIC macro allows you to automatically run uic on .ui files and creates a dependency of the ui_xxxx.h by xxxx.cpp (since this is the file that #include's ui_xxxx.h).  An example usage would be as follows:

SET(foo_UI
  Widget1.ui
  Widget2.ui
)

QT4_AUTOUIC(${foo_UI})

These two macros solve the problems I've been having with moc'able files existing outside the source dir, and also allows me to define a build_dir outside the source tree.  Please review them and if acceptable could a cmake maintainer please incorporate them into the cmake source tree?

Regards,
Patrick




MACRO(QT4_AUTOMOC2 moc_SRCS)
  QT4_GET_MOC_INC_DIRS(_moc_INCS)

  SET(_matching_FILES )
  FOREACH (_current_FILE ${ARGN})

     GET_FILENAME_COMPONENT(_abs_FILE ${_current_FILE} ABSOLUTE)
     # if "SKIP_AUTOMOC" is set to true, we will not handle this file here.
     # here. this is required to make bouic work correctly:
     # we need to add generated .cpp files to the sources (to compile them),
     # but we cannot let automoc handle them, as the .cpp files don't exist yet when
     # cmake is run for the very first time on them -> however the .cpp files might
     # exist at a later run. at that time we need to skip them, so that we don't add two
     # different rules for the same moc file
     GET_SOURCE_FILE_PROPERTY(_skip ${_abs_FILE} SKIP_AUTOMOC)

     IF ( NOT _skip AND EXISTS ${_abs_FILE} )

        FILE(READ ${_abs_FILE} _contents)

        GET_FILENAME_COMPONENT(_abs_PATH ${_abs_FILE} PATH)

        STRING(REGEX MATCHALL "Q_OBJECT" _match "${_contents}")
        IF(_match)
            GET_FILENAME_COMPONENT(_basename ${_current_FILE} NAME_WE)
            SET(_header ${_abs_PATH}/${_basename}.h)
            SET(_moc    ${CMAKE_CURRENT_BINARY_DIR}/moc_${_basename}.cpp)

            ADD_CUSTOM_COMMAND(OUTPUT ${_moc}
                COMMAND ${QT_MOC_EXECUTABLE}
                ARGS ${_moc_INCS} ${_header} -o ${_moc}
                DEPENDS ${_header}
            )

            ADD_FILE_DEPENDENCIES(${_abs_FILE} ${_moc})
            SET(${moc_SRCS} ${${moc_SRCS}} ${_moc})
            
        ENDIF(_match)
     ENDIF ( NOT _skip AND EXISTS ${_abs_FILE} )
  ENDFOREACH (_current_FILE)
ENDMACRO(QT4_AUTOMOC2)

MACRO(QT4_AUTOUIC)

  SET(_matching_FILES )
  FOREACH (_current_FILE ${ARGN})

     GET_FILENAME_COMPONENT(_abs_FILE ${_current_FILE} ABSOLUTE)

     IF ( EXISTS ${_abs_FILE} )

        FILE(READ ${_abs_FILE} _contents)

        GET_FILENAME_COMPONENT(_abs_PATH ${_abs_FILE} PATH)

        GET_FILENAME_COMPONENT(_basename ${_current_FILE} NAME_WE)
        SET(_outfile ${CMAKE_CURRENT_SOURCE_DIR}/ui_${_basename}.h)
        SET(_header ${_basename}.h)
        SET(_source ${_basename}.cpp)
        
        ADD_CUSTOM_COMMAND(OUTPUT ${_outfile}
            COMMAND ${QT_UIC_EXECUTABLE}
            ARGS -o ${_outfile} ${_abs_FILE}
            MAIN_DEPENDENCY ${_abs_FILE})

        ADD_FILE_DEPENDENCIES(${_source} ${_outfile})
            
     ENDIF ( EXISTS ${_abs_FILE} )
  ENDFOREACH (_current_FILE)
ENDMACRO(QT4_AUTOUIC)


More information about the CMake mailing list