Qt笔记-构建较为层次较为分明项目工程

前言

  一般情况下,在Qt或者是VS创建一个项目后,只会简单的生成三个Filter过滤器,头文件+源文件+UI设计师文件;
在这里插入图片描述
  实际项目中的代码是这样子的:
在这里插入图片描述
  小项目或者是Demo,这样组建项目是没有问题的。但是当项目代码有一定规模,或者一个项目从小项目不断追加形成一个大项目时,就会发现这种构建项目的缺点:无组织无纪律;头文件和源文件以及UI文件都掺杂在一块;毫无层次,毫无模块的划分;这时是不是就需要对这些文件进行分门别类整理,该使用MVC的使用MVC,该对公有工具类或者是算法类独立为静态库或者动态库单独模块就赶紧肝起来;
  项目的管理和电脑上文件的管理的思路是一样的,好的文件管理,就是能够清晰文件之间类别,让使用者方便查找和快速查找;有经验的程序员都知道,写代码的时间很短,查找代码和看代码的时间是占了绝大部分时间;代码功能内聚,模块之间低耦合,就是给自己和别人看代码提供了最大的方便。
  比如:
在这里插入图片描述
  在文件的构建和编译过程中,需要对pro和pri文件有所一定的了解;
  对项目的分解、整理的目的,除了控制子项目的类型等基本信息,剩下的就是约束子项目的输出文件夹位置、输入库和引用头文件位置、引入第三方库、设置宏控制进行条件编译;

具体操作

  创建一个子目录项目,在“其他项目”分类下选择“子目录项目”;
在这里插入图片描述
  在子目录项目下,添加“新子项目”,只有在子目录项目中,右击才会出现这个选择,其他情况此选项是置灰不可用的;
在这里插入图片描述
  新增三个子项目,一个是主窗口界面APP(MainWindow),一个是基础类库(静态库Utils),另外一个是ImageReconstructionLib;
  总目录下的pro文件内容如下:

TEMPLATE = subdirs
# 不再推荐使用ordered配置;
CONFIG+=ordered
# 我先创建的app,然后创建的Utils和ImageReconstructionLib;
SUBDIRS += \
    ImageReconstructionLib \
    Utils \
    app
TEMPLATE = subdirs

  subdirs表示本项目将扫描指定的子目录集合并执行相关操作,常配合SUBDIRS使用。

CONFIG+=ordered

  之前项目中多使用ordered,后来不再推荐使用;这里是有问题的,在之后的实践过程中,发现如果不设定ordered,会出现编译报错,库可能在app之后编译;
  结构如下:
在这里插入图片描述
  在子项目的根目录下有pro文件,每个独立的子文件夹内有各自的pri文件;
  在项目配置中设置环境变量TRAINDEVHOME指定项目的所在文件夹位置,供pro文件和pri文件使用;
在这里插入图片描述

基础类库Utils

  pro文件内容:

QT -= gui
include(./Math/Math.pri)
# TARGET变量指定生成的目标库文件的名字,生成应用程序时即指定生成应用程序名
# 可以确保windows下debug模式生成的动态库可以自动加个d
TARGET = $$qtLibraryTarget(Utils)
TEMPLATE = lib
#动态库,如果是静态库CONFIG += staticlib。
CONFIG += staticlib
CONFIG += c++11

SOURCES +=
HEADERS += \
    utils_include.h

#配置:项目使用debug和release两种模式构建;
CONFIG += debug_and_release
CONFIG(debug,debug|release) {
    message("Utils debug")
    # DESTDIR指定目标文件的输出文件路径
    DESTDIR = $$PWD/../thirdParty/lib/debug/
} else {
    message("Utils release")
    DESTDIR = $$PWD/../thirdParty/lib/release/
}

# Default rules for deployment.
unix {
    target.path = $$[QT_INSTALL_PLUGINS]/generic
}
!isEmpty(target.path): INSTALLS += target

