您现在的位置是:首页 >技术教程 >Flutter - 搭建引擎调试环境(iOS)网站首页技术教程

Flutter - 搭建引擎调试环境(iOS)

crasowas 2024-06-17 10:19:00
简介Flutter - 搭建引擎调试环境(iOS)


前言

刚开始学Flutter开发时搭建过,没有记录。现在有需要时又忘了,果然好记性不如烂笔头。

注意,调试环境搭建会占用较大硬盘空间。粗略统计,Flutter引擎项目(包含依赖的第三方库)约20GB,host_debug_unopt构建编译后约16GB,ios_debug_xxx构建编译后约5GB。所以如果想搭建成功,至少需要准备41GB的剩余硬盘空间。

开发环境

  • macOS: 13.3.1
  • Flutter: 3.7.12
  • Xcode: 14.3

安装依赖环境

1. python3

后续很多工具依赖python环境,如果执行python3命令失败,那么需要先安装python3。可以通过官网下载安装或brew命令安装:

brew install python

安装过程可能会遇到这样的问题:

Error: python@3.11: the bottle needs the Apple Command Line Tools to be installed.
  You can install them, if desired, with:
    xcode-select --install

执行xcode-select --install命令安装Xcode命令行工具解决。

2. depot_tools

depot_tools是Chromium的源码管理工具,后续获取源码和构建编译都需要用到。

安装流程:

  1. 切换到想要存放的路径执行clone命令(需要代理)
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
  1. 配置环境变量

~/.bashrc~/.zshrc文件中加上:

export PATH=[存放的路径]/depot_tools:$PATH

参考文档:

获取引擎项目

Flutter的文档应先fork项目,不过那是针对贡献者的流程,如果你只是调试,可以跳过这一流程。

1. 创建engine空目录

切换到想要存放Flutter引擎源码的位置新建engine目录:

mkdir engine

2. 创建.gclient文件并配置

切换到engine目录下执行:

touch .gclient

配置.gclient文件:

solutions = [{
	"managed": False,
	"name": "src/flutter",
	"url": "git@github.com:<your_name_here>/engine.git",
	"custom_deps": {},
	"deps_file": "DEPS",
	"safesync_url": "",
}, ]

<your_name_here>请按需替换,如果没有fork引擎项目,可以替换为flutter,如果有fork,可以替换为自己的Github账户名。

如果想了解这些配置的作用,参考官方文档:gclient file

3. 指定引擎版本

前面的配置获取的是最新的Flutter引擎源码,但是Flutter引擎的调试离不开Flutter框架,如果版本不匹配可能会遇到一些问题,所以最好指定Flutter引擎版本为当前Flutter框架所需要的版本。那么这个版本怎么指定呢?

Flutter引擎版本其实就是commit id,可以在Flutter SDK目录/bin/internal/engine.version文件中获得。例如我当前电脑的Flutter版本是3.7.12engine.version文件位于/opt/homebrew/Caskroom/flutter/3.7.12/flutter/bin/internal/目录,引擎版本是:

1a65d409c7a1438a34d21b60bf30a6fd5db59314

既然Flutter引擎版本是commit id,那么就可以通过修改前面的配置指定版本。修改后:

solutions = [{
	"managed": False,
	"name": "src/flutter",
	"url": "git@github.com:<your_name_here>/engine.git@1a65d409c7a1438a34d21b60bf30a6fd5db59314",
	"custom_deps": {},
	"deps_file": "DEPS",
	"safesync_url": "",
}, ]

4. 同步引擎源码

engine目录下执行(需要代理):

gclient sync

项目有点大,大概需要下载10GB,其中很大一部分是在下载依赖的第三方库,后续编译也相当耗时。

同步成功后,engine目录下会有一个src目录,如果在这个路径下执行git log,会发现commit id好像有点不对:

