Compilación de aleteo de Android

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

inserte la descripción de la imagen aquí

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)
inserte la descripción de la imagen aquí
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

inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí
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

inserte la descripción de la imagen aquí

inserte la descripción de la imagen aquí

inserte la descripción de la imagen aquí
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
inserte la descripción de la imagen aquí

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
inserte la descripción de la imagen aquí

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.

Supongo que te gusta

Origin blog.csdn.net/weixin_41548050/article/details/128657671
Recomendado
Clasificación