jmb*_*eck 15 c++ linux qt gcc qt-creator
编辑:我已经大量编辑了这篇文章,将项目剥离到其基本要素.我还添加了一个Github存储库,包括本文中未引用的文件.
我有一个使用subdirs模板的Qt Creator项目(qmake,Qt 5.2.0,Creator 3.0.0).有三个子项目:
TEMPLATE = lib和的图书馆CONFIG += staticlib.TEMPLATE = lib和CONFIG += staticlib并使用Field图书馆.我正在Windows 8.1(MSVC2012)和Linux(gcc 4.8.1)上构建此应用程序.它在Windows上没有问题,但Linux构建表现奇怪.
我得到的错误看起来像这样:
undefined reference to 'vtable for Stadium::Engine'
Run Code Online (Sandbox Code Playgroud)
我已经将这个项目重写为一组显示错误的裸文件.你可以在Github上找到它:足球.随意克隆它,并为自己看到所有的错误.该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
Run Code Online (Sandbox Code Playgroud)
这是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
Run Code Online (Sandbox Code Playgroud)
和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.";
}
Run Code Online (Sandbox Code Playgroud)
如果我将构造函数定义从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
Run Code Online (Sandbox Code Playgroud)
我已经尝试过清理,重新运行qmake,删除构建目录和重建.在Linux中构建此项目的唯一方法是删除CONFIG += staticlibStadium库的.pro文件中的else:unix: PRE_TARGETDEPS += $$OUT_PWD/../stadium/libstadium.a行(当然也包括Game.pro中的相应行).这样就可以成功构建项目并且无问题地运行.但我只是不明白为什么.我也不明白为什么定义构造函数定义很重要.
有任何想法吗?
Ali*_*Ali 13
答案非常简单:图书馆链接的顺序错误.
我查看了调用链接器的命令(链接器错误正上方):
g++ [...] -lStadium [...] -lFootball
Run Code Online (Sandbox Code Playgroud)
我还查看了代码:Football子项目引用了Stadium子项目,因此库的顺序错误,例如,参见GCC C++ Linker错误的接受答案:未定义的引用'vtable for XXX',Undefined reference to' ClassName :: ClassName()'用于解释.
实际上,如果我在Server.pro文件中交换这两个库(从提交派生09836f9,为了简洁而删除了不相关的win32特定细节):
[...]
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
Run Code Online (Sandbox Code Playgroud)
现在命令行看起来像:
g++ [...] -lFootball [...] -lStadium
Run Code Online (Sandbox Code Playgroud)
它在我的Linux机器上编译并运行得很好.
| 归档时间: |
|
| 查看次数: |
4339 次 |
| 最近记录: |