commit 8747bce41d0dc6d9dc45c4d1b46d2100bb9ee688 (HEAD)
Author: Jenn Magder <magder@google.com>
Date:   Wed Nov 30 14:05:32 2022 -0800

    Sort macOS SDK paths to keep order stable between runs (#652)
...

别急,真正的引擎项目在src目录下的flutter目录。src目录中的项目是这个buildroot,用于搭建Flutter引擎的构建环境。

参考文档:

搭建调试环境

1. 构建编译

注意,以下所有命令都在engine/src目录路径下运行。

1.1 生成构建所需文件

1.1.1 主机端

flutter/tools/gn --unoptimized

生成的文件存放于engine/src/out/host_debug_unopt目录。

1.1.2 iOS端

  • 真机调试
flutter/tools/gn --ios --unoptimized

生成的文件存放于engine/src/out/ios_debug_unopt目录。

  • 模拟器调试
flutter/tools/gn --ios --simulator --unoptimized
# 如果是M系列芯片电脑,建议加上--simulator-cpu=arm64参数,用于支持arm64架构的模拟器
flutter/tools/gn --ios --simulator --simulator-cpu=arm64 --unoptimized

生成的文件存放于engine/src/out/ios_debug_sim_unoptengine/src/out/ios_debug_sim_unopt_arm64目录。

如果是M系列芯片电脑,没有加上--simulator-cpu=arm64参数,后续Xcode模拟器调试可能会遇到没有iOS设备可选择的情况:

screenshot1

解决方法:按这个步骤[Xcode菜单栏] -> [Product] -> [Destination] -> [Destination Architectures] -> [Show Both]操作,显示全部iOS模拟器。

以上只生成了Debug模式相关的文件用于后续调试,如果需要更多模式(Profile/Release等),可以参考文档Flutter’s modes或通过flutter/tools/gn -h命令了解更多用法。

1.2 完成构建编译

  • 真机调试
ninja -C out/ios_debug_unopt && ninja -C out/host_debug_unopt
  • 模拟器调试
ninja -C out/ios_debug_sim_unopt && ninja -C out/host_debug_unopt
# 如果前面使用了--simulator-cpu=arm64参数
ninja -C out/ios_debug_sim_unopt_arm64 && ninja -C out/host_debug_unopt

首次构建编译比较耗时,CPU会满载(电脑买来这么久一直没转过的风扇终于了有表现的机会?)。后面调试过程中,如果修改了源码需要重新执行构建编译命令。如果文件有增删,需要重新执行前面生成构建所需文件的命令。

参考文档:

2. Xcode调试

准备一个用于调试的Flutter项目,以下命令都在该项目目录路径下执行。

2.1 设置本地引擎

官方文档Debugging iOS builds with Xcode是通过flutter build命令设置:

flutter build ios --local-engine ios_debug_unopt --config-only

这种方式对于模拟器调试不是那么好用,所以我选择flutter run命令,设置项目本地引擎后还会运行一遍项目,在后续用Xcode调试时还能提前避免一些问题。

flutter run --local-engine=ios_debug_xxx --local-engine-src-path=/xxx/engine/src -d xxx
  • --local-engine:设置本地引擎名称,例如真机调试为ios_debug_unopt,模拟器调试为ios_debug_sim_unoptios_debug_sim_unopt_arm64
  • --local-engine-src-path:设置本地引擎源路径,engine/src目录所在的绝对路径
  • -d:指定要运行的设备名称,例如模拟器iPhone 8(名称有空格时需要转义或加单/双引号)

如果Flutter项目的入口文件路径不是默认的,需要追加-t xxx参数;如果有使用多环境配置,那可能需要追加--flavor xxx参数。

设置成功后,Flutter项目下的ios/Flutter/Generated.xcconfig文件会增加以下设置:

FLUTTER_ENGINE=/xxx/engine/src
LOCAL_ENGINE=ios_debug_xxx

2.2 导入引擎项目

  1. 检查Xcode项目是否存在工作空间

如果用于调试的Flutter项目不存在ios/Runner.xcworkspace文件,可以先随意依赖一个Flutter插件库,然后执行前面的flutter run ...命令快速创建工作空间。注意,不能用Android Studio直接运行Flutter项目,否则项目本地引擎设置会被重置。

  1. 导入引擎项目到工作空间(任选一种方式)
  • 简单拖拽

用Xcode打开用于调试的Flutter项目(打开ios/Runner.xcworkspace文件),将ios_debug_xxx目录下的flutter_engine.xcodeproj文件拖到Xcode的左侧项目导航区:

screenshot2

  • 修改配置

选中ios/Runner.xcworkspace文件,右键显示包内容即可找到contents.xcworkspacedata配置文件。打开后增加一条FileRef配置:

<?xml version="1.0" encoding="UTF-8"?>
<Workspace version = "1.0">
   ...
   <FileRef
      location = "group:/xxx/engine/src/out/ios_debug_xxx/flutter_engine.xcodeproj">
   </FileRef>
</Workspace>

以上两种方式本质是一样的。到此,准备工作都做完了,可以开始调试啦?!

2.3 测试调试功能

先找个地方打断点,从AppDelegate.swift文件的FlutterAppDelegate可以来到引擎项目,在这打断点肯定会进到调试:

screenshot3

使用Xcode运行项目一切正常,成功进入调试:

screenshot4

如果调试过程中发现变量列表显示不全,可以将左下角的筛选项Auto改为All

screenshot5

最后

如果这篇文章对你有所帮助,请不要吝啬你的点赞?加星?,谢谢~

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。