概念
Flutter Engine使用GN和Ninja進(jìn)行編譯,GN編譯后生成Ninja的構(gòu)建文件,Ninja將輸入文件編譯成最終產(chǎn)物。
- depot_tools:一個工具包,包含gclient,gn和ninja等工具
- ninja:是google推出的注重速度的構(gòu)建工具,將編譯任務(wù)并行組織,大大提高構(gòu)建速度
- gclient:代碼獲取工具,是google推出的用于管理多源項(xiàng)目所編寫的腳本,可以將多個源碼管理系統(tǒng)中的代碼放在一起管理。甚至包括將git和svn代碼放在一起管理。
- .gclient文件是gclient的控制文件,是一個pythone腳本,格式如下:
solutions = [
{
//checkout出源碼的名字
"name" : "src",
//源碼所在的目錄
"url" : "svn://svnserver/component/trunk/src",
//這是一個文件名(不包括路徑),指在工程目錄中包含依賴列表的文件,該項(xiàng)為可選,默認(rèn)值為"DEPS"
"deps_file" :"DEPS"
//這是一個可選的字典對象,會覆蓋工程的"DEPS"文件定義的條目
"custom_deps" : {
# To use the trunk of a component instead of what's in DEPS:
#"component": "https://svnserver/component/trunk/",
# To exclude a component from your working copy:
#"data/really_large_component": None,
}
},
]
工具準(zhǔn)備
- git
- ssh
- curl , unzip (
gclient sync需要) - xcode
- python --version 2.7版本
- depot_tools
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
export PATH=$PATH:/path/to/depot_tools
工程準(zhǔn)備
- 配置ssh https://help.github.com/articles/generating-ssh-keys/
image.png
圖例我加了兩個key,此處只需要一個就行 - fork https://github.com/flutter/engine 到自己的git倉庫
image.png git clone <你的git上fork的engine地址>- engine目錄下vim .gclient
solutions = [
{
"managed": False,
"name": "src/flutter",
"url": "git@github.com:<your_name_here>/engine.git",
"custom_deps": {},
"deps_file": "DEPS",
"safesync_url": "",
},
]
- engine目錄下
gclient sync獲取Flutter依賴的所有源代碼 - 進(jìn)入src/flutter目錄
cd src/flutter
git remote add upstream git@github.com:flutter/engine.git
//關(guān)聯(lián)到`flutter/engine`以獲取master更新
git pull upstream master
版本匹配
- 找到當(dāng)前flutter對應(yīng)的engine版本
cat /Users/heq/flutter/bin/internal/engine.version
我這里顯示的是b863200c37df4ed378042de11c4e9ff34e4e58c9
- 進(jìn)入engine/src/flutter目錄,將這里的flutter版本跟上一步的版本保持一致
git reset --hard b863200
當(dāng)前環(huán)境查看
heq-Mac:flutter heq$ git rev-parse HEAD
b863200c37df4ed378042de11c4e9ff34e4e58c9
heq-Mac:flutter heq$ flutter --version
Flutter 1.9.1+hotfix.2 ? channel stable ? https://github.com/flutter/flutter.git
Framework ? revision 2d2a1ffec9 (3 months ago) ? 2019-09-06 18:39:49 -0700
Engine ? revision b863200c37
Tools ? Dart 2.5.0
- 拉取數(shù)據(jù)
Checkout all the submodules at their branch DEPS revisions.
gclient sync --with_branch_heads --with_tags
編譯構(gòu)建
切換到engine/src目錄
usage: gn [-h] [--unoptimized] [--runtime-mode {debug,profile,release}]
[--dynamic] [--interpreter] [--dart-debug]
[--target-os {android,ios,linux}] [--android]
[--android-cpu {arm,x64,x86,arm64}] [--ios] [--ios-cpu {arm,arm64}]
[--simulator] [--linux-cpu {x64,x86,arm64,arm}]
[--arm-float-abi {hard,soft,softfp}] [--goma] [--no-goma] [--lto]
[--no-lto] [--clang] [--no-clang] [--target-sysroot TARGET_SYSROOT]
[--target-toolchain TARGET_TOOLCHAIN]
[--target-triple TARGET_TRIPLE]
[--toolchain-prefix TOOLCHAIN_PREFIX]
[--operator-new-alignment OPERATOR_NEW_ALIGNMENT] [--enable-vulkan]
[--embedder-for-target] [--coverage] [--out-dir OUT_DIR]
通過GN進(jìn)行的預(yù)編譯生成Ninja的構(gòu)建文件,除了預(yù)編譯指定平臺的構(gòu)建文件之外,還需要預(yù)編譯Host的構(gòu)建文件(即PC編譯平臺的),當(dāng)通過Ninja進(jìn)行最終產(chǎn)物的編譯時,會用到指定平臺的構(gòu)建文件和Host的構(gòu)建文件進(jìn)行編譯
# unopt-debug
# prepare build files for device-side executables.
./flutter/tools/gn --unoptimized --android --runtime-mode debug --android-cpu arm
./flutter/tools/gn --unoptimized --android --runtime-mode debug --android-cpu arm64
./flutter/tools/gn --unoptimized --android --runtime-mode debug --android-cpu x64
# prepare the build files for host-side executables.
./flutter/tools/gn --unoptimized --runtime-mode debug --android-cpu arm
./flutter/tools/gn --unoptimized --runtime-mode debug --android-cpu arm64
./flutter/tools/gn --unoptimized --runtime-mode debug --android-cpu x64
ninja -C out/android_debug_unopt
ninja -C out/android_debug_unopt_arm64
ninja -C out/android_debug_unopt_x64
ninja -C out/host_debug_unopt
ninja -C out/host_debug_unopt_arm64
ninja -C out/host_debug_unopt_x64
# unopt-profile
./flutter/tools/gn --unoptimized --android --runtime-mode profile --android-cpu arm
./flutter/tools/gn --unoptimized --android --runtime-mode profile --android-cpu arm64
./flutter/tools/gn --unoptimized --android --runtime-mode profile --android-cpu x64
./flutter/tools/gn --unoptimized --runtime-mode profile --android-cpu arm
./flutter/tools/gn --unoptimized --runtime-mode profile --android-cpu arm64
./flutter/tools/gn --unoptimized --runtime-mode profile --android-cpu x64
ninja -C out/android_profile_unopt
ninja -C out/android_profile_unopt_arm64
ninja -C out/android_profile_unopt_x64
ninja -C out/host_profile_unopt
ninja -C out/host_profile_unopt_arm64
ninja -C out/host_profile_unopt_x64
# unopt-release
./flutter/tools/gn --unoptimized --android --runtime-mode release --android-cpu arm
./flutter/tools/gn --unoptimized --android --runtime-mode release --android-cpu arm64
./flutter/tools/gn --unoptimized --android --runtime-mode release --android-cpu x64
./flutter/tools/gn --unoptimized --runtime-mode release --android-cpu arm
./flutter/tools/gn --unoptimized --runtime-mode release --android-cpu arm64
./flutter/tools/gn --unoptimized --runtime-mode release --android-cpu x64
ninja -C out/android_release_unopt
ninja -C out/android_release_unopt_arm64
ninja -C out/android_release_unopt_x64
ninja -C out/host_release_unopt
ninja -C out/host_release_unopt_arm64
ninja -C out/host_release_unopt_x64
# opt-debug
./flutter/tools/gn --android --runtime-mode debug --android-cpu arm
./flutter/tools/gn --android --runtime-mode debug --android-cpu arm64
./flutter/tools/gn --android --runtime-mode debug --android-cpu x64
./flutter/tools/gn --runtime-mode debug --android-cpu arm
./flutter/tools/gn --runtime-mode debug --android-cpu arm64
./flutter/tools/gn --runtime-mode debug --android-cpu x64
ninja -C out/android_debug
ninja -C out/android_debug_arm64
ninja -C out/android_debug_x64
ninja -C out/host_debug
ninja -C out/host_debug_arm64
ninja -C out/host_debug_x64
# opt-profile
./flutter/tools/gn --android --runtime-mode profile --android-cpu arm
./flutter/tools/gn --android --runtime-mode profile --android-cpu arm64
./flutter/tools/gn --android --runtime-mode profile --android-cpu x64
./flutter/tools/gn --runtime-mode profile --android-cpu arm
./flutter/tools/gn --runtime-mode profile --android-cpu arm64
./flutter/tools/gn --runtime-mode profile --android-cpu x64
ninja -C out/android_profile
ninja -C out/android_profile_arm64
ninja -C out/android_profile_x64
ninja -C out/host_profile
ninja -C out/host_profile_arm64
ninja -C out/host_profile_x64
# opt-release
./flutter/tools/gn --android --runtime-mode release --android-cpu arm
./flutter/tools/gn --android --runtime-mode release --android-cpu arm64
./flutter/tools/gn --android --runtime-mode release --android-cpu x64
./flutter/tools/gn --runtime-mode release --android-cpu arm
./flutter/tools/gn --runtime-mode release --android-cpu arm64
./flutter/tools/gn --runtime-mode release --android-cpu x64
ninja -C out/android_release
ninja -C out/android_release_arm64
ninja -C out/android_release_x64
ninja -C out/host_release
ninja -C out/host_release_arm64
ninja -C out/host_release_x64
Tips: ninja 可使用&&,如:
ninja -C out/android_release && ninja -C out/host_release
gn操作后目錄結(jié)構(gòu):

