Flutter之Gradle配置


一、引入flutter.gradle文件

基于flutter1.9.1版本。
Flutter项目android工程app主模块,引入flutter.gradle配置文件,该文件在flutter sdk的flutter/packages/flutter_tools/gradle/目录下,目的是在普通android工程的编译打包流程中插入一些Flutter任务。

apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"

app主模块,当Gradle运行到apply from时,进入flutter.gradle执行,代码流程。

apply from引入flutter.gradle的代码流程

在flutter.gradle文件,首先执行buildscript代码块,然后顺序执行,代码结构。

flutter.gradle文件概况

定义一个FlutterPlugin插件,实现接口Plugin的apply方法,Gradle运行到apply plugin: FlutterPlugin语句时,去执行apply方法(插入任务),执行结束回到app主模块,继续主模块Gradle文件后面的代码。
FlutterTask任务类、FlutterPluginTask任务类。

引入flutter.gradle的配置文件仅执行buildscript代码块和FlutterPlugin插件的apply方法,目的是插入Flutter任务。


二、插件

定义FlutterPlugin插件,实现接口Plugin,apply方法。

@Override
void apply(Project project) {
}

Project代表android工程的app模块,project.getName()是app。

project.afterEvaluate this.&addFlutterTasks

afterEvaluate,当apply()方法结束,project(app模块)的Gradle完成,再添加Flutter任务,调用addFlutterTasks()方法。

String flutterRootPath = resolveProperty(project, "flutter.sdk", System.env.FLUTTER_ROOT)

查找父目录下的local.properties文件,即(工程根目录),获取flutter.sdk路径和bin目录下可执行文件。

String flutterExecutableName = Os.isFamily(Os.FAMILY_WINDOWS) ? "flutter.bat" : "flutter"
flutterExecutable = Paths.get(flutterRoot.absolutePath, "bin", flutterExecutableName).toFile();

根据不同平台去加载可执行文件。

# basePlatform目标平台默认:android-arm64
String basePlatformArch = getBasePlatform(project)

Path baseEnginePath = Paths.get(flutterRoot.absolutePath, "bin", "cache", "artifacts", "engine")
File debugJar = baseEnginePath.resolve("${basePlatformArch}").resolve("flutter.jar").toFile()
baseJar["debug"] = debugJar

baseJar["profile"] = baseEnginePath.resolve("${basePlatformArch}-profile").resolve("flutter.jar").toFile()
baseJar["release"] = baseEnginePath.resolve("${basePlatformArch}-release").resolve("flutter.jar").toFile()

从sdk的/bin/cache/artifacts/engine/路径,创建flutter.jar文件的Flie,三种构建模式debug,profile和release,从android-arm64-xxx对应目录加载。

project.android.buildTypes.each {
    def buildMode = buildModeFor(it)
    println "each buildTypes 构建类型: $buildMode 添加flutter.jar依赖"
    addApiDependencies(project, it.name, project.files {
        baseJar[buildMode]
    })
}

遍历构建模式,通过project.dependencies.add()方法,添加android主模块对flutter.jar的依赖,project是android工程的app模块。

if (project.getConfigurations().findByName("api")) {
    configuration = "${variantName}Api";
} else {
    configuration = "${variantName}Compile";
}
project.dependencies.add(configuration, dependency, config)

构建类型XxxApi,依赖文件。


三、任务

插件apply()完成,afterEvaluate设置addFlutterTasks()任务添加方法执行。

private void addFlutterTasks(Project project) {
}

通过project.tasks.create()方法添加。

## 目标平台:[android-arm, android-arm64]
def targetPlatforms = getTargetPlatforms(project)

默认平台是arm和arm64。

1,编译任务
FlutterTask compileTask = project.tasks.create(name: taskName, type: FlutterTask) {
}

任务名:compileFlutterDebug构建模式+平台,类型是FlutterTask类,自定义任务类。

compileFlutterBuildXxxArm,compileFlutterBuildXxxArm64
构建模式:Debug,Profile,Release
abi平台:Arm(32)和Arm64

编译任务和执行产物

addFlutterTasks方法仅将任务添加到Gradle的构建流程中,运行在编译过程中触发。

编译过程中任务执行

FlutterTask类build方法,父类DefaultTask的buildBundle()方法。

@TaskAction
void build() {
    buildBundle()
}

编译任务生成Dart产物build目录:intermediates/flutter/xxx/平台/。在平台目录下,产物debug和release模式不同,
debug模式:flutter_assets目录下kernel_blob.bin,vm_snapshot_data,isolate_snapshot_data。
releass模式:flutter_assets目录+app.so。

2,lib任务
Task packFlutterSnapshotsAndLibsTask = project.tasks.create(name: 
    "packLibs${FLUTTER_BUILD_PREFIX}${variant.name.capitalize()}", type: Jar) {
}

