Earth Guardian

You are not LATE!You are not EARLY!

0%

Gradle Kotlin Plugin

使用 Kotlin 实现 Gradle Plugin

Gradle 4.10 开始支持 Kotlin DSL ,即之后的版本都支持使用 Kotlin 实现编译脚本,其后缀为 *.gradle.kts ;而 Android Studio 4 开始全面支持 Kotlin 实现的 Gradle 编译脚本。

Kotlin DSL

AS 在多模块项目中,支持混合编写的 gradle 脚本,即某个模块可以是 Groovy 编写的 build.gradle 脚本文件;而其他模块是 Kotlin 编写的 build.gradle.kts 脚本文件。

Plugin 模块

AS 中新建一个 Java Libary 的模块,并将 build.gradle 文件名修改为 build.gradle.kts ,使用 Kotlin 重写该文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
plugins {
`kotlin-dsl` // 添加 kotlin-dsl 插件
`maven-publish` // 版本发布插件
}

dependencies {
compileOnly("com.android.tools.build:gradle:4.0.1") // APK 编译过程中,遍历 .class 文件
}

gradlePlugin {
plugins {
register("MyAsmPlugin") { // 注册我的插件,并且发布为 jar 包时的信息
group = "com.xmt" // 插件 group
version = "1.0" // 版本
// name = "***" // name 被 final 修饰了,不能设置,默认为 project.module 的名称
id = "asmplugin" // 插件 id ,后续在 build.gradle 中引入插件时使用该名称
implementationClass = "com.xmt.demo.kt.asmplugin.AsmPlugin" // 插件实现类的全名(包含包名)
}
}
}

publishing {
repositories {
maven(url = "../repository") // 发布到本地根目录下的 repositories 目录下,发布的 groupId, artifactsId, version 共用插件的字符
}
}

repositories {
jcenter()
}

使用 gradlePlugin 插件后,不需要手动添加 resources 目录以及 com.**.android.properties 文件(这个文件名称通常为插件名称);这里 gradlePlugin 会自动生成 id=asmplugin 的文件,所以插件名称为 asmplugin
配置完毕后,就可以使用 Kotlin 编写插件代码了;编写完毕后通过 Task 中的 publishing -> publish 发布后,会在根目录的 repositories 目录下生成对应 jar 包。
发到 Maven 仓库,需要使用 publishPluginMavenPublicationToMavenRepository 命令,不管任务取的什么名字,都是编译这个任务!!!

引用 Plugin 模块的插件

  • 项目根目录下的顶级编译脚本 build.gradle 中,引入该插件及对应版本
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    buildscript {
    ext.kotlin_version = "1.3.72"
    repositories {
    google()
    jcenter()
    maven {
    url uri('repository') // 引入本地仓库
    }
    }
    dependencies {
    classpath "com.android.tools.build:gradle:4.0.1"
    classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    classpath 'com.xmt:asmplugin:1.0' // 引入 Plugin 的 jar 包,参与编译

    // NOTE: Do not place your application dependencies here; they belong
    // in the individual module build.gradle files
    }
    }
  • App 目录下的编译脚本 build.gradle 中,引入插件,至此插件会参与到 App 的编译!
    1
    apply plugin: 'asmplugin'       // 名称为版本发布时,指定的插件名称

注意事项

  • Plugin 模块有修改时,需要重新发布。特别是本地发布时,如果版本号没改,需要先注释掉顶级 build.gradle 以及 App 模块的 build.gradle 中,所有关于该插件的引入,注释掉后删掉插件发布的本地仓库,重新编译并发布后,顶级 build.gradleApp 模块的 build.gradle 重新引入
  • Jar 模块不能依赖 Aar 模块,提示的错误是 Failed to resolve: project::**sdk ,单独从错误根本无法排查出原因,实际上是因为 **sdk 是一个 Aar 包;在 App 模块中就能成功依赖 **sdk 模块
  • Snapshot 的更新: Right-click on the project name in the Gradle Tool Window and select Refresh Gradle Dependencies from the context menu

gradle kts 手册 https://docs.gradle.org/current/userguide/kotlin_dsl.html
初始化脚本 https://docs.gradle.org/current/userguide/init_scripts.html
groovy 迁移到 kotlin https://guides.gradle.org/migrating-build-logic-from-groovy-to-kotlin/
jar 包发布: https://docs.gradle.org/6.3/userguide/publishing_maven.html

仓库发布:
远程仓库及用户名和密码设置 https://docs.gradle.org/6.3/dsl/org.gradle.api.artifacts.repositories.MavenArtifactRepository.html
发布配置参考文档 https://docs.gradle.org/6.3/userguide/publishing_maven.html
插件配置:
插件配置 https://plugins.gradle.org/docs/publish-plugin
插件配置 https://docs.gradle.org/6.3/userguide/java_gradle_plugin.html

snapshot 不更新: https://stackoverflow.com/questions/32652738/how-can-i-force-update-all-the-snapshot-gradle-dependencies-in-intellij
maven 库 SNAPSHOT 含义 https://www.jianshu.com/p/998f7bf66c53
gradle error无法找到方法dependencyManagement() http://www.voidcn.com/article/p-tnmjyigx-buo.html

ASM

版本记录: https://asm.ow2.io/versions.html

private val mLambdaMethodCells: HashMap<String, MethodCell> = mutableMapOf<String, MethodCell>()
private val mLambdaMethodCells: HashMap<String, MethodCell> = mutableMapOf<String, MethodCell>() as HashMap<String, MethodCell>

参考文档

【Android】函数插桩(Gradle + ASM) https://www.jianshu.com/p/16ed4d233fd1
ASM基础《深入理解Java虚拟机》JVM指令 https://www.jianshu.com/p/dbe81a531ad6

Kotlin之美——DSL篇 https://www.jianshu.com/p/f5f0d38e3e44

gralde 插桩优化及编译方法优化方案 https://mp.weixin.qq.com/s/e1L6gB_s5H38unSfhf4c6A
字节跳动开源 gradel ASM 插件库 https://github.com/bytedance/ByteX

ASM 版本 及 gradle 插件版本对应关系: https://github.com/luckybilly/CC/issues/161

  • []
  • []
  • []
  • []
  • []
  • []
  • []
  • []
  • []
  • []