Qt的CMake部署API

Qt's CMake deployment API

Qt的CMake部署API

September 02, 2022 by Jörg Bornemann | Comments

2022年9月2日 由Jörg Bornemann |评论

Say you have just started with Qt. You installed a recent version with the Qt online installer, found your way through the C++ and QML API, and now have a nice desktop application that works for you ™. Now you want to share your precious marvel with others, for eternal fame and/or profit! But you don’t want to share just your code but a binary that also end-users can install and run without installing a compiler, Qt ... How do you do this?

假设您刚刚开始使用Qt。您安装了Qt在线安装程序的最新版本,通过C++和QML API找到了自己的方法,现在有了一个很好的桌面应用程序™. 现在你想与他人分享你珍贵的奇迹,以获得永恒的名声或利润!但是您不想只共享您的代码,而是一个二进制文件,终端用户也可以在不安装编译器的情况下安装和运行,Qt…如何做到这一点?

A popular approach is to create a folder that contains both your application executable, but also the Qt libs and plugins, in the right structure, so that the executable finds everything it needs in the folder. Qt does help you in setting up such a folder with several command line tools, named windeployqt, and macdeployqt, and androiddeployqt. But how do you use them from  CMake? Enter Qt’s CMake deployment API!

一种流行的方法是创建一个文件夹,其中既包含应用程序可执行文件,也包含Qt库和插件(需结构正确),以便可执行文件在该文件夹中找到所需的所有内容。Qt确实可以通过几个命令行工具帮助您设置这样的文件夹,这些工具名为windeployqt、macdeployqt和androiddeployqt。但是你如何使用CMake的?输入Qt的CMake部署API!

The usual deployment process consists of the following steps:

通常的部署过程包括以下步骤:

1.installing the application into a staging area. The staging area is determined by CMAKE_INSTALL_PREFIX (or more generally, CMAKE_STAGING_PREFIX in cross builds).

1.将应用程序安装到临时区域。暂存区域由CMAKE_INSTALL_PREFIX(或更一般地,交叉构建中的CMAKE_STAGING_PREFIX)确定。

2.Calling windeployqt or macdeployqt to copy Qt libraries, plugins and assets into the staging area.

2.调用windeployqt或macdeployqt将Qt库、插件和资产复制到暂存区。

3.Custom adjustments that are not covered by our *deployqt tools.

3.我们的*deployqt工具不包括的自定义调整。

After these steps, the staging area is ready to be archived and shipped.

完成这些步骤后,准备归档和装运暂存区。

Usually, it's up to the user to create a separate script that handles the full deployment.

通常,由用户创建一个单独的脚本来处理完整部署。

Since version 6.3, Qt offers a way to define additional deployment steps that are executed on installation. Our goal for this article is to show how to deploy a Qt application using Qt's CMake deployment API.

自版本6.3以来,Qt提供了一种定义安装时执行的其他部署步骤的方法。本文的目标是展示如何使用Qt的CMake部署API部署Qt应用程序。

We start off with a simple Qt application.

我们从一个简单的Qt应用程序开始。

cmake_minimum_required(VERSION 3.22)
project(MyApp)

find_package(Qt6 REQUIRED COMPONENTS Widgets)
qt_standard_project_setup()

qt_add_executable(MyApp main.cpp)
target_link_libraries(MyApp PRIVATE Qt::Widgets)

We add statements to install the application target. On macOS, we install directly into ${CMAKE_INSTALL_PREFIX}, on other platforms into the "bin" directory underneath.

我们添加语句来安装应用程序目标。在macOS上,我们直接安装到${CMAKE_INSTALL_PREFIX},在其他平台上安装到下面的“bin”目录中。

install(TARGETS MyApp
    BUNDLE  DESTINATION .
    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)

Note that qt_standard_project_setup pulls in GNUInstallDirs.cmake. This is what defines the CMAKE_INSTALL_BINDIR variable.

请注意,qt_standard_project_setup引入了GNUInstallDirs.cmake。这定义了CMAKE_INSTALL_BINDIR变量。

A call to cmake --install ... would now only install the application's executable (or bundle) to the install prefix.

调用cmake --install …现在只将应用程序的可执行文件(或包)安装到安装前缀目录。

Up to this point, there's nothing new. But now we are going to instruct CMake to call macdeployqt or windeployqt on installation. In order to do that, we use CMake's ability to run a CMake script on installation.

到目前为止,没有什么新鲜事。但现在我们将指示CMake在安装时调用macdeployqt或windeployqt。为了做到这一点,我们使用CMake的能力在安装时运行CMake脚本。

qt_generate_deploy_app_script(
    TARGET MyApp
    FILENAME_VARIABLE deploy_script
    NO_UNSUPPORTED_PLATFORM_ERROR
)
install(SCRIPT ${deploy_script})

This generates a CMake script file that calls macdeployqt or windeployqt on our application target. The file name of the generated script file is stored in deploy_script. With the install(SCRIPT) call we instruct CMake to run the script on installation.

这将生成一个CMake脚本文件,在我们的应用程序目标上调用macdeployqt或windeployqt。生成的脚本文件的文件名存储在deploy_script中。通过install(SCRIPT)调用,我们指示CMake在安装时运行脚本。

We can now configure, build and install the project. Here's what it looks like on Windows:

我们现在可以配置、构建和安装项目。下面是它在Windows上的输出:

D:\projects\myapp\build>D:\Qt\bin\qt-cmake -GNinja -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=D:/TEMP/myapp ..
...
D:\projects\myapp\build>ninja
...
D:\projects\myapp\build>ninja install
-- Install configuration: "Release"
-- Installing: D:/TEMP/myapp/bin/myapp.exe
-- Writing D:/TEMP/myapp/bin/qt.conf
-- Running Qt deploy tool for bin/myapp.exe in working directory 'D:/TEMP/myapp'
'D:/Qt/bin/windeployqt.exe' 'bin/myapp.exe' '--dir' '.' '--libdir' 'bin' '--plugindir' 'plugins' '--force'
D:\TEMP\myapp\dist\bin\myapp.exe 64 bit, release executable
Direct dependencies: Qt6Core Qt6Gui Qt6Widgets
All dependencies   : Qt6Core Qt6Gui Qt6Widgets
To be deployed     : Qt6Core Qt6Gui Qt6Widgets
Updating Qt6Core.dll.
Updating Qt6Gui.dll.
Updating Qt6Widgets.dll.
Updating d3dcompiler_47.dll.
Updating vc_redist.x64.exe.
Creating directory D:/TEMP/myapp/plugins/imageformats.
Updating qgif.dll.
Updating qico.dll.
Updating qjpeg.dll.
Creating directory D:/TEMP/myapp/plugins/platforms.
Updating qwindows.dll.
Creating directory D:/TEMP/myapp/plugins/styles.
Updating qwindowsvistastyle.dll.

The installation produced a self-contained directory, ready to be packaged - for example by cpack.​
安装产生了一个自包含的目录,可以打包,例如通过cpack​

Under the hood

深度分析

The call to qt_generate_deploy_app_script generates a CMake script file in the build directory that does two things:

对qt_generate_deploy_app_script的调用在构建目录中生成一个CMake脚本文件,该文件执行两件事:

  • include the QtDeploySupport.cmake file
  • 包括QtDeploySupport.cmake文件
  • call qt6_deploy_runtime_dependencies on the installed executable
  • 在已安装的可执行文件上调用qt6_deploy_runtime_dependencies

The QtDeploySupport.cmake file provides the CMake commands that aid us with deployment. Also, it sets variables like QT_DEPLOY_PREFIX.

QtDeploySupport.cmake文件提供了帮助我们进行部署的cmake命令。此外,它还设置变量,如QT_DEPLOY_PREFIX。

The qt_deploy_runtime_dependencies command is the actual driver of the deployment process. It calls mac/windeployqt and generates a qt.conf file, if necessary.

​qt_deploy_runtime_dependencies命令是部署过程的实际驱动程序。它调用mac/windeployqt并生成qt.conf文件,如有必要。

For setups that need more customization, we have to do the script generation ourselves.

对于需要更多定制的设置,我们必须自己生成脚本。

set(deploy_script "${CMAKE_CURRENT_BINARY_DIR}/deploy_MyApp.cmake")
file(GENERATE OUTPUT ${deploy_script} CONTENT "
include(\"${QT_DEPLOY_SUPPORT}\")

qt_deploy_runtime_dependencies(
    EXECUTABLE \"\${QT_DEPLOY_BIN_DIR}/$<TARGET_FILE_NAME:MyApp>\"
    GENERATE_QT_CONF
)")

For the initial include statement we need to expand the CMake variable QT_DEPLOY_SUPPORT that is available at configure time.

对于初始include语句,我们需要扩展配置时可用的CMake变量QT_DEPLOY_SUPPORT。

In the remainder of the script we access the QT_DEPLOY_BIN_DIR variable that is available at installation time. That's why it must be escaped: we don't want to evaluate it at configuration time.

在脚本的其余部分,我们访问安装时可用的QT_DEPLOY_BIN_DIR变量。这就是为什么它必须被转义:我们不想在配置时评估它。

Lastly, we use a generator expression to extract the target file name of the MyApp target.

最后,我们使用生成器表达式提取MyApp目标的目标文件名。

Suppose our project provides its own qt.conf, we don't want qt_deploy_runtime_dependencies to generate one. To do that, we can remove the GENERATE_QT_CONF.

假设我们的项目提供了自己的qt.conf,我们不希望qt_deploy_runtime_dependencies生成一个。为此,我们可以删除GENERATE_QT_CONF。

The layout of the staging area

暂存区的布局

Qt's CMake deployment API uses the CMAKE_INSTALL_BINDIR and CMAKE_INSTALL_LIBDIR variables defined by GNUInstallDirs.cmake to determine the layout of the staging area.

​Qt的CMake部署API使用由GNUInstallDirs.cmake定义的CMAKE_INSTALL_BINDIRCMAKE_INSTALL_LIBDIR变量,确定暂存区的布局。

On installation time, these directory variables are available as QT_DEPLOY_BIN_DIR and QT_DEPLOY_LIB_DIR.

​在安装时,这些目录变量可用为QT_DEPLOY_BIN_DIR和QT_DEPLOY_LIB_DIR。

Make sure to use CMAKE_INSTALL_BINDIR as DESTINATION in the install command for executables and CMAKE_INSTALL_LIBDIR for libraries.

对于可执行文件,确保在安装命令中使用CMAKE_INSTALL_BINDIR作为DESTINATION,对于库,确保使用CMAKE_INSTALL_LIBDIR

To change the values of CMAKE_INSTALL_BINDIR or CMAKE_INSTALL_LIBDIR, set the variables before the Qt6Core package is found.

要更改CMAKE_INSTALL_BINDIR或CMAKE_INSTALL_LIBDIR的值,请在找到Qt6Core包之前设置变量。

Qt plugins are deployed into QT_DEPLOY_PLUGINS_DIR, which defaults to "plugin". QML modules are deployed into QT_DEPLOY_QML_DIR, which defaults to "qml".

​Qt插件部署到QT_DEPLOY_PLUGINS_DIR,默认为“plugin”。QML模块部署到QT_DEPLOY_QML_DIR中,默认为“QML”。

Deployment of QtQuick projects

QtQuick项目的部署

Deploying QtQuick projects is a tad more involved - fortunately not for the user. The details are hidden by the command qt_generate_deploy_qml_app_script.

​部署QtQuick项目更为复杂——幸运的是,对用户来说不是这样。详细信息由命令qt_generate_deploy_qml_app_script隐藏。

Let's have a look how to prepare the CMakeLists.txt of a QtQuick application.

让我们看看如何准备QtQuick应用程序的CMakeLists.txt

First, we create the QtQuick application.

首先,我们创建QtQuick应用程序。

qt_add_executable(MyApp main.cpp)
qt_add_qml_module(MyApp
    URI Application
    VERSION 1.0
    QML_FILES main.qml MyThing.qml
)

We need to add the regular install command:

我们需要添加常规安装命令:

install(TARGETS MyApp
    BUNDLE  DESTINATION .
    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)

And call qt_generate_deploy_qml_app_script:

并调用qt_generate_deploy_qml_app_script:

qt_generate_deploy_qml_app_script(
    TARGET MyApp
    FILENAME_VARIABLE deploy_script
)
install(SCRIPT ${deploy_script})

On installation, the application binary will be deployed, including the QML files and the bits of Qt that are used by the project.

安装时,将部署应用程序二进制文件,包括QML文件和项目使用的Qt库。

qt_generate_deploy_qml_app_script calls qt_deploy_qml_imports in addition to qt_deploy_runtime_dependencies. Refer to the documentation of these commands for details.

​qt_generate_deploy_qml_app_script除了调用qt_ deplloy_runtime_dependencies之外,还调用qt _deploy_ qml_ imports。有关详细信息,请参阅这些命令的文档。

Outlook

观点

At the moment, Qt's CMake deployment API is supported on Windows and macOS only. Android is handled via build targets.

目前,Qt的CMake部署API仅在Windows和macOS上受支持。Android是通过构建目标来处理的。

We strive to add more platforms in the future, including Linux (QTBUG-74940).

​我们努力在未来添加更多平台,包括Linux(QTBUG-74940)。

The CMake deployment API is in technical preview for the time being. Please try it on your favorite project and provide feedback on System Dashboard - Qt Bug Tracker.

​CMake部署API目前处于技术预览阶段。请在您最喜欢的项目上尝试,并在系统仪表板上提供反馈-Qt Bug Tracker。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值