nginx操作后內(nèi)容:

This builds a debug-enabled ("unoptimized") binary configured to run Dart in checked mode ("debug"). There are other versions, see Flutter's modes.
官方wiki上給出的例子
set -ex
cd ~/dev/engine/src/flutter
git fetch upstream
git rebase upstream/master
gclient sync
cd ..
flutter/tools/gn --unoptimized --runtime-mode=debug
flutter/tools/gn --android --unoptimized --runtime-mode=debug
flutter/tools/gn --android --runtime-mode=profile
flutter/tools/gn --android --runtime-mode=release
cd out
find . -mindepth 1 -maxdepth 1 -type d | xargs -n 1 sh -c 'ninja -C $0 || exit 255'
heq-Mac:out heq$ find . -mindepth 1 -maxdepth 1 -type d
./host_debug_unopt
./android_profile
./android_debug_unopt
./android_release
find命令: -type d 表示目錄
xargs命令:可以將管道或標(biāo)準(zhǔn)輸入(stdin)數(shù)據(jù)轉(zhuǎn)換成命令行參數(shù),也能夠從文件的輸出中讀取數(shù)據(jù)。-n num 后面加次數(shù),表示命令在執(zhí)行的時候一次用的argument的個數(shù),默認(rèn)是用所有的。
使用方式
- flutter run --local-engine-src-path /Users/heq/engine/src --local-engine=android_debug_unopt
- 替換掉flutter目錄中的engine
/Users/heq/flutter/bin/cache/artifacts/engine
使用校驗(yàn)
- 修改/Users/heq/engine/src/flutter/shell/platform/android/io/flutter/app/FlutterActivity.java部分代碼:
@Override
protected void onCreate(Bundle savedInstanceState) {
System.out.println("FlutterActivity.onCreate in Engine!!");
super.onCreate(savedInstanceState);
eventDelegate.onCreate(savedInstanceState);
}
- 編譯engine
- 新建工程,然后使用
flutter run --local-engine-src-path /Users/heq/engine/src --local-engine=android_debug_unopt運(yùn)行,每次啟動FlutterActivity,logcat打印
com.example.t_flutter_app I/System.out: FlutterActivity.onCreate in Engine!!
證明engine中的修改生效了
調(diào)試engine中的Android代碼
- 導(dǎo)入
engine/src/flutter/shell/platform/android作為新的工程 - 確認(rèn)Engine SDK Version和Java Version
File > Project Structure > Project Settings > Project
image.png - 可選:代碼關(guān)聯(lián)
File > Project Structure > Modules消除Missing import錯誤提示。主要是關(guān)聯(lián)engine/src/third_party/android_support
image.png -
在engine android工程中所需位置設(shè)上斷點(diǎn)
image.png - 使用
flutter run --local-engine-src-path /Users/heq/engine/src --local-engine=android_debug_unopt運(yùn)行項(xiàng)目工程 -
在engine android工程中attach debugger對應(yīng)的項(xiàng)目工程,即可斷點(diǎn)成功
image.png
image.png
參考:手把手教你編譯Flutter engine
Compiling the engine
Flutter Engine與SDK的定制化與編譯
Contributing to the Flutter engine
Debugging the engine






