Directorio de artículos
- Preparación ambiental
- Combinación de proceso de apk de compilación de Flutter
- Resumir
- Flutter tools (dardo) depuración de código fuente
-
- Método 1: aplicación de línea de comandos Dart
- Método 2: Depuración remota de Dart
-
- Use la opción vm que se acaba de proporcionar para iniciar dart vm para realizar la tarea de compilación flutter
- referencia
Preparación ambiental
flutter_windows_3.3.10-estable (sdk de flutter)
ventanas 10
Combinación de proceso de apk de compilación de Flutter
Nota:
La siguiente {ruta del sdk de flutter} indica el directorio de instalación del sdk de flutter
1. El flutter aquí es {flutter sdk path}\bin\flutter.bat programa por lotes
La esencia del programa por lotes es ejecutar el programa 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, y \flutter_tools.snapshot aquí es esencialmente un producto intermedio de la compilación de dart. ? ? ? La función de entrada es la función principal en {flutter sdk path}\packages\flutter_tools\bin\flutter_tools.dart
2. Rastree el archivo dart paso a paso para
{ruta del SDK de Flutter}\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);
。。。
}
{ruta del SDK de Flutter}\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.'
);
}
Se puede ver que gradlew.bat en realidad se ejecuta ... ensamblar xxx
donde ensamblar xxx es la tarea de compilación definida por gradle de Android
3. Accede al complemento gradle personalizado de flutter para encontrar pistas
Defina la función addFlutterTasks en {flutter sdk path}\packages\flutter_tools\gradle\flutter.gradle,
y cree una tarea gradle personalizada para FlutterTask. Específicamente, ¿debe estudiarse cómo se relaciona esta tarea con la tarea de compilación de gradle de Android? ? ?
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 hereda de BaseFlutterTask, BaseFlutterTask tiene la función 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
}
}
Regrese a la secuencia de comandos flutter.bat en flutter sdk para ejecutar flutter ensamblar
4. Vuelva al script flutter.bat en el SDK de flutter para ejecutar flutter ensamblar
En este momento, originalmente pensé que el ensamblaje gradlexxx se ejecutaba en un bucle, pero no fue
porque el ensamblaje flutter fue al programa dart después de la ejecución.
{ruta del sdk de flutter}\packages\flutter_tools\lib\src\commands\assemble.dart
¿Necesitas analizar en detalle cómo ejecutar la compilación del programa dart en flutter? ¿Cómo generar flutter_assets? ¿Y cuáles son las funciones de los tres archivos kernel_blob.bin, vm_snapshot_data y aislar_snapshot_data en modo de depuración y cómo se generan en el directorio flutter_assets?
Aquí hay dos archivos muy importantes
{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
Uno es el producto intermedio de la compilación de dart, que debe usarse con dart vm y es responsable de generar archivos de kernel.
¿Un ejecutable binario puro que es responsable de generar el ejecutable aot?
而这个frontend_server.dart.snapshot不同于之前的flutter_tool.snapshot,他是存在于engine的Dart代码中的,而不是Flutter SDK中。
engine的代码需要单独下载:https://github.com/flutter/engine
Resumir
Flutter tools (dardo) depuración de código fuente
El directorio completo de {flutter sdk}\packages\flutter_tools se abre como el directorio raíz del proyecto dart (si as no reconoce el proyecto, verifique si el proyecto ha especificado la ruta de dart sdk, file->settings->dart , especifique la ruta del sdk de dart como {flutter sdk} \bin\cache\dart-sdk y aplique)
Hay dos formas:
Método 1: Aplicación de línea de comandos de Dart
Método 2: Depuración remota de Dart
Método 1: aplicación de línea de comandos Dart
Especifique el archivo de entrada de dart, el parámetro de línea de comando es build apk, y el directorio de trabajo selecciona cualquier directorio raíz del proyecto flutter (el comando dart se ejecutará en el directorio especificado, aquí es para ejecutar flutter para compilar apk de Android)
Método 2: Depuración remota de Dart
Aquí puede ver que se deben especificar dos opciones --enable-vm-service:12345 --pause_isolates_on_start cuando se inicia el dart vm correspondiente, de las cuales 12345 se especifica a voluntad y se usará más adelante
Use la opción vm que se acaba de proporcionar para iniciar dart vm para realizar la tarea de compilación flutter
1. Primero, modifica el archivo flutter.bat
existir
“%dart%” --packages=“%flutter_tools_dir%.dart_tool\package_config.json” %FLUTTER_TOOL_ARGS% “%snapshot_path%” %* & “%exit_with_errorlevel%”
Antes de asignar la variable FLUTTER_TOOL_ARGS
SET FLUTTER_TOOL_ARGS=–enable-vm-service:12345 --pause_isolates_on_start --disable-service-auth-codes %FLUTTER_TOOL_ARGS%
2. Luego vaya directamente al directorio raíz de cualquier proyecto flutter para ejecutar flutter build apk
Por ejemplo
G:\MyWork\Flutter\Tools\flutter_windows_3.7.3-stable\flutter\bin\flutter.bat --no-color build apk
3. Se encontró un problema: Dart Remote Debug no puede afirmar que ha rastreado el archivo de código fuente flutter_tools.dart
Pero si es la aplicación Dart Command Line
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
Luego, normalmente afirma la función principal del código fuente de flutter_tools.dart
Compara los comandos ejecutados por el lote 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” --apk de compilación sin color
La comparación encontró que puede deberse a que no se especifica la opción –enable-asserts al iniciar dart vm
Modifique la opción de inicio dart vm en flutter.bat, agregue --enable-asserts
El archivo de instantánea no es compatible con la aserción.
Modifique la entrada de inicio de dart vm en flutter.bat y reemplace el archivo de instantánea con el archivo flutter_tools.dart (¡¡efectivo!!!)
Manojo
SET snapshot_path=%cache_dir%\flutter_tools.snapshot
cambiado a
CONFIGURAR snapshot_path=%flutter_tools_dir%\bin\flutter_tools.dart
Vuelva a ejecutar el paso 2 flutter build apk
ahora puede afirmar la función principal del archivo flutter_tools.dart normalmente
referencia
https://developer.aliyun.com/article/761239
https://juejin.cn/post/7093388612078665764
Nota: Las dos publicaciones de blog anteriores usan otras versiones de flutter sdk, por lo que son un poco diferentes del contenido compartido esta vez. Por ejemplo, la versión de flutter sdk de ensamblar.dart en la publicación de blog de referencia no existe.