Flutter Engine 编译笔记

主要步骤说明:
1、clone 一份 depot_tools 代码
2、在 github 是 fork 一份 flutter-engine 代码
3、使用 gclient 同步代码
4、使用 gn 生成编译配置文件
5、使用 ninja 编译
 
编译说明:
1、MAC OS 平台:支持编译MAC OS、 Android 和 iOS;
2、Linux 平台:支持编译 Linux、Android、Fuchsia,不支持iOS;
3、Windows平台:仅支持 Windows,不支持编译 Android、iOS、Fuchsia;
 
笔者环境:MacBook、XCode、Android Studio、Git等。
 
 

1、准备 depot_tools

 
 depot_tools 集合了我们所用到的所有编译工具,包括:pythongclientninja等。
 使用以下代码克隆一份 depot_tools 代码:

clarkwain@ClarkdeMacBook-Pro Developer %pwd
/Users/clarkwain/Developer

clarkwain@ClarkdeMacBook-Pro Developer %git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
Cloning into 'depot_tools'...
remote: Total 44718 (delta 30187), reused 44718 (delta 30187)
Receiving objects: 100% (44718/44718), 40.05 MiB | 325.00 KiB/s, done.
Resolving deltas: 100% (30187/30187), done.

 
 然后,将 depot_tools 目录添加到 PATH 环境变量。
 MAC 系统操作如下:

clarkwain@ClarkdeMacBook-Pro ~ % vim ~/.bash_profile

 
 更改 PATH 值:

export PATH=$PATH:$HOME/Developer/depot_tools

 
 保存文件并退出,接着应用修改:

clarkwain@ClarkdeMacBook-Pro ~ % source .bash_profile

2、准备 flutter-engine代码

 
 flutter-engine 源码地址:https://github.com/flutter/engine
 使用浏览器打开,然后 fork 一份到自己的仓库,方便以后管理。
 接着给自己的 git 仓库配置 ssh,以便通过 ssh 访问自己 forkflutter-engine
 

3、代码同步

 
 只有 flutter-engine 代码是无法进行编译的,因为它还依赖了 libwebp、libpng、zlib、skia 等众多第三方库,这些库在不同的 git 地址,如果手工去拉下来就很麻烦了。这时候就需要使用到 depot_tools 里面的 gclient 工具了。
 
 gclient 是 Google 推出的一个针对多仓库管理的工具,可以自动拉取所依赖的仓库。
 gclient 的配置文件是 “.gclient”,在需要存放 flutter-engine 代码的地方创建一个目录,写入以下内容:

solutions = [
  {
    
    
    "managed": False,
    "name": "src/flutter",
    "url": "[email protected]:ClarkWain/engine.git",
    "custom_deps": {
    
    },
    "deps_file": "DEPS",
    "safesync_url": "",
  },
]

   代码说明:

  • 上面的代码中,只需要把 url 的值改为你刚刚 fork 后的仓库地址就可以了。
     

   创建后,如下:

clarkwain@ClarkdeMacBook-Pro flutter_engine % pwd 
/Users/clarkwain/flutter_engine

clarkwain@ClarkdeMacBook-Pro flutter_engine % ls -a
.        ..       .gclient

clarkwain@ClarkdeMacBook-Pro flutter_engine % cat .gclient 
solutions = [
  {
    
    
    "managed": False,
    "name": "src/flutter",
    "url": "[email protected]:ClarkWain/engine.git",
    "custom_deps": {
    
    },
    "deps_file": "DEPS",
    "safesync_url": "",
  },
]

   然后在终端打开到 “.gclient” 所在目录,执行以下命令开始同步代码:

gclient sync

   这个过程比较漫长,需要1个半小时以上,差不多10G文件。中途一定不能取消、或断开网络、或休眠!!不然会很麻烦(我就重新下了一遍)。
 
   下载完成之后,如下:

clarkwain@ClarkdeMacBook-Pro src %pwd
/Users/clarkwain/engine/src

clarkwain@ClarkdeMacBook-Pro src %du -d 1 -h
1.3G	./buildtools
 76K	./tools
 12K	./gpu
  0B	./out
500M	./fuchsia
251M	./ios_tools
313M	./flutter
8.9G	./third_party
 12K	./build_overrides
8.0M	./build
 26M	./.git
 11G	.

   说明:

  • 核心代码在 engine/src 目录下。

4、生成编译配置文件

 
   代码准备好之后,接下来就需要使用 gn 工具生成编译配置文件了。
   这个 gn 工具位于 src/flutter/tools/gn。 用法如下:

clarkwain@ClarkdeMacBook-Pro src % pwd
/Users/clarkwain/engine/src

clarkwain@ClarkdeMacBook-Pro src % ./flutter/tools/gn --ios --unoptimized --no-goma
Generating GN files in: out/ios_debug_unopt
Generating Xcode projects took 80ms
Done. Made 422 targets from 187 files in 2278ms

   gn 命令说明:

  • :表示编译目录为当前主机平台(例如:mac下编译则为mac平台)
  • –ios :表示编译目标为 ios 平台;
  • –android :表示编译目标为 android 平台;
  • –android-cpu=arm64 :表示针对 android 64位;
  • –android-cpu x86 :表示针对 x86 模拟器
  • –android-cpu x64 :表示针对 x64 模拟器
  • –unoptimized :表示不做编译优化,这样可以编译速度快,而且方便进行调试;
  • –no-goma :表示不使用 goma(针对mac系统);
  • –xcode-symlinks:表示编译目标为 mac os 并且使用 goma时,需要加上这个参数;
  • –simulator:表示针对 ios 模拟器;
  • –ios-cpu=arm:表示针对 arm 架构;

 
 需要注意一点是flutter-engine 依赖 dart-sdk,而 dart-sdk 仅在目标平台为 host 的时候才会编译的,所以我们需要执行多个 gn 命令

clarkwain@ClarkdeMacBook-Pro src % ./flutter/tools/gn --unoptimized --no-goma                
Generating GN files in: out/host_debug_unopt
Generating Xcode projects took 206ms
Done. Made 739 targets from 228 files in 1199ms

clarkwain@ClarkdeMacBook-Pro src % ./flutter/tools/gn --ios --unoptimized --no-goma 
Generating GN files in: out/ios_debug_unopt
Generating Xcode projects took 87ms
Done. Made 422 targets from 187 files in 2288ms

clarkwain@ClarkdeMacBook-Pro src % ./flutter/tools/gn --android --unoptimized --no-goma
Generating GN files in: out/android_debug_unopt
Generating Xcode projects took 87ms
Done. Made 438 targets from 193 files in 2371ms

   以上生成了主机平台、Android 平台 以及 iOS 平台的编译配置文件。
   上述命令执行完之后,就可以看到当前目录下多了一个 out 目录,配置文件就在 out 目录下:

clarkwain@ClarkdeMacBook-Pro src %ls -l out 
total 34944
drwx------  78 clarkwain  staff      2496  7 19 15:19 host_debug_unopt
drwx------  25 clarkwain  staff       800  7 17 20:10 ios_debug_unopt
drwx------  37 clarkwain  staff      1184  7 18 22:55 android_debug_unopt
-rw-r--r--   1 clarkwain  staff  17029113  7 19 15:33 compile_commands.json

   对于 Windows 来说,需要添加以下系统变量:

DEPOT_TOOLS_WIN_TOOLCHAIN=0
GYP_MSVS_OVERRIDE_PATH="C:\Program Files (x86)/Microsoft Visual Studio/2019/Community"
WINDOWSSDKDIR="C:\Program Files (x86)\Windows Kits\10"

   生成编译配置文件的时候,使用以下命令:

python .\flutter\tools\gn --unoptimized --no-goma

   说明:

  • 必须要用 python2.7 才行,python3.x 会报错。前面提到的 depot_tools 工具包里面有 python 2.7;
  • Windows只能编译 host 和 web,不支持 android、ios等。

6、开始编译

   使用 gn 生成编译配置文件之后,接下来就可以使用 ninjia 来编译了。

clarkwain@ClarkdeMacBook-Pro src % pwd
/Users/clarkwain/engine/src

clarkwain@ClarkdeMacBook-Pro src % ninja -C out/ios_debug_unopt

   说明:

  • out/host_debug_unopt:表示编译目标为当前系统平台;
  • out/ios_debug_unopt:表示编译目标为 ios 平台,不使用优化;
  • out/ios_debug_sim_unopt:表示编译给模拟器使用;
  • out/out/ios_debug_unopt_arm:表示 iPhone4s及以前的设备;
  • out/android_debug_unopt:表示编译目标为 android 平台,不使用优化;
  • out/android_debug_unopt_arm64:表示编译目标为 android 64位;
  • out/android_debug_unopt_x86:表示android 32位模拟器;
  • out/android_debug_unopt_x64:表示android 64位模拟器;

 
 前面说了,主机平台是一定要编译的(不然没有dart-sdk,也就无法编译其它平台了,而且 dart-sdk更改后,需要重新编译host),可以使用组合命令编译多个目标平台(前提是先用gn文件生成对应平台的配置文件):

