[关闭]
@qidiandasheng 2021-02-28T15:54:03.000000Z 字数 4870 阅读 3237

Flutter Engine源码编译(😁)

Flutter


介绍

Flutter 作为一个跨平台,高性能的移动开发框架,通过Skia绘制引擎对UI进行渲染,可以用于快速地构建iOS和Android应用。如果想要深入的学习或者进行定制操作,那么就会对Flutter源码进行编译构建。

Flutter源码分为两个部分:

环境

源码下载

flutter/flutter

flutter/flutter可以直接通过git下载:

  1. $ mkdir flutter_source_code
  2. $ cd flutter_source_code
  3. $ flutter_source_code git clone https://github.com/flutter/flutter.git

在~/.bash_profile或~/.zshrc添加镜像和路径的环境变量配置:

  1. //前两个是镜像地址,后面的`/flutter/bin:$PATH`是你clone的仓库地址,这里默认就是在你当前的系统路径中
  2. export PUB_HOSTED_URL=https://pub.flutter-io.cn
  3. export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn
  4. export PATH=~/flutter_source_code/flutter/bin:"$PATH"

运行 flutter doctor

运行以下命令查看是否需要安装其它依赖项来完成安装:

  1. flutter doctor

查看版本

  1. //进入目录
  2. $ cd /Users/dasheng/Work/flutter_source_code/flutter/bin/internal
  3. $ cat engine.version
  4. 2c144c3eeb4b25fd78b90dd3e2a24c36f4201021

flutter/engine

flutter/engine需要通过gclient工具获取,因为engine有很多依赖,gclient可以很好地处理这些依赖,简化源码管理流程。

拉取depot_tools工具

  1. $ git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git

设置环境变量

  1. //也可编辑 ~/.bashrc或者 ~/.zshrc
  2. $ export PATH=~/depot_tools:"$PATH"

创建源码目录

  1. $ flutter_source_code mkdir engine
  2. $ flutter_source_code cd engine

配置文件

engine目录下创建.gclient文件用于同步源码

  1. $ engine touch .gclient
  1. solutions = [
  2. {
  3. "managed": False,
  4. "name": "src/flutter",
  5. "url": "git@github.com:flutter/engine.git",
  6. "custom_deps": {},
  7. "deps_file": "DEPS",
  8. "safesync_url": "",
  9. },
  10. ]

如果想指定flutter engine revision,则可以配置url加入@revision

  1. solutions = [
  2. {
  3. "managed": False,
  4. "name": "src/flutter",
  5. "url": "git@github.com:flutter/engine.git@2c144c3eeb4b25fd78b90dd3e2a24c36f4201021",
  6. "custom_deps": {},
  7. "deps_file": "DEPS",
  8. "safesync_url": "",
  9. },
  10. ]

开始拉取代码(这一步比较耗时)

  1. $ engine gclient sync

安装ant和ninja

  1. brew install ant
  2. 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 Engineflutter版本最好跟flutter/flutter里的版本一致,以下方法查看版本:

  1. //进入目录
  2. $ cd /Users/dasheng/Work/flutter_source_code/flutter/bin/internal
  3. $ cat engine.version
  4. 2c144c3eeb4b25fd78b90dd3e2a24c36f4201021
  1. //.gclient文件
  2. solutions = [
  3. {
  4. "managed": False,
  5. "name": "src/flutter",
  6. "url": "git@github.com:flutter/engine.git@2c144c3eeb4b25fd78b90dd3e2a24c36f4201021",
  7. "custom_deps": {},
  8. "deps_file": "DEPS",
  9. "safesync_url": "",
  10. },
  11. ]
  12. //开始同步
  13. $ gclient sync
  1. cd /path/to/engine/src/flutter
  2. git reset --hard 2c144c3eeb4b25fd78b90dd3e2a24c36f4201021
  3. gclient sync --with_branch_heads --with_tags --verbose

构建MacOS产物

