主要步骤说明:
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等。
depot_tools
集合了我们所用到的所有编译工具,包括:python
、gclient
、ninja
等。
使用以下代码克隆一份 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
flutter-engine 源码地址:https://github.com/flutter/engine。
使用浏览器打开,然后 fork 一份到自己的仓库,方便以后管理。
接着给自己的 git 仓库配置 ssh,以便通过 ssh 访问自己 fork 的 flutter-engine。
只有 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
目录下。
代码准备好之后,接下来就需要使用 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 命令说明:
需要注意一点是: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
说明:
depot_tools
工具包里面有 python 2.7;
使用 gn
生成编译配置文件之后,接下来就可以使用 ninjia
来编译了。
clarkwain@ClarkdeMacBook-Pro src % pwd
/Users/clarkwain/engine/src
clarkwain@ClarkdeMacBook-Pro src % ninja -C out/ios_debug_unopt
说明:
前面说了,主机平台是一定要编译的(不然没有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_unopt
、out/ios_debug_unopt
、out/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呢?请看下面。
上面编译好 Flutter Engine 之后,就可以通过使用 Flutter tools 在编译我们App项目的时候指定为我们编译出来的 Flutter Engine 了。
先创建一个 Flutter App 工程:
flutter create --platforms=android,ios flutter_engine_test
cd flutter_engine_test
说明:
local.properties
中配置 ndk.src=/path/to/ndk
,指定 NDK
的路径
接着将手机连接上电脑,设为调试模式,在 App 目录执行以下命令开始编译和运行。
flutter run --local-engine-src-path /Users/clarkwain/engine/src --local-engine=android_debug_unopt
说明:
运行结果:
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
上面的一切似乎都成功了,那么如何验证编译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 确实生效了。
平时开发都是在 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
.
.
.
.