使用CMake构建/Qt 5和Qt 6兼容性

Qt 5 and Qt 6 compatibility

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.

Qt5和Qt6中CMake API的语义在很大程度上是兼容的。但是,在Qt 5.14之前,所有导入的Qt库目标和命令都包含版本号作为名称的一部分。这使得编写同时适用于Qt5和Qt6的CMake代码有些麻烦。因此,Qt 5.15引入了无版本目标和命令,以支持编写对不同Qt版本基本不可知的CMake代码。

Versionless targets

无版本目标

In addition to the existing imported targets, Qt 5.15 introduced versionless targets. That is, to link against Qt Core one can both reference Qt6::Core, or Qt::Core:

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

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

add_executable(helloworld
    ...
)

target_link_libraries(helloworld PRIVATE Qt::Core)

Above snippet first tries to find a Qt 6 installation. If that fails, it tries to find a Qt 5.15 package. Independent of whether Qt 6 or Qt 5 is used, we can use the imported Qt::Core target.

上面的代码片段首先尝试查找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.

​默认情况下定义无版本目标。在第一次调用find_package()之前设置QT_NO_CREATE_VERSIONLESS_目标以禁用它们。

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

注意:导入的Qt::Core目标将不具有Qt6::Core目标中可用的目标属性。

Versionless commands

无版本命令

Since Qt 5.15, the Qt modules also provide versionless variants of their commands. You can for instance now use qt_add_translation to compile translation files, independent of whether you use Qt 5 or Qt 6.

​自Qt 5.15以来,Qt模块还提供其命令的无版本变量。例如,现在可以使用qt_add_translation来编译翻译文件,这与使用qt 5还是qt 6无关。

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

​在第一次find_package()调用之前设置QT_NO_CREATE_VERSIONLESS_函数,以防止创建无版本命令。

Mixing Qt 5 and Qt 6

混合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).

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

In such a setup the versionless targets and commands will be implicitly referring to the first Qt version that was found via find_package. Set the QT_DEFAULT_MAJOR_VERSION CMake variable before the first find_package call to make the version explicit.

​在这种设置中,无版本的目标和命令将隐含地引用通过find_package找到的第一个Qt版本。在第一次find_package调用之前设置QT_DEFAULT_MAJOR_VERSION CMake变量,使版本显式。

Supporting older Qt 5 versions

支持较旧的Qt5版本

If you need to support also Qt 5 versions older than Qt 5.15, you can do so by storing the current version in an CMake variable:

如果还需要支持比Qt 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)

Here we let find_package(<PackageName>...) try to find first Qt 6, and if that fails Qt 5, under the name QT. If either of them is found, find_package will succeed, and the CMake variable QT_VERSION_MAJOR will be defined to either 5 or 6.

在这里,我们让find_package(<PackageName>)尝试查找第一个Qt 6,如果失败,则使用Qt 5。如果找到其中任何一个,find_package将成功,CMake变量QT_VERSION_MAJOR将被定义为5或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, and will print an error otherwise.

然后,我们通过动态创建名称Qt${Qt_version_MAJOR}再次为确定的Qt版本加载包。这是必需的,因为CMAKE_AUTOMOC希望包名为Qt5或Qt6,否则将打印错误。

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

我们也可以使用相同的模式来指定导入库的名称。在调用target_link_libraries之前,CMake会将Qt${Qt_VERSION_MAJOR}::Widgets解析为Qt5::Widgets或Qt6::Widgets。

推荐做法

Use the versionless variants of the CMake commands where possible.

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

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.

无版本导入的目标对于需要同时使用Qt 5和Qt 6编译的项目最有用。由于缺少目标属性,我们不建议在默认情况下使用它们。

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.

​如果需要支持Qt 5.15之前的Qt 5版本,或者无法控制是否在可能定义Qt_NO_CREATE_VERSIONLESS_FUNCTIONS或Qt_NO_CREATE_VERSIONLESS_TARGETS的上下文中加载CMake代码,请使用CMake命令和目标的版本化版本。在这种情况下,您仍然可以通过变量确定实际的命令或目标名称来简化代码。

Unicode support in Windows

Windows中的Unicode支持

In Qt 6, the 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 6中,UNICODE和_UNICODE编译器定义默认为链接到Qt模块的目标设置。这与qmake行为一致,但与qt5中的cmake api行为相比,这是一个变化。

Call qt_disable_unicode_defines() on the target to not set the definitions.

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

find_package(Qt6 COMPONENTS Core)

add_executable(helloworld
    ...
)

qt_disable_unicode_defines(helloworld)

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值