2025 Flutter Engine Source Setup

2025 Flutter Engine Source Setup

我的学习笔记以及感悟还有一些小坑,仅供参考~ 北京有岗位内推的练习我啊~~~🤣


Fltter 开发团队的核心成员大都有Chromium项目工作经验,所以在Flutter源码获取的过程中,都或多或少的看到Chromium的影子。

Flutter在软件设计上是一个可灵活扩展的分层架构,每个组件功能都是以库的形式存在,每个库都依赖下一层的库。

这样设计的好处是让框架的每一个组件都变得可插拔、可替换。作为一个跨平台框架,对服用和移植到其它平台非常合适。

💡

插入一个题外话~看到这张图,是不是有中似曾相似的感觉,在看《Android的第一行代码》《UNIX编程艺术》等,甚至OSI七层模型,相信其他系统在书本中也有类似架构,和Flutter的分层架构设计大同小异。在《UNIX编程艺术》对这种设计有一个贴切的称呼:**正交性。由于正交性存在,OSI模型才会有各种协议(如运输层的TCP UDP) **

自底向上的简要分析下每一层:

Embedder:

Embedder顾名思义,将Flutter嵌入到Native平台,如iOS,Android, Windows ,Linux,所以每个平台上,都会包含一个特定的嵌入层。它的职责是渲染UI到Surface【一块可以被GPU渲染显示到区域,FlutterUI渲染最终都会输出到Surface上,Embedder负责创建和管理Surface,不同平台实现方式不同,Flutter Engine通过Skia绘制UI到Surface,然后由操作系统合成并显示到屏幕上】、处理单机事件等与底层平台交互行为提供一个入口。Embedder使用的编程语言与特定平台有关,比如Android 使用Java和C++, iOS 和 macOS 使用 Swift 和 Objective-C/Objective-C++,Windows 和 Linux 则使用 C++。

Engine:

Flutter的核心部分,大部分代码是C++,包装成Dart代码,这个库是最底层的原语 主要职责是图形绘制,文字渲染,文件/玩过IO,无障碍支持,平台插件,Dart运行时管理和编译器工具链等。主要通过dart:ui暴露给Flutter框架层进行双向交互。

Framework:

通常我们只需要关注Framework层。这一层由Dart语言开发。提供现代、响应式的UI框架。这一层也是分层的。

**Foundation & Animation & Painting & Gestures: **

提供公用底层能力,对engine的抽象和封装

**Render: **

主要负责Render Tree的Layout操作等,最终将绘制指令发送给Engine进行绘制。通过这一层,可以构建一个可渲染对象的树结构==》 Render Tree。

**Widgets: **

对上一层Render的上层分装,Render Tree虽然能够决定最终UI,但是过于复杂,不适合开发使用,Widgets则通过组合思想,提供了丰富的widgets组件,供开发者使用。 Render层中每个渲染对象在这一层都有对应的类。wigets层可以自由组合需要复用的类,这一层引入了响应式编程Reactive Programming。

**Material & Cupertino: **

这俩个组件是针对Widgets进一步封装,Widgets对于开发者来说还是很原始,这俩个组件是基于iOS和Android设计规范提供了更完备的组件,保证开发者开箱即用。

应用剖析

简单分析 flutter create 命令创建的应用结构概览,展示了 Flutter 引擎在此技术栈中的位置,标明了 API 边界,并注明了各组件所在的代码库。下方图例阐释了描述 Flutter 应用组件时常用的术语。

Dart App:

开发者自己写的UI&业务逻辑代码,使用FrameworkSDK提供的Widgets构建UI。

Owned by app developer.

