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": "git@github.com: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里可以自由调试~~ 待写

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

相关推荐
孤鸿玉3 小时前
Fluter InteractiveViewer 与ScrollView滑动冲突问题解决
flutter
叽哥9 小时前
Flutter Riverpod上手指南
android·flutter·ios
BG1 天前
Flutter 简仿Excel表格组件介绍
flutter
zhangmeng1 天前
FlutterBoost在iOS26真机运行崩溃问题
flutter·app·swift
恋猫de小郭1 天前
对于普通程序员来说 AI 是什么?AI 究竟用的是什么?
前端·flutter·ai编程
卡尔特斯1 天前
Flutter A GlobalKey was used multipletimes inside one widget'schild list.The ...
flutter
w_y_fan1 天前
Flutter 滚动组件总结
前端·flutter
醉过才知酒浓1 天前
Flutter Getx 的页面传参
flutter
火柴就是我2 天前
flutter 之真手势冲突处理
android·flutter
Speed1232 天前
`mockito` 的核心“打桩”规则
flutter·dart