2.1 Flutter源码调试

2022-03-29  本文已影响0人  刘小厨

一般情况下,通过flutter run 构建并运行flutter工程时,会生成Engine/Embedder的依赖配置并通过Gradle从云端仓库下载官方已经构建好病上传的构建产物,但是我们也可以自定义参数指定使用本地自己构建的Engine/Embedder产物。Flutter 编译Engine/Embedder见:Flutter源码获取与编译

基于本地构建产物编译Flutter应用

$ ../flutter/bin/flutter run --local-engine-src-path ~/flutter_source/src --local-engine=android_debug_unopt     #使用自己的目录

Flutter Framework层调试

Framework层调试,Android Studio本身就是支持的,就不做赘述了。

Flutter Embedder层调试

  通过上述的指令(--local-engine-src-path,--local-engine)参数指定自定义的Engine和Embeder构建一个Flutter App,并不能在Android Studio中像Framework那样调试Embedder的Java代码,因为当前项目呗识别为Flutter工程,而非Android工程。如果使用Android Studio直接打开flutter工程下的android目录,则相关的Local Engine参数都没有配置,自然无法被当作源码解析。
  对于Embedder的调试,也是可以通过Android项目构建时候增加相关参数,指定使用自己编译后的文件,在src/out/android_debug_unopt中有Embedder的jar文件和pom文件,可以构建自己的本地仓库,代替默认的远程仓库。
  但是也可以通过更简单的方式来调试

使用Android Studio 对Embedder源码调试

无论是使用VS Code还是Android Studio都需要上述LLDB的配置准备工作,推荐使用上面的VS Code,因为使用Android Studio的这种方式调试的时候使用的是Engine变异产物的flutter.jar文件
步骤:

  1. 创建一个Flutter Module工程,命令行创建
../flutter/bin/flutter create -t module flutter_module
  1. 将上述flutter module打包成aar
../flutter/bin/flutter build aar
  1. 创建一个常规的Android 工程,将Enfine源码构建出来的flutter.jar文件和上面打包的aar文件复制到libs目录
  2. 配置app/build.gradle
android {
 defaultConfig {
        ndk { // 确保加入目标架构的libflutter.so进行构建
            abiFilters "armeabi-v7a" 
        }
    }

 compileOptions { // Embedder须使用JDK1.8构建
        sourceCompatibility 1.8
        targetCompatibility 1.8
    }
}

dependencies {
    implementation files('libs/flutter.jar') // Engine和Embedder源码
    implementation files('libs/flutter_debug-1.0.aar') // Framework的构建产物
}

Engine源码调试

  对于Engine的调试相对来说就会复杂一些,简单说明下,调试时候,源码在PC端,而代码运行在具体设备(Android/IOS等),那么挑食过程必然有数据通信和通信协议,比如Java代码调试常见的Socket和JDWP,而Engine是基于C++开发,很多步骤要手动完成。此外会准备一个Flutter项目方便后续调试,下面提到的com.lwj.flutter_app是一个Flutter的默认计数器demo项目。

关于lldb远程调试的配置方式参考:LLDB Remote Debugging
(PS:按照上面文档配置后存在一个问题,就是最后挂载进程时,无法关联到我们的flutter应用进程。这个是因为系统权限限制,除非将手机ROOT,否则一直会提示attach fail
那这个问题怎么解决?其实可以将lldb-server添加到需要调试的应用中。通过run-as获取应用权限,进入应用目录下进行操作。注意,使用run-as的应用只能是debug应用,其他应用不可以使用。)

LLDB配置步骤大致如下:

  1. 确定lldb-文件位置(可手动下载 LLDB,)
# Android studio安装目录下的路径(不确定从那个版本开始内置)
/Applications/Android\ Studio.app/Contents/plugins/android-ndk/resources/lldb/android/armeabi/lldb-server 
# Flutter Engine目录下的lldb-server路径
/Users/lwj/Desktop/flutter_source/engine/src/third_party/android_tools/ndk/toolchains/llvm/prebuilt/darwin-x86_64/lib64/clang/11.0.5/lib/linux/arm/lldb-server
  1. 找到lldb-server所在目录位置,并将其推送到手机中
    我用的是Flutter Engine 编译产物目录下的lldb-server,执行adb命令,将lldb-server push到临时文件夹
adb push /Users/lwj/Desktop/flutter_source/engine/src/third_party/android_tools/ndk/toolchains/llvm/prebuilt/darwin-x86_64/lib64/clang/11.0.5/lib/linux/arm/lldb-server /data/local/tmp/lldb-server
  1. 将lldb-server复制到app的私有目录
    执行命令如下:
adb shell run-as com.lwj.flutter_app cp -F /data/local/tmp/lldb-server /data/data/com.lwj.flutter_app/lldb-server
  1. 赋予lldb-server可执行权限
adb shell run-as com.lwj.flutter_app \chmod a+x /data/data/com.lwj.flutter_app/lldb-server
  1. 启动lldb-server,这样设备就可以接受相应调试命令了
adb shell "run-as com.lwj.flutter_app sh -c '/data/data/com.lwj.flutter_app/lldb-server platform --server --listen unix-abstract:///data/data/com.lwj.flutter_app/debug.socket'"
  1. 获取待调试应用进程id
    先使用自己编译的Flutter Engine启动demo工程
    在demo目录下执行命令
flutter run --local-engine-src-path=/Users/lwj/Desktop/flutter_source/engine/src --local-engine=/Users/lwj/Desktop/flutter_source/engine/src/out/android_debug_unopt

执行命令获取pid

adb shell pidof com.lwj.flutter_app
30226

到这里LLDB的配置就完成了,我们可以基于上面的配置,通过VS Code断点调试Flutter Engine源码

使用VS Code源码调试

  1. 使用VS Code打开Engine所在目录
  2. 配置 launch.json文件
{
    "version": "0.2.0",
    "configurations": [
    {
      "type": "lldb",
      "request": "attach",
      "name": "android_attach",
      "pid": "30226",  # 上面获取的pid
      "initCommands": [
        "platform select remote-android",
        "platform connect unix-abstract-connect:///data/data/com.lwj.flutter_app/debug.socket"
      ],
      "postRunCommands": [
        "add-dsym /Users/lwj/Desktop/flutter_source/engine/src/out/android_debug_unopt/libflutter.so",
        "settings set target.source-map /Users/lwj/Desktop/flutter_source/engine/src/out/android_debug_unopt /Users/lwj/Desktop/flutter_source/engine/src/"
      ]
    }
    ]
  }
  1. 设置断点,F5开始调试。
    我将断点打到了 src/flutter/lib/ui/window/window.cc
    点击demo的+号,触发断点
    断点

参考:
《Flutter内核源码剖析》
Flutter Engine源码调试

上一篇下一篇

猜你喜欢

热点阅读