QT 5 和 QT 6 兼容性

The semantics of the CMake API in Qt 5 and Qt 6 are largely compatible. However, up to Qt 5.14, all imported Qt library targets and commands contained the version number as part of the name. This makes writing CMake code that should work with both Qt 5 and Qt 6 somewhat cumbersome. Qt 5.15 therefore introduced versionless targets and commands to enable writing CMake code that is largely agnostic to the different Qt versions.

无版本目标

除现有导入目标外,Qt 5.15 引入 versionless targets. That is, to link against Qt Core one can both reference 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 目标。

The versionless targets are defined by default. Set QT_NO_CREATE_VERSIONLESS_TARGETS before the first find_package() call to disable them.

注意: The imported Qt::Core target will not feature the target properties that are available in the Qt6::Core target.

无版本命令

Since Qt 5.15, the Qt modules also provide versionless variants of their 命令 。例如,现在可以使用 qt_add_translation to compile translation files, independent of whether you use Qt 5 or Qt 6.

Set QT_NO_CREATE_VERSIONLESS_FUNCTIONS before the first find_package() call to prevent the creation of versionless commands.

混合 Qt 5 和 Qt 6

There might be projects that need to load both Qt 5 and Qt 6 in one CMake context (though mixing Qt versions in one library or executable is not supported, so be careful there).

在这样的设置中,无版本目标和命令将隐式引用找到的首个 Qt 版本凭借 find_package 。设置 QT_DEFAULT_MAJOR_VERSION CMake 变量先于首个 find_package call to make the version explicit.

支持旧 QT 5 版本

若还需要支持早于 5.15 的 Qt 5 版本,可以通过将当前版本存储在 CMake 变量中做到这点:

find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core)
add_executable(helloworld
    ...
)
target_link_libraries(helloworld PRIVATE Qt${QT_VERSION_MAJOR}::Core)
					

在此,让 find_package(<PackageName>...) try to find first Qt 6, and if that fails Qt 5, under the name QT 。若找到它们中的任一, find_package will succeed, and the CMake variable QT_VERSION_MAJOR will be defined to either 5 or 6 .

We then do load the package for the determined Qt version again by creating the name Qt${QT_VERSION_MAJOR} on the fly. This is needed because CMAKE_AUTOMOC expects the package name to be either Qt5 or Qt6 ,否则将打印错误。

We can use the same pattern to also specify the name of the imported library. Before calling target_link_libraries ,CMake 将解析 Qt${QT_VERSION_MAJOR}::Widgets Qt5::Widgets or Qt6::Widgets .

Use the versionless variants of the CMake commands where possible.

Versionless imported targets are mostly useful for projects that need to compile with both Qt 5 and Qt 6. Because of the missing target properties, we do not recommend using them by default.

Use the versioned versions of the CMake commands and targets if you need to support Qt 5 versions older than Qt 5.15, or if you cannot control whether your CMake code is loaded in a context where QT_NO_CREATE_VERSIONLESS_FUNCTIONS or QT_NO_CREATE_VERSIONLESS_TARGETS might be defined. In this case you can still simplify your code by determining the actual command or target name through a variable.

Unicode support in Windows

在 Qt 6, UNICODE and _UNICODE compiler definitions are set by default for targets that link against Qt modules. This is in line with the qmake behavior, but it is a change compared to the CMake API behavior in Qt 5.

调用 qt_disable_unicode_defines() on the target to not set the definitions.

find_package(Qt6 COMPONENTS Core)
add_executable(helloworld
    ...
)
qt_disable_unicode_defines(helloworld)
					

Qt CMake policies CMake 命令参考