HarmonyOS 6.1 云应用客户端适配实战(一):环境搭建与编译系统
前言
随着 HarmonyOS 生态的快速发展,越来越多的应用需要从 Android 平台迁移到 HarmonyOS。本系列文章将以一个真实的云应用客户端项目为例,详细记录从 Android 到 HarmonyOS 6.1 的完整适配过程。
项目背景:
- 原项目是一个基于 WebSocket 的云桌面/云应用客户端
- 使用 C++ 实现核心功能(视频解码、网络通信、输入处理)
- Android 端使用 JNI 封装,HarmonyOS 需要改用 N-API
- 依赖多个第三方库:OpenSSL、FFmpeg、Protobuf、Poco、Boost 等
本文作为系列第一篇,重点介绍环境搭建和编译系统的适配工作。
一、开发环境准备
1.1 工具链安装
必需工具:
# HarmonyOS NDK(包含在 DevEco Studio 中)路径:D:\Program Files\Huawei\DevEco Studio\sdk\default\openharmony\native# CMake 3.16+# Ninja 构建工具# Python 3.x(用于构建脚本)关键环境变量:
exportOHOS_SDK_NATIVE=/path/to/ohos/nativeexportPATH=$OHOS_SDK_NATIVE/llvm/bin:$PATH1.2 工具链特点
HarmonyOS NDK 使用的是LLVM/Clang工具链,与 Android NDK 类似,但有几个关键差异:
| 特性 | Android NDK | HarmonyOS NDK |
|---|---|---|
| 编译器 | Clang (Android 定制) | Clang (OpenHarmony) |
| 标准库 | libc++ | libc++ |
| 目标三元组 | aarch64-linux-android | aarch64-linux-ohos |
| 系统根目录 | sysroot | sysroot |
重点注意:目标架构名称的差异会影响到第三方库的交叉编译。
二、CMake 配置适配
2.1 平台识别
首先需要在 CMakeLists.txt 中添加 HarmonyOS 平台的识别:
# 检测 HarmonyOS 平台 if(CMAKE_SYSTEM_NAME STREQUAL "OHOS") set(OHOS_PLATFORM ON) add_definitions(-DOHOS -DOHOS_PLATFORM) message(STATUS "Building for HarmonyOS platform") endif()2.2 编译器和链接器配置
if(OHOS_PLATFORM) # 设置编译器 set(CMAKE_C_COMPILER "${OHOS_SDK_NATIVE}/llvm/bin/clang") set(CMAKE_CXX_COMPILER "${OHOS_SDK_NATIVE}/llvm/bin/clang++") # 设置 sysroot set(CMAKE_SYSROOT "${OHOS_SDK_NATIVE}/sysroot") # 目标架构 set(CMAKE_SYSTEM_PROCESSOR aarch64) # 编译选项 add_compile_options( --target=aarch64-linux-ohos --sysroot=${CMAKE_SYSROOT} -D__MUSL__ ) # 链接选项 add_link_options( --target=aarch64-linux-ohos --sysroot=${CMAKE_SYSROOT} ) endif()2.3 条件编译宏的使用
在代码中需要大量使用条件编译来区分平台:
// 平台检测示例#ifdefined(OHOS)||defined(OHOS_PLATFORM)// HarmonyOS 特定代码#include<native_window/external_window.h>#include<hilog/log.h>#elifdefined(__ANDROID__)// Android 特定代码#include<android/native_window.h>#include<android/log.h>#elifdefined(_WIN32)// Windows 特定代码#include<windows.h>#endif最佳实践:
- 使用
#if defined(OHOS) || defined(OHOS_PLATFORM)而不是#ifdef OHOS - 在 CMake 中同时定义两个宏,确保兼容性
- 关键分支点添加日志,便于排查条件编译错误
三、第三方库交叉编译
3.1 OpenSSL 编译
OpenSSL 是网络通信的基础库,编译步骤:
# 配置./Configure linux-aarch64\--prefix=/path/to/install\--cross-compile-prefix=aarch64-linux-ohos-\CC=clang\--sysroot=$OHOS_SDK_NATIVE/sysroot\no-shared\no-tests# 编译make-j8makeinstall关键点:
- 使用
linux-aarch64配置(没有专门的 ohos 配置) - 必须指定
--cross-compile-prefix - 建议编译静态库(
no-shared)
3.2 FFmpeg 编译
FFmpeg 是视频解码的核心库,配置较为复杂:
./configure\--prefix=/path/to/install\--enable-cross-compile\--cross-prefix=aarch64-linux-ohos-\--arch=aarch64\--target-os=linux\--cc=clang\--cxx=clang++\--sysroot=$OHOS_SDK_NATIVE/sysroot\--extra-cflags="--target=aarch64-linux-ohos"\--extra-ldflags="--target=aarch64-linux-ohos"\--disable-shared\--enable-static\--disable-programs\--disable-doc\--enable-decoder=h264\--enable-decoder=hevc\--enable-parser=h264\--enable-parser=hevcmake-j8makeinstall重点配置说明:
--target-os=linux:HarmonyOS 内核基于 Linux,使用 linux 配置--extra-cflags和--extra-ldflags:必须显式指定目标三元组- 裁剪配置:只编译需要的解码器,减小体积
3.3 Protobuf 编译
Protobuf 用于消息序列化,需要注意宿主机和目标机的兼容性:
# 第一步:编译宿主机版本(用于生成代码)mkdirbuild-hostcdbuild-host cmake..-DCMAKE_INSTALL_PREFIX=/path/to/protobuf-hostmake-j8makeinstall# 第二步:交叉编译目标版本mkdirbuild-ohoscdbuild-ohos cmake..\-DCMAKE_SYSTEM_NAME=OHOS\-DCMAKE_C_COMPILER=clang\-DCMAKE_CXX_COMPILER=clang++\-DCMAKE_SYSROOT=$OHOS_SDK_NATIVE/sysroot\-DCMAKE_C_FLAGS="--target=aarch64-linux-ohos"\-DCMAKE_CXX_FLAGS="--target=aarch64-linux-ohos"\-Dprotobuf_BUILD_TESTS=OFF\-DCMAKE_INSTALL_PREFIX=/path/to/protobuf-ohosmake-j8makeinstall为什么需要两个版本?
- 宿主机版本的
protoc用于在编译时生成.pb.cc和.pb.h文件 - 目标版本的
libprotobuf.a用于链接到最终的 HarmonyOS 应用中
3.4 Poco 编译
Poco 是一个 C++ 网络库,用于 HTTP 和 WebSocket 通信:
mkdirbuild-ohoscdbuild-ohos cmake..\-DCMAKE_SYSTEM_NAME=Linux\-DCMAKE_C_COMPILER=clang\-DCMAKE_CXX_COMPILER=clang++\-DCMAKE_SYSROOT=$OHOS_SDK_NATIVE/sysroot\-DCMAKE_C_FLAGS="--target=aarch64-linux-ohos"\-DCMAKE_CXX_FLAGS="--target=aarch64-linux-ohos -std=c++17"\-DENABLE_NETSSL_WIN=OFF\-DENABLE_NETSSL=ON\-DENABLE_CRYPTO=ON\-DENABLE_TESTS=OFF\-DCMAKE_INSTALL_PREFIX=/path/to/poco-ohosmake-j8makeinstall注意事项:
CMAKE_SYSTEM_NAME使用Linux而不是OHOS- 需要启用
ENABLE_NETSSL和ENABLE_CRYPTO支持 HTTPS - 关闭测试以加快编译速度
四、主项目 CMake 配置
4.1 第三方库集成
# 设置第三方库路径 set(THIRD_PARTY_DIR "${CMAKE_SOURCE_DIR}/3rdparty") if(OHOS_PLATFORM) set(OPENSSL_ROOT "${THIRD_PARTY_DIR}/openssl-ohos") set(FFMPEG_ROOT "${THIRD_PARTY_DIR}/ffmpeg-ohos") set(PROTOBUF_ROOT "${THIRD_PARTY_DIR}/protobuf-ohos") set(POCO_ROOT "${THIRD_PARTY_DIR}/poco-ohos") endif() # 添加头文件路径 include_directories( ${OPENSSL_ROOT}/include ${FFMPEG_ROOT}/include ${PROTOBUF_ROOT}/include ${POCO_ROOT}/include ) # 链接库 link_directories( ${OPENSSL_ROOT}/lib ${FFMPEG_ROOT}/lib ${PROTOBUF_ROOT}/lib ${POCO_ROOT}/lib )4.2 源文件组织
# 公共源文件 set(COMMON_SOURCES src/cloud_client.cc src/net/control_client.cc src/FFmpegDecoder.cpp # ... 其他公共文件 ) # 平台特定源文件 if(OHOS_PLATFORM) set(PLATFORM_SOURCES src/gles/GLViewOHOS.cpp src/gles/GLViewBase.cpp # ... HarmonyOS 特定文件 ) elseif(ANDROID) set(PLATFORM_SOURCES src/gles/GLViewAndroid.cpp # ... Android 特定文件 ) endif() # 创建静态库 add_library(cloudappclient STATIC ${COMMON_SOURCES} ${PLATFORM_SOURCES} )4.3 链接配置
if(OHOS_PLATFORM) target_link_libraries(cloudappclient # 系统库 ace_napi.z hilog_ndk.z native_window EGL GLESv3 # 第三方库(注意顺序) PocoNetSSL PocoNet PocoCrypto PocoFoundation ssl crypto avcodec avutil swscale protobuf pthread dl z ) endif()链接顺序很重要:
- 依赖关系:PocoNetSSL → PocoNet → PocoCrypto → OpenSSL
- 错误的顺序会导致符号未定义错误
五、常见问题与解决方案
5.1 找不到系统头文件
错误信息:
fatal error: 'hilog/log.h' file not found解决方案:
# 显式添加系统头文件路径 include_directories( ${OHOS_SDK_NATIVE}/sysroot/usr/include )5.2 链接时未定义符号
错误信息:
undefined reference to `OH_NativeWindow_CreateNativeWindowFromSurfaceId'解决方案:
# 确保链接了正确的系统库 target_link_libraries(your_target native_window # 注意:不是 native_window.z )5.3 C++ 标准库问题
错误信息:
error: no member named 'make_unique' in namespace 'std'解决方案:
# 设置 C++ 标准为 17 或更高 set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON)5.4 OpenSSL 版本兼容
如果第三方库(如 Poco)依赖特定版本的 OpenSSL,需确保:
# 查看依赖的 OpenSSL 版本strings libPocoNetSSL.a|grep"OpenSSL"# 编译时指定 OpenSSL 路径cmake..\-DOPENSSL_ROOT_DIR=/path/to/openssl-3.x\-DOPENSSL_INCLUDE_DIR=/path/to/openssl-3.x/include\-DOPENSSL_LIBRARIES="/path/to/openssl-3.x/lib/libssl.a;/path/to/openssl-3.x/lib/libcrypto.a"六、构建脚本示例
为了简化编译流程,建议编写自动化脚本:
#!/bin/bash# build_ohos.shset-e# 环境变量exportOHOS_SDK_NATIVE="/path/to/ohos/native"exportPATH=$OHOS_SDK_NATIVE/llvm/bin:$PATH# 创建构建目录BUILD_DIR="build_ohos_arm64"rm-rf$BUILD_DIRmkdir$BUILD_DIRcd$BUILD_DIR# 配置cmake..\-DCMAKE_SYSTEM_NAME=OHOS\-DCMAKE_SYSTEM_PROCESSOR=aarch64\-DCMAKE_C_COMPILER=clang\-DCMAKE_CXX_COMPILER=clang++\-DCMAKE_SYSROOT=$OHOS_SDK_NATIVE/sysroot\-DCMAKE_C_FLAGS="--target=aarch64-linux-ohos"\-DCMAKE_CXX_FLAGS="--target=aarch64-linux-ohos -std=c++17"\-DCMAKE_BUILD_TYPE=Release\-GNinja# 编译ninja-j8# 复制输出文件cpapi/libdlca_cloudapp.so../output/echo"Build completed successfully!"七、总结
本文介绍了 HarmonyOS 6.1 云应用客户端适配的第一步:环境搭建和编译系统配置。关键要点:
- 工具链理解:HarmonyOS NDK 基于 LLVM,目标三元组为
aarch64-linux-ohos - CMake 配置:正确设置编译器、sysroot 和目标架构
- 第三方库编译:需要单独交叉编译每个依赖库
- 条件编译:使用宏区分不同平台的代码路径
- 链接顺序:注意库的依赖关系,避免符号未定义
下一篇预告:
在完成编译系统配置后,下一篇将深入介绍视频渲染的适配,包括 Native Window API 的使用、EGL 初始化、OpenGL ES 纹理渲染等核心功能的实现。
参考资料
- HarmonyOS NDK 开发指南
- CMake Cross Compiling
- FFmpeg Compilation Guide
作者:Frame Not Work
日期:2026年6月
系列文章:HarmonyOS 6.1 云应用客户端适配实战
