Das Erstellen der Qt-App mit CONFIG +=staticlib verursacht einen undefinierten Verweis auf vtable-Fehler

 C Programming >> C-Programmierung >  >> Tags >> Qt
Das Erstellen der Qt-App mit CONFIG +=staticlib verursacht einen undefinierten Verweis auf vtable-Fehler


BEARBEITEN:Ich habe diesen Beitrag stark bearbeitet, um das Projekt auf das Wesentliche zu reduzieren. Ich habe auch ein Github-Repository hinzugefügt, einschließlich der Dateien, auf die in diesem Beitrag nicht verwiesen wird.



Ich habe ein Qt Creator-Projekt (qmake, Qt 5.2.0, Creator 3.0.0), das den subdirs verwendet Schablone. Es gibt drei Unterprojekte:



  1. Stadion - Bibliothek, die als TEMPLATE = lib konfiguriert ist und CONFIG += staticlib .

  2. Fußball - Bibliothek, die als TEMPLATE = lib konfiguriert ist und CONFIG += staticlib und verwendet den Field Bibliothek.

  3. Server – eine QML-Anwendung, die sowohl Stadium- als auch Football-Bibliotheken verwendet.


Ich erstelle diese Anwendung sowohl unter Windows 8.1 (MSVC2012) als auch unter Linux (gcc 4.8.1). Es funktioniert ohne Probleme unter Windows , aber der Linux-Build verhält sich seltsam.


Die Fehler, die ich bekomme, sehen so aus:


undefined reference to 'vtable for Stadium::Engine'

Ich habe dieses Projekt in eine Reihe von nackten Dateien umgeschrieben, die den Fehler anzeigen. Sie finden es auf Github hier:Fußball. Fühlen Sie sich frei, es zu klonen und alle Fehler selbst zu sehen. Die 661441c commit löst das Problem und die 09836f9 commit enthält die Fehler.


Die Datei Stadium Engine.h ist eine abstrakte Klasse. Es sieht so aus:


#ifndef STADIUM_ENGINE_H
#define STADIUM_ENGINE_H
#include <QObject>
namespace Stadium {
class Engine : public QObject
{
Q_OBJECT
public slots:
virtual void executeCommand() = 0;
};
} // namespace Stadium
#endif // STADIUM_ENGINE_H

Hier ist die Football Engine.h-Datei, die von der obigen Stadium Engine.h-Datei erbt:


#ifndef FOOTBALL_ENGINE_H
#define FOOTBALL_ENGINE_H
#include <QObject>
#include "../Stadium/Engine.h"
namespace Football
{
class Engine : public Stadium::Engine
{
Q_OBJECT
public:
Engine();
~Engine() {}
public slots:
void executeCommand();
};
} // namespace Football
#endif // FOOTBALL_ENGINE_H

Und die Datei Football Engine.cpp:


#include "Engine.h"
#include <QDebug>
Football::Engine::Engine()
{
qDebug() << "[Football::Engine] Created.";
}
void Football::Engine::executeCommand()
{
qDebug() << "[Football::Engine] The command was executed.";
}

Wenn ich die Konstruktordefinition aus dem cpp in die Header-Datei verschiebe, wird sie ohne Fehler erstellt.


Unten ist die Datei Server.pro. Es ist bezeichnend für alle meine anderen Pro-Dateien, da die statischen Linkbeschreibungen (automatisch von Qt Creator generiert) gleich aussehen.


QT       += core
QT -= gui
TARGET = Server
CONFIG += console
CONFIG -= app_bundle
TEMPLATE = app
SOURCES += main.cpp
win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../Stadium/release/ -lStadium
else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../Stadium/debug/ -lStadium
else:unix: LIBS += -L$$OUT_PWD/../Stadium/ -lStadium
INCLUDEPATH += $$PWD/../Stadium
DEPENDPATH += $$PWD/../Stadium
win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../Stadium/release/libStadium.a
else:win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../Stadium/debug/libStadium.a
else:win32:!win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../Stadium/release/Stadium.lib
else:win32:!win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../Stadium/debug/Stadium.lib
else:unix: PRE_TARGETDEPS += $$OUT_PWD/../Stadium/libStadium.a
win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../Football/release/ -lFootball
else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../Football/debug/ -lFootball
else:unix: LIBS += -L$$OUT_PWD/../Football/ -lFootball
INCLUDEPATH += $$PWD/../Football
DEPENDPATH += $$PWD/../Football
win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../Football/release/libFootball.a
else:win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../Football/debug/libFootball.a
else:win32:!win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../Football/release/Football.lib
else:win32:!win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../Football/debug/Football.lib
else:unix: PRE_TARGETDEPS += $$OUT_PWD/../Football/libFootball.a

