在这里总结一下关于Qt工程文件管理的一些知识,希望这个分享能给新手们快速上手。
工程目录结构
Qt工程目录是以工程名为根目录的,Qmake首先从(例如a.pro).pro开始读取配置文件, 然后进行预编译,编译工作。
工程类型:
应用程序
库
我们在用Qt做开发的时候,一般就只会做这两类开发,一个是应用程序开发,一个是库(链接库,插件)开发。我们可以在QtCreator中新建工程的时候能看到这两个首选
是否是应用程序还是库,其实是可以在.pro文件中看到一个变量:TEMPLATE
当TEMPLATE = app 时,我们构建的程序最后是生成可执行文件;当TEMPLATE = lib 时,我们构建的程序最后是库文件。
-
windows 平台
app: .exe文件
lib: .lib(静态库)或者是.dll(动态库)文件
-
linux 平台
app: 二进制可执行文件
lib: .lib(静态库)或者是.so(动态库)文件
资源文件管理
qt的资源文件管理使用的是.qrc文件。为啥要使用资源文件?我们直接把资源文件放到一个目录,然后程序去读取不就行了嘛?一开始我也是很纳闷,后来做开发久了才发现里边是有它的原因的。首先我们先简单了解一下qrc文件的规则是怎么样的:
dialog.qrc
dialogs/images/check_focus.png dialogs/images/dark_check_checked_hover.png dialogs/images/dark_check_checked.png dialogs/images/dark_check.png dialogs/images/dark_close_small_hover.png dialogs/images/dark_close_small_normal.png dialogs/images/dark_close_small_press.png dialogs/images/dark_minimise_small_hover.png dialogs/images/dark_minimise_small_normal.png dialogs/images/dark_minimise_small_press.png dialogs/images/light/checkbox-checked-hover.png dialogs/images/light/checkbox-checked.png dialogs/images/light/checkbox-focus.png dialogs/images/light/checkbox-hover.png dialogs/images/light/checkbox-unchecked.png dialogs/images/light/window_close_hover.png dialogs/images/light/window_close_normal.png dialogs/images/light/window_close_press.png dialogs/images/light/window_min_hover.png dialogs/images/light/window_min_normal.png dialogs/images/light/window_min_press.png dialogs/images/user-trash-full-opened.png dialogs/images/dialog_warning_64.png dialogs/images/share_password.png dialogs/qss/dark.qss dialogs/qss/light.qss
上面的是一个qrc配置文件内容,其实里边就是一个xml配置文件,以<RCC></RCC>标签为根节点进行资源描述。我们程序里边要使用这些资源的时候很方便,不需要关心你要用的资源在哪个相对目录或者绝对目录,当然我们要了解按着怎么样格式去读取我们想要的资源文件的。
c++里边读取资源 ":/prefix/file"
qml里边读取资源 "qrc:/prefix/file"
对的,就两个格式,分别是在c++ 代码读取和qml代码读取的方式。prefix其实就是<qresource>标签里边的prefix属性值,而file就是<file>标签的内容。
了解了.qrc结构之后,我们简单了解一下qrc资源文件和自己读取相对路径或者绝对路径资源文件的区别:
.qrc 资源文件
.qrc资源文件在构建项目的时候会把资源编译到当前工程代码中,它是在qmake的时候,qmake会去扫描所有的qrc资源文件,然后把文件内容根据qrc配置定义成一大堆全局资源宏,宏的值其实就是资源文件的二进制内容了。这样程序在通过规则字符串找到资源文件的宏匹配,把资源内容读取出来。也就是说,我们的资源文件都被编译到了代码当中去了,成为了一个常量,不可修改替代的资源(重点)。
相对路径或者绝对路径读取资源
其实相对路径或者绝对路径读取资源我们非常熟悉,它就是我们经常通过IO操作读取本地或者网络上的资源。这里就不多解释了。
在这里我们应该很清晰使用qrc资源管理和本地(非本地)资源管理的区别了。简单来说就是qrc资源管理是把资源编译到程序当中去了,编译后不可修改,只能读取使用的资源。本地(非本地)资源就是把资源放到一个自己设定的目录,然后通过I/o操作读取资源,资源随时可修改。至于我们什么时候用qrc管理资源,什么时候有本地资源,就取决于需求问题了,比如qrc资源文件是有大小限制的,超过限定大小(具体多大忘了)了是无法通过编译的,但是我们又想一些又小而且不需要做任何修改的资源不被做修改,这时候可以考虑把资源文件放到qrc中一起编译到程序中去。然而有些配置文件需要经常修改的,动态读取的,这时候我们的文件就不应该放到qrc里边去了,因为放进去了,我们只能读取而不能做任何修改。
常用内置变量
在工程文件当中,我们对工程的控制基本都是对变量的控制,这些变量可以是自定义的,也可以是Qt内置的,内置的变量决定这工程实质性编译工作。这里介绍一些常用的变量和解释(好了这里就不按着官方文档的套路给大家介绍了)。
TEMPLATE
TEMPLATE 变量决定着我们的工程是什么来着,如果把这个变量设置成 app,那我们的工程将会构建成可执行文件,如果这个变量设置成 lib,那我们的工程将会构建成库文件,下面是它的值还有意义:
app: 工程将会被构建成可执行文件
lib: 工程将会被构建成库文件
subdirs: 工程是一个多工程系项目,里边可以嵌套着多个子工程,孙工程,孙孙工程, 呵呵
例子
TEMPLATE = app
QT
QT这个变量是专门引入Qt各个代码模块的,我们知道Qt库相很庞大,如果不把他瓜分一个个模块,那么我们程序将会变得很庞大很笨重(模块其实就是一个个库文件。库文件如果都集成一个模块里边,然而我们使用的库函数其实都很少,那么我们岂不就调了qt几个函数却依赖着它这个体积庞大的库?)。为了选择性依赖qt部分的代码库,我们手动加入需要使用的模块,这样编译程序所依赖Qt模块就是有用的而且体积会没那么庞大,模块就是为了降低我们程序的体积而设计的。QT 的模块有很多,比如widgets(图形库),networks,等等。我们需要哪个库的时候,就是在这个变量中追加的了。例子:
QT += widgets concurrent
TARGET
TARGET是我们工程的目标输出名字,比如应用程序中的 aaa,库文件中的bbb。TARGET会根据不同的平台生产对应的后缀名,比如windows下会生产 target.exe/target.dll/target.lib ,linux下 target/target.lib/target.so等等。
DEFINES
DEFINES是一个全局宏控制。这个是一个很有用的变量。我们在写代码的时候,可以找到DEFINES里边的全局宏定义。 其实 qmake 会去检索DEFINES这个变量值,然后在最后生成makefile的时候将这些宏作为make编译的宏参数,这样程序就可以使用这些宏定义了。简单说一下这些宏定义的使用场景:如果在做一个跨平台的应用开发,我们又想一个项目代码走遍全平台,那这时候就可以通过对编译环境来选择添加DEFINES的内容。比如:
windows平台编译代码: DEFINES += USE_WINDOWS_LIBS
linux平台编译代码:DEFINES += USE_LINUX_LIBS
然后我们就可以在程序里边判断在哪个宏定义做哪些事情了。例子:
isEqual(ARCH, sw_64) | isEqual(ARCH, mips64) | isEqual(ARCH, mips32) { DEFINES += ARCH_MIPSEL #use classical file section mode DEFINES += CLASSICAL_SECTION DEFINES += AUTO_RESTART_DEAMON DEFINES += LOAD_FILE_INTERVAL=150 DEFINES += DDE_COMPUTER_TRASH }
HEADERS
HEADERS是我们的头文件包含变量,这个比较简单,看着配置就懂它是干嘛得了,不多解释:
HEADERS += \ controllers/appcontroller.h \ views/dmovablemainwindow.h \ views/dleftsidebar.h \ views/dtoolbar.h \ views/dfileview.h \ views/ddetailview.h \ views/dicontextbutton.h \
SOURCES
HEADERS是我们的源文件包含变量,这个比较简单,看着配置就懂它是干嘛得了,不多解释:
SOURCES += \ controllers/appcontroller.cpp \ views/dmovablemainwindow.cpp \ views/dleftsidebar.cpp \ views/dtoolbar.cpp \ views/dfileview.cpp \
RESOURCES
RESOURCES是资源文件包含变量,上面我们解释过资源文件的概念和使用。
RESOURCES += \ skin/skin.qrc \ skin/dialogs.qrc \ skin/filemanager.qrc \ themes/themes.qrc
LIBS
LIBS 是用来描述依赖的第三方库文件,我们在使用第三方库的时候可以通过这个来关联依赖。
LIBS += -lmagic -lffmpegthumbnailer
PWD
PWD是一个目录变量,它是一个只读变量,用来记录当前工程所在的路径。
$$PWD/translations/$${TARGET}_zh_CN.ts
INSTALLS
INSTALLS是一个安装配置变量,qmake会找INSTALLS变量的值,然后根据这些值找到对应的资源,和目标安装路径,然后生成makefile配置(其实在makefile配置里边会有一个install:cmd字段,cmd就是一个shell命令,把选定的资源拷贝到特定目录中去),然后我们在make install的时候我们的资源文件就会被拷贝到我们想放的目录中去。
icon.path = $$INSTALLDIR //INSTALLDIR这个是自定义的变量icon.files = skin/images/$${TARGET}.svgINSTALLS += icon
SUBDIRS
SUBDIRS 是在TEMPLATE值为subdirs的时候有效。这个是一个多工程管理变量。我们可以通过SUBDIRS来增加多个子项目。
SUBDIRS += \ dde-file-manager \ dde-file-manager-daemon \ dde-file-manager-lib \ dde-file-manager-plugins \ usb-device-formatter
TRANSLATIONS
TRANSLATIONS是在做国际化的时候用到的变量,我们通过这个变量指定国际化文件。
TRANSLATIONS += $$PWD/translations/$${TARGET}.ts \ $$PWD/translations/$${TARGET}_zh_CN.ts当我们指定好国际化翻译文件后,结合lupdate,linguist,lrelease这三个工具分别进行更新国际化文本(.ts),翻译文本(.ts),发布国际化二进制文本(.qm文件)
PKGCONFIG
PKGCONFIG这个变量是Linux系统下独有的变量,也就是说它值适合用在linux下,它的作用个LIBS差不多一样。只是使用这个变量之前我们得确保好我们系统是否已经安装了pkg-config这个工具。因为这个变量其实就是qmake通过这个变量的值,调用pkg-config来匹配到对应的链接库路径,然后才能正常通过编译依赖。最后要在CONFIG变量中追加ling_pkgconfig这个值。
CONFIG
CONFIG变量个人理解为全局配置变量,它就好比跟cmake的配置设置项一样,我们可以配置当前程序的编译环境,比如开启c++11,编译debug版本,release版本,等等 ,都是在这个变量中进行控制的。
编译配置
引入链接库
使用pkgconfig
工程变量调试调试
模块化代码管理
多工程管理技巧
安装配置
后面内容留着精细推敲,先开坑。