Flutter 引擎编译、运行与调试
编译
操作步骤
- 安装
depot_tools
并添加到环境变量。gclient
来自 depot_tools 工具 - fork flutter/engine (注意配置 ssh 访问)
- 创建空的
engine
目录并在目录中创建.gclient
配置文件 - 在
engine
目录中执行gclient sync
(它会git clone
必要的项目及其依赖)
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
export PATH=/path/to/depot_tools:$PATH
mkdir engine
cd engine
touch .gclient
# edit .gclient
gclient sync
.gitclient
配置如下:
solutions = [
{
"managed": False,
"name": "src/flutter",
"url": "https://github.com/<your_name>/engine.git",
"custom_deps": {},
"deps_file": "DEPS",
"safesync_url": "",
},
]
- 切换源码。编译前的一个重要操作是将源码切换到 本地 Flutter SDK 的 engine version (一个 commit id) 对应的提交点,避免可能出现的报错
# 查看本地 Flutter SDK 引擎版本, 这个文件中是包含对应的 commit id
vim src/flutter/bin/internal/engine.version
# 调整代码
cd engine/src/flutter
git reset --hard <commit id>
gclient sync -D --with_branch_heads --with_tags
# 准备构建文件
cd engine/src
# flutter 1.12 使用以下命令生成 host_debug_unopt 编译配置
# ./flutter/tools/gn --runtime-mode debug
# flutter 1.17 使用以下命令生成 host_debug_unopt 编译配置
./flutter/tools/gn --unoptimized
# android arm (armeabi-v7a) 编译配置
./flutter/tools/gn --android --unoptimized
# android arm64 (armeabi-v8a) 编译配置
./flutter/tools/gn --android --unoptimized --runtime-mode=debug --android-cpu=arm64
# 编译
ninja -C out/host_debug_unopt -j 16
ninja -C out/android_debug_unopt -j 16
ninja -C out/android_debug_unopt_arm64 -j 16
尤其注意这里的 ninja -C out/host_debug_unopt
命令。官方文档提到它是必要的:
Note that if you use particular android or ios engine build, you will need to have corresponding host build available next to it: if you use android_debug_unopt, you should have built host_debug_unopt, android_profile -> host_profile, etc. 这个命令的编译结果包含
dart-sdk
,使用自己构建的 Flutter 引擎编译 App 时会调用dart-sdk
中相关工具。
编译完成后的目录如下:
运行
命令行中使用自定义引擎:
# 创建一个 Flutter 工程
flutter create --org com.yourdomain your_app_name
# 使用本地引擎运行 Flutter App
flutter run
--local-engine-src-path <engine path>/src
--local-engine=android_debug_unopt_arm64
IDE 中使用自定义引擎:
# 创建一个 Flutter 工程
flutter create --org com.yourdomain your_app_name
# 在 Android Studio 中打开 以上工程
# 注意这里是 Android 工程视角,即打开目录为 your_app_name/android
# 在 gradle.properties 文件中添加 localEngineOut 属性
在 gradle.properties 文件中添加 localEngineOut 属性,配置如下:
localEngineOut=<engine_dir>/out/android_debug_unopt_arm64
注意:
- 应当指定的本地引擎应当跟 Android 系统架构匹配,比如 armeabi-v8a 机器上使用
android_debug_unopt_arm64
- 尤其注意某些项目通过自行将 Flutter SDK
libflutter.so
拷贝到代码库的方式来集成 Flutter,这会导致上述方式失效,实际运行时并不会加载指定的本地引擎。解决方法是将拷贝对应的目录下(如android_debug_unopt_arm64
)的libflutter.so
覆盖代码库中已有有libflutter.so
即可
常见运行错误
最常见的问题是找不到指定的引擎导致无法运行 Flutter App。原因通常包括:
- 引擎文件路径写错
- 架构不匹配。以我手头的测试机华为 Nova 2 为例,它要求使用 arm64 类型的引擎,而我编译时没有注意到这一点,选择的是 arm 类型,最后发现引擎架构不匹配
- 缺少
host
产物。错误提示如下图
Mac 系统当然无法执行 Linux 平台的二进制文件。
调试
断点调试 Flutter 引擎来一步步观察引擎代码如何运行,是学习 Flutter 引擎代码的一个好办法。在介绍如何调试 Flutter 引擎前我们先来看看 Flutter 开发中可能遇到哪些调试场景:
- 调试 Flutter App Dart 代码
- 调试 Flutter SDK Dart 代码
- 调试 Flutter 引擎 Java 代码
- 调试 Flutter 引擎 C++ 代码
第一种场景非常简单,只要在 VS Code 中给 Flutter App 中的 Dart 代码打上断点即可进行调试。
第二种场景也比较简单,在 VS Code 中配置 Dart & Flutter 插件,允许调试第三方库和 Flutter SDK Dart 代码即可在相关源码中设置断点进行调试
调试 Java 代码
再来看第三种场景,调试 Flutter 引擎中的 Java 代码。主要是参考以下资料(建议动手操作一下):
步骤如下:
- 第一步,将
engine/src/flutter/shell/platform/android
工程(称之为Flutter 引擎工程)导入到 Android Studio。注意一定是这个目录!另外,确认该工程的 Android SDK 和 JDK 版本正确 (当前分别是 29 和 8) - 第二步,使用自定义 Flutter 引擎运行 Flutter App(称之为Flutter App 工程),具体见上文描述
- 第三步,Flutter 引擎工程 中给源码设置断点并启动 Debugger 连接到已启动的 Flutter App 进程
调试 C++ 代码
最后来看怎样调试 Flutter 引擎 C++ 代码。主要参考资料是:
转载自:https://juejin.cn/post/6989063428706926605