美文网首页
2.1 Flutter源码调试

2.1 Flutter源码调试

作者: 刘小厨 | 来源:发表于2022-03-29 11:07 被阅读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,简单说明下lldb,Android端调试Native代码一般也使用lldb,在Android Studio SDK Manager界面可以安装lldb(注意: 低版本的Android Studio 可能找不到该选项,高版本的Android studio也有可能找不到该选项,高版本找不到是因为lldb相当于内置了,不需要单独安装,但是不方便外部调用(手动下载戳 LLDB),Android Studio的安装目录和Flutter Engine编译产物的文件夹下都有lldb-server文件,不必纠结Android studio版本和是否可以独立下载 )
      lldb示意图

    关于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源码调试

    相关文章

      网友评论

          本文标题:2.1 Flutter源码调试

          本文链接:https://www.haomeiwen.com/subject/eichjrtx.html