目录
  • qtcreator.pro

    • 包含qtcreator.pri

      • include(filename)
    • Qt版本判断
      • message(string)
      • $$运算符
      • error(string)
    • 包含doc.pri
    • 源码组织架构
      • TEMPLATE
      • SUBDIRS
    • 指定dist文件列表
      • DISTFILES
      • files(pattern[, recursive=false])
      • Replace Functions概述
    • qbs配置
      • exists(filename)
      • Test Functions概述
    • 指定架构和平台
      • contains(variablename, value)
      • Scopes
    • 指定基础名
    • 指定linux平台安装内容
      • INSTALLS
      • Installing Files
    • 指定其他平台安装内容
      • INSTALL_ROOT
      • QTC_PREFIX
      • PWD
      • OUT_PWD
      • TARGET
      • QMAKE_EXTRA_TARGETS
      • Adding Custom Targets
    • 指定安装存档
      • Operators
    • 指定额外构建目标

qtcreator.pro

首先我们来学习根项目文件qtcreator.pro

包含qtcreator.pri

qtcreator.pro第一行为

include(qtcreator.pri)

include(filename)

包含filename指定的文件内容到当前项目中。 如果filename被包含,则此函数运行成功; 否则失败。 被包含的文件将立即被解析。

将此函数作为某个作用域的判断条件,可以检查是否成功包含文件。 例如:

include( shared.pri )
OPTIONS = standard custom
!include( options.pri ) {message( "No custom build options specified" )
OPTIONS -= custom}

我们学习过C/C++,这和#include非常相似。

qtcreator.pri中定义了很多宏和通用操作。定义在pri中的函数,必须先include后pro才能使用。qmake处理pro和pri文件是线性从上往下解析的。对比C/C++,我们可以认为pri文件是头文件,pro文件是源文件

如果你使用 Qt Creator 打开项目,你会发现include语句会在项目树的左侧显示一个节点。这种节点只需要include不同的 pri 文件即可,是虚拟目录节点,使项目结构层次看起来清晰很多。

有关qtcreator.pri的内容,请见下节。

Qt版本判断

接下来是

\#version check qt
!minQtVersion(5, 6, 2) {message("Cannot build $$IDE_DISPLAY_NAME with Qt version $${QT_VERSION}.")error("Use at least Qt 5.6.2.")
}

minQtVersion()顾名思义是最小Qt版本的意思,函数定义在qtcreator.pri中。当 Qt 的版本低于5.6.2时,minQtVersion()返回false,!取反则为true,因此会执行块中的操作。

message(string)

函数运行不会失败,并将string作为常规消息显示给用户。 与error()函数不同,此函数允许qmake继续往下处理。

message( "This is a message" )

上一行导致"This is a message"被写入控制台。引号的使用是可选的,但建议使用。

注意:默认情况下,消息被写入qmake为给定项目生成的每个Makefile中。 如果要确保消息在每个项目中仅出现一次,在作用域中联合使用build_pass变量测试,用于构建时过滤掉消息。例如:

!build_pass:message( "This is a message" )

这里输出的是"Cannot build $$IDE_DISPLAY_NAME with Qt version $${QT_VERSION}.",其中$${QT_VERSION}是占位符,会使用QT_VERSION变量的内容进行替换。

$$运算符

Variable

项目文件中使用的许多变量是特殊变量,用于qmake生成Makefile时使用,例如DEFINES,SOURCES和HEADERS。另外,您可以创建自己的变量。在给某个名称赋值时,qmake使用该名称创建新变量。例如:

MY_VARIABLE = value

您可以对自己的变量执行任何操作,因为qmake会忽略它们,除非在处理作用域时需要评估它们。

您还可以通过在变量名称前添加$$来将当前变量的值分配给另一个变量。例如:

MY_DEFINES = $$DEFINES

现在,MY_DEFINES变量包含了此时DEFINES变量的内容。这也等效于:

MY_DEFINES = $${DEFINES}

第二种表示法允许您将变量的内容附加到另一个值,而不用空格将两者分开。例如,以下内容将确保为最终的可执行文件指定一个名称,其中包括正在使用的项目模板:

TARGET = myproject_$${TEMPLATE}

Variable Expansion

$$运算符用于提取变量的内容,并可用于在变量之间传递值或将其提供给函数:

EVERYTHING = $$SOURCES $$HEADERS
message("The project contains the following files:")
message($$EVERYTHING)

