# Using Qt's moc preprocessor

This example shows a makefile for a utility that uses Troll Tech's Qt GUI library. The only thing that's slightly unusual about this is that you must run a preprocessor called `moc` on most `.h` files that contain widget definitions, but you don't want to run `moc` on any `.h` files that don't use the `Q_OBJECT` macro.

You could, of course, just list all of the `.h` files that need to have `moc` run on them. If you're rapidly developing new widgets, however, it may be something of a nuisance to keep updating the list in the makefile. You can get around the need to list the moc modules explicitly with something like this:

    MOC	:= $(QTDIR)/bin/moc
    MODULES	:= whatever modules you happen to have in your program
    MOC_MODULES := $(patsubst %.h, moc_%, $(shell grep -l Q_OBJECT *.h))
    			# Scans all the .h files for the Q_OBJECT macro.

    my_program: $(MODULES).o $(MOC_MODULES).o
    			# This puts a .o after every word in the two
    			# variables; see variable substitution
    			# in the manual for details.

    	$(CXX) $(inputs) -o $(output)

    moc_%.cxx: %.h		# Makes the moc files from the .h files.
    	$(MOC) $(input) -o $(output)

    %.o: %.cxx
    	$(CXX) $(CXXFLAGS) -c $(input) -o $(output)

This approach scans each of your `.h` files every time makepp is run, looking for the `Q_OBJECT` macro. This sounds expensive, but it probably won't take long at all.

Another approach is to `#include` the output from the `moc` preprocessor in your widget implementation file. This means you have to remember to write the `#include`, but it has the advantage that there are fewer modules to compile, and so compilation goes faster. (For most C++ compilation, the majority of the time is spent reading the header files, and the output from the preprocessor needs to include almost as many files as your widget anyway.) For example:

    // my_widget.h
    class MyWidget : public QWidget {
      Q_OBJECT
    // ...
    }

    // my_widget.cpp

    #include "my_widget.moc"	// my_widget.moc is the output from the
    				// moc preprocessor.
    // Other implementation things here.
    MyWidget::MyWidget(QWidget * parent, const char * name) :
      QWidget(parent, name)
    {
     // ...
    }

Now you need to have a rule in your makefile to make all the `.moc` files, like this:

    MOC	:= $(QTDIR)/bin/moc
    # Rule to make .moc files:
    %.moc: %.h
    	$(MOC) $(input) -o $(output)

Makepp is smart enough to realize that it needs to make `my_widget.moc` if it doesn't already exist, or if it's out of date.

This second approach is the one that I usually use because it speeds up compilation.

Last modified: Wed Aug 23 19:49:21 PDT 2000