如何使用 qmake 在 C++ 中创建分层项目结构
How to create layered project structure in c++ using qmake
在 windows 下使用 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
我想实现的是我的应用程序使用模块a,模块a使用模块b,而我的应用程序对模块b一无所知。模块 a 仅通过其实现引用模块 b(模块 b 的 #include
位于模块 a 的 .cpp 中)。
我试图通过在 qmake 中将 module-a 和 module-b 配置为静态库来实现这一点。不幸的是,在编译时我收到链接器错误 'undefined reference to ModuleB::doSmthB()'
我明白这个链接问题的原因,我的问题是是否有可能以某种方式实现类似于提议的分层结构的东西?
来源:
我的-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 += $$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();
}
模块-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();
}
模块-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;
}
要修复我的示例,需要进行以下更改:
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
)必须放置在应用程序的直接依赖项之后(在 [=19 之后) =]).
我在这里找到的第二点提示:
3) LIBS
属性 必须使用 -L
和 -l
选项定义(至少在 windows 下),例如而不是:
LIBS += $$clean_path($$OUT_PWD/../module-a/debug/libmodule-a.a)
使用以下内容:
LIBS += -L$$clean_path($$OUT_PWD/../module-a/debug/) -lmodule-a
固定的解决方案如下所示(仅限修改后的文件):
我的-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)
}
模块-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)
}
在 windows 下使用 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
我想实现的是我的应用程序使用模块a,模块a使用模块b,而我的应用程序对模块b一无所知。模块 a 仅通过其实现引用模块 b(模块 b 的 #include
位于模块 a 的 .cpp 中)。
我试图通过在 qmake 中将 module-a 和 module-b 配置为静态库来实现这一点。不幸的是,在编译时我收到链接器错误 'undefined reference to ModuleB::doSmthB()'
我明白这个链接问题的原因,我的问题是是否有可能以某种方式实现类似于提议的分层结构的东西?
来源:
我的-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 += $$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();
}
模块-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();
}
模块-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;
}
要修复我的示例,需要进行以下更改:
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
)必须放置在应用程序的直接依赖项之后(在 [=19 之后) =]).
我在这里找到的第二点提示:
3) LIBS
属性 必须使用 -L
和 -l
选项定义(至少在 windows 下),例如而不是:
LIBS += $$clean_path($$OUT_PWD/../module-a/debug/libmodule-a.a)
使用以下内容:
LIBS += -L$$clean_path($$OUT_PWD/../module-a/debug/) -lmodule-a
固定的解决方案如下所示(仅限修改后的文件):
我的-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)
}
模块-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)
}