EDIT: я сильно отредактировал этот пост, чтобы лишить проект до его сути. Я также добавил репозиторий Github, в том числе файлы, на которые не ссылаются в этом сообщении.
У меня есть проект Qt Creator (qmake, Qt 5.2.0, Creator 3.0.0), который использует шаблон subdirs
. Существует три подпроекта:
- Стадион - библиотека, настроенная как
TEMPLATE = lib
иCONFIG += staticlib
. - Футбол - библиотека, которая настроена как
TEMPLATE = lib
иCONFIG += staticlib
и использует библиотекуField
. - Сервер - приложение 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. Это указывает на все мои другие файлы 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 - это удалить строку CONFIG += staticlib
в .pro файле библиотеки стадиона (и соответствующую строку else:unix: PRE_TARGETDEPS += $$OUT_PWD/../stadium/libstadium.a
в Game.pro тоже, конечно). Это успешно создает проект и запускается без проблем. Но я просто не понимаю, почему. Я также не понимаю, почему это имеет значение, когда определено определение конструктора.
Любые идеи?