Flutter engine編譯&調(diào)試

概念

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)備

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):

image.png

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

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)是用所有的。

使用方式

  1. flutter run --local-engine-src-path /Users/heq/engine/src --local-engine=android_debug_unopt
  2. 替換掉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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容