ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Flutter编译开发HarmonyOS环境搭建:从零到跑通的完整指南

Flutter编译开发HarmonyOS环境搭建:从零到跑通的完整指南 训练营进行到Day3我总算把Flutter编译开发HarmonyOS的环境真正跑通了。在开源鸿蒙这个方向上前两天大多在理解系统能力、熟悉IDE界面、跑预置Demo到了Day3才轮到自己动手搭建一套能用的跨平台开发环境——这一环卡住的人相当多网上资料又比较分散。我这篇文章就把整条搭建链路、版本选型、踩过的坑和排查思路完整记录下来给后面准备做开源鸿蒙Flutter开发的读者提供一份可以直接照抄的参考。这篇文章适合两类人一类是刚接触开源鸿蒙、想用Flutter做跨平台应用的开发者另一类是已经装了一半环境、被各种报错卡住不知道怎么往下走的人。我会尽量把每一步都讲清楚包括为什么要这样做、出问题时从哪个方向排查而不是只贴几个命令让你盲目复制。1. 热身准备训练营Day3到底要解决什么问题1.1 为什么是Day3才真正动手装环境训练营前两天的任务更偏认知层面了解开源鸿蒙的系统架构、理解应用开发的不同范式、知道IDE里各个面板是干什么的。真正把开发环境落到自己机器上反而放到了第三天我认为是有意设计的——先让每个人对系统有个整体认识再进入环境搭建遇到问题时不至于完全懵。Day3的目标非常明确让一个Flutter工程能够编译成开源鸿蒙的hap包并且成功运行在模拟器或真机上。这不是跑一个hello world就完事而是要打通Flutter代码 - Dart运行时 - Flutter引擎 - 鸿蒙系统能力这条链路。环境搭建本质上是在为这条链路准备所有环节的翻译官和通行证。我在Day3开始前其实已经踩过一次坑。当时图省事直接从Flutter官网下载了官方SDK结果执行flutter doctor的时候完全没有鸿蒙相关选项花了一下午才意识到问题出在SDK选型上。这一点我放在下一节重点讲因为它是整个环境搭建中最容易被忽略、又最致命的起点。1.2 我准备的硬件与前置工具清单先把配置要求说清楚。训练营助教给的官方建议是内存16GB以上、磁盘剩余空间80GB以上我实际体验下来如果是Mac或者内存达到32GB的Windows机器整个过程会舒服很多。模拟器启动和Flutter首次编译都是吃资源的大户8GB内存的机器跑起来会非常吃力频繁卡顿容易让人误判是环境问题。需要准备的前置工具如下工具版本要求用途操作系统Windows 10/11、macOS、Ubuntu 20.04开发宿主机环境Node.js16.x LTS 或更高工具链依赖、部分脚本执行JDK17编译鸿蒙应用所需的Java运行时Git2.30拉取Flutter分支SDK、工程管理官方IDE训练营指定的稳定版本鸿蒙SDK管理、签名配置、模拟器运行注意Node.js和JDK都要提前确认版本。有些坑表面上出在Flutter侧实际是Node.js版本太老导致脚本执行异常或者JDK版本太高触发编译工具的不兼容问题。我的建议是不要追求最新版本尽量用训练营或者官方文档明确验证过的版本组合。2. 版本矩阵与工具链选型环境搭建里最容易翻车的起点2.1 Flutter官方SDK和鸿蒙分支SDK的差别这是我认为Day3最大的坑也是最多人栽跟头的地方。开源鸿蒙对Flutter的支持并不是直接集成在官方Flutter SDK里的而是由社区维护了一套fork版本。也就是说你不能从flutter.dev下载官方SDK然后指望它认识鸿蒙设备。官方SDK认识的是Android和iOS它不知道鸿蒙的设备协议、不知道hdc工具、更不知道hap打包规范。鸿蒙分支SDK做的事情是在Flutter框架层增加一个ohos平台的嵌入式实现同时把构建链路的产物从apk/aab转成hap。这套实现目前还处在快速演进阶段不同分支、不同时间点拉下来的代码差异会很大。我当时拿到的版本组合大致是这样Flutter fork版本基于3.x分支配合开源鸿蒙4.x的系统SDKIDE侧也要求一个对应版本。训练营统一提供了版本号我建议不要自己去翻最新版因为Flutter的fork仓库更新很快新版本可能引入新依赖也可能跟IDE不兼容。记录好自己使用的组合后面排查问题会省很多事。2.2 SDK、IDE、Node.js的版本搭配建议版本搭配这件事我画不出严格的依赖树但可以给出一组亲测稳定的组合参考组件推荐版本备注Flutter fork SDK基于Flutter 3.x的鸿蒙分支从开源鸿蒙社区指定仓库克隆开源鸿蒙SDK4.x Release版本与系统镜像保持同一大版本IDE官方稳定版版本号需与SDK配套Node.js16.20.x 或 18.x LTS太低或太高都会有兼容性问题JDK17不要用JDK 21或更高这里有个很关键的原则开源鸿蒙系统镜像、SDK、IDE三者要保持同一个大版本。比如你烧录的设备是4.x版本开发环境的SDK也应该是4.xIDE也要选择支持4.x的版本。跨大版本混用是最常见的报错来源而且报错信息往往不会直接告诉你版本不匹配而是以各种奇怪的形式出现比如构建失败、签名失败、设备连接不稳定等。2.3 理解编译开发HarmonyOS的整条工具链环境搭建本质上是让链路上的每个环节互相认识。我借用快递物流来类比Flutter代码是包裹Dart运行时负责打包Flutter引擎是运输车鸿蒙系统是收货方。环境搭建要做的就是让运输车Flutter引擎模块适配收货方的仓库标准鸿蒙API并且在运输路径上贴好正确的地址标签签名证书。具体到技术层面Flutter应用跑在鸿蒙上需要经过这么几层Flutter框架层你的Dart代码调用Widget等UI能力。Flutter引擎层负责Dart运行时、渲染、事件处理这部分需要用C编译成鸿蒙系统可以加载的so库。嵌入层EmbedderFlutter引擎和鸿蒙系统之间的适配层负责创建窗口、处理生命周期、对接输入事件。鸿蒙应用框架层最终的hap包通过系统Ability机制启动把Flutter内容嵌入到鸿蒙应用的页面中。理解了这条链路你就会明白几个现象为什么首次编译特别慢因为引擎层需要从头编译C代码。为什么有时候改了Dart代码也要重新构建so因为嵌入层的接口可能随版本变化。为什么环境变量配置错了会报一些看起来跟Flutter无关的错误因为构建脚本需要通过环境变量定位SDK路径找不到路径时会把错误抛给下游的编译工具。3. 从零搭建从空目录到Flutter应用跑上模拟器3.1 基础依赖安装Node.js、JDK、Git这一步我没遇到太多问题但还是把要点记录下来。Node.js在Windows和macOS下都有安装包直接一路默认即可。需要注意的只有一点安装时选对LTS版本不要选Current版本。有些自动化脚本对Node的API有依赖Current版本虽然更新反而可能触发兼容问题。JDK方面我安装了JDK 17。这一步有个容易踩的坑机器上可能已经装过其它版本的JDK多个JDK同时存在时终端里执行的java -version和你以为的版本不一致。我建议在安装完成后单独开一个终端执行java -version确认输出的版本是17。如果不对检查系统的JAVA_HOME环境变量是否指向了正确路径。在macOS上可能还要留意系统自带的旧版Java工具链对PATH的干扰。Git的安装比较简单Windows用户注意选择从命令行使用Git的安装选项这样后续在终端里直接执行git命令不会找不到。装完之后顺手配置一下用户信息避免提交代码时被卡住git config --global user.name yourname git config --global user.email youexample.com3.2 安装IDE并补齐SDK组件接下来安装鸿蒙开发IDE。这里我不提具体品牌名就说官方的鸿蒙开发工具。安装好IDE之后首次启动会引导你下载SDK组件包括系统SDK、平台工具、命令行工具等。这一步强烈建议全部下载完整不要只装基础部分否则后面编译会缺各种组件。IDE安装完成后命令行工具hdc会被放在SDK目录下。hdc就是鸿蒙设备调试工具类比Android平台的adb后面连接模拟器、安装hap包都要靠它。SDK默认安装路径在不同系统上不一样Windows一般在用户目录下的AppData相关路径macOS在用户目录下的Library目录。建议把这个路径记下来配置环境变量时要用。训练营里有个同学因为没把hdc所在目录加进PATH导致Flutter构建脚本找不到设备白白折腾了几小时。我在后面章节会专门写这个问题。3.3 获取Flutter鸿蒙分支SDK并创建项目这一步是整个环境搭建的核心。先克隆flutter仓库的指定分支。我没有用官方仓库用的是开源鸿蒙社区维护的fork仓库。训练营给的命令大概是这样git clone https://gitee.com/openharmony-sig/flutter_flutter.git -b dev这里要强调一下分支名会随着社区迭代变化我建议以你参加的训练营或开源鸿蒙sig组的最新文档为准。克隆出来的目录会很大因为Flutter SDK本身包含引擎源码、第三方依赖等磁盘空间预留充足。克隆完成后需要配置环境变量。我整理了一张环境变量的说明表不同系统下配置方式略有区别但变量名是通用的环境变量用途示例值PATH让终端能找到flutter、hdc、node等命令加入flutter/bin、hdc目录FLUTTER_ROOT告诉Flutter工具链自己的位置/path/to/flutter_flutterOHOS_SDK_HOME定位鸿蒙SDKIDE中SDK的安装路径配置好之后新开终端执行flutter doctor如果一切正常输出里会出现ohos或鸿蒙相关的检查项。我给个建议flutter doctor第一次执行时可能触发下载或初始化多跑几次等输出稳定了再做判断。创建项目同样很简单flutter create --platforms ohos my_first_ohos_app注意--platforms参数要指定ohos。如果这个参数在你的版本上不生效检查一下当前flutter分支是否支持。有些老分支只支持android和ios平台这也是版本选型时的一个判断依据。3.4 首次构建与模拟器运行构建之前先启动一个模拟器。IDE自带的模拟器管理器里可以创建不同类型的设备镜像选择与SDK版本匹配的镜像启动。启动之后打开一个终端验证设备是否被识别hdc list targets输出能列出设备序列号说明hdc与模拟器通信正常。然后运行flutter run -d ohos首次构建的时间会比较长通常在10到30分钟不等主要取决于机器性能和网络状况。构建过程会先编译Flutter引擎再编译Dart代码最后打包成hap并部署到模拟器。我在等待过程中一度怀疑是不是卡住了实际上只是慢。这里提醒一下不要因为构建日志暂时没动静就中断进程多等五分钟再决定。如果一切顺利模拟器上会出现Flutter应用的默认页面终端也会输出Dart DevTools调试地址。为了节省时间我建议首次运行时不加--debug参数以外的额外选项先跑通再说。4. 训练营实测中的五大问题完整排查链路复盘这一节是全文的重头戏。Day3现场几乎每个人都遇到了至少两三个问题我把训练营里高频出现的问题整理成排查链路按我的经验和最终的解决方法逐条展开。4.1 问题一flutter doctor不识别鸿蒙设备现象执行flutter doctor后输出里完全没有ohos相关条目设备列表也是空的。看起来像是Flutter根本不认识鸿蒙。排查链路第一步先确认flutter的版本来源。执行flutter --version如果输出的Machine或渠道信息显示来自官方稳定分支基本可以断定问题出在SDK选型。我用官方SDK的时候这里显示的是stable渠道而flutter doctor压根不会检查鸿蒙环境。第二步检查环境变量是否生效。在终端里执行echo $FLUTTER_ROOT如果是空的说明环境变量没有配置成功。问题可能出在配置了但没开新终端、或者配置到了错误的shell配置文件中。第三步确认Flutter分支的仓库地址。进入Flutter SDK目录执行git remote -v如果remote指向的是github.com/flutter/flutter那就是官方仓库如果指向社区fork仓库说明分支选对了。最终解决方法切换到社区fork版本重新配置环境变量清空Flutter缓存后再次执行flutter doctor。清空缓存用flutter clean这一步能重置很多奇怪的中间状态。4.2 问题二编译时提示缺NDK或CMake版本不匹配现象flutter run执行到原生编译阶段突然报错提示找不到NDK或者CMake版本低于要求。排查链路先看完整报错信息不要只看第一行。报错里通常会给出具体路径和最低版本要求。我遇到的是CMake 3.20.0 or higher is required而系统里的CMake是3.18。第一次遇到时我直接手动装了新版本CMake结果发现构建脚本走的路径跟系统PATH还不一致继续报错。后来才明白鸿蒙SDK自带了一套Native编译工具链构建脚本优先使用SDK内置的工具而不是系统PATH里的工具。解决思路分三步在IDE的SDK管理器中检查是否安装了Native工具组件。如果缺失下载并安装。如果SDK内置的CMake版本不符合要求再去考虑编译环境变量或修改构建配置。训练营里这个问题的解决方案是在IDE中把Native工具更新到SDK要求的版本。不要轻易卸载系统的CMake多个版本共存是可以的关键是构建脚本能不能找到正确的那个。4.3 问题三环境变量改了但终端不生效现象已经设置了FLUTTER_ROOT、OHOS_SDK_HOME等变量但新开的终端执行echo还是为空甚至flutter命令依然提示找不到。排查链路Windows和macOS的表现不一样分开说。Windows上最常见的两个原因一是没有重新打开终端环境变量修改后当前窗口不会自动刷新二是受Windows系统字符编码影响环境变量里的路径包含非ASCII字符导致解析异常。我建议路径尽量全用英文不要放在用户名为中文的目录下面。macOS上问题一般出在配置文件上。如果用的是zsh需要把export写入~/.zshrc如果用的是bash要写~/.bash_profile或~/.bashrc。很多人改了文件但忘记执行source或者把配置写在了错误的文件中导致新终端也无法加载。排查链路里最实用的一步是用短命令验证还是长命令验证。比如echo $OHOS_SDK_HOME输出为空时再用env | grep OHOS确认变量是否存在。如果env里有但echo没有说明当前shell的解释器路径有问题检查当前用的到底是bash还是zsh。4.4 问题四模拟器能启动但应用装不上现象hdc list targets能看到模拟器flutter run也显示设备在线但构建完成后的安装阶段报错提示签名验证失败。排查链路这个问题的根源通常不在代码而在签名证书。开源鸿蒙系统对hap包有签名校验机制模拟器虽然不像真机那么严格但开发调试证书如果没有正确配置安装阶段依然会失败。我当时的报错信息是install signature verify fail第一反应是系统镜像问题还重新刷了一次模拟器镜像毫无作用。后来训练营助教提醒我检查IDE中的签名配置我这才发现自己的调试证书信息没有关联到当前的工程。正确的做法是在IDE中生成开发调试证书然后在项目的配置文件build-profile相关配置中填入证书信息。证书生成时需要提供指纹信息IDE一般会引导完成。配置完之后重新执行flutter clean并重新构建问题才真正解决。这里提醒一句如果换了一台电脑继续开发原来的证书文件可能失效需要重新生成。训练营里有同学就是因为换了机器证书没有迁移卡在了同样的问题上。4.5 问题五首次构建依赖拉取超时现象构建过程中长时间停留在downloading或fetching状态然后直接超时失败。表现最明显的是Gradle依赖和npm依赖的拉取。排查链路第一步确认网络状态。如果是公共网络或者企业网络可能对某些仓库的访问不稳定这是很常见的事不代表你的配置有问题。第二步检查镜像配置。开源鸿蒙生态在构建时会访问多个仓库国内开发者一般会配置镜像源加速。配置方式是在工程或者用户目录下增加相关的源配置比如npm组件的registry、Gradle的仓库镜像等。第三步如果修改了配置注意清理已经下载的缓存。缓存的半成品很可能导致旧的错误信息反复出现。我后来用了一个比较稳的配置方式把所有依赖仓库相关的地址统一换成训练营提供的镜像地址同时在构建命令前面加长超时时间。这个操作让整个构建过程顺利了很多。需要说明一点改镜像地址并不代表绕过任何合规限制它就是普通的软件源配置操作在开源生态里非常常见开发者可以使用可选的软件源来加速代码和依赖下载。5. 让环境更稳的收尾操作训练营课后的检查清单5.1 一键自检脚本与输出解读环境搭建完成后我写了一个简单的自检脚本每次开始开发前先跑一遍能快速发现环境是否被改动过#!/bin/bash echo Flutter version flutter --version | head -n 2 echo Flutter doctor flutter doctor echo hdc targets hdc list targets echo SDK env echo OHOS_SDK_HOME$OHOS_SDK_HOME echo FLUTTER_ROOT$FLUTTER_ROOT输出解读有一个小技巧每次的输出单独保存成一个日志文件命名带上日期。我坚持做了一个多星期发现系统的SDK、IDE出现过自动更新的情况更新之后部分配置就偏离了预期。有了日志对比程序报错时我能立刻判断是环境变化导致的还是代码本身的问题。5.2 清理与重编译的正确姿势环境出问题时很多人第一反应是把整个项目目录删掉重新clone这是最笨的方法而且容易引入新的问题。正确的清理姿势只清理Flutter构建产物flutter clean清理鸿蒙侧构建产物在工程目录下执行hvigor的清理命令清理系统里的缓存组件根据报错信息定位到具体的缓存目录精准删除千万不要上来就删整个SDK目录或整个Flutter SDK那会让你重新走一遍所有网络下载流程。训练营里有人因为反复失败把flutter_flutter目录删了两次直接浪费了整整一个晚上。5.3 我保留的一组推荐配置和调试建议环境稳定之后我把几组关键配置记录在了自己的笔记里供后续使用配置项我的设置说明设备调试方式模拟器优先不需要额外刷机失败成本低构建模式debug首次跑通前不要折腾releaseDart分析开启flutter analyze 能提前暴露问题工程拆分单模块训练营阶段切忌拆分过多模块排查麻烦调试方面我最常用的命令是flutter logs这个命令会持续输出应用运行时的日志。模拟器上的应用如果闪退看这套日志通常能直接定位到具体是哪一行代码出了问题。环境搭建阶段如果应用闪退优先看是不是证书失效或者系统镜像版本不对不要直接往代码的问题上想。最后分享一个个人习惯每次改动环境配置之后我都会先跑一遍第5.1节里的自检脚本确认基础环境没问题再开始写代码。环境问题如果不解决就强行编译反复出现的会是最折磨人的错误信息不断变化但项目毫无进展的状态。训练营第三天真正让我收获的其实是这套先自查环境、再怀疑代码的排查思路后面几天写应用时这个思路帮我省下了大量时间。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进