ninja -C & ninja -C out/ios_debug_unopt  & ninja -C out/android_debug_unopt 

   编译过程大概20~30分钟,完成之后,在 out/host_debug_unoptout/ios_debug_unoptout/android_debug_unopt 目录中可以找到编译结果文件:

clarkwain@ClarkdeMacBook-Pro src %ls out/host_debug_unopt 
 -                                       gen_snapshot
FlutterEmbedder.framework                gen_snapshot_product
FlutterEmbedder.stamp                    gyp-mac-tool
FlutterMacOS.framework                   icudtl.dat
FlutterMacOS.podspec                     jni_unittests
FlutterMacOS.stamp                       kernel-service.dart.snapshot
LICENSE                                  libEGL.dylib
accessibility_unittests                  libEGL.dylib.TOC
android_external_view_embedder_unittests libFlutterMacOS.dylib
args.gn                                  libFlutterMacOS.dylib.TOC
build.ninja                              libGLESv2.dylib
build.ninja.d                            libGLESv2.dylib.TOC
client_wrapper_glfw_unittests            libflutter_engine.dylib
client_wrapper_unittests                 libflutter_engine.dylib.TOC
common_cpp_core_unittests                no_dart_plugin_registrant_unittests
common_cpp_unittests                     obj
dart                                     platform_view_android_delegate_unittests
dart-sdk                                 runtime_unittests
dart_precompiled_runtime_product         shell_benchmarks
dartdev.dart.snapshot                    shell_unittests
dartdev.dill                             testing_unittests
dds.dart.snapshot                        tonic_unittests
embedder_proctable_unittests             toolchain.ninja
embedder_unittests                       txt_benchmarks
flow_unittests                           txt_unittests
flutter_channels_unittests               ui_benchmarks
flutter_desktop_darwin_unittests         ui_unittests
flutter_embedder.h                       vm_outline_strong.dill
flutter_engine.xcodeproj                 vm_outline_strong_product.dill
flutter_patched_sdk                      vm_outline_strong_stripped.dill
flutter_tester                           vm_platform_strong.dill
fml_benchmarks                           vm_platform_strong.dill.S
fml_unittests                            vm_platform_strong.dill.d
font-subset                              vm_platform_strong_product.dill
frontend_server.dart.snapshot            vm_platform_strong_product.dill.d
frontend_server.dart.snapshot.d          vm_platform_strong_stripped.dill
gen                                      vm_platform_strong_stripped.dill.d

clarkwain@ClarkdeMacBook-Pro src % ls out/ios_debug_unopt 
Flutter.framework                             gyp-mac-tool
Flutter.podspec                               libFlutter.dylib
Flutter.xcframework                           libFlutter.dylib.TOC
LICENSE                                       libcopy_and_verify_framework_module.dylib
args.gn                                       libcopy_and_verify_framework_module.dylib.TOC
build.ninja                                   obj
build.ninja.d                                 toolchain.ninja
clang_x64                                     vm_outline_strong.dill
flutter_engine.xcodeproj                      vm_platform_strong.dill
flutter_patched_sdk                           vm_platform_strong.dill.d
gen

clarkwain@ClarkdeMacBook-Pro src % ls out/android_debug_unopt
args.gn                                       flutter_engine.xcodeproj
armeabi_v7a_debug.jar                         flutter_icu
armeabi_v7a_debug.maven-metadata.xml          flutter_patched_sdk
armeabi_v7a_debug.pom                         gen
build.ninja                                   gyp-mac-tool
build.ninja.d                                 icudtl.dat
check_android_imports                         lib.stripped
clang_x64                                     libflutter.so
flutter.jar                                   libflutter.so.TOC
flutter_embedding_debug-sources.jar           obj
flutter_embedding_debug-sources.jar.md5.stamp toolchain.ninja
flutter_embedding_debug.jar                   vm_outline_strong.dill
flutter_embedding_debug.jar.md5.stamp         vm_platform_strong.dill
flutter_embedding_debug.maven-metadata.xml    vm_platform_strong.dill.d
flutter_embedding_debug.pom                   zip_archives

