Flutter engine编译&调试

概念

Flutter Engine使用GN和Ninja进行编译,GN编译后生成Ninja的构建文件,Ninja将输入文件编译成最终产物。

  • depot_tools:一个工具包,包含gclient,gn和ninja等工具
  • ninja:是google推出的注重速度的构建工具,将编译任务并行组织,大大提高构建速度
  • gclient:代码获取工具,是google推出的用于管理多源项目所编写的脚本,可以将多个源码管理系统中的代码放在一起管理。甚至包括将git和svn代码放在一起管理。
  • .gclient文件是gclient的控制文件,是一个pythone脚本,格式如下:
solutions = [
{ 
//checkout出源码的名字
"name"        : "src",
//源码所在的目录
"url"         : "svn://svnserver/component/trunk/src",
//这是一个文件名(不包括路径),指在工程目录中包含依赖列表的文件,该项为可选,默认值为"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,
  }
 },
]

工具准备

  • 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

工程准备

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依赖的所有源代码
  • 进入src/flutter目录
cd src/flutter
git remote add upstream git@github.com:flutter/engine.git
//关联到`flutter/engine`以获取master更新
git pull upstream master

版本匹配

  • 找到当前flutter对应的engine版本
cat /Users/heq/flutter/bin/internal/engine.version

我这里显示的是b863200c37df4ed378042de11c4e9ff34e4e58c9

  • 进入engine/src/flutter目录,将这里的flutter版本跟上一步的版本保持一致
git reset --hard b863200

当前环境查看

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
  • 拉取数据

Checkout all the submodules at their branch DEPS revisions.

gclient sync --with_branch_heads --with_tags

编译构建

切换到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进行的预编译生成Ninja的构建文件,除了预编译指定平台的构建文件之外,还需要预编译Host的构建文件(即PC编译平台的),当通过Ninja进行最终产物的编译时,会用到指定平台的构建文件和Host的构建文件进行编译

# 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操作后目录结构:

image.png

nginx操作后内容:
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命令:可以将管道或标准输入(stdin)数据转换成命令行参数,也能够从文件的输出中读取数据。-n num 后面加次数,表示命令在执行的时候一次用的argument的个数,默认是用所有的。

使用方式

  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

使用校验

  • 修改/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 运行,每次启动FlutterActivity,logcat打印
com.example.t_flutter_app I/System.out: FlutterActivity.onCreate in Engine!!

证明engine中的修改生效了

调试engine中的Android代码

  • 导入engine/src/flutter/shell/platform/android作为新的工程
  • 确认Engine SDK Version和Java Version File > Project Structure > Project Settings > Project
    image.png
  • 可选:代码关联 File > Project Structure > Modules 消除Missing import错误提示。主要是关联engine/src/third_party/android_support
    image.png
  • 在engine android工程中所需位置设上断点


    image.png
  • 使用flutter run --local-engine-src-path /Users/heq/engine/src --local-engine=android_debug_unopt 运行项目工程
  • 在engine android工程中attach debugger对应的项目工程,即可断点成功


    image.png

    image.png

参考:手把手教你编译Flutter engine
Compiling the engine
Flutter Engine与SDK的定制化与编译
Contributing to the Flutter engine
Debugging the engine

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容