Ender
Ender

Reputation: 1778

How to use Qt moc in autotools project (in 2017)?

Trying to compile a basic Qt application (new to Qt) with autotools (which I've done many projects with) on Linux.

Everything seems to compile fine until the linking starts, and thats when I get the following results.

test-mainwindow.o: In function `MainWindow::MainWindow()':
mainwindow.cpp:5: undefined reference to `vtable for MainWindow'
mainwindow.cpp:5: undefined reference to `vtable for MainWindow'
mainwindow.o: In function `MainWindow::~MainWindow()':
mainwindow.cpp:11: undefined reference to `vtable for MainWindow'
mainwindow.cpp:11: undefined reference to `vtable for MainWindow'
mainwindow.o: In function `MainWindow::tr(char const*, char const*, int)':
mainwindow.h:10: undefined reference to `MainWindow::staticMetaObject'
collect2: error: ld returned 1 exit status
make[4]: *** [Makefile:415: test] Error 1

I've not done a Qt app before, so I suspect maybe something to do with the moc, or Q_OBJECT in my MainWindow header? Most all examples I could find online are 4+ years old.

Here's what the Makefile.am in my source dir looks like.

include $(top_srcdir)/common.am

bin_PROGRAMS = test

test_SOURCES =               \
    main.cpp                 \
    mainwindow.cpp

test_CPPFLAGS = -I/usr/include -I/usr/local/include -I$(QT5_INCL) -I$(QT5_INCL)/QtWidgets -I$(QT5_INCL)/QtCore

test_LDFLAGS = -L/usr/lib64 -L/usr/local/lib64 -L/usr/local/lib -L$(QT5_LIBS)

test_LDADD = -lrt -lQt5Core -lQt5Gui -lQt5Widgets

And if I append this to the Makefile.am, which I'm sure isn't fully correct at this point ...

moc-%.cpp: %.h
    /usr/lib64/qt5/bin/moc $(DEFINES) $(INCPATH) $< -o $@

moc-%.cc: %.h
    @MOC@ -o$@ $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(MOC_CPPFLAGS) $<

ui-%.h: %.ui
    @UIC@ -o $@ $<

qrc-%.cc: %.qrc
    @RCC@ -o $@ $<

Automake will complain w/ this before I even try to compile ...

Makefile.am:19: warning: '%'-style pattern rules are a GNU make extension
Makefile.am:24: warning: '%'-style pattern rules are a GNU make extension
Makefile.am:27: warning: '%'-style pattern rules are a GNU make extension
Makefile.am:30: warning: '%'-style pattern rules are a GNU make extension

Anyone have ideas about how to implement the moc part of things using autotools?

Upvotes: 1

Views: 606

Answers (1)

John Bollinger
John Bollinger

Reputation: 181028

Automake does not automatically recognize that your program depends on unspecified sources that need to be created by processing other files with moc or other Qt tools. Your *_SOURCES variables need to name such derived sources explicitly, and you need to provide a literal make rule or rules for building them.

You may furthermore need to name some of those in the value of the BUILT_SOURCES variable. C++ top-level source files are unlikely to need this treatment, but built header files (or any other sources named in an #include directive) very likely do need it.

The details are somewhat up to you, and I cannot offer a specific solution because it's unclear what your exact needs are. But the desired Automake file might look something like this:

include $(top_srcdir)/common.am

bin_PROGRAMS = test

# headers that must be processed with moc to generate C++ source files
test_qtheaders = mainwindow.h

# the source files that will be generated via moc.  The string "_moc" is inserted
# to, hopefully, avoid name collisions
test_moc_sources = $(test_qtheaders:.h=_moc.cpp)

test_SOURCES =               \
    main.cpp                 \
    mainwindow.cpp           \
    $(test_moc_sources)

test_CPPFLAGS = -I/usr/include -I/usr/local/include -I$(QT5_INCL) -I$(QT5_INCL)/QtWidgets -I$(QT5_INCL)/QtCore

test_LDFLAGS = -L/usr/lib64 -L/usr/local/lib64 -L/usr/local/lib -L$(QT5_LIBS)

test_LDADD = -lrt -lQt5Core -lQt5Gui -lQt5Widgets

# A traditional-style Make suffix rule for generating *_moc.cpp files from *.h
# files via moc.  For the former (especially) to be recognized as a suffix,
# you need to tell Automake about it via the `SUFFIXES` variable.
# The mkdir is present to support out-of-source building.
# Assumes that the MOC variable will be set by configure.
.h_moc.cpp:
    $(MKDIR_P) `dirname $@`
    $(MOC) -o $@ $(test_CPPFLAGS) $(CPPFLAGS) $<

SUFFIXES = .h _moc.cpp

You may also want to list the built sources among your CLEANFILES, else they will be left behind when you make clean.

Upvotes: 2

Related Questions