@qidiandasheng
2021-02-28T15:54:03.000000Z
字数 4870
阅读 3237
Flutter
Flutter 作为一个跨平台,高性能的移动开发框架,通过Skia绘制引擎对UI进行渲染,可以用于快速地构建iOS和Android应用。如果想要深入的学习或者进行定制操作,那么就会对Flutter源码进行编译构建。
Flutter源码分为两个部分:
flutter/flutter
是框架层,为开发者提供各种接口,主要是dart代码。flutter/engine
是引擎层,负责Flutter的渲染以及宿主的交互。flutter/flutter可以直接通过git下载:
$ mkdir flutter_source_code
$ cd flutter_source_code
$ flutter_source_code git clone https://github.com/flutter/flutter.git
在~/.bash_profile或~/.zshrc添加镜像和路径的环境变量配置:
//前两个是镜像地址,后面的`/flutter/bin:$PATH`是你clone的仓库地址,这里默认就是在你当前的系统路径中
export PUB_HOSTED_URL=https://pub.flutter-io.cn
export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn
export PATH=~/flutter_source_code/flutter/bin:"$PATH"
运行 flutter doctor
运行以下命令查看是否需要安装其它依赖项来完成安装:
flutter doctor
查看版本
//进入目录
$ cd /Users/dasheng/Work/flutter_source_code/flutter/bin/internal
$ cat engine.version
2c144c3eeb4b25fd78b90dd3e2a24c36f4201021
flutter/engine
需要通过gclient
工具获取,因为engine
有很多依赖,gclient
可以很好地处理这些依赖,简化源码管理流程。
拉取depot_tools工具
$ git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
设置环境变量
//也可编辑 ~/.bashrc或者 ~/.zshrc
$ export PATH=~/depot_tools:"$PATH"
创建源码目录
$ flutter_source_code mkdir engine
$ flutter_source_code cd engine
配置文件
在engine目录下创建.gclient文件用于同步源码
$ engine touch .gclient
solutions = [
{
"managed": False,
"name": "src/flutter",
"url": "git@github.com:flutter/engine.git",
"custom_deps": {},
"deps_file": "DEPS",
"safesync_url": "",
},
]
如果想指定flutter engine revision
,则可以配置url加入@revision
solutions = [
{
"managed": False,
"name": "src/flutter",
"url": "git@github.com:flutter/engine.git@2c144c3eeb4b25fd78b90dd3e2a24c36f4201021",
"custom_deps": {},
"deps_file": "DEPS",
"safesync_url": "",
},
]
开始拉取代码(这一步比较耗时)
$ engine gclient sync
brew install ant
brew install ninja
Flutter Engine
是基于Ninja进行构建的,Ninja是Google为了改进编译速度而开发出来的,Chromium目前也是通过Ninja进行构建的,由此看来,Flutter在工程上借鉴了很多Chromium的东西。
Flutter Engine的构建产物总体上有以下几种组合,对于编译参数可以参考Compiling the engine · flutter/flutter Wiki:
是否优化(默认为optimized) | 运行模式 |
---|---|
unoptimized | debug |
optimized | debug |
unoptimized | profile |
optimized | profile |
unoptimized | release |
optimized | release |
对于Andorid来说,有arm,arm64,x86和x86_64的产物区分,默认为arm,对于iOS来说,有arm,arm64的产物区分,默认为arm64。iOS还有模拟器的产物(使用--simulator参数)。
除了设备端的产物,Host端(即PC)也需要编译出产物与之对应。Host端的产物是Android和iOS共用的,因此无需重复编译。
具体的所有组合可以参考 Flutter’s Mode
为了避免出现问题,Flutter Engine
下flutter
版本最好跟flutter/flutter
里的版本一致,以下方法查看版本:
//进入目录
$ cd /Users/dasheng/Work/flutter_source_code/flutter/bin/internal
$ cat engine.version
2c144c3eeb4b25fd78b90dd3e2a24c36f4201021
//.gclient文件
solutions = [
{
"managed": False,
"name": "src/flutter",
"url": "git@github.com:flutter/engine.git@2c144c3eeb4b25fd78b90dd3e2a24c36f4201021",
"custom_deps": {},
"deps_file": "DEPS",
"safesync_url": "",
},
]
//开始同步
$ gclient sync
cd /path/to/engine/src/flutter
git reset --hard 2c144c3eeb4b25fd78b90dd3e2a24c36f4201021
gclient sync --with_branch_heads --with_tags --verbose
MacOS debug 未优化版本(模拟器和真机都使用的这个)
cd /engine/src/
./flutter/tools/gn --unoptimized
ninja -C out/host_debug_unopt
iOS arm64未优化release版本
cd /engine/src/
./flutter/tools/gn --ios --unoptimized --runtime-mode=release
ninja -C out/ios_release_unopt -j 8
iOS arm优化profile版本
cd /engine/src/
./flutter/tools/gn --ios --ios-cpu=arm --runtime-mode=profile
ninja -C out/ios_profile_arm -j 8
iOS 模拟器未优化版本
cd /engine/src/
./flutter/tools/gn --ios --simulator --unoptimized
ninja -C out/ios_debug_sim_unopt -j 8
通过ninja
编译得到最后的产物Flutter.framework
,Flutter.framework
即为 Flutter Engine
部分的代码,由 C++ 编译而成。
$ flutter create hello_world
使用flutter并指定本地engine运行(不指定则会拉远程的、已经构建好的engine)
flutter run --local-engine-src-path /Users/dasheng/Work/flutter_source_code/engine/src --local-engine=ios_debug_sim_unopt
我们用xcode打开工程能看到xcconfig
里增加了两个值:
在Build Phases
能看到运行了Flutter
里的脚本代码:
在脚本中我们能看到使用了xcconfig
里设置的两个值来获取到本地engine
进行设置使用:
需要安装C/C++
与CodeLLDB
这两个插件,正常安装即可。
Flutter engine
源码使用VSCode打开engine/src/flutter
目录下的Flutter engine
源码
调试模式下添加Configuration
,会新增一个launch.json
文件,内容如下
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "lldb",
"request": "attach",
"name": "Debug",
"pid": "65018"
}
]
}
pid获取:在通过flutter run
运行起app之后,通过ps aux | grep dasheng
(dasheng是我的用户名)获取到当前用户所有的进程,全局搜索Runner.app
(flutter创建的工程默认app名),即可得到当前app的pid。
在Engine::BeginFrame
下添加断点,每次app数字点击+的时候断点就会执行:
以下为网上版本说需要添加调试信息(可能是Android需要)
{
//add-dsym 添加符号表
//settings set target.source-map源代码和符号路径作一个关联
"version": "0.2.0",
"configurations": [
{
"type": "lldb",
"request": "attach",
"name": "Debug",
"pid": "28448",
"initCommands": [
"platform select ios-simulator",
"platform connect 2F66A886-28CA-44DD-9B41-4DC06E540D68"
],
"postRunCommands": [
"add-dsym /Users/dasheng/Work/flutter_source_code/engine/src/out/ios_debug_sim_unopt/libFlutter.dylib",
"settings set target.source-map /Users/dasheng/Work/flutter_source_code/engine/src/out/ios_debug_sim_unopt /Users/dasheng/Work/flutter_source_code/engine/src"
]
}
]
}
Flutter Engine 编译指北
Flutter Engine源码调试
Flutter源码剖析(一):源码获取与构建
调试Flutter Native Engine初探