Qt配置文件详解
Qt配置文件总是不知其然,每次工程建立,需要改配置文件,不论是qmake的.pro,还是cmake的CMakeLists.txt,都是靠一手浏览器解决,从未真正掌握过。因此这篇文章开始学习和掌握Qt配置文件的语法和书写,进行知识总结。
以参考官方手册为佳
一、Qt工具moc,uic,rcc详解
Qt可看作一个C++界面库,对C++语法进行了扩展,可以跨平台编译。
MOC
Qt将源码交给标准C++编译器前,需要事先将这些扩展的语法解析,完成这一操作的就是moc。
moc全称Meta-Object Compiler,元对象编译器。MOC分析Qt的C++源文件时,如果发现在一个头文件中包含了宏Q_OBJECT,则会生成另一个C++源文件,该文件中包含了Q_OBJECT宏的实现代码,该文件的名称将会是原文件名前加上“moc_”构成。moc的执行在预处理器之前,因为预处理器执行后,Q_OBJECT宏就不存在了。新生成的源文件参与到标准编译器的编译中,编译过程中如果找不到对应的moc文件将出现链接错误。
1 | moc myclass.h -o moc_myclass.cpp |
UIC
用designer设计的x.ui文件可通过uic工具转换为头文件,名称为ui_x.ui。ui文件的使用就是利用默认工具uic自动产生一个类,然后用该类的setui函数加载界面到相应的对象上。
.ui文件使用有三种形式:1.直接使用,2.定义一个新类,声明一个ui子对象,利用该对象来加载界面,3.将ui作为基类派生新的类。
1 | uic app.ui -o ui_app.h |
RCC
rcc用于将.qrc里面描述的图片、文档等编译成对应的源代码文件qrc_*.cpp或者独立的二进制资源文件*.rcc。
生成独立的二进制资源文件.rcc
对于太大的图片、音频、视频等文件,不适合集成到目标程序内部,可以放到操作系统文件目录,或单独编译成外挂资源.rcc。
1 | rcc -binary myresource.qrc -o myresource.rcc |
代码中使用myresource.rcc,需要在main函数开始的位置注册这个独立的二进制资源文件:
1 | QResource::registerResource("/path/to/myresource.rcc"); |
使用文件时用虚拟文件路径,在qml中使用rcc的内容,前缀是qrc:/
;在Qt C++中前缀是:
。
应用程序内嵌资源
如果希望一个资源描述文件application.qrc在程序编译时内嵌到目标程序里,需要在*.pro文件里添加:
1 | RESOURCES += application.qrc |
qmake会自动为application.qrc添加编译脚本。
rcc工具会解析 application.qrc内的 XML文本,找到需要添加的各种文件,默认情况下,rcc 工具会对这些文件做ZIP压缩,然后将压缩后的ZIP数据的每个字节转换成比如 0x6f数值形式,所有文件压缩后的数据对应一个C++静态数组 qt_resource_data[],并添加注册、取消注册、初始化、清除等函数和资源描述结构体,最终形成一个 qrc_application.cpp文件。然后用编译器编译qrc_application.cpp文件,得到 qrc_applicaotion.o ,链接到目标程序内部,就可以用 “:/images/copy.png” 等形式访问程序内嵌资源了。
注意到刚才向 .pro 文件里添加 qrc 资源描述文件使用的运算符是+=,也就是说可以为应用程序添加多个.qrc 文件,如果涉及的图片比较多,可以用多个*.qrc 对图片分类存放:
1 | RESOURCES += buttons.qrc |
使用多个*.qrc
与使用一个*.qrc
的方式是一样的,虚拟文件路径都类似 “:/buttons/ok.png” 、”:/backgrounds/bgmain.png” 等,这里的 ok.png 放在项目文件夹的 buttons 子文件夹里,而 bgmain.png 是放在项目文件夹的 backgrounds 子文件夹里,因此两个文件的路径是不同的。
qmake 为内嵌资源添加的 rcc 编译命令,类似下面这样:
1 | rcc -name application application.qrc -o qrc_application.cpp |
得到 qrc_application.cpp 源文件之后,剩下的编译、链接就与普通 .cpp 文件一模一样了。
qrc_application.cpp 文件中不仅有各种图片、文档对应的静态数组,还有些结构体和函数,比如初始化和清除函数。
对于rcc命令,如果不加-name application选项参数,那么在 qrc_application.cpp 里面生成的初始化和清除函数名为:
1 | int QT_RCC_MANGLE_NAMESPACE(qInitResources)(); |
如果加了-name application选项参数,那么资源的初始化和清除函数名变为:
1 | int QT_RCC_MANGLE_NAMESPACE(qInitResources_application)(); |
QT_RCC_MANGLE_NAMESPACE() 这个宏其实没什么用,仅用于提示作用。资源的初始化函数和清除函数会在资源加载和卸载时自动被调用。
应用程序的内嵌资源通常不需要手动初始化,但也有例外情况,比如在使用某些链接库中的资源文件时,如果出现使用了正确的文件路径 “:/images/copy.png” 却找不到资源里图片文件的情况,那么需要在使用该资源的类声明里或者在 main 函数里打头的位置加入一句手动初始化:
1 | Q_INIT_RESOURCE(resources); |
resources 是指 resources.qrc 的简短名字形式,不需要扩展名。
二、qmake的.pro配置
应当仔细阅读Qt qmake手册
qmake工具是与Qt一起提供的,为不同平台和编译器生成Makefile。
对于某些简单的项目,可以在其项目顶层目录下直接执行qmake -project
命令来自动生成.pro文件,对复杂程序,需要手动改写.pro文件。
常用Pro文件变量
HEADERS
指定项目的头文件。qmake会自动检测头文件的类中是否需要moc,并增加适当的依赖关系和文件到项目中,来生成和链接moc文件
SOURCES
指定项目的C++文件
TEMPLATE
模板变量告诉qmake为这个应用程序生成哪种makefile。
选项 | 说明 |
---|---|
qpp | 创建一个用于构建应用程序的Makefile(默认)。 |
lib | 创建一个用于构建库的Makefile。 |
subdirs | 创建一个用于构建目标子目录的Makefile,子目录使用SUBDIRS变量指定。 |
aux | 创建一个不建任何东西的Makefile。如果没有编译器需要被调用来创建目标,比如你的项目使用解释型语言写的,使用此功能。注:此模板类型只能用于Makefile-based生成器。特别是,它不会工作在vcxproj和Xcode生成器。 |
vcapp | 仅适用于Windows。创建一个Visual Studio应用程序项目。 |
vclib | 仅适用于Windows。创建一个Visual Studio库项目。 |
vcsubdirs | Visual Studio解决方案,构建子目录项目 |
FORMS
指定需要uic处理的由Qt designer 生成的.ui文件。所有的构建这些UI文件所需的依赖、头文件和源文件都会被自动添加到项目中
RESOURCES
指定需要rcc处理的.qrc文件
DEFINES
指定预定义的C++预处理器符号
INCLUDEPATH
指定C++编译器搜索全局头文件的路径。如果包含空格,需引号。
LIBS
指定工程要链接的库。-l library -L library_path
CONFIG
指定各种用于工程配置和编译的参数。
QT
指定工程所要使用的Qt模板(默认是core,gui对应于QtCore和QtGui,以确保标准的GUI应用程序无需进一步的配置就可以构建)。如果想建立一个不包含Qt GUI模块的项目,可以使用-=
操作符。
TARGET
指定可执行文件的基本文件名
DESTDIR
指定可执行文件放置的目录
DEPENDPATH
指定查看解决依赖关系的目录列表,当包含文件时使用
MOC_DIR
指定来自moc的所有中间文件(含Q_OBJECT宏的头文件转换成标准.h文件的存放目录)放置的目录
OBJECTS_DIR
指定所有中间文件.o放置的目录
RCC_DIR
指定Qt资源编译器输出文件的目录
TRANSLATIONS
指定包含用户界面翻译文本的翻译(.ts)文件列表
1 | TRANSLATIONS += Resource/myapp_zh.ts \ |
UI_DIR
指定来自uic的所有中间文件放置的目录
CONFIG变量用于指定编译器选项和项目配置,参数如下:
选项 | 说明 |
---|---|
qt | 指应用程序使用Qt。此选项是默认包括的。CONFIG如果包含qt,可以使用QT变量(QT变量默认包含gui和core模块)控制应用程序需要的任何附加Qt模块 |
debug | 编译出具有调试信息的可执行程序 |
release | 使用release模式构建,如果debug也被指定会被忽略 |
dll | 动态编译库文件 |
staticlib | 静态编译库文件 |
console | 指应用程序需要写控制台(使用cout、cerro、qWarning()等) |
debug_and_release | 项目准备以debug和release两种模式构建。 |
debug_and_release_target | 此选项默认设置。如果也指定了debug_and_release,最终的debug和release构建在不同的目录。 |
build_all | 如果指定了debug_and_release,默认情况下,该项目会构建为debug和release模式。 |
autogen_precompile_source | 自动生成一个.cpp文件,包含在.pro中指定的预编译头文件。 |
ordered | 使用subdirs模板时,此选项指定应该按照目录列表的顺序处理它们。 |
precompile_header | 可以在项目中使用预编译头文件的支持。 |
warn_on | 编译器应该输出尽可能多的警告。如果也指定了warn_off,最后一个生效。 |
warn_off | 编译器应该输出尽可能少的警告。 |
exceptions | 启用异常支持。默认设置。 |
exceptions_off | 禁用异常支持。 |
rtti | 启用RTTI支持。默认情况下,使用编译器默认。 |
rtti_off | 禁用RTTI支持。默认情况下,使用编译器默认。 |
stl | 启用STL支持。默认情况下,使用编译器默认。 |
stl_off | 禁用STL支持。默认情况下,使用编译器默认。 |
thread | 启用线程支持。当CONFIG包括qt时启用,这是缺省设置。 |
c++11 | 启用c++11支持。如果编译器不支持c++11这个选项,没有影响。默认情况下,支持是禁用的。 |
c++14 | 启用c++14支持。如果编译器不支持c++14这个选项,没有影响。默认情况下,支持是禁用的。 |
内置函数和控制流
include()可引用外部项目
1 | include(other.pro) |
通过作用域实现条件语句,类似编程语言中的if语句
1 | win32 { |
其它包括find(),unique(),count()等
同时CONFIG()可以用来测试配置选项是否被包含
1 | CONFIG(opengl){ |
变量扩展
$$
操作符用来提取变量的值,可被用来将值在变量与函数间传递
访问qmake特性
特殊$$[...]
操作符可用来访问qmake特性:
1 | message(Qt version: $$[QT_VERSION]) |
三、cmake的CMakeLists.txt
应参考
前言
CMake可以找到并使用Qt 4 和Qt 5。Qt 4库是由CMake附带的 FindQt4 查找模块找到的,而Qt 5库是使用Qt 5附带的“配置文件包”找到的。
Qt 4和Qt 5可以在同一 CMake buildsystem 一起使用:
1 | cmake_minimum_required(VERSION 3.8.0 FATAL_ERROR) |
一个 CMake 目标不能同时链接到 Qt 4 和 Qt 5。如果试图这样做或者是目标依赖性评估的结果,就会发出一个诊断。
Qt构建工具
Qt依赖于一些捆绑的代码生成工具,例如moc用于元对象代码生成,uic用于小部件布局和填充,以及rcc用于虚拟文件系统内容生成。如果满足适当的条件,这些工具可以有cmake自动调用。自动工具调用可以与Qt 4和Qt 5一起使用。
AUTOMOC
AUTOMOC属性控制cmake是否检查目标中的C++文件,以确定它们是否需要运行moc,并在适当的时间创建规则执行moc。
如果在头文件中找到来自AUTOMOC_MACRO_NAMES的宏,则将在该文件上运行moc。结果将放入如moc_<basename>.cpp命名的文件中。如果在C++实现文件中找到该宏,则将按照Qt约定将moc输出到如<basename>.moc命名的文件中。用户必须使用预处理器#include将<basename>.moc包含在C++实现文件中。
包含的moc_*.cpp
和*.moc
文件将在<AUTOGEN_BUILD_DIR>/include
目录中生成,该目录会自动添加到目标的INCLUDE_DIRECTORIES中。
- 这与CMake 3.7及以下版本不同,详情请看他们的文档
- 对于multi configuration generators,include目录为
<AUTOGEN_BUILD_DIR>/include_<CONFIG>
- 参见AUTOGEN_BUILD_DIR
不包括在内的moc_<basename>.cpp
文件将在自定义文件夹中生成,以避免名称冲突,并包含在一个单独的文件中,该文件已编译到目标中,名为<AUTOGEN_BUILD_DIR>/mocs_compilation.cpp
或<AUTOGEN_BUILD_DIR>/mocs_compilation_$<CONFIG>.cpp
moc命令行将消耗从被调用的目标中处理COMPILE_DEFINITIONS和INCLUDE_DIRECTORIES目标属性为适当的构建配置。
通过设置CMAKE_AUTOMOC变量,AUTOMOC目标属性可为之后所有目标预置。AUTOMOC_MOC_OPTIONS可以填充设置选项传递给moc。可以填充CMAKE_AUTOMOC_MOC_OPTIONS变量,以为之后所有目标预置选项。
可将其它要搜索的宏名称添加到AUTOMOC_MACRO_NAMES中。
可使用AUTOMOC_DEPEND_FILTERS从源代码中提取其它moc依赖项文件名。
通过启用SKIP_AUTOMOC或更广泛的SKIP_AUTOGEN,可将C++源文件从AUTOMOC处理中排除。
AUTOUIC
AUTOUIC目标属性控制cmake是否检查目标中的C++文件,以确定它们是否需要运行uic,并在合适时机创建规则运行uic。
如果找到与 <path>ui_<basename>.h
匹配的预处理器 #include
指令,并且存在 <basename>.ui
文件,则将执行 uic
生成适当的文件。该 <basename>.ui
文件中搜索在以下地方
<source_dir>/<basename>.ui
<source_dir>/<path><basename>.ui
<AUTOUIC_SEARCH_PATHS>/<basename>.ui
<AUTOUIC_SEARCH_PATHS>/<path><basename>.ui
其中,
生成的 ui_*.h
文件放置在
该 AUTOUIC 目标属性可以通过设置对所有以下目标预先设定 CMAKE_AUTOUIC 变量。该 AUTOUIC_OPTIONS 目标属性可被填充设置选项传递给 uic 。该 CMAKE_AUTOUIC_OPTIONS 变量可被填充到预先设定的所有以下目标的选项。所述 AUTOUIC_OPTIONS 源文件属性可以在被设置 <basename>.ui
文件为文件组特定选项。这将覆盖来自 AUTOUIC_OPTIONS 目标属性的选项。
目标可以使用调用 uic 时应使用的选项来填充 INTERFACE_AUTOUIC_OPTIONS 目标属性。这必须与 AUTOUIC_OPTIONS 目标的AUTOUIC_OPTIONS目标属性内容一致。所述 CMAKE_DEBUG_TARGET_PROPERTIES 变量可被用于跟踪这样的原点目标 INTERFACE_AUTOUIC_OPTIONS 。这意味着为Qt提供替代翻译系统的库可以指定在运行 uic 时应使用的选项:
1 | add_library(KI18n klocalizedstring.cpp) |
链接到从上游导出的目标的消耗项目当uic由于AUTOUIC而运行时自动使用适当的选项,作为与导入目标链接的结果:
1 | set(CMAKE_AUTOUIC ON) |
通过启用 SKIP_AUTOUIC 或更广泛的 SKIP_AUTOGEN ,可以将源文件从 AUTOUIC 处理中排除。
AUTORCC
AUTORCC目标属性控制cmake是否创建规则来执行 rcc
在适当的时间在其上具有后缀源文件 .qrc
。
1 | add_executable(myexe main.cpp resource_file.qrc) |
该 AUTORCC 目标属性可以通过设置对所有以下目标预先设定 CMAKE_AUTORCC 变量。该 AUTORCC_OPTIONS 目标属性可被填充设置选项传递给 rcc 。该 CMAKE_AUTORCC_OPTIONS 变量可被填充到预先设定的所有以下目标的选项。所述 AUTORCC_OPTIONS 源文件属性可以在被设置 <name>.qrc
文件设置为文件特定的选项。这将覆盖来自 AUTORCC_OPTIONS 目标属性的选项。
通过启用 SKIP_AUTORCC 或更广泛的 SKIP_AUTOGEN ,可以将源文件从 AUTORCC 处理中排除。
<ORIGIN>_autogen
目标
moc 和 uic 工具作为由CMake生成的综合的<ORIGIN>_autogen
custom target 一部分被执行。默认情况下该 <ORIGIN>_autogen
目标继承 <ORIGIN>
目标的依赖(见 AUTOGEN_ORIGIN_DEPENDS )。可以通过将目标依赖项添加到 AUTOGEN_TARGET_DEPENDS 目标属性中的方式将它们添加到<ORIGIN>_autogen
目标中。