变量可用于存储环境变量的内容。可以在运行qmake时对其进行评估,或者包含到项目构建时生成的Makefile中进行评估。

要在运行qmake时,获取环境变量值的内容,请使用$$(...)运算符:

DESTDIR = $$(PWD)
message(The project will be installed in $$DESTDIR)

在上述赋值中,当处理项目文件时,PWD环境变量的值被读取。

要在生成的Makefile被处理时,获取环境变量值的内容,请使用$(...)运算符:

DESTDIR = $$(PWD)
message(The project will be installed in $$DESTDIR)DESTDIR = $(PWD)
message(The project will be installed in the value of PWD)
message(when the Makefile is processed.)

在上述赋值中,当处理项目文件时,PWD的值被立即读取,但是$(PWD)被赋值给生成的Makefile中的DESTDIR。这使得构建过程更加灵活,只要在处理Makefile时正确设置了环境变量。

Accessing qmake Properties

特殊的$$[...]运算符可用于访问qmake属性:

message(Qt version: $$[QT_VERSION])
message(Qt is installed in $$[QT_INSTALL_PREFIX])
message(Qt resources can be found in the following locations:)
message(Documentation: $$[QT_INSTALL_DOCS])
message(Header files: $$[QT_INSTALL_HEADERS])
message(Libraries: $$[QT_INSTALL_LIBS])
message(Binary files (executables): $$[QT_INSTALL_BINS])
message(Plugins: $$[QT_INSTALL_PLUGINS])
message(Data files: $$[QT_INSTALL_DATA])
message(Translation files: $$[QT_INSTALL_TRANSLATIONS])
message(Settings: $$[QT_INSTALL_CONFIGURATION])
message(Examples: $$[QT_INSTALL_EXAMPLES])

有关更多信息,请参见Configuring qmake。

该操作符可访问的属性,通常用于集成第三方插件和组件到Qt中。 例如,如果在其项目文件中进行了以下声明,则可以将Qt Designer自定义插件安装到Qt Designer内置插件路径中:

target.path = $$[QT_INSTALL_PLUGINS]/designer
INSTALLS += target

最后是error()函数,显示错误信息,并退出。

error(string)

此函数从不返回值。 qmake将字符串作为错误消息显示给用户并退出。 此功能仅应用于不可恢复的错误。

包含doc.pri

接下来是

include(doc/doc.pri)

doc.pri中对qdocconf进行了配置,关于qdocconf干什么用的,请看我发布的文章。

源码组织架构

下面是重点,涉及源码的整体架构和组织模式。

TEMPLATE  = subdirs
CONFIG   += orderedSUBDIRS = src share
unix:!macx:!isEmpty(copydata):SUBDIRS += bin
!isEmpty(BUILD_TESTS):SUBDIRS += tests

TEMPLATE

指定生成项目时要使用的模板的名称。 允许的值为:

选项 描述
app 创建用于构建应用程序的Makefile(默认)。 有关更多信息,请参见Building an Application。
lib 创建用于构建库的Makefile。 有关更多信息,请参见Building a Library。
subdirs 创建用于在子文件夹中构建目标的Makefile。 子文件夹是使用SUBDIRS变量指定的。
aux 创建一个不生成任何内容的Makefile。 如果不需要调用任何编译器来创建目标,请使用此选项; 例如,因为您的项目是以解释性语言编写的。
注意:此模板类型仅适用于基于Makefile的生成器。 特别是,它不适用于vcxproj和Xcode生成器。
vcapp 仅Windows系统。 为Visual Studio创建一个应用程序项目。 有关更多信息,请参见Creating Visual Studio Project Files。
vclib 仅Windows系统。 为Visual Studio创建一个库。

例如:

TEMPLATE = lib
SOURCES = main.cpp
TARGET = mylib

模板可以被覆盖,通过使用-t命令行选项指定新的模板类型。 覆盖模板类型在处理.pro文件之后。 对于使用.pro文件的模板类型来确定项目生成方式的,必须在命令行上声明TEMPLATE,而不要使用-t选项。

SUBDIRS

此变量与subdirs模板一起使用,指定所有子文件夹的名称,或者包含需要构建的项目部分的项目文件。使用此变量指定的每个子文件夹,都必须包含其自己的项目文件。

建议每个子目录中的项目文件都具有与子目录本身相同的基本名称,因为这样可以省略文件名。 例如,如果子目录名为myapp,则该目录中的项目文件应名为myapp.pro。