MacOS debug 未优化版本(模拟器和真机都使用的这个)

  1. cd /engine/src/
  2. ./flutter/tools/gn --unoptimized
  3. ninja -C out/host_debug_unopt

构建iOS引擎产物

iOS arm64未优化release版本

  1. cd /engine/src/
  2. ./flutter/tools/gn --ios --unoptimized --runtime-mode=release
  3. ninja -C out/ios_release_unopt -j 8

iOS arm优化profile版本

  1. cd /engine/src/
  2. ./flutter/tools/gn --ios --ios-cpu=arm --runtime-mode=profile
  3. ninja -C out/ios_profile_arm -j 8

iOS 模拟器未优化版本

  1. cd /engine/src/
  2. ./flutter/tools/gn --ios --simulator --unoptimized
  3. ninja -C out/ios_debug_sim_unopt -j 8

最后生成的产物

通过ninja编译得到最后的产物Flutter.frameworkFlutter.framework 即为 Flutter Engine 部分的代码,由 C++ 编译而成。

截屏2021-02-07 上午11.28.53.png-161.6kB

源码使用

创建工程

  1. $ flutter create hello_world

指定本地engine运行

使用flutter并指定本地engine运行(不指定则会拉远程的、已经构建好的engine)

  1. flutter run --local-engine-src-path /Users/dasheng/Work/flutter_source_code/engine/src --local-engine=ios_debug_sim_unopt

我们用xcode打开工程能看到xcconfig里增加了两个值:

截屏2021-02-07 上午11.15.10.png-425kB

Build Phases能看到运行了Flutter里的脚本代码:

截屏2021-02-07 上午11.17.51.png-82.4kB

在脚本中我们能看到使用了xcconfig里设置的两个值来获取到本地engine进行设置使用:

截屏2021-02-07 上午11.20.11.png-353kB

调试

下载插件

需要安装C/C++CodeLLDB这两个插件,正常安装即可。

截屏2021-02-06 下午12.16.03.png-351.4kB

截屏2021-02-06 下午12.16.20.png-238.4kB

打开Flutter engine源码

使用VSCode打开engine/src/flutter目录下的Flutter engine源码

attach到app进程调试

截屏2021-02-06 下午12.01.06.png-433.1kB

调试模式下添加Configuration,会新增一个launch.json文件,内容如下

  1. {
  2. // Use IntelliSense to learn about possible attributes.
  3. // Hover to view descriptions of existing attributes.
  4. // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
  5. "version": "0.2.0",
  6. "configurations": [
  7. {
  8. "type": "lldb",
  9. "request": "attach",
  10. "name": "Debug",
  11. "pid": "65018"
  12. }
  13. ]
  14. }

pid获取:在通过flutter run运行起app之后,通过ps aux | grep dasheng(dasheng是我的用户名)获取到当前用户所有的进程,全局搜索Runner.app(flutter创建的工程默认app名),即可得到当前app的pid。

开始调试

Engine::BeginFrame下添加断点,每次app数字点击+的时候断点就会执行:

截屏2021-02-06 下午12.10.23.png-253.9kB

网上版本

以下为网上版本说需要添加调试信息(可能是Android需要)

  1. {
  2. //add-dsym 添加符号表
  3. //settings set target.source-map源代码和符号路径作一个关联
  4. "version": "0.2.0",
  5. "configurations": [
  6. {
  7. "type": "lldb",
  8. "request": "attach",
  9. "name": "Debug",
  10. "pid": "28448",
  11. "initCommands": [
  12. "platform select ios-simulator",
  13. "platform connect 2F66A886-28CA-44DD-9B41-4DC06E540D68"
  14. ],
  15. "postRunCommands": [
  16. "add-dsym /Users/dasheng/Work/flutter_source_code/engine/src/out/ios_debug_sim_unopt/libFlutter.dylib",
  17. "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"
  18. ]
  19. }
  20. ]
  21. }

参考

Flutter Engine 编译指北
Flutter Engine源码调试
Flutter源码剖析(一):源码获取与构建
调试Flutter Native Engine初探

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注