一般说的是工程内****lib/** **下的代码

Framework 框架:

提供了上层API封装,构建高质量应用,例如( widget、触摸检测、手势竞技、无障碍和文字输入)。

将开发者的应用的Widgets树构建至一个Scene中,传递给下层Engine的skia处理,再传递给对应的平台

就是我们安装的SDK,**flutter/packages/flutter/lib/ **

Engine:

  • 将上层传递过来的Scene 栅格化

  • 对Flutter的核心API进行了底层封装(如图形图像,文本布局,Dart运行时)

  • 将其功能通过dart:ui暴露给上层Framework

  • 使用引擎的 Embedder API 与特定平台集成。

我们平时用到的engine都是编译好的引擎产物,位置在这里****flutter/bin/cache/artifacts/engine/ios/** **

我这里看的iOS平台的Engine框架,这里有好多平台的,MacOS 、Android。

点个模拟器平台的看一下:

用 烂苹果 看一下:

模拟器提供了俩个架构的,用file命令也可以看

看下下载的引擎源码:

红框的都属于引擎源码

Embedder:

  • 与底层操作系统协调,获取渲染表面、无障碍功能和输入等服务。

  • 管理事件循环。

  • 暴露平台特定 API,将嵌入器集成到应用中。

对应Engine源码中Embedder位置:

Runner:

  • 将嵌入器(Embedder)提供的平台特定 API 组件整合成可在目标平台上运行的应用程序包。

  • flutter create 生成的应用程序模板的一部分,归应用程序开发者所有。

  • 对应各个平台宿主的App


开始编译Engine

Flutter官方仓库

**温馨提示:在开始前,最好提前把VPN连着。 **

准备环境

要编译环境,直接从github上下载Flutter和Engine这俩个仓库是不不能构建的,因为Engine和Flutter它俩本身还依赖了很多第三方库,定义在engine根目录的DEPS文件中。

打开这个文件看一下,第一句就描述了这个文件作用

depot_tools工具下载

准备一个文件夹 ,mkdir flutter_source 创建一个空文件夹

bash 复制代码
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git

export PATH=/path/to/depot_tools:$PATH
  • 克隆下载

  • 配置环境变量

cd flutter_source 转到这个目录下:

把这个depot_tools 工具克隆在这里, 再配置下环境变量就可以用了**

配置.gclient文件

bash 复制代码
solutions = [

  {

    "managed": False,

    "name": "src/flutter", 

    "url": "[email protected]:flutter/engine.git", 

    "custom_deps": {},

    "deps_file": "DEPS", 

    "safesync_url": "",

  },

]
  • name指定仓库位置

  • url 指定要下载的仓库

  • dep_file 指定存放第三方依赖的文件名

执行gclient sync

在当前目录执行这个命令,等待下载engine以及它的依赖。执行完得等待一会,可以通过系统监视器查看当前网络状态,判断gclient执行是否正常。

在终端输出 " Syncing projects: 100%。 done" 后还会启动cipd_client下载部分大文件,直至完成。**

clone Flutter代码仓库

最后文件夹就是这些文件

  • depot工具

  • engineplay 是一个flutter工程

  • flutter 是framework sdk

  • src里就是.gclient文件配置的engine源码下载路径

匹配Engine和FlutterSDK版本

Engine是没有版本概念的,但它的CommitID可以在Flutter里看到

我当前的Flutter SDK版本对应的engine是

通过 flutter ---version也可以看到

gclient sync

**找到了这个CommitID号后,进入src/flutter目录执行 **git checkout 83bacfc525** , 把代码库恢复到这个提交,就和这个版本对应上了。 之后就可以编译了。 **

都准备好后,在 ****** **src/flutter**这个目录执行 **gclient sync ---with_branch_heads ---with_tags** **这是因为在切换提交的时候,可能DEPS可能发生改变。每次切换后都要进行同步操作。后面俩个参数表示将tag、refspecs等仓库信息一起同步。

💡

⚠️ 注意: 这里有一个坑点, 我看的好多资料,都是比较老的,我下载最新sdk 3.29.1 ,对应的Commit号:871f65ac1bf129edb222c3293a636ff4b67534a6,可能在engine源码里切换找不到这个commiID, 我猜想可能没同步, 之后会延迟FlutterSDK同步,所以我用了3.27版本。不知道之前有没有人遇到过这个。

构建准备

Flutter引擎的源码是需要通过Ninja来编译的,所以需要系统提前装好Ninja,通过brew一键安装。

而gn工具是一个生成Ninja编译所需的构建文件的元文件。

引擎部分大部分都是由C++代码组成,最终的机器码和运行平台与CPU架构是强相关的。对于不同平台,Embedder也有所不同。但是Futter已经借助Chromium工程的GN和Ninja工具链大大简化了这个构建过程。

在src目录下,需要用到这个命令 ****** **./flutter/tools/gn** ** 命令,需要加上路径,因为前边设置的depot_tools里也有gn命令。这里注意下就可以**

  • --runtime-mode {debug,profile,release,jit_release} 构建产物的类型,
  • debug日常开发,基于DartVM运行,性能较低。

  • profile 性能测试 release 正式发布 俩者都是编译成机器码,性能较高

  • --target-os {android,ios,mac,linux,fuchsia,wasm,win} 构建产物运行平台,对于Android和iOS还可以通过---android---ios指定。

  • --android-cpu {arm,x64,x86,arm64} Android产物所属的架构,通常x86用于pc模拟器,其它三种用于真机。

构建iOS产物

准备设备端可执行文件的构建文件 ./flutter/tools/gn --ios --unoptimized

bash 复制代码
 # 1. device-side executables 设备端可执行文件的构建文件 

 # 输出 out/ios_debug_unopt/flutter_engine.xcodeproj 

 ./flutter/tools/gn --ios --unoptimized # 真机debug版本

  ./flutter/tools/gn --ios --unoptimized --runtime-mode=release # 真机release版本(日常开发使用,如果我们要自定义引擎)

 # 这句是为模拟器生成元件 输出 out/ios_debug_sim_unopt_arm64

 ./flutter/tools/gn --ios --simulator --unoptimized --simulator-cpu=arm64 #模拟器版本

 # 2. host-side executables 主机端可执行文件准备构建文件

 # 输出 host_debug_unopt_arm64

 ./flutter/tools/gn --unoptimized --mac-cpu arm64 # 主机端(Mac)构建

 # 3. 

 ninja -C out/ios_debug_unopt && ninja -C out/host_debug_unopt

 ninja -C host_debug_unopt && ninja -C ios_debug_sim_unopt && ninja -C ios_debug_unopt && ninja -C ios_release_unopt

  

这是我们生成的准备元件,执行完第3行ninja -C ,接下来就是漫长的等待了。

引擎调试

首先启动一个flutter工程,flutter sdk版本指定本地

通过命令行指定编译好的engine

bash 复制代码
cd engineplay

flutter run --local-engine-src-path engine/src --local-engine=ios_debug_sim_unopt --local-engine-host host_debug_unopt_arm64

也可以在AS参数里指定

然后打开引擎源代码:

在这加一句输出

接着在AS跑个代码【前提AS配置好了自定义引擎】

说明这个工程现在依赖的是我本地编译好的引擎代码。

接下来在Xcode跑一下:

不依赖AS,直接打开项目的Runner。

在xcode里可以自由调试~~ 待写

如果有帮助,请赞,有错误请留言

相关推荐
meimeiqian3 小时前
flutter android端抓包工具
android·flutter
星释8 小时前
鸿蒙Flutter实战:18-组合而非替换,现有插件快速鸿蒙化
flutter·华为·harmonyos
一人前行8 小时前
Flutter_学习记录_AppBar中取消leading的占位展示
flutter
嘿嘿嘿呼呼嘿11 小时前
Riverpod源码分析1:Provider & ProviderFamily
flutter
zacksleo14 小时前
鸿蒙Flutter实战:20. Flutter集成高德地图,同层渲染
flutter·harmonyos
zacksleo14 小时前
鸿蒙Flutter实战:19-Flutter集成高德地图,跳转页面方式
flutter·harmonyos
A0微声z14 小时前
从0到1掌握Flutter(四)方法与类
flutter
嘿嘿嘿呼呼嘿14 小时前
Riverpod源码分析3:Provider的观察、刷新与销毁
flutter
嘿嘿嘿呼呼嘿14 小时前
Riverpod源码分析2:作用域 ProviderScope
flutter
小墙程序员16 小时前
Flutter 教程(四)包管理
flutter