# 在install拷贝头文件时,需要将每个文件夹下的头文件拷贝到目标文件对应文件夹下;
# 在不同pri文件内,设置files和path的对象不能重名;
Utils_File_Path.files = $$PWD/*.h
Utils_File_Path.path = $$(TRAINDEVHOME)/thirdParty/include/Utils
INSTALLS += Utils_File_Path

DISTFILES += \
    include_utils.pri

  INSTALLS可以将输出内容拷贝到指定目录,但需要从项目属性设置“Build的步骤”后,才能生效;
在这里插入图片描述
  编译输出:
在这里插入图片描述
  使用INSTALL把库内的头文件拷贝到指定文件夹下;
注意:编写路径时,需要使用“/”而不是“\”。有跨行内容时在行末使用“\”进行换行,并在“\”前加一个空格。
  库内增加文件夹Math,内部放置常用的算法和函数;

HEADERS += \
    $$PWD/base_function.h \
    $$PWD/data_define.h \
    $$PWD/line2d.h \
    $$PWD/point2d.h

SOURCES += \
    $$PWD/base_funtion.cpp
message("Math")
message($$PWD)
message($$(TRAINDEVHOME))
#在install拷贝头文件时,需要将每个文件夹下的头文件拷贝到目标文件对应文件夹下;
Math_File_Path.files = $$PWD/*.h
Math_File_Path.path = $$(TRAINDEVHOME)/thirdParty/include/Utils/Math/
INSTALLS += Math_File_Path

  在qmake后:
在这里插入图片描述
  Utils库对外提供一个include_utils.pri文件和一个utils_include .h文件,方便使用Utils库;
  include_utils.pri文件:

#加载外部头文件
INCLUDEPATH += $$(TRAINDEVHOME)/thirdParty/include/Utils
#配置加载不同的库文件
CONFIG+=debug_and_release
CONFIG(debug,debug|release) {
    message("debug")
    LIBS += $$(TRAINDEVHOME)/thirdParty/lib/debug/Utilsd.lib
} else {
    message("release")
    LIBS += $$(TRAINDEVHOME)/thirdParty/lib/release/Utils.lib
}

  utils_include .h文件:

#ifndef UTILS_INCLUDE_H
#define UTILS_INCLUDE_H
// 将对外提供的所有.h头文件都放在这个h文件内;
#include "Math/data_define.h"
#include "Math/base_function.h"
#include "Math/point2d.h"
#include "Math/line2d.h"
#endif // UTILS_INCLUDE_H

ImageReconstructionLib库

  同Utils库基本相同,这里把pro文件内容贴一下:

QT -= gui
TARGET = $$qtLibraryTarget(ImageReconstructionLib)
TEMPLATE = lib
# 配置:静态库
CONFIG += staticlib
CONFIG += c++11

SOURCES +=
HEADERS += \
    image_reconstruction_include.h

#配置:项目使用debug和release两种模式构建;
CONFIG+=debug_and_release
CONFIG(debug,debug|release) {
    message("ImageReconstructionLib debug")
    DESTDIR = $$PWD/../thirdParty/lib/debug/
} else {
    message("ImageReconstructionLib release")
    DESTDIR = $$PWD/../thirdParty/lib/release/
}

# Default rules for deployment.
unix {
    target.path = $$[QT_INSTALL_PLUGINS]/generic
}
!isEmpty(target.path): INSTALLS += target

ImageReconstructionLib_Root.files = $$PWD/*.h
ImageReconstructionLib_Root.path = $$PWD/../thirdParty/include/ImageReconstructionLib/

message($$PWD)
INSTALLS += ImageReconstructionLib_Root
message($$INSTALLS)

DISTFILES += \
    include_image_reconstruction.pri

app工程

  app是对外显示的界面app,用于界面交互和数据显示,调用工具库Utils和图像处理库
  app的pro文件内容,默认生成如下内容:

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

CONFIG += c++11
# 引入Utils工具库
include(../Utils/include_utils.pri)
# 引入ImageReconstructionLib图像处理库
include(../ImageReconstructionLib/include_image_reconstruction.pri)

SOURCES += \
    main.cpp \
    mainwindow.cpp

HEADERS += \
    mainwindow.h

FORMS += \
    mainwindow.ui

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

  注意:在复制操作时,除了使用INSTALL外,还可以使用QMAKE_POST_LINK或者QMAKE_PRE_LINK;在pro配置文件中添加各种编译前后的操作及配置,就是通过 QMAKE_POST_LINK和QMAKE_PRE_LINK;
  QMAKE_POST_LINK表示编译后执行内容
  QMAKE_PRE_LINK表示编译前执行内容

target.path = $$[QT_INSTALL_PLUGINS]/designer
INSTALLS    += target
#拷贝dll和lib文件
CONFIG(debug, debug|release) {

    compiled = debug
    libName = scatterplugind.lib
    dllName = scatterplugind.dll
} else {
    compiled = release
    libName = scatterplugin.lib
    dllName = scatterplugin.dll
}

#设置目标输出路径
DESTDIR = $$PWD/bin/$$compiled
# lib的路径
libSourePath = $$DESTDIR/$$libName
libDesPath = $$PWD/../../app/thirdParty/libs/$$libName
message($$libDesPath)
#QT默认安装路径
libQTDesingerPath = $$[QT_INSTALL_PLUGINS]/designer/$$dllName
#dll的路径
dllSourePath = $$DESTDIR/$$dllName
dllDesPath = $$PWD/../../app/$$compiled/$$dllName

#复制操作,复制到指定目录上面,包括指定的QT默认路径下面
QMAKE_POST_LINK += copy $${replace(libSourePath, /, \\)} $${replace(libDesPath, /, \\)}
QMAKE_POST_LINK += && copy $${replace(dllSourePath, /, \\)} $${replace(dllDesPath, /, \\)}
QMAKE_POST_LINK += && copy $${replace(dllSourePath, /, \\)} $${replace(libQTDesingerPath, /, \\)}

  至此,算是建立了一个较为清晰的目录结构。我们忽略了指定中间文件等等的各种文件路径的设置,在之后使用的过程中,在逐步增加进来。

遇到的问题

静态库中使用第三方库

  当新增静态库DecodeDICOM子项目,使用DCMTK库解析DICOM文件;
  编译app,app使用DecodeDICOM库;
  提示链接库没有找到:
在这里插入图片描述
  在app使用的include_decode_dicom.pri文件中增加:

include(./import_dicom.pri)

  则可以编译通过;
  之前在VS中也遇到过类似情况,使用静态库时,就需要导入静态库使用的第三方库的lib;

参考资料

1.警惕 CONFIG+=ordered

  • 2
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

黑山老妖的笔记本

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值