Ich habe versucht, zu bereinigen, qmake erneut auszuführen, das Build-Verzeichnis zu entfernen und neu zu erstellen. Die einzige Möglichkeit, dieses Projekt unter Linux zu erstellen, besteht darin, CONFIG += staticlib zu entfernen Zeile in der .pro-Datei der Stadium-Bibliothek (und die entsprechende else:unix: PRE_TARGETDEPS += $$OUT_PWD/../stadium/libstadium.a natürlich auch in der Game.pro). Dadurch wird das Projekt erfolgreich erstellt und ohne Probleme ausgeführt. Aber ich verstehe einfach nicht warum. Ich verstehe auch nicht, warum es darauf ankommt, wo die Konstruktordefinition definiert ist.


Irgendwelche Ideen?


Einige Code-Antworten


undefined reference to 'vtable for Stadium::Engine' 
#ifndef STADIUM_ENGINE_H #define STADIUM_ENGINE_H  #include <QObject>
namespace Stadium { class Engine : public QObject {
Q_OBJECT public slots:
virtual void executeCommand() = 0;
};
} // namespace Stadium #endif // STADIUM_ENGINE_H
#ifndef FOOTBALL_ENGINE_H #define FOOTBALL_ENGINE_H  #include <QObject>
#include "../Stadium/Engine.h" namespace Football { class Engine : public Stadium::Engine {
Q_OBJECT public:
Engine();
~Engine() {} public slots:
void executeCommand();
};
} // namespace Football #endif // FOOTBALL_ENGINE_H
#include "Engine.h"  #include <QDebug>
Football::Engine::Engine() {
qDebug() <<
"[Football::Engine] Created.";
} void Football::Engine::executeCommand() {
qDebug() <<
"[Football::Engine] The command was executed.";
}
QT
+= core QT
-= gui TARGET = Server CONFIG += console CONFIG -= app_bundle TEMPLATE = app SOURCES += main.cpp win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../Stadium/release/ -lStadium else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../Stadium/debug/ -lStadium else:unix: LIBS += -L$$OUT_PWD/../Stadium/ -lStadium INCLUDEPATH += $$PWD/../Stadium DEPENDPATH += $$PWD/../Stadium win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../Stadium/release/libStadium.a else:win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../Stadium/debug/libStadium.a else:win32:!win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../Stadium/release/Stadium.lib else:win32:!win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../Stadium/debug/Stadium.lib else:unix: PRE_TARGETDEPS += $$OUT_PWD/../Stadium/libStadium.a win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../Football/release/ -lFootball else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../Football/debug/ -lFootball else:unix: LIBS += -L$$OUT_PWD/../Football/ -lFootball INCLUDEPATH += $$PWD/../Football DEPENDPATH += $$PWD/../Football win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../Football/release/libFootball.a else:win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../Football/debug/libFootball.a else:win32:!win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../Football/release/Football.lib else:win32:!win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../Football/debug/Football.lib else:unix: PRE_TARGETDEPS += $$OUT_PWD/../Football/libFootball.a
g++ [...] -lStadium [...] -lFootball  
[...]  SOURCES += main.cpp  LIBS += -L$$OUT_PWD/../Football/ -lFootball INCLUDEPATH += $$PWD/../Football DEPENDPATH += $$PWD/../Football PRE_TARGETDEPS += $$OUT_PWD/../Football/libFootball.a  LIBS += -L$$OUT_PWD/../Stadium/ -lStadium INCLUDEPATH += $$PWD/../Stadium DEPENDPATH += $$PWD/../Stadium PRE_TARGETDEPS += $$OUT_PWD/../Stadium/libStadium.a 
g++ [...] -lFootball [...] -lStadium 
inline Stadium::Engine::Engine() {} inline Stadium::Engine::~Engine() {}