当前位置: 首页 > news >正文

【CXX-Qt】2.1.1 为 WebAssembly 构建

CXX-Qt 及其编写的应用程序可以编译为 WebAssembly,但存在一些限制。以下是关于如何为 WASM 目标构建的详细说明。

你需要安装 Qt for WebAssembly。下一篇将展示已测试的版本。

此外,如果尚未完成,请从此处克隆 emsdk git 仓库。

使用正确的版本

用于构建 CXX-Qt 及其程序的 Emscripten 版本应与用于构建 Qt for WebAssembly 的版本匹配。这是因为 Emscripten 不保证不同版本之间的 ABI 兼容性,因此使用不同版本不能保证完全正常工作,甚至可能根本无法工作。

以下是相关的 Qt 和 Emscripten 版本,以及它们当前是否与 CXX-Qt for WebAssembly 兼容:

Qt 版本Emscripten 版本
6.22.0.14
6.33.0.0
6.43.1.14
6.53.1.25
6.63.1.37

设置 emsdk

确定要使用的 Qt 和 Emscripten 版本后,导航到 emsdk 仓库的根目录并运行以下命令:

$ ./emsdk install <emscripten 版本>
$ ./emsdk activate <emscripten 版本>
$ source ./emsdk_env.sh

例如,如果你要使用 Qt 6.4,对应的 Emscripten 版本是 3.1.14,因此第一条命令将是:

$ ./emsdk install 3.1.14

在 Windows 上,第三步(设置环境变量,类似于 Unix 环境中的 source 命令)是不必要的,因为所需的环境设置已经完成。

工具链

使用 CMake 配置时,需要将 CMAKE_TOOLCHAIN_FILE 变量设置为正确的工具链文件。例如,如果在 WebAssembly 上使用 Qt 6.4.2,工具链文件通常位于 /path/to/Qt/6.4.2/wasm_32/lib/cmake/Qt6/qt.toolchain.cmake。这将设置 CMake 使用正确的 Qt 路径、编译器、链接器等。

通常,这不需要手动完成。使用与所选 Qt WASM 版本捆绑的 qt-cmake 二进制文件将自动为你设置工具链文件。

例如,如果使用 Qt 6.4.2:

$ /path/to/Qt/6.4.2/wasm_32/bin/qt-cmake -B build .

然而,在 Qt 6.3 及以下版本中,捆绑的 CMake 版本为 3.22,而 CXX-Qt 至少需要 3.24 版本。对于这些 Qt 版本,需要使用更新的 CMake 二进制文件进行配置,因此需要将 CMAKE_TOOLCHAIN_FILE 传递给 cmake 命令。

如果使用不同的 CMake 二进制文件,请执行以下操作:

$ cmake -DCMAKE_TOOLCHAIN_FILE=/path/to/qt.toolchain.cmake -B build .

对于 Qt 6.5 或更高版本,请使用 wasm_singlethread 工具链。对于早于 6.5 的版本,请使用 wasm_32。

Qt 6.5 及更高版本中提供的 wasm_multithread 工具链目前不受支持。更多信息请参阅本页底部的“已知问题”部分。

为 WebAssembly 编译项目

要为使用 CXX-Qt crate 的项目构建 WebAssembly,请首先按照“使用正确的版本”和“设置 emsdk”部分中的说明进行操作。

CMakeLists.txt

在为 wasm 编译 CXX-Qt 项目时,必须将 Rust 目标设置为 wasm32-unknown-emscripten,并且项目必须配置为使用 POSIX 线程。确保你已经通过 rustup target add wasm32-unknown-emscripten 安装了 Emscripten 目标。

set(Rust_CARGO_TARGET wasm32-unknown-emscripten)
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)

使用 CMake 时,add_executable 在针对 wasm 时不会输出 HTML 文件。为了渲染 HTML 文件,必须使用 qt_add_executable 代替。假设项目有一个 CMake 标志 BUILD_WASM 用于切换 wasm 和本地构建,可以编写以下内容:

if(BUILD_WASM)
    qt_add_executable(${APP_NAME} ${SOURCE_FILES})
else()
    add_executable(${APP_NAME} ${SOURCE_FILES})
endif()

配置、构建和运行
按照“工具链”部分中的说明配置构建目录。

现在,在构建目录上运行 cmake --build 以编译和链接项目。这可以是任何 CMake 二进制文件;此处使用操作系统包即可:

$ cmake --build build

然后可以像这样运行构建的应用程序:

$ emrun ./build/path/to/<appname>.html

从源代码编译 CXX-Qt WASM
如果你是从源代码编译 CXX-Qt,工作流程类似。首先,按照“使用正确的版本”和“设置 emsdk”部分中的说明进行操作。

CXX-Qt 仓库根目录中的 CMakeLists.txt 文件有一个选项 BUILD_WASM,用于切换 WebAssembly 构建。只需使用正确的 emsdk 和工具链编译并将此选项设置为 ON,即可为 WebAssembly 构建库和示例。

构建

在继续之前,请阅读“工具链”部分。然后导航到 CXX-Qt 仓库的根目录。

如果使用与 Qt for WebAssembly 捆绑的 qt-cmake 二进制文件,请运行以下命令来配置 CXX-Qt:

$ /path/to/qt-cmake -DBUILD_WASM=ON -B build .

如果使用不同的 CMake 二进制文件,请执行以下操作:

$ <cmake 二进制文件> -DCMAKE_TOOLCHAIN_FILE=/path/to/qt.toolchain.cmake -DBUILD_WASM=ON -B build .

最后,在配置的构建目录上运行 cmake --build 以编译和链接项目及示例。这可以是任何 CMake 二进制文件;此处使用操作系统包即可:

$ cmake --build build

然后可以像这样运行 qml_minimal 示例:

$ emrun ./build/examples/qml_minimal/example_qml_minimal.html

可用的示例
并非所有示例当前都支持 WASM 构建。

示例是否可用
qml-minimal-no-cmake❌ 不可用
demo_threading❌ 不可用
qml_features✅ 可用
qml_minimal✅ 可用

更多信息请参阅本页底部的“已知问题”部分。

已知问题

wasm_multithread 工具链
CXX-Qt 目前无法使用 wasm_multithread 版本的 Qt 构建。

wasm-ld: error: --shared-memory is disallowed by qml_minimal-e6f36338b0e1fa5c.17g6vcid2nczsjj0.rcgu.o 
            because it was not compiled with 'atomics' or 'bulk-memory' features.

此问题与 libc crate 中的 pthread 有关。手动使用 -pthread 编译 cxx 和 libc crate 可能会解决此问题。

仅使用 cargo 构建

示例 qml-minimal-no-cmake 无法使用 cargo 为 WebAssembly 构建,尝试在没有 cmake 的情况下使用 cargo 构建将无法工作。这是由于 libc crate 的上游问题,它不支持 wasm 并可能导致构建失败。

cannot find function `pthread_kill` in crate `libc`

demo_threading 示例
示例 demo_threading 无法为 WebAssembly 构建,这是由于 async-std 的上游问题,它不支持 wasm。在 Linux 上,观察到的构建失败是由于 socket2 使用其 unix.rs 文件来针对 Unix 环境而不是 wasm 环境,导致来自 unix.rs 的错误消息如下:

error[E0433]: failed to resolve: use of undeclared type `IovLen`

socket2 是 async-io 的依赖项,而 async-io 又是 async-std 的依赖项。

有关在 async-std 的 GitHub 仓库中支持 wasm 的讨论正在进行中,进展可以在此处跟踪。

相关文章:

  • 汽车免拆诊断案例 | 2024 款路虎发现运动版车无法正常识别智能钥匙
  • Java EE 进阶:MyBatis
  • 【NLP】 11. 神经网络,线性模型,非线性模型,激活函数,感知器优化,正则化学习方法
  • SpringBoot配置文件加载优先级
  • 最大公约数(GCD)和最小公倍数(LCM)专题练习 ——基于罗勇军老师的《蓝桥杯算法入门C/C++》
  • 蓝桥杯2023年第十四届省赛真题-接龙数列
  • Linux后门程序工作原理的详细解释,以及相应的防御措施
  • c语言数据结构 双循环链表设计(完整代码)
  • Ubuntu版免翻墙搭建BatteryHistorian
  • freeswitch(开启抓包信息)
  • 观察RenderDoc截帧UE时“Event”代表什么
  • ssh 多重验证的好处:降低密钥长度,动态密码
  • 分布式任务调度
  • 事件响应计划:网络弹性的关键
  • C++ :try 语句块和异常处理
  • IDEA批量替换项目下所有文件中的特定内容
  • Python Cookbook-4.7 在行列表中完成对列的删除和排序
  • 主流加固方案深度剖析(梆梆/腾讯/阿里)
  • 《数据库原理教程》—— 第三章 关系数据模型 笔记
  • 解释 RESTful API,以及如何使用它构建 web 应用程序
  • 车主质疑零跑汽车撞车后AEB未触发、气囊未弹出,4S店:其把油门当刹车
  • 国防部:中方愿与俄方不断增强两军关系良好发展势头
  • AI含量非常高,2025上海教育博览会将于本周五开幕
  • 泽连斯基批准美乌矿产协议
  • 巴基斯坦称对印度发起军事行动
  • 方正证券总裁何亚刚到龄退休,54岁副总裁姜志军接棒