或者,您可以在任何目录中指定.pro文件的相对路径。 强烈建议您仅在当前项目的父目录或其子目录中指定路径。

例如:

SUBDIRS = kernel \tools \myapp

如果需要确保以特定顺序构建子目录,请在相关的SUBDIRS元素上使用.depends修饰符。

例如:

SUBDIRS += my_executable my_library tests doc
my_executable.depends = my_library
tests.depends = my_executable

上面的配置确保my_library是在my_executable之前构建的,并且my_executable是在tests之前构建的。 但是,doc可以与其他子目录并行构建,从而加快了构建过程。

注意:可以列出多个依赖项,并且它们都将在依赖它们的目标之前构建。

注意:不建议使用CONFIG += ordered,因为它会减慢多核并行构建。与上面的示例不同,所有构建不会并行而是依次发生,即使它们没有依赖性。

除了定义构建顺序之外,还可以通过为SUBDIRS元素提供其他修饰符来修改SUBDIRS的默认行为。 支持的修饰符是:

修饰符 效果
.subdir 使用指定的子目录而不是SUBDIRS值。
.file 显式指定子项目pro文件。 不能与.subdir修饰符一起使用。
.depends 本子项目依赖指定的子项目。
.makefile 子项目的makefile。 仅在使用makefile的平台上可用。
.target 用于与此子项目相关的makefile目标的基本字符串。 仅在使用makefile的平台上可用。

例如,定义两个子目录,这两个子目录都位于与SUBDIRS值不同的目录中,并且其中一个子目录必须在另一个子目录之前构建:

SUBDIRS += my_executable my_library
my_executable.subdir = app
my_executable.depends = my_library
my_library.subdir = lib

看了上面的解释,我们可以理解得到,使用subdirs模式依次顺序构建项目,首先构建src文件夹,然后是share文件夹。在src文件夹中,还可以划分为多个子目录,再次使用subdirs模式。

下面解释一下最后两行。

  1. 对于 Unix 平台(unix),如果不是 Mac OS(!macx),并且copydata不为空(!isEmpty(copydata)),则需要再增加一个 bin 目录。

  2. 如果BUILD_TESTS不为空(!isEmpty(BUILD_TESTS)),则再增加一个 tests 目录。

copydataBUILD_TESTS都是在 qtcreator.pri 中定义的宏。

指定dist文件列表

接下来是

DISTFILES += dist/copyright_template.txt \README.md \$$files(dist/changes-*) \qtcreator.qbs \qbs/pluginjson/pluginjson.qbs \$$files(scripts/*.py) \$$files(scripts/*.sh) \$$files(scripts/*.pl)

DISTFILES

指定要包含在dist目标中的文件列表。 仅UnixMake规范支持此功能。

例如:

DISTFILES += ../program.txt

files(pattern[, recursive=false])

扩展指定的通配符pattern并返回文件名列表。 如果recursive为true,则此函数会下降到子目录中进行递归。

Replace Functions概述

qmake提供了用于在配置过程中处理变量内容的函数。 这些函数称为替换函数。 通常,它们返回可以分配给其他变量的值。 您可以通过在函数前面加上$$运算符来获取这些值。 替换函数可以分为内置函数和函数库。

那么我们就可以理解$$files(dist/changes-*),就是返回当前目录下的 dist 文件夹中,所有以 changes- 开头的文件。

qbs配置

接下来是

exists(src/shared/qbs/qbs.pro) {# Make sure the qbs dll ends up alongside the Creator executable.QBS_DLLDESTDIR = $${IDE_BUILD_TREE}/bincache(QBS_DLLDESTDIR)...
}

exists(filename)

测试具有给定filename文件名的文件是否存在。 如果文件存在,则函数成功;否则失败。如果为文件名指定了正则表达式,则只要任何一个文件与指定的正则表达式匹配,则此函数成功。

例如:

exists( $(QTDIR)/lib/libqt-mt* ) {message( "Configuring for multi-threaded Qt..." )CONFIG += thread
}

注意:无论使用什么平台,都应将“ /”用作目录分隔符。

Test Functions概述

测试函数返回一个布尔值,您可以在作用域范围的条件部分中进行测试。 测试函数可以分为内置函数和函数库。

略。

指定架构和平台

接下来是

contains(QT_ARCH, i386): ARCHITECTURE = x86
else: ARCHITECTURE = $$QT_ARCHmacx: PLATFORM = "mac"
else:win32: PLATFORM = "windows"
else:linux-*: PLATFORM = "linux-$${ARCHITECTURE}"
else: PLATFORM = "unknown"

contains(variablename, value)

如果变量variablename包含值value,则成功; 否则失败。 可以为参数value指定正则表达式。

您可以使用作用域范围来检查此函数的返回值。

例如:

contains( drivers, network ) {# drivers contains 'network'message( "Configuring for network build..." )HEADERS += network.hSOURCES += network.cpp
}

仅当drivers变量包含值network时,才处理范围内的内容。 在这种情况下,会将适当的文件添加到SOURCES和HEADERS变量中。

Scopes

作用域范围类似于过程编程语言中的if语句。如果满足某个条件,则将处理域内的声明。

Scope Syntax

作用域三部分组成,第一行为条件语句和在同一行上的左大括号,一系列命令和定义,以及另起一行上的右大括号:

<condition> {<command or definition>...
}

左大括号必须与条件在同一行上。 作用域可以串联起来,以包含多个条件,如以下各节所述。

作用域和条件
作用域由一个条件后跟一对大括号中包含的一系列声明组成。 例如:

win32 {SOURCES += paintwidget_win.cpp
}

以上代码,在Windows平台构建时,会将paintwidget_win.cpp文件添加到生成的Makefile中的源文件列表中。 在其他平台构建时,定义将被忽略。

作用域中使用的条件也可以取反,以提供多种声明方式,可在原始条件为false时进行处理。例如,要在除Windows以外的所有平台构建时进行处理,请对作用域取反,如下所示:

!win32 {SOURCES -= paintwidget_win.cpp
}

作用域可以嵌套,以联合多个条件。 例如,要为特定平台包括特定文件,且仅在启用调试的情况下包含,请编写以下内容:

macx {CONFIG(debug, debug|release) {HEADERS += debugging.h}
}

要少写嵌套作用域,可以使用:运算符来进行嵌套。上例中的嵌套作用域可以通过以下方式重写:

macx:CONFIG(debug, debug|release) {HEADERS += debugging.h
}

您也可以使用:运算符来执行单行条件赋值。 例如:

win32:DEFINES += USE_MY_STUFF

上一行仅在Windows平台构建时,才将USE_MY_STUFF添加到DEFINES变量中。 通常,:运算符的行为类似于逻辑AND运算符,将多个条件结合在一起,并且要求所有条件都为真。

这里还有一个|运算符,其行为类似于逻辑OR运算符,将多个条件结合在一起,并且仅要求其中一个为真。

win32|macx {HEADERS += debugging.h
}

如果需要混合使用两个运算符,则可以使用if函数指定运算符优先级。

if(win32|macos):CONFIG(debug, debug|release) {# Do something on Windows and macOS,# but only for the debug configuration.
}
win32|if(macos:CONFIG(debug, debug|release)) {# Do something on Windows (regardless of debug or release)# and on macOS (only for debug).
}

该条件接受通配符,可匹配一系列CONFIG值或mkspec名称。

win32-* {# Matches every mkspec starting with "win32-"SOURCES += win32_specific.cpp
}

注意:以前,使用通配符检查mkspec名称是qmake检查平台的方法。 如今,我们建议使用mkspec定义的QMAKE_PLATFORM变量中的值。

您还可以使用else 作用域来提供多种声明方式。 如果前面作用域的条件为false,则处理下面的else作用域。此外,你还可以通过联合其他作用域,编写复杂的测试(如上所述,由:运算符分隔)。 例如:

win32:xml {message(Building for Windows)SOURCES += xmlhandler_win.cpp
} else:xml {SOURCES += xmlhandler.cpp
} else {message("Unknown configuration")
}

[Configuration and Scopes](Configuration and Scopes)

CONFIG变量中存储的值被qmake特殊处理。 每个可能的值都可以用作作用域的条件。 例如,可以使用opengl值扩展CONFIG的值的列表:

CONFIG += opengl

作为此操作的结果,所有测试opengl的作用域将被处理。我们可以使用此功能为最终可执行文件指定适当的名称:

opengl {TARGET = application-gl
} else {TARGET = application
}

通过此功能,可以轻松更改项目的配置,而不会丢失特定配置可能需要的所有自定义设置。 在上面的代码中,第一个作用域中的声明被处理,最终的可执行文件为application-gl。 但是,如果未指定opengl,则将处理第二个作用域中的声明,最终的可执行文件为application。

由于可以在CONFIG行上放置自己的值,因此这为您提供了一种方便的方法,来自定义项目文件并微调生成的Makefile。

Platform Scope Values

除了在许多作用域条件中使用的win32,macx和unix值之外,还可以使用各种其他内置平台和特定编译器的值。 这些都基于Qt的mkspecs文件夹中提供的平台规范。 例如,项目文件中的以下几行显示了当前使用的规范,并测试了linux-g++规范:

message($$QMAKESPEC)linux-g++ {message(Linux)
}

您可以测试任何其他平台-编译器组合,只要在mkspecs文件夹中存在针对它的规范即可。

很明显,这里进行了判断,并最终指定了ARCHITECTURE和PLATFORM的值。

指定基础名

接下来是

BASENAME = $$(INSTALL_BASENAME)
isEmpty(BASENAME): BASENAME = qt-creator-$${PLATFORM}$(INSTALL_EDITION)-$${QTCREATOR_VERSION}$(INSTALL_POSTFIX)

对于BASENAME,这是是一种常见的写法。首先,定义BASENAME宏为$$(INSTALL_BASENAME);之后,如果BASENAME为空的话(使用测试函数isEmpty()判断),则定义新的BASENAME的值。

这种写法允许我们在编译时通过命令行传入自定义值改变默认设置(也就是说,如果之前定义了INSTALL_BASENAME,那么就会使用我们定义的值),否则就会生成一个默认值。以后我们会发现,Qt Creator 的 pro 文件中,很多地方都使用了类似的写法。

指定linux平台安装内容

接下来是

linux {appstream.files = dist/org.qt-project.qtcreator.appdata.xmlappstream.path = $$QTC_PREFIX/share/metainfo/desktop.files = dist/org.qt-project.qtcreator.desktopdesktop.path = $$QTC_PREFIX/share/applications/INSTALLS += appstream desktop
}

INSTALLS

指定执行make install或类似安装命令时将安装的资源列表。 列表中的每个项目通常都定义有属性,这些属性提供有关安装位置的信息。

例如,以下target.path定义描述了构建目标的安装位置,并且INSTALLS赋值将构建目标添加到要安装的现有资源列表中:

target.path += $$[QT_INSTALL_PLUGINS]/imageformats
INSTALLS += target

Installing Files

在Unix上,通常也使用构建工具来安装应用程序和库。 例如,通过调用make install。 因此,qmake具有安装集(install set)的概念,该对象包含如何安装项目内容的指令集。例如,可以通过以下方式描述文档文件的集合:

documentation.path = /usr/local/program/doc
documentation.files = docs/*

path成员通知qmake应该将文件安装在/usr/local/program/doc中,并且files成员指定应复制到安装目录的文件。 在这种情况下,docs目录中的所有内容都将复制到/usr/local/program/doc中。

完整描述了安装集后,您可以使用如下行将其追加到安装列表中:

INSTALLS += documentation

qmake确保将指定的文件复制到安装目录。 如果需要对该过程进行更多控制,则还可以为对象的extra成员提供定义。 例如,下行告诉qmake为此安装集执行一系列命令:

unix:documentation.extra = create_docs; mv master.doc toc.doc

Unix作用域可确保仅在Unix平台上执行这些特定命令。 可以使用其他作用域规则来定义用于其他平台的适当命令。

对象首先执行extra成员中指定的命令,再执行对象的其他成员中的指令。

如果您将内置安装集附加到INSTALLS变量,并且不指定files或extra成员,则qmake将决定需要为您复制哪些内容。 当前,支持targetdlltarget安装集。 例如:

target.path = /usr/local/myprogram
INSTALLS += target

在以上几行中,qmake知道需要复制什么,并将自动处理安装过程。

想必大家也都明白了吧,如果是linux平台,则把.files指定的文件拷贝到.path指定的路径中。

指定其他平台安装内容

接下来是

macx {APPBUNDLE = "$$OUT_PWD/bin/$${IDE_APP_TARGET}.app"BINDIST_SOURCE = "$$OUT_PWD/bin/$${IDE_APP_TARGET}.app"deployqt.commands = $$PWD/scripts/deployqtHelper_mac.sh \"$${APPBUNDLE}\" \"$$[QT_INSTALL_BINS]\" \"$$[QT_INSTALL_TRANSLATIONS]\" \"$$[QT_INSTALL_PLUGINS]\" \"$$[QT_INSTALL_IMPORTS]\" \"$$[QT_INSTALL_QML]\"codesign.commands = codesign --deep -s \"$(SIGNING_IDENTITY)\" $(SIGNING_FLAGS) \"$${APPBUNDLE}\"dmg.commands = python -u \"$$PWD/scripts/makedmg.py\" \"$${BASENAME}.dmg\" \"Qt Creator\" \"$$IDE_SOURCE_TREE\" \"$$OUT_PWD/bin\"# dmg.depends = deployqtQMAKE_EXTRA_TARGETS += codesign dmg
} else {BINDIST_SOURCE = "$(INSTALL_ROOT)$$QTC_PREFIX"BINDIST_EXCLUDE_ARG = "--exclude-toplevel"deployqt.commands = python -u $$PWD/scripts/deployqt.py -i \"$(INSTALL_ROOT)$$QTC_PREFIX/bin/$${IDE_APP_TARGET}\" \"$(QMAKE)\"deployqt.depends = installwin32 {deployartifacts.depends = installdeployartifacts.commands = git clone --depth 1 -b $$BINARY_ARTIFACTS_BRANCH \"http://code.qt.io/qt-creator/binary-artifacts.git" \&& xcopy /s /q /y /i "binary-artifacts\\win32" \"$(INSTALL_ROOT)$$QTC_PREFIX\" \&& rmdir /s /q binary-artifactsQMAKE_EXTRA_TARGETS += deployartifacts}
}

INSTALL_ROOT

环境变量

make install时更改安装目录的位置,例如$BUILDDIR/install/qtcreator(在Mac上不使用),具体安装到$(INSTALL_ROOT)$$QTC_PREFIX中。

QTC_PREFIX

qmake变量

用于make install安装目录的目录前缀,以及make bindist打包的目录对象,且必须以/开头,例如/qt-creator-x.y.z,安装到$(INSTALL_ROOT)$$QTC_PREFIX中。

PWD

指定包含正在被解析的当前文件的目录的完整路径。在编写支持影子构建的项目文件时,这对于引用源文件树中的文件很有用。

注意:请勿尝试覆盖此变量的值。

OUT_PWD

指定文件夹完整路径,qmake把生成的Makefile放到此文件夹中。

注意:请勿尝试覆盖此变量的值。

TARGET

指定目标文件的名称。 默认情况下包含项目文件的基本名称。

例如:

TEMPLATE = app
TARGET = myapp
SOURCES = main.cpp

上面的项目文件将在unix上生成一个名为myapp的可执行文件,在Windows上生成一个名为myapp.exe的可执行文件。

QMAKE_EXTRA_TARGETS

指定额外的qmake目标的列表。

另请参阅Adding Custom Targets。

Adding Custom Targets

qmake试图做一个跨平台构建工具所期望的一切。当您确实需要运行特殊的平台相关命令时,这通常不理想。 但是,这可以使用平台特定的指令指向不同的qmake后端来实现。

自定义Makefile输出可通过执行对象风格(object-style)的API来实现,如在qmake中的其他位置所发现的那样。在指定成员时会自动定义对象。 例如:

mytarget.target = .buildfile
mytarget.commands = touch $$mytarget.target
mytarget.depends = mytarget2mytarget2.commands = @echo Building $$mytarget.target

上面的定义定义了一个名为mytarget的qmake目标,目标包含一个名为.buildfile的Makefile目标,并通过touch命令生成。 最后,.depends成员指定mytarget依赖于mytarget2,后者是随后定义的另一个目标。 mytarget2是一个虚拟目标。 它仅定义为向控制台回显一些文本。

最后一步是使用QMAKE_EXTRA_TARGETS变量来指示qmake该对象是要构建的目标:

QMAKE_EXTRA_TARGETS += mytarget mytarget2

这是实际构建自定义目标所需要做的一切。 当然,您可能希望将这些目标的其中一个与qmake构建目标(qmake build target)联系起来。 为此,您只需要在PRE_TARGETDEPS列表中包括Makefile目标即可。

自定义目标规范支持以下成员:

成员 描述
commands 用于生成自定义构建目标的命令。
CONFIG 自定义构建目标的特定配置选项。 可以设置为recursive,以指示应在Makefile中创建规则,以调用子目标特定的Makefile中的相关目标。 该成员默认为每个子目标创建一个条目。
depends 自定义构建目标所依赖的现有构建目标。
recurse 指定子目标,在Makefile中创建规则是被使用,以调用子目标特定的Makefile。 此成员仅当CONFIG设置为recursive时才使用。 典型值为"Debug"和"Release"。
recurse_target 指定应该通过Makefile的规则对应的子目标Makefile构建的目标。 该成员添加了类似$(MAKE) -f Makefile.[subtarget] [recurse_target]的东西。 此成员仅当CONFIG设置为recursive时才使用。
target 自定义构建目标的名称

上面的语句中用到了Scopes条件判断,$$运算符,自定义目标等内容,我们在前面都已经讲过了。现在我们也清楚了,首先进行了平台判断,然后定义了自定义构建目标,用于编译输出。大家感兴趣,可以使用message()函数进行输出。具体内容就不深究了。

指定安装存档

接下来是

INSTALLER_ARCHIVE_FROM_ENV = $$(INSTALLER_ARCHIVE)
isEmpty(INSTALLER_ARCHIVE_FROM_ENV) {INSTALLER_ARCHIVE = $$OUT_PWD/$${BASENAME}-installer-archive.7z
} else {INSTALLER_ARCHIVE = $$OUT_PWD/$$(INSTALLER_ARCHIVE)
}INSTALLER_ARCHIVE_DEBUG = $$INSTALLER_ARCHIVE
INSTALLER_ARCHIVE_DEBUG ~= s/(.*)[.]7z/\1-debug.7z

Operators

在许多项目文件中,赋值(=)和追加(+ =)运算符可用于包括有关项目的所有信息。 典型的使用模式是为变量分配值列表,并根据各种测试的结果附加更多值。 由于qmake使用默认值定义某些变量,因此有时有必要使用remove(-=)运算符过滤掉不需要的值。 以下各节描述如何使用运算符来操纵变量的内容。

Assigning Values

=运算符为变量分配一个值:

TARGET = myapp

上一行将TARGET变量设置为myapp。 这将使用myapp覆盖先前为TARGET设置的任何值。

Appending Values

+=运算符将新值附加到变量的值列表中:

DEFINES += USE_MY_STUFF

上一行将USE_MY_STUFF追加到预处理定义列表中,最后写入生成的Makefile。

Removing Values

-=运算符从变量的值列表中删除一个值:

DEFINES -= USE_MY_STUFF

上一行从预处理定义列表中删除了USE_MY_STUFF。

Adding Unique Values

*=运算符将一个值添加到变量的值列表中,但前提是尚不存在。 这样可以防止将值多次包含在变量中。 例如:

DEFINES *= USE_MY_STUFF

在上面的行中,如果尚未定义USE_MY_STUFF,则只会将其添加到预处理定义列表中。 请注意,unique()函数还可用于确保变量仅包含每个值的一个实例。

Replacing Values ~=

〜=运算符将所有与正则表达式匹配的值替换为指定的值:

DEFINES ~= s/QT_[DT].+/QT

在上一行中,列表中以QT_D或QT_T开头的任何值都将替换为QT。

INSTALLER_ARCHIVE的定义方式,我们在"指定基础名"小节中就介绍过这种用法,不再赘述。对于INSTALLER_ARCHIVE_DEBUG的~=运算,就是在文件名后面加了-debug。

指定额外构建目标

最后是


bindist.commands = python -u $$PWD/scripts/createDistPackage.py $$OUT_PWD/$${BASENAME}.7z \"$$BINDIST_SOURCE\"
bindist_installer.commands = python -u $$PWD/scripts/createDistPackage.py $$BINDIST_EXCLUDE_ARG $${INSTALLER_ARCHIVE} \"$$BINDIST_SOURCE\"
bindist_debug.commands = python -u $$PWD/scripts/createDistPackage.py --debug $$BINDIST_EXCLUDE_ARG $${INSTALLER_ARCHIVE_DEBUG} \"$$BINDIST_SOURCE\"win32 {deployqt.commands ~= s,/,\\\\,gbindist.commands ~= s,/,\\\\,gbindist_installer.commands ~= s,/,\\\\,g
}QMAKE_EXTRA_TARGETS += deployqt bindist bindist_installer bindist_debug

首先创建了bindist,bindist_installer和bindist_debug三个自定义构建目标,然后在win32平台下进行了替换。最终添加到QMAKE_EXTRA_TARGETS进行编译构建。

简单解释下上面的正则表达式,其实就是替换路径中的分隔符,全局替换unix中的/为windows下的\\。


原创造福大家,共享改变世界

献出一片爱心,温暖作者心灵


qt creator源码全方面分析(3-1)相关推荐

  1. qt creator源码全方面分析(2-6)

    目录 User Interface Text Guidelines 语法和风格 标点 编写工具提示tooltips 设计模式中编写工具提示 编写消息 UI文本大写 使用书本样式大写 检查书本样式大写 ...

  2. qt插件元数据不包含一个有效的元数据_qt creator源码全方面分析(2-10-2)

    Creating Your First Plugin 本节介绍,如何使用Qt Creator提供的插件模板,来创建Qt Creator插件,并获取对插件的组成和结构的第一印象. 创建一个插件项目 Qt ...

  3. JAVA源码优化、分析工具

    JAVA源码优化.分析工具 一.11款用于优化.分析源代码的Java工具 1. PMD from http://pmd.sourceforge.net/ PMD能够扫描Java 源代码,查找类似以下的 ...

  4. 【Camera专题】Camera驱动源码全解析_下

    系列文章 1.手把手撸一份驱动 到 点亮 Camera 2.Camera dtsi 完全解析 3.Camera驱动源码全解析上 4.Camera驱动源码全解析下 上篇文章分析了C文件函数的实现,本文继 ...

  5. 机器学习算法源码全解析(三)-范数规则化之核范数与规则项参数选择

    前言 参见上一篇博文,我们聊到了L0,L1和L2范数,这篇我们絮叨絮叨下核范数和规则项参数选择.知识有限,以下都是我一些浅显的看法,如果理解存在错误,希望大家不吝指正.谢谢. 机器学习算法源码全解析( ...

  6. Dalvik解释器源码到VMP分析

    前言 学习这块的主要目的还是想知道vmp是如何实现的,如何与系统本身的虚拟机配合工作,所以简单的学习了Dalvik的源码并对比分析了数字公司的解释器.笔记结构如下: dalvik解释器分析 dalvi ...

  7. ReviewForJob——最小生成树(prim + kruskal)源码实现和分析

    [0]README 1)本文旨在给出 ReviewForJob--最小生成树(prim + kruskal)源码实现和分析, 还会对其用到的 技术 做介绍: 2)最小生成树是对无向图而言的:一个无向图 ...

  8. php授权验证系统源码-全解开源版

    简介: php授权验证系统源码全解开源版,正版授权查询管理. 安装方法:上传PHP环境,访问域名instll,根据提示自动安装! 网盘下载地址: http://kekewl.org/MBJa7XXNk ...

  9. strings.Builder 源码阅读与分析

    strings.Builder源码阅读与分析 背景之字符串拼接 在 Go 语言中,对于字符串的拼接处理有很多种方法,那么那种方法才是效率最高的呢? str := []string{"aa&q ...

最新文章

  1. 顺时针打印矩阵 python
  2. 调用bat文件执行java文件
  3. Lintcode 993 解题思路和c++代码
  4. android 版本权限差别,android apk 的root 权限和USB adb 权限的区别
  5. jQuery 图片裁剪插件 Jcrop
  6. 删除顽固node_modules
  7. SpringSecurity简单教程(源码开源免费提供)
  8. 单片机课设———基于51单片机的智能风扇控制器(汇编语言)
  9. UI自动化之分层思想pom模式
  10. unity透明通道加颜色_半透明物体的描边和投影
  11. IE和谷歌浏览器区分
  12. win10访问服务器共享文件夹密码不对,WIN10 Samba文件共享的设置方法,解决不能访问和密码错误的问题...
  13. SpringCloudGateway爆漏洞,快看看你的服务中招没?
  14. 大南湖地磅房升级需要改造哪些方面
  15. 揭秘闲鱼赚钱项目的高端玩法
  16. Python + Excel——飞速处理数据分析与处理
  17. 51单片机学习:LED点阵实验(显示图像)
  18. 最优包裹组合问题-贪心算法
  19. java计算机毕业设计的问卷调查系统设计与实现源程序+mysql+系统+lw文档+远程调试
  20. 一狼 GHOST 系统_sp3_v2.4.iso

热门文章

  1. 从今天开始学习iOS开发(iOS 7版)-- 构建一款App之App开发过程 (二)
  2. 快速web app之道
  3. 【图说word】 宏
  4. ubuntu vim中输入中文
  5. Spring学习笔记专题三
  6. 断开式数据集DataSet 1129
  7. 数据结构与算法-时间复杂度的级别-时间复杂度的算法
  8. python-模块-pymysql操作数据库
  9. javascripts-for循环-while循环-标签的选择与操作
  10. git 常用命令思维导图