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<Project>的apply方法,Gradle运行到apply plugin: FlutterPlugin语句时,去执行apply方法(插入任务),执行结束回到app主模块,继续主模块Gradle文件后面的代码。
FlutterTask任务类、FlutterPluginTask任务类。

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


二、插件

定义FlutterPlugin插件,实现接口Plugin<Project>,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目录。


任重而道远

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容