任务名:packLibsflutterBuild构建模式,类型是Jar类,Gradle内置任务类,将sdk中对应平台libflutter.so文件写入libs.jar压缩包。

packLibsflutterBuildXxx,依赖对应编译任务
构建模式:Debug,Profile,Release
abi平台:依赖编译任务生成的目标平台

debug模式,增加两个平台。

if (flutterBuildMode == 'debug') {
    libFlutterPlatforms.add('android-x86')
    libFlutterPlatforms.add('android-x64')
}

在build/intermediates/flutter/xxx目录,定义一个libs.jar文件,将sdk的engine平台flutter.jar中lib目录下的so文件(lib/**)复制到压缩包libs.jar,当debug模式,多复制x86和x64平台的libflutter.so文件。其他模式,复制android-arm-xxx(32位)目录中的文件。

debug模式lib任务

将intermediates/flutter/release/android-arm和64的so文件(app.so),release模式编译过程,Dart产物包括so文件,重命名libapp.so,拷贝到libs.jar压缩包文件。

// 包含so产物的intermediates/flutter/平台/,release和profile
compileTasks.each { compileTask ->
    from(compileTask.intermediateDir) {
        include '*.so'
        rename { String filename ->
            println "rename:"+compileTask.intermediateDir
            return "lib/${compileTask.abi}/lib${filename}"
        }
    }
}
release模式libs.jar文件查看
3,拷贝任务
Task copyFlutterAssetsTask = project.tasks.create(name: 
    "copyFlutterAssets${variant.name.capitalize()}", type: Copy) {
}

任务名:copyFlutterAssets构建模式,类型是Copy类,Gradle内置任务类,

copyFlutterAssetsXxx,依赖对应编译任务和packLibsflutterBuild任务
构建类模式:Debug,Profile,Release
abi平台:依赖编译任务生成的目标平台
依赖cleanMergeXxxAssets,mergeXxxAssets

# clean动作先执行
variant.mergeAssets.mustRunAfter("clean${variant.mergeAssets.name.capitalize()}")

拷贝是从intermediates的flutter目录到merged_assets目录下。

/build/intermediates/merged_assets/release/mergeReleaseAssets/out

拷贝内容是flutter_assets文件夹目录下/*。

addApiDependencies(project, variant.name, project.files {
    packFlutterSnapshotsAndLibsTask
})

依赖packLibsflutterBuild任务。

拷贝任务
## 运行拷贝任务
> Task :app:cleanMergeDebugAssets UP-TO-DATE
> Task :app:compileFlutterBuildDebugArm
> Task :app:compileFlutterBuildDebugArm64
> Task :app:mergeDebugShaders
> Task :app:compileDebugShaders
> Task :app:generateDebugAssets
> Task :app:packLibsflutterBuildDebug UP-TO-DATE
> Task :app:mergeDebugAssets
> Task :app:copyFlutterAssetsDebug
8 actionable tasks: 6 executed, 2 up-to-date
11:42:04: Task execution finished 'copyFlutterAssetsDebug'.
4,构建顺序

Debug模式,Gradle顺序。

Debug模式Run tasks

四、Dart编译命令

BaseFlutterTask基类的buildBundle()方法,调用Flutter构建命令,生成Futter产物。
sourceDir目录,即根目录中,包含lib/main.dart文件的目录,添加任务时,构建目录默认是lib/main.dart,通过project.exec {..}方法,执行命令。

void buildBundle() {
    intermediateDir.mkdirs()
    if (buildMode == "profile" || buildMode == "release") {
        project.exec {
            executable flutterExecutable.absolutePath
            workingDir sourceDir
            args "build", "aot"
            args "--target", targetPath
            args "--output-dir", "${intermediateDir}"
            ...//args参数
        }
    }
    project.exec {
        executable flutterExecutable.absolutePath
        workingDir sourceDir
        args "build", "bundle"
        args "--target", targetPath
        args "--target-platform", "${targetPlatform}"
        ...//args参数
        args "--asset-dir", "${intermediateDir}/flutter_assets"
        if (buildMode == "debug") {
            args "--debug"
        }
        if (buildMode == "profile") {
            args "--profile"
        }
        if (buildMode == "release") {
            args "--release"
        }
    }
}

release和profile构建模式,两次命令,第一个project.exec。

flutter build aot --suppress-analytics --quiet --target lib/main.dart --target-platform android-arm --output-dir build/app/intermediates/flutter/release --release

输出目录是intermediates/flutter/release/平台/,产物是app.so文件,不支持debug构建模式。
所有构建模式,第二个project.exec。

flutter build bundle --suppress-analytics --target lib/main.dart --precompiled --asset-dir build/app/intermediates/flutter/release/flutter_assets --release

build bundle,产物是flutter_assets目录。


任重而道远

你可能感兴趣的:(Flutter之Gradle配置)