QT — Как создать многоуровневую структуру проекта в C ++, используя qmake

Под окнами с использованием MinGW, C ++ 11, Qt 5 и qmake у меня есть следующая структура проекта:

/my-project
my-project.pro
/my-app
my-app.pro
main.cpp
/module-a
module-a.pro
modulea.h
modulea.cpp
/module-b
module-b.pro
moduleb.h
moduleb.cpp

Зависимости между модулями должны выглядеть так:

my-app ==> module-a ==> module-b

Чего я хочу достичь, так это того, что my-app использует module-a, module-a использует module-b, а my-app ничего не знает о module-b. Модуль-ссылка модуль-б только через его реализацию ( #include для модуля-b находится в .cpp модуля-a).

Я попытался реализовать это, настроив module-a и module-b как статические библиотеки в qmake. К сожалению, во время компиляции я получаю сообщение об ошибке компоновщика, говорящее «неопределенная ссылка на ModuleB :: doSmthB ()»

Я понимаю причину этой проблемы связывания, мой вопрос заключается в том, можно ли каким-то образом добиться чего-то похожего на предложенную многоуровневую структуру?

Источники:

my-project.pro:

TEMPLATE = subdirs
SUBDIRS += module-b
SUBDIRS += module-a
SUBDIRS += my-app
my-app.depends = module-a
module-a.depends = module-b

my-app.pro:

QT += widgets
TARGET = my-app
TEMPLATE = app
CONFIG += c++11
SOURCES += *.cpp
win32 {
INCLUDEPATH += $$clean_path($$PWD/../module-a)
DEPENDPATH += $$clean_path($$PWD/../module-a)
LIBS += $$clean_path($$OUT_PWD/../module-a/debug/libmodule-a.a)
PRE_TARGETDEPS += $$clean_path($$OUT_PWD/../module-a/debug/libmodule-a.a)
}

main.cpp:

#include <QApplication>
#include <QGraphicsView>
#include <QGraphicsScene>

#include "modulea.h"
int main(int argc, char *args[])
{
QApplication app(argc, args);
QGraphicsView view;
QGraphicsScene *scene = new QGraphicsScene(0, 0, 300, 300, &view);
ModuleA moduleA;
scene->addText(QString::number(moduleA.doSmthA())); // undefined reference to ModuleB::doSmthB()
view.setScene(scene);
view.show();
return app.exec();
}

module-a.pro:

QT -= core gui
TARGET = module-a
TEMPLATE = lib
CONFIG += staticlib
CONFIG += c++11
HEADERS += *.h
SOURCES += *.cpp
win32 {
INCLUDEPATH += $$clean_path($$PWD/../module-b)
DEPENDPATH += $$clean_path($$PWD/../module-b)
LIBS += $$clean_path($$OUT_PWD/../module-b/debug/libmodule-b.a)
PRE_TARGETDEPS += $$clean_path($$OUT_PWD/../module-b/debug/libmodule-b.a)
}

modulea.h:

#ifndef MODULEA_H
#define MODULEA_H

struct ModuleA
{
int doSmthA();
};

#endif // MODULEA_H

modulea.cpp:

#include "modulea.h"#include "moduleb.h"
int ModuleA::doSmthA() {
ModuleB other;
return other.doSmthB();
}

module-b.pro:

QT -= core gui
TARGET = module-b
TEMPLATE = lib
CONFIG += staticlib
CONFIG += c++11
HEADERS += *.h
SOURCES += *.cpp

moduleb.h:

#ifndef MODULEB_H
#define MODULEB_H

struct ModuleB
{
int doSmthB();
};

#endif // MODULEB_H

moduleb.cpp:

#include "moduleb.h"
int ModuleB::doSmthB() {
return 12345;
}

5

Решение

Чтобы исправить мой пример, необходимы следующие изменения:

1) Добавить CONFIG += create_prl к файлам .pro всех прямых зависимостей приложения (в моем случае module-a). Это не помешает изменить все модули, как это.

Объяснение здесь:
http://doc.qt.io/qt-5/qmake-advanced-usage.html#library-dependencies

2) В основном .pro (в моем примере my-project.pro) объявление subdir приложения (SUBDIRS += my-app) должен быть помещен ПОСЛЕ прямых зависимостей приложения (после SUBDIRS += module-a).

Подсказка для второго пункта, который я нашел здесь: https://stackoverflow.com/a/1417859/6223445

3) LIBS свойство должно быть определено с помощью -L а также -l варианты (по крайней мере, под окнами), например вместо:

LIBS += $$clean_path($$OUT_PWD/../module-a/debug/libmodule-a.a)

используйте следующее:

LIBS += -L$$clean_path($$OUT_PWD/../module-a/debug/) -lmodule-a

Фиксированное решение выглядит так (только измененные файлы):

my-project.pro:

TEMPLATE = subdirs
SUBDIRS += module-b
SUBDIRS += module-a
SUBDIRS += my-app
my-app.depends = module-a
module-a.depends = module-b

my-app.pro:

QT += widgets
TARGET = my-app
TEMPLATE = app
CONFIG += c++11
SOURCES += *.cpp
win32 {
INCLUDEPATH += $$clean_path($$PWD/../module-a)
DEPENDPATH += $$clean_path($$PWD/../module-a)
LIBS += -L$$clean_path($$OUT_PWD/../module-a/debug/) -lmodule-a
PRE_TARGETDEPS += $$clean_path($$OUT_PWD/../module-a/debug/libmodule-a.a)
}

module-a.pro:

QT -= core gui
TARGET = module-a
TEMPLATE = lib
CONFIG += staticlib
CONFIG += c++11
CONFIG += create_prl
HEADERS += *.h
SOURCES += *.cpp
win32 {
INCLUDEPATH += $$clean_path($$PWD/../module-b)
DEPENDPATH += $$clean_path($$PWD/../module-b)
LIBS += -L$$clean_path($$OUT_PWD/../module-b/debug/) -lmodule-b
PRE_TARGETDEPS += $$clean_path($$OUT_PWD/../module-b/debug/libmodule-b.a)
}
2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]