编辑:我对此帖子进行了大量编辑,将项目简化到其基本要素。我还添加了一个Github代码库,其中包括此帖子中未引用的文件。
我有一个使用subdirs
模板的 Qt Creator 项目(qmake,Qt 5.2.0,Creator 3.0.0)。它有三个子项目:
- Stadium-配置为
TEMPLATE=lib
和CONFIG+=staticlib
的库。 - Football - 配置为
TEMPLATE = lib
和CONFIG += staticlib
的库,并使用Field
库。 - Server - 一个 QML 应用程序,使用 Stadium 和 Football 库。
我在 Windows 8.1(MSVC2012)和 Linux (gcc 4.8.1) 上构建这个应用程序。在 Windows 上可以正常工作,但是在 Linux 上构建时表现出奇怪的行为。
我得到的错误看起来像这样:
undefined reference to 'vtable for Stadium::Engine'
我已经将这个项目重写成一组裸文件,显示了错误。你可以在Github上找到它:Football。请随意克隆并自行查看所有的错误。提交661441c
解决了问题,而提交09836f9
包含了错误。
Stadium Engine.h文件是一个抽象类,长这样:
#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
这里是Football Engine.h文件,它继承了上面的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
还有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.";
}
如果我将构造函数从cpp文件移动到头文件中,它可以无错误地编译。
以下是Server.pro文件。它代表了我所有其他pro文件的示例,因为Qt Creator自动生成的静态链接描述看起来都一样。
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
我已尝试清理、重新运行 qmake、删除构建目录并重新构建。在Linux中获取此项目构建的唯一方法是在Stadium库的.pro文件中删除CONFIG += staticlib
行(当然,在Game.pro中也要删除相应的else:unix: PRE_TARGETDEPS += $$OUT_PWD/../stadium/libstadium.a
行)。这将成功构建该项目,并且可以无问题地运行。但我不明白为什么会这样。我也不明白为什么构造函数定义所在的位置很重要。有什么想法吗?
vtable
这个东西暗示着缺少对象/类定义。启用 所有 警告,并仔细检查它们。这可能是编译器之间的标准不匹配?清除所有生成的文件,还要清除~/.ccache
,然后从头开始构建。 - vonbrand