说明:

  • 在上面的编译结果文件中,有一个 flutter_engine.xcodeproj 文件,这个是 XCode的工程文件,可以直接用 XCode 打开。

 
 例如:使用 XCode 打开 ios_debug_unopt/flutter_engine.xcodeproj 如下:

在这里插入图片描述
   以后调试就可以通过上面的工程进行调试了。

   对于 Windows 系统来说,编译的命令是一样的(注意,Windows只能编译windows平台和Web平台):

ninja -C .\out\host_debug_unopt

   在 Windows 系统下编译出来的文件中,有一个文件叫 all.sln,这个是 Visual Studio 的工程文件,可以使用 Visual Studio 直接打开,方便查看和调试 Flutter Engine的代码。

PS E:\Developer\flutter-engine\src\out\host_debug_unopt> dir *.sln


    目录: E:\Developer\flutter-engine\src\out\host_debug_unopt


Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a----         2021/7/20      9:58         285709 all.sln

   那么如何在开发中使用我们编译出来的 Flutter Engine呢?请看下面。
 

7、使用自编译Flutter Engine

 
 上面编译好 Flutter Engine 之后,就可以通过使用 Flutter tools 在编译我们App项目的时候指定为我们编译出来的 Flutter Engine 了。
 
  先创建一个 Flutter App 工程:

flutter create --platforms=android,ios flutter_engine_test
cd flutter_engine_test

说明:

  • ios 平台需要在 XCode 中配置签名信息
  • android 平台需要在 local.properties 中配置 ndk.src=/path/to/ndk,指定 NDK 的路径

 
 接着将手机连接上电脑,设为调试模式,在 App 目录执行以下命令开始编译和运行。

flutter run --local-engine-src-path /Users/clarkwain/engine/src --local-engine=android_debug_unopt

   说明:

  • run :表示编译和运行App项目;
  • -local-engine-src-path :指定 Flutter Engine 的代码目录;
  • –local-engine :指定 Fluttern Engine 的目标平台。
     

   运行结果:

clarkwain@ClarkdeMacBook-Pro flutter_engine_test %flutter run --local-engine-src-path /Users/clarkwain/engine/src --local-engine=android_debug_unopt
Launching lib/main.dart on Pixel 3 in debug mode...
Running Gradle task 'assembleDebug'...                                  
Running Gradle task 'assembleDebug'... Done                         7.5s
✓  Built build/app/outputs/flutter-apk/app-debug.apk.
Installing build/app/outputs/flutter-apk/app.apk...              1,409ms

 
效果图:

 

8、修改Flutter Engine

 
 上面的一切似乎都成功了,那么如何验证编译App的时候,确实用了我们自编译的 Flutter Engine 呢?我们可以修改 Flutter Eingine ,加一些日志输出看看。
 
 使用 XCode 打开 engine/src/out/android_debug_unopt/flutter_engine.xcodeproj 工程文件。
 
 然后,打开 代码文件 engine/src/flutter/shell/common/engine.cc 源代码文件。
Engine:Run 函数中,添加以下日志输出。如下图所示:

   然后在 engine/src 目录下,重新执行以下命令进行编译:

ninja -C out/android_debug_unopt

说明:

  • 因为以前已经编译过一遍了,所以再次编译的时候,速度很快

 
 接着,重新编译并运行 App 项目:

flutter run --local-engine-src-path /Users/clarkwain/engine/src --local-engine=android_debug_unopt

 
 运行起来后,就可以看到日志输出了:
在这里插入图片描述
 如此一来,就证明我们自编译的 Flutter Engine 确实生效了。
 

9、全局配置

 
 平时开发都是在 XCode 或者 Android Studio 中进行的,如果每次都使用 flutter run 命令,就不利用调试了。此时,我们可以把 Flutter Engine 的配置作为额外参数放到 flutter run 命令中。
 
 下面以 Android Studio 为例:
 
 使用 Android Studio 打开 App 工程,然后点击 Run 菜单,选择 Edit Configuration 选项,如下,添加 Flutter Engine 的相关参数。

在这里插入图片描述
   点击 OK 保存,此时在 Android Studio 中运行 App 项目,效果如下:
在这里插入图片描述
 
   
 好了,今天的笔记就到这里了。
 
 

参考文档:
https://github.com/flutter/flutter/wiki/Setting-up-the-Engine-development-environment
https://github.com/flutter/flutter/wiki/Compiling-the-engine
https://github.com/flutter/flutter/wiki/The-flutter-tool

.
.
.
.

猜你喜欢

转载自blog.csdn.net/eieihihi/article/details/118914052