Qt 5 和 Qt 6 兼容性

Qt 5 和 Qt 6 中 CMake API 的语义在很大程度上是兼容的,尽管这些命令的行为和附加接口仅在后一版本中存在一些差异。本指南主要面向希望从一个主要版本逐步迁移到另一个主要版本的项目。

在 Qt 5.14 之前,所有导入的 Qt 库目标和命令都将版本号作为名称的一部分,例如qt5_add_library 。这使得编写同时适用于 Qt 5 和 Qt 6 的 CMake 代码变得有些麻烦。因此,Qt 5.15 引入了无版本的目标和命令,即qt_add_library ,以便编写的 CMake 代码能在很大程度上与不同的 Qt 版本无关。

无版本目标

除了现有的导入目标,Qt 5.15 还引入了无版本目标。也就是说,要链接到 Qt Core既可以引用Qt6::Core ,也可以引用Qt::Core

find_package(Qt6 COMPONENTS Core)
if (NOT Qt6_FOUND)
    find_package(Qt5 5.15 REQUIRED COMPONENTS Core)
endif()

add_executable(helloworld
    ...
)

target_link_libraries(helloworld PRIVATE Qt::Core)

上述代码段首先尝试查找 Qt 6 安装。如果失败,它会尝试查找 Qt 5.15 软件包。无论使用的是 Qt 6 还是 Qt 5,我们都可以使用导入的Qt::Core target。要跳过 Qt 6 检查,请在调用 CMAKE_DISABLE_FIND_PACKAGE_Qt6要跳过 Qt 6 检查,请在调用find_package 之前设置

无版本目标是默认定义的。在首次调用find_package() 之前设置QT_NO_CREATE_VERSIONLESS_TARGETS可禁用它们。

无版本命令

自 Qt 5.15 起,Qt 模块还为其命令提供了无版本变体。例如,现在您可以使用qt_add_translation来编译翻译文件,与使用 Qt 5 还是 Qt 6 无关。

在首次调用find_package() 之前设置QT_NO_CREATE_VERSIONLESS_FUNCTIONS,以防止创建无版本的命令。

混合使用 Qt 5 和 Qt 6

有些项目可能需要在一个 CMake 上下文中同时加载 Qt 5 和 Qt 6(但不支持在一个库或可执行文件中混合使用 Qt 版本,因此要小心)。

在这种情况下,无版本目标和命令将隐式引用通过find_package 找到的第一个 Qt 版本。请在首次调用find_package 之前设置QT_DEFAULT_MAJOR_VERSIONCMake 变量,以明确版本。

支持早于 5.15 的 Qt 5 版本

如果您也需要支持比 Qt 5.15 更早版本的 Qt 5,您可以将当前版本存储在 CMake 变量 (QT_VERSION_MAJOR) 中:

find_package(Qt6 COMPONENTS Core)
if(Qt6_FOUND)
    set(QT_VERSION_MAJOR 6)
else()
    find_package(Qt5 REQUIRED COMPONENTS Core)
    set(QT_VERSION_MAJOR 5)
endif()

add_executable(helloworld
    ...
)

target_link_libraries(helloworld PRIVATE Qt${QT_VERSION_MAJOR}::Core)

与无版本方法相比,目标指向Qt${QT_VERSION_MAJOR}::Core ,在调用target_link_libraries 时会解析为Qt5::CoreQt6::Core

尽可能使用 CMake 命令的无版本变量。

除非您必须在同一项目中支持 Qt 5 和 Qt 6,否则请使用有版本的目标。

如果必须使用无版本目标,请注意 "使用无版本目标时的陷阱"。

如果您需要支持早于 Qt 5.15 的 Qt 5 版本,或您无法控制 CMake 代码是否在定义了QT_NO_CREATE_VERSIONLESS_FUNCTIONSQT_NO_CREATE_VERSIONLESS_TARGETS的情况下加载,请使用版本控制版本的 CMake 命令和目标。在这种情况下,您仍可通过变量确定实际命令或目标名称,从而简化代码。

使用无版本目标时的陷阱

使用无版本目标有几个缺点。

无版本目标通常是ALIAS 目标,您不能使ALIAS 目标指向ALIAS 目标。请使用 ALIASED_TARGET目标属性。

对于旧版本的 Qt 6,导入的Qt::Core 目标并不具备Qt6::Core 公开的所有目标属性。如果使用 CMake 3.18 或更新版本与 Qt 6.8 或更新版本链接,这一问题将得到解决。

项目不得导出暴露无版本目标的目标。例如,被另一个项目使用的库不得导出公开链接无版本目标的目标。否则,传递依赖关系可能会被破坏,或者该库的用户会不由自主地混合使用 Qt5 和 Qt6 目标。

Windows 中的 Unicode 支持

在 Qt 6 中,针对 Qt 模块链接的目标默认设置了UNICODE_UNICODE 编译器定义。这与 qmake 行为一致,但与 Qt 5 中的 CMake API 行为相比有所改变。

在目标上调用qt_disable_unicode_defines()可以不设置定义。

find_package(Qt6 COMPONENTS Core)

add_executable(helloworld
    ...
)

qt_disable_unicode_defines(helloworld)

© 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.