【发布时间】:2014-02-26 00:53:21
【问题描述】:
编辑:我对这篇文章进行了大量编辑,以将项目精简到它的本质。我还添加了Github repository,包括本文未提及的文件。
我有一个使用 subdirs 模板的 Qt Creator 项目(qmake、Qt 5.2.0、Creator 3.0.0)。共有三个子项目:
- Stadium - 配置为
TEMPLATE = lib和CONFIG += staticlib的库。 - Football - 配置为
TEMPLATE = lib和CONFIG += staticlib并使用Field库的库。 - 服务器 - 一个使用 Stadium 和 Football 库的 QML 应用程序。
我正在 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 文件。它表示我所有其他专业文件,因为静态链接描述(由 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 行)。这成功地构建了项目并且运行没有问题。但我就是不明白为什么。我也不明白为什么定义构造函数的地方很重要。
有什么想法吗?
【问题讨论】:
-
当你需要再次运行 qmake 时我看到了这个
-
@paulm,没错,但它似乎不起作用。我开始怀疑构建过程中存在错误。
-
显示继承自Engine的代码
-
@paulm,您的暗示建议至少部分正确。 :) 从 Engine 继承的代码有一个额外的 Q_OBJECT 宏(不必要,因为继承的类已经有了)。奇怪的是,构建过程从未标记继承类中的错误。我仍在试图弄清楚我尝试过的 15 件事中究竟哪一个有所帮助,但我会尽快发布解决方案。
-
有时 msvc 或 clang 会给出更有意义的错误 - 虽然在这种情况下可能不会,但可能值得一试
标签: c++ linux qt gcc qt-creator