Under windows using MinGW, C++11, Qt 5 and qmake I have following project structure:
/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
The dependencies between modules should look like this:
my-app ==> module-a ==> module-b
What I want to achieve is that my-app uses module-a, module-a uses module-b and my-app doesn't know anything about module-b. The module-a references module-b only through its implementation (the #include
for module-b is located in .cpp of module-a).
I've tried to implement this by configuring module-a and module-b as static libraries in qmake. Unfortunately while compiling I receive linker error saying 'undefined reference to ModuleB::doSmthB()'
I understand the reason of this linking problem, my question is if it is somehow possible to achieve something similar to the proposed layered structure?
Sources:
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;
}
The qmake tool provides you with a project-oriented system for managing the build process for applications, libraries, and other components. This approach gives you control over the source files used, and allows each of the steps in the process to be described concisely, typically within a single file.
The project file format used by qmake can be used to support both simple and fairly complex build systems. Simple project files use a straightforward declarative style, defining standard variables to indicate the source and header files that are used in the project.
pro) File. I'm sure you already know about the Qt Project File since we have mentioned it countless times throughout the book. A .pro file is actually the project file used by qmake to build your application, library, or plugin.
To fix my example following changes are required:
1) Add CONFIG += create_prl
to the .pro files of all app's direct dependencies (in my case module-a
). It won't hurt to modify all modules like this.
Explanation here: http://doc.qt.io/qt-5/qmake-advanced-usage.html#library-dependencies
2) In the main .pro (in my example the my-project.pro
) the subdir declaration of app (SUBDIRS += my-app
) has to be placed AFTER the direct dependencies of app (after SUBDIRS += module-a
).
A hint for the second point I've found here: https://stackoverflow.com/a/1417859/6223445
3) The LIBS
property have to be defined using -L
and -l
options (at least under windows), e.g. instead of:
LIBS += $$clean_path($$OUT_PWD/../module-a/debug/libmodule-a.a)
use following:
LIBS += -L$$clean_path($$OUT_PWD/../module-a/debug/) -lmodule-a
The fixed solution looks like this (modified files only):
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)
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With