赞
踩
flutter_windows_3.3.10-stable(flutter sdk)
windows 10
注意:
以下{flutter sdk path}表示flutter sdk安装目录
而批处理程序本质是运行了dart程序
"%dart%" --disable-dart-dev --packages="%flutter_tools_dir%\.dart_tool\package_config.json" %FLUTTER_TOOL_ARGS% "%snapshot_path%" %* & exit /B !ERRORLEVEL!
{flutter sdk path}\bin\cache\dart-sdk\bin\dart.exe {flutter sdk path}\bin\cache\flutter_tools.snapshot,而这里的\flutter_tools.snapshot本质上是dart编译的中间产物????入口函数为{flutter sdk path}\packages\flutter_tools\bin\flutter_tools.dart中的main函数
{flutter sdk path}\packages\flutter_tools\lib\src\android\gradle.dart
Future<void> buildGradleApp({ required FlutterProject project, required AndroidBuildInfo androidBuildInfo, required String target, required bool isBuildingBundle, required List<GradleHandledError> localGradleErrors, bool validateDeferredComponents = true, bool deferredComponentsEnabled = false, int retry = 0, @visibleForTesting int? maxRetries, }) async { 。。。 final String assembleTask = isBuildingBundle ? getBundleTaskFor(buildInfo) : getAssembleTaskFor(buildInfo); 。。。 。。。 final List<String> command = <String>[ _gradleUtils.getExecutable(project),//这里windows环境下就是gradlew.bat批处理程序 ]; if (_logger.isVerbose) { command.add('--full-stacktrace'); command.add('--info'); command.add('-Pverbose=true'); } else { command.add('-q'); } 。。。 。。。 command.add(assembleTask); 。。。 }
{flutter sdk path}\packages\flutter_tools\lib\src\android\gradle_utils.dart
/// Gets the Gradle executable path and prepares the Gradle project. /// This is the `gradlew` or `gradlew.bat` script in the `android/` directory. String getExecutable(FlutterProject project) { final Directory androidDir = project.android.hostAppGradleRoot; injectGradleWrapperIfNeeded(androidDir); final File gradle = androidDir.childFile( _platform.isWindows ? 'gradlew.bat' : 'gradlew', ); if (gradle.existsSync()) { _logger.printTrace('Using gradle from ${gradle.absolute.path}.'); // If the Gradle executable doesn't have execute permission, // then attempt to set it. _operatingSystemUtils.makeExecutable(gradle); return gradle.absolute.path; } throwToolExit( 'Unable to locate gradlew script. Please check that ${gradle.path} ' 'exists or that ${gradle.dirname} can be read.' ); }
可以看到其实是执行gradlew.bat … assemblexxx
这里的assemblexxx就是android gradle定义的编译task
在{flutter sdk path}\packages\flutter_tools\gradle\flutter.gradle
定义函数addFlutterTasks,创建了FlutterTask自定义gradle task,具体这个task怎么跟android gradle编译task关联起来,需要重点研究下???
private void addFlutterTasks(Project project) { 。。。 FlutterTask compileTask = project.tasks.create(name: taskName, type: FlutterTask) { flutterRoot this.flutterRoot flutterExecutable this.flutterExecutable buildMode variantBuildMode localEngine this.localEngine localEngineSrcPath this.localEngineSrcPath targetPath getFlutterTarget() verbose isVerbose() fastStart isFastStart() fileSystemRoots fileSystemRootsValue fileSystemScheme fileSystemSchemeValue trackWidgetCreation trackWidgetCreationValue targetPlatformValues = targetPlatforms sourceDir getFlutterSourceDirectory() intermediateDir project.file("${project.buildDir}/${AndroidProject.FD_INTERMEDIATES}/flutter/${variant.name}/") extraFrontEndOptions extraFrontEndOptionsValue extraGenSnapshotOptions extraGenSnapshotOptionsValue splitDebugInfo splitDebugInfoValue treeShakeIcons treeShakeIconsOptionsValue dartObfuscation dartObfuscationValue dartDefines dartDefinesValue bundleSkSLPath bundleSkSLPathValue performanceMeasurementFile performanceMeasurementFileValue codeSizeDirectory codeSizeDirectoryValue deferredComponents deferredComponentsValue validateDeferredComponents validateDeferredComponentsValue doLast { project.exec { if (Os.isFamily(Os.FAMILY_WINDOWS)) { commandLine('cmd', '/c', "attrib -r ${assetsDirectory}/* /s") } else { commandLine('chmod', '-R', 'u+w', assetsDirectory) } } } } 。。。 }
FlutterTask继承自BaseFlutterTask,BaseFlutterTask有函数buildBundle()
void buildBundle() { if (!sourceDir.isDirectory()) { throw new GradleException("Invalid Flutter source directory: ${sourceDir}") } intermediateDir.mkdirs() // Compute the rule name for flutter assemble. To speed up builds that contain // multiple ABIs, the target name is used to communicate which ones are required // rather than the TargetPlatform. This allows multiple builds to share the same // cache. String[] ruleNames; if (buildMode == "debug") { ruleNames = ["debug_android_application"] } else if (deferredComponents) { ruleNames = targetPlatformValues.collect { "android_aot_deferred_components_bundle_${buildMode}_$it" } } else { ruleNames = targetPlatformValues.collect { "android_aot_bundle_${buildMode}_$it" } } project.exec { logging.captureStandardError LogLevel.ERROR executable flutterExecutable.absolutePath workingDir sourceDir if (localEngine != null) { args "--local-engine", localEngine args "--local-engine-src-path", localEngineSrcPath } if (verbose) { args "--verbose" } else { args "--quiet" } args "assemble" args "--no-version-check" args "--depfile", "${intermediateDir}/flutter_build.d" args "--output", "${intermediateDir}" if (performanceMeasurementFile != null) { args "--performance-measurement-file=${performanceMeasurementFile}" } if (!fastStart || buildMode != "debug") { args "-dTargetFile=${targetPath}" } else { args "-dTargetFile=${Paths.get(flutterRoot.absolutePath, "examples", "splash", "lib", "main.dart")}" } args "-dTargetPlatform=android" args "-dBuildMode=${buildMode}" if (trackWidgetCreation != null) { args "-dTrackWidgetCreation=${trackWidgetCreation}" } if (splitDebugInfo != null) { args "-dSplitDebugInfo=${splitDebugInfo}" } if (treeShakeIcons == true) { args "-dTreeShakeIcons=true" } if (dartObfuscation == true) { args "-dDartObfuscation=true" } if (dartDefines != null) { args "--DartDefines=${dartDefines}" } if (bundleSkSLPath != null) { args "-dBundleSkSLPath=${bundleSkSLPath}" } if (codeSizeDirectory != null) { args "-dCodeSizeDirectory=${codeSizeDirectory}" } if (extraGenSnapshotOptions != null) { args "--ExtraGenSnapshotOptions=${extraGenSnapshotOptions}" } if (extraFrontEndOptions != null) { args "--ExtraFrontEndOptions=${extraFrontEndOptions}" } args ruleNames } }
又回到flutter sdk中的flutter.bat脚本执行flutter assemble
此时原本以为循环执行gradle assemblexxx,其实不是
因为flutter assemble执行后走到的是dart程序
{flutter sdk path}\packages\flutter_tools\lib\src\commands\assemble.dart
需要具体分析下这里怎么执行flutter中dart程序编译的?怎么生成flutter_assets的?以及debug模式下三个文件kernel_blob.bin、vm_snapshot_data、isolate_snapshot_data有什么作用以及如何生成到flutter_assets目录下的?
这里还有两个很重要的文件
{flutter sdk path}\bin\cache\artifacts\engine\windows-x64\frontend_server.dart.snapshot
{flutter sdk path}\bin\cache\artifacts\engine\android-arm-release\windows-x64\gen_snapshot.exe
一个是dart编译的中间产物,需要配合dart vm使用,负责生成kernel文件?
一个纯二级制可执行文件,负责生成aot可执行文件?
而这个frontend_server.dart.snapshot不同于之前的flutter_tool.snapshot,他是存在于engine的Dart代码中的,而不是Flutter SDK中。
engine的代码需要单独下载:https://github.com/flutter/engine
{flutter sdk}\packages\flutter_tools整个目录作为dart工程根目录打开(如果出现as不识别工程,查工程有没有指定dart sdk路径,file->settings->dart,指定dart sdk路径为{flutter sdk}\bin\cache\dart-sdk并apply)
有两种方式:
方式1:Dart Command Line App
方式2:Dart Remote Debug
指定dart入口文件,命令行参数为build apk,工作目录选择任意flutter工程根目录(会在指定的目录下执行dart命令,此处是执行flutter编译android apk)
这里可以看到要求对应的dart vm启动时必须指定 --enable-vm-service:12345 --pause_isolates_on_start 两个选项,其中12345随意指定,后续要用到
在
“%dart%” --packages=“%flutter_tools_dir%.dart_tool\package_config.json” %FLUTTER_TOOL_ARGS% “%snapshot_path%” %* & “%exit_with_errorlevel%”
之前赋值变量FLUTTER_TOOL_ARGS
SET FLUTTER_TOOL_ARGS=–enable-vm-service:12345 --pause_isolates_on_start --disable-service-auth-codes %FLUTTER_TOOL_ARGS%
比如
G:\MyWork\Flutter\Tools\flutter_windows_3.7.3-stable\flutter\bin\flutter.bat --no-color build apk
但是如果是Dart Command Line App
G:/MyWork/Flutter/Tools/flutter_windows_3.7.3-stable/flutter/bin/cache/dart-sdk/bin/dart.exe --enable-asserts --pause_isolates_on_start --enable-vm-service:63036 G:\MyWork\Flutter\Tools\flutter_windows_3.7.3-stable\flutter\packages\flutter_tools\bin\flutter_tools.dart build apk
则正常断言到flutter_tools.dart源码main函数
对比flutter.bat批处理执行的命令
“G:\MyWork\Flutter\Tools\flutter_windows_3.7.3-stable\flutter\bin\cache\dart-sdk\bin\dart.exe” --packages=“G:\MyWork\Flutter\Tools\flutter_windows_3.7.3-stable\flutter\packages\flutter_tools.dart_tool\package_config.json” --enable-vm-service:12345 --pause_isolates_on_start --disable-service-auth-codes “G:\MyWork\Flutter\Tools\flutter_windows_3.7.3-stable\flutter\bin\cache\flutter_tools.snapshot” --no-color build apk
对比发现可能是启动dart vm时候没有指定选项–enable-asserts导致
报错snapshot文件不支持assert
把
SET snapshot_path=%cache_dir%\flutter_tools.snapshot
改为
SET snapshot_path=%flutter_tools_dir%\bin\flutter_tools.dart
重新执行步骤2 flutter build apk
此时可以正常断言到flutter_tools.dart文件的main函数
https://developer.aliyun.com/article/761239
https://juejin.cn/post/7093388612078665764
注意:以上两个博文都是使用的其他版本flutter sdk,所以跟本次分享的内容有点差异,如assemble.dart在参考博文中的flutter sdk版本是不存在的
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。