高级用法

添加新的配置功能

qmake 可以让你创建自己的features ,通过将它们的名称添加到CONFIG变量指定的值列表中,就可以将它们包含在项目文件中。特性是.prf 文件中自定义函数和定义的集合,可以位于许多标准目录之一。这些目录的位置在许多地方都有定义,qmake 在查找.prf 文件时会按以下顺序检查每个目录:

  1. QMAKEFEATURES 环境变量中列出的目录,该环境变量包含一个由平台路径列表分隔符(Unix 为冒号,Windows 为分号)分隔的目录列表。
  2. QMAKEFEATURES 属性变量中列出的目录,该目录包含一个由平台路径列表分隔符分隔的目录列表。
  3. mkspecs mkspecs 目录可以位于 环境变量中列出的任何目录之下,该环境变量包含由平台路径列表分隔符分隔的目录列表。例如: 。QMAKEPATH $QMAKEPATH/mkspecs/<features>
  4. QMAKESPEC环境变量提供的目录下的功能目录中。例如:$QMAKESPEC/<features>
  5. 位于data_install/mkspecs 目录中的功能目录。例如:data_install/mkspecs/<features>
  6. 作为QMAKESPEC 环境变量指定的目录的同级目录而存在的特性目录中。例如:$QMAKESPEC/../<features>

将在以下功能目录中搜索功能文件:

  1. features/unix,features/win32, 或features/macx, 视使用的平台而定
  2. features/

例如,请考虑项目文件中的以下赋值:

CONFIG += myfeatures

CONFIG 变量中添加此变量后,qmake 将在解析完项目文件后,在上述位置搜索myfeatures.prf 文件。在 Unix 系统中,它将查找以下文件:

  1. $QMAKEFEATURES/myfeatures.prf (环境变量 中列出的每个目录)QMAKEFEATURES
  2. $$QMAKEFEATURES/myfeatures.prf ( 属性变量中列出的每个目录)。QMAKEFEATURES
  3. myfeatures.prf (项目根目录中)。项目根目录由顶级 文件决定。但是,如果将 文件放在子目录或子项目的目录中,那么项目根目录就变成了子目录本身。.pro .qmake.cache
  4. $QMAKEPATH/mkspecs/features/unix/myfeatures.prf 和 (针对 环境变量中列出的每个目录)$QMAKEPATH/mkspecs/features/myfeatures.prf QMAKEPATH
  5. $QMAKESPEC/features/unix/myfeatures.prf$QMAKESPEC/features/myfeatures.prf
  6. data_install/mkspecs/features/unix/myfeatures.prfdata_install/mkspecs/features/myfeatures.prf
  7. $QMAKESPEC/../features/unix/myfeatures.prf$QMAKESPEC/../features/myfeatures.prf

注意: .prf 文件的名称必须小写。

安装文件

在 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 变量中附加了内置安装集,但没有指定filesextra 成员,qmake 会为您决定需要复制的内容。目前支持targetdlltarget 安装集。例如

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

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

添加自定义目标

qmake 试图完成一个跨平台编译工具所应做的一切。当你真的需要运行依赖于平台的特殊命令时,这往往不是那么理想。这可以通过向不同的 qmake 后端发送特定指令来实现。

Makefile 输出的定制是通过对象风格的 API 来实现的,这在 qmake 的其他地方也能找到。对象是通过指定其成员自动定义的。例如

mytarget.target = .buildfile
mytarget.commands = touch $$mytarget.target
mytarget.depends = mytarget2

mytarget2.commands = @echo Building $$mytarget.target

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

最后一步是使用QMAKE_EXTRA_TARGETS 变量来指示 qmake 这个对象是要编译的目标:

QMAKE_EXTRA_TARGETS += mytarget mytarget2

这就是构建自定义目标所需的全部步骤。当然,你可能想把其中一个目标绑定到qmake联编目标上。为此,您只需在PRE_TARGETDEPS 列表中包含您的 Makefile 目标。

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

成员描述
命令生成自定义联编目标的命令。
配置自定义联编目标的特定配置选项。可设置为recursive ,表示应在 Makefile 中创建规则,以便在特定于子目标的 Makefile 中调用相关目标。该成员默认为每个子目标创建一个条目。
取决于自定义联编目标所依赖的现有联编目标。
递归指定在 Makefile 中创建规则时应使用哪些子目标,以便在特定于子目标的 Makefile 中调用。只有在CONFIG 中设置了recursive 时,才会使用该成员。典型值为 "Debug "和 "Release"。
递归目标为 Makefile 中的规则指定应通过子目标 Makefile 联编的目标。该成员会添加类似$(MAKE) -f Makefile.[subtarget] [recurse_target] 的内容。只有在CONFIG 中设置了recursive 时,才会使用该成员。
目标自定义编译目标的名称。

添加编译器

可以定制 qmake 以支持新的编译器和预处理器:

new_moc.output  = moc_${QMAKE_FILE_BASE}.cpp
new_moc.commands = moc ${QMAKE_FILE_NAME} -o ${QMAKE_FILE_OUT}
new_moc.depend_command = g++ -E -M ${QMAKE_FILE_NAME} | sed "s,^.*: ,,"
new_moc.input = NEW_HEADERS
QMAKE_EXTRA_COMPILERS += new_moc

有了上述定义,如果 moc 可用,你就可以用它来替代。命令会在NEW_HEADERS 变量(来自input 成员)的所有参数上执行,执行结果会写入output 成员定义的文件。该文件将被添加到项目中的其他源文件中。此外,qmake 会执行depend_command 来生成依赖关系信息,并将此信息也放入项目中。

自定义编译器规范支持以下成员:

成员说明
命令用于从输入生成输出的命令。
配置自定义编译器的特定配置选项。详情请参阅 CONFIG 表格。
依赖命令指定用于生成输出依赖项列表的命令。
依赖类型指定输出文件的类型。如果是已知类型(如 TYPE_C、TYPE_UI、TYPE_QRC),则按这些类型的文件处理。
依赖指定输出文件的依赖关系。
输入指定自定义编译器应处理的文件的变量。
名称自定义编译器工作内容的描述。仅在某些后端中使用。
输出自定义编译器生成的文件名。
输出函数指定用于指定要创建的文件名的自定义 qmake 函数。
变量表示此处指定的变量在 pro 文件中以 $(VARNAME) 代替。
变量输出从输出创建的文件应添加到的变量。

CONFIG 成员支持以下选项:

选项说明
合并表示将所有输入文件合并为一个输出文件。
target_predeps表示应将输出添加到PRE_TARGETDEPS 列表中。
显式依赖项输出的依赖关系只从 depends 成员生成,而不从其他地方生成。
dep_existing_only.depend_command 产生的每个依赖关系都会被检查是否存在。不存在的依赖关系将被忽略。此值在 Qt 5.13.2 中引入。
dep_lines.depend_command 的输出被解释为每行一个文件。默认值是以空白分割,仅出于向后兼容的原因而保留。
无链接表示不应将输出添加到要链接的对象列表中。

库依赖关系

通常情况下,当针对一个库进行链接时,qmake 会依赖底层平台来了解该库还链接了哪些其他库,并让平台将它们拉入。但在许多情况下,这还不够。例如,静态链接一个库时,不会链接到其他库,因此也不会创建对这些库的依赖关系。如果您显式启用了跟踪,qmake 会在适当的情况下尝试跟踪库的依赖关系。

第一步是在库本身启用依赖关系跟踪。为此,你必须告诉 qmake 保存有关库的信息:

CONFIG += create_prl

这只与lib 模板有关,其他模板都将忽略。启用此选项后,qmake 将创建一个以 .prl 结尾的文件,保存一些关于库的元信息。这个元文件就像普通的项目文件,但只包含内部变量声明。安装这个库时,只要在INSTALLS声明中指定它为目标,qmake 就会自动将 .prl 文件复制到安装路径。

这个过程的第二步是在使用静态库的应用程序中启用读取这些元信息:

CONFIG += link_prl

启用此功能后,qmake 将处理应用程序链接到的所有库,并找到它们的元信息。qmake 将利用这些元信息来确定相关的链接信息,特别是在应用程序项目文件的DEFINESLIBS 列表中添加值。qmake 处理完这个文件后,就会在LIBS 变量中查找新引入的库,并找到它们的 .prl 依赖文件,直到所有的库都被解决为止。此时,Makefile 会像往常一样创建,而库则会显式链接到应用程序中。

.prl 文件只能由 qmake 创建,不应在操作系统之间传输,因为其中可能包含平台相关信息。

© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.