2

I am trying to turn ovpn3's ovpncli example into a class that derives from QObject. I'm unable to turn the source file into a separate interface (.h) and implementation (.cpp) file. To make the MOC happy, I've put #include "openvpn.moc" at the end of openvpn.cpp (the source file). I am getting this error however: :-1: error: No rule to make target 'openvpn.moc', needed by 'openvpnmanager.o'. Stop. I've cleaned the build directory, re-ran qmake, and rebuilt it 1000 times. Despite this, it still refuses to work. What am I doing wrong?

myproject.pro:

QT       += core widgets network
CONFIG += c++11
UI_SOURCES_DIR = src/gui
UI_HEADERS_DIR = include

. . .

SOURCES += \
    src/main.cpp \
    src/gui/loginwindow.cpp \
    src/api/api.cpp \
    src/openvpn/openvpn.cpp \
    src/alert.cpp \
    src/gui/vpn.cpp \
    src/api/account.cpp \
    src/crypto.cpp \
    src/killswitch.cpp \
    src/vpnstatus.cpp \
    src/gui/logdialog.cpp \
    src/logitem.cpp \
    src/authenticationworker.cpp \
    src/api/error.cpp \
    src/openvpn/openvpnmanager.cpp \
    src/api/server.cpp \
    src/api/authenticationresponse.cpp

HEADERS += \
    include/loginwindow.h \
    include/api.h \
    include/alert.h \
    include/vpn.h \
    include/account.h \
    include/crypto.h \
    include/killswitch.h \
    include/configtype.h \
    include/vpnstatus.h \
    include/connectionstatus.h \
    include/loglevel.h \
    include/logdialog.h \
    include/logitem.h \
    include/authenticationworker.h \
    include/error.h \
    include/openvpnmanager.h \
    include/server.h \
    include/authenticationresponse.h \

FORMS += \
    src/gui/loginwindow.ui \
    src/gui/vpn.ui \
    src/gui/logdialog.ui

RESOURCES += \
    src/resources.qrc

DISTFILES +=

openvpn.cpp:

class Client : public QObject, public ClientAPI::OpenVPNClient {
    Q_OBJECT
public:
    . . .
Chase
  • 95
  • 11

1 Answers1

3

TL;DR

Simply delete your build-xxx folder, and rebuild from scratch!

Context

You (almost) never have to include a .moc file. Moc files are created automatically by the mocompiler and compiled and linked in a dedicated translation unit (i.e. like any .cpp file).

The only exception is when your QObject class is declared in a cpp file (which happens to be your case!), because the .moc implementation will still require your class definition to compile. As suggested in the comments, there is a detailed explanation here.

Potential issues

Regarding your specific issue, moc file issues can originate from:

  • the Q_OBJECT keyword is missing (but you have it). This token is used to trigger the generation of a .moc file for that specific class. Without it, most QObject features are missing.
  • the class was parsed/compiled previously without the Q_OBJECT keyword, and cached as a non-QObject class. In that case, you just have to manually delete your build folder (or run qmake manually), to force identifying again which classes should be moced.
  • You are using the wrong filename for your moced file. The correct name is typically
    • moc_filename.cpp when your class is declared in a header file
    • filename.moc when your class is declared in a source file
  • qmake does not actually parses your .cpp file. This can be the case if your .pro file doesn't include it in the SOURCES variable, or if you are just never running qmake (specific setup, etc.)

Sample Makefile

You can double check it your moc files has appropriate rules in the Makefile of its project. Below is a sample portion of a Makefile:

compiler_moc_source_make_all: mysourcefile.moc

compiler_moc_source_clean:
    -$(DEL_FILE) mysourcefile.moc

mysourcefile.moc: /home/aleravat/Qt/5.9.7/gcc_64/include/QtCore/QCoreApplication \
        /home/aleravat/Qt/5.9.7/gcc_64/include/QtCore/qcoreapplication.h \
        /home/aleravat/Qt/5.9.7/gcc_64/include/QtCore/qglobal.h \
        /home/aleravat/Qt/5.9.7/gcc_64/include/QtCore/qconfig-bootstrapped.h \
        # [...] more includes
    /home/aleravat/Qt/5.9.7/gcc_64/bin/moc $(DEFINES) --include ./moc_predefs.h [...] mysourcefile.cpp -o mysourcefile.moc
Adrien Leravat
  • 2,731
  • 18
  • 32
  • Clarification: you must include moc in the cpp file manually if you place QObject derived class into a cpp file. See good explanation from [here](https://stackoverflow.com/questions/34928933/why-is-important-to-include-moc-file-at-end-of-a-qt-source-code-file) – talamaki Mar 27 '19 at 21:52
  • Oh thanks! I actually didn't see that the OP had his class definition in a `.cpp` file. That was the reason of my "(almost) never", but I guess it totally makes sense to explain it now. – Adrien Leravat Mar 27 '19 at 21:57
  • I'm looking at my Makefile generated by Qt's qmake and there is no moc_openvpn.cpp anywhere. In the 3rd bulletpoint are you suggesting that openvpn.cpp must be renamed? – Chase Mar 27 '19 at 23:45
  • You're defining your class in a cpp file, so your original name is probably the right one, `openvpn.moc`. Do you see any reference to that particular one or any variation around `openvpn`? Are you sure that your file is listed in the `SOURCES` variable of your `.pro` as well? – Adrien Leravat Mar 28 '19 at 00:15
  • These two files are included in my Makefile under openvpnmanager.o (openvpnmanager.cpp includes openvpn.cpp): `src/openvpn/openvpn.cpp \ openvpn.moc \ ` – Chase Mar 28 '19 at 00:46
  • Ok so you have something missing. Did you check the SOURCES variable in your .pro? Or do you call `qmake` manually and pass it that specific .cpp? – Adrien Leravat Mar 28 '19 at 18:57
  • My openvpn.cpp file included in the SOURCES variable as indicated by the .pro file I posted. – Chase Mar 28 '19 at 19:05
  • Mhh.. you've got an extraneous \ at the end of your header list also, you probably want to fix that. Can you share your makefile? – Adrien Leravat Mar 28 '19 at 20:10
  • `openvpn.cpp` is not in the SOURCES in your makefile, only mentioned in `openvpnmanager.o`. So either you are not qmaking the right file, or this is a different Makefile – Adrien Leravat Mar 29 '19 at 02:22
  • @AdrienLeravat How would I go about fixing this? This is the command used by Qt: `qmake myproject.pro -spec linux-g++ CONFIG+=debug CONFIG+=qml_debug && /usr/bin/make qmake_all`. Before I tried making the Client class a QObject, compilation worked fine with the exact same .pro file. – Chase Mar 29 '19 at 02:39
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/190883/discussion-between-adrien-leravat-and-chase). – Adrien Leravat Mar 29 '19 at 04:00