2016-04-19 10 views
4

Под окнами с помощью MinGW, C++ 11, Qt 5 и QMAKE я следующую структуру проекта:Как создать многоуровневую структуру проекта в C++ с использованием 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 

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

Я попытался реализовать это, настроив модули-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(); 
} 

модуль-а .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; 
} 

ответ

2

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

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

Расшифровка здесь: http://doc.qt.io/qt-5/qmake-advanced-usage.html#library-dependencies

2) В главном .pro (в моем примере my-project.pro) подкаталога декларация приложения (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 

мой -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) 
}