Qt for HarmonyOS/user development/deveco cmake guide cross compile zh
DevEco Studio 使用 CMake 开发 Qt 应用(交叉编译)
本文以 Qt 官方 Qt Widgets 示例 calculator(位于 qtbase/examples/widgets/widgets/calculator)为例,说明如何在 DevEco Studio 中通过 CMake 编译并运行一个 Qt 应用(HarmonyOS Stage 工程 + Native C++)。
1. 前置条件
- 已安装 DevEco Studio,并配置好 OHOS SDK(包含 `native` 工具链、CMake、Ninja)。
- 已准备好 Qt for HarmonyOS 的交叉编译安装目录(Qt 前缀目录),并确认其中存在:
- lib/cmake/Qt5/Qt5Config.cmake
- 已准备好鸿蒙模板工程,可参考:
- 已准备好运行 Qt 所需的运行时库(至少包括 libqohos.so 以及 Qt 依赖库)。
工程内示例路径:
- Qt for HarmonyOS 交叉编译安装目录(示例):
/Users/dev/Qt/5.12.12/ohos-arm64-v8a-clang
- Qt 运行时库放置目录:
entry/libs/arm64-v8a/
2. 鸿蒙模板工程结构速览(calculator)
2.1 C++(Qt 应用本体)
- entry/src/main/cpp/main.cpp:Qt 应用入口 `main()`
- entry/src/main/cpp/calculator.cpp / calculator.h:Calculator UI 与逻辑
- entry/src/main/cpp/button.cpp / button.h:按钮控件
- entry/src/main/cpp/CMakeLists.txt:CMake 构建脚本(生成 libcalculator.so)
2.2 ArkTS 胶水代码
- entry/src/main/ets/common/QtAppConstants.ets:配置要加载的 Qt 应用库名
** 示例: export const APP_LIBRARY_NAME = 'libcalculator.so';
3. 在 DevEco Studio 中配置 CMake
3.1 指定 CMakeLists 和 Qt 前缀目录
编辑模块级 entry/build-profile.json5,配置 externalNativeOptions:
{
"buildOption": {
"externalNativeOptions": {
"path": "./src/main/cpp/CMakeLists.txt",
"arguments": "-DCMAKE_PREFIX_PATH=/Users/dev/Qt/5.12.12/ohos-arm64-v8a-clang",
"abiFilters": ["arm64-v8a"]
}
}
}说明:
- path:指向本模块的 CMake 入口文件
- arguments:关键参数 `-DCMAKE_PREFIX_PATH`,必须指向 Qt 的安装前缀目录
- abiFilters:需与目标设备 ABI 匹配,否则可能导致库无法加载或打包失败
4. CMakeLists.txt 怎么写
4.1 查找 Qt(find_package)
工程中的 entry/src/main/cpp/CMakeLists.txt 使用如下方式查找 Qt:
- find_package(QT NAMES Qt5 Qt6 REQUIRED COMPONENTS Core)
- find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core Widgets)
在交叉编译场景下,需要注意 OHOS SDK 的 toolchain 默认设置了:
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
该设置位于:
DevEco-Studio/Contents/sdk/default/openharmony/native/build/cmake/ohos.toolchain.cmake
当该模式为 ONLY 时,如果 Qt 安装在 sysroot 之外(通常如此),即使传入 CMAKE_PREFIX_PATH, find_package(Qt5) 也可能找不到 Qt5Config.cmake。
因此需要在查找 Qt 前临时放宽策略:
- 在 find_package() Qt 前设置:
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE BOTH)
- Qt 找到后立即恢复原值,避免影响其它依赖
4.2 生成库名需与 ArkTS 配置一致
当前示例中:
- CMake:
* add_library(calculator SHARED ...) * 生成 libcalculator.so
- ArkTS:
* QtAppConstants.ets 中: APP_LIBRARY_NAME = 'libcalculator.so'
若修改 CMake target 名称(如 myapp),请同步修改:
- QtAppConstants.ets 中的 APP_LIBRARY_NAME
4.3 CMakeLists.txt 完整示例(calculator)
以下示例可直接用于模板工程 entry/src/main/cpp/CMakeLists.txt:
cmake_minimum_required(VERSION 3.5)
project(ohosQtTemplate)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
# OHOS toolchains commonly set CMAKE_FIND_ROOT_PATH_MODE_PACKAGE=ONLY for
# cross-compiling, which prevents CMake from finding Qt via CMAKE_PREFIX_PATH
# when Qt is installed outside the sysroot.
if(CMAKE_CROSSCOMPILING)
set(_saved_root_path_mode_package "${CMAKE_FIND_ROOT_PATH_MODE_PACKAGE}")
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE BOTH)
endif()
find_package(QT NAMES Qt5 Qt6 REQUIRED COMPONENTS Core)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core Widgets)
if(CMAKE_CROSSCOMPILING)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE "${_saved_root_path_mode_package}")
unset(_saved_root_path_mode_package)
endif()
set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR})
include_directories(
${NATIVERENDER_ROOT_PATH}
${NATIVERENDER_ROOT_PATH}/include
)
set(PROJECT_SOURCES
main.cpp
button.cpp
calculator.cpp
)
add_library(calculator SHARED
${PROJECT_SOURCES}
)
target_link_libraries(calculator
PRIVATE
Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::Widgets
)
5. 构建与运行(DevEco Studio)
- 使用 DevEco Studio 打开工程根目录:
ohostemplateforqtapplication
- 确认已选择正确的 product / target(如 default)和 ABI(如 arm64-v8a)
- 点击 Build / Run(或执行 hvigor 任务)
- Native 构建阶段会触发 `compileNative`
- 安装到设备或模拟器后启动应用,Qt UI 会由 QAbilityStage 拉起并显示
6. 运行时库(Qt / 插件)如何放置
Native .so 需放置在 OHOS 约定目录:
- entry/libs/<abi>/
至少需要保证以下库被打包进 HAP:
- Qt OHOS QPA:libqohos.so
- Qt 依赖库:libQt5Core.so、libQt5Gui.so、libQt5Widgets.so 等
- 应用库:libcalculator.so
判断依赖缺失的方法: 运行时日志中通常会出现:
- dlopen failed
- cannot locate symbol
- cannot load ...so
---
7. 将 Calculator 替换为你的 Qt 应用
最小操作步骤:
- 将你的 Qt 源码放入 entry/src/main/cpp/(或子目录)
- 修改 entry/src/main/cpp/CMakeLists.txt:
- 更新 PROJECT_SOURCES
- find_package() 增加所需模块(如 Network、Quick)
- 保证生成库名与 APP_LIBRARY_NAME 一致
- 将所需 Qt 运行时 .so / 插件复制到 entry/libs/<abi>/