Kotlin-KCP的应用-第二篇
前言
接Kotlin-KCP的应用-第一篇,本文是第二篇,以下是本文的目标:
- 记录如何简单搭建 KCP 开发环境
- 使用 KCP 解决第一篇中的问题
何为KCP?为何不使用KSP?
KSP
KSP 即 Kotlin Symbol Processing(Kotlin符号处理器),KSP 目前只能生成代码,不能修改字节码,第一篇中的问题需要修改字节码,因此 KSP 不能满足需求
KCP
KCP 即 Kotlin Compiler Plugin(Kotlin编译器插件),在 kotlinc 过程中提供 hook 时机,在此期间可以生成代码、修改字节码等
标准的 KCP 架构如下1:

Plugin
- Gradle 插件,与 Kotlin 无关,在 build.gradle 脚本中提供一个入口
- 通过 Gradle 扩展设置配置信息
Subplugin
- 介于 Gradle 和 Kotlin 直接的 APIs 接口
- 读取 Gradle 扩展配置信息并写入
SubpluginOptions - 定义编译器插件的唯一
ID - 定义 Kotlin 插件的 Maven 坐标信息,便于编译器下载它
CommandLinProcessor
- 设置 Kotlin 插件唯一 ID
- 读取 kotlinc -Xplugin 参数
- 读取
SubpluginOptions配置信息,并写入CompilerConfigurationKeys
ComponentRegistrar
- 读取
CompilerConfigurationKeys - 注册
Extension到各编译流程
Extension
- 生成代码
- 修改字节码
- 多种类型的扩展,比如
- ExpressionCodegenExtension
- ClassBuilderInterceptorExtension
- StorageComponentContainerContributor
- IrGenerationExtension
实现KCP
目标
根据 KCP 的架构,下面一一进行实现

上图是本仓库架构,旨在通过 KCP 在 Java 字节码中 @Hide 注解目标上设置 ACC_SYNTHETIC 标识,使其在 Java 中不能正常调用,达到隐藏 API 的效果
build.gradle - project level
在项目级别的 build.gradle 脚本中配置插件依赖
buildscript {
// 配置 Kotlin 插件唯一ID
ext.kotlin_plugin_id = "com.guodong.android.mask.kcp"
// 配置 Kotlin 插件版本
ext.plugin_version = 'x.x.x'
}
plugins {
// 配置 Gradle 发布插件,可以不再写 META-INF
id("com.gradle.plugin-publish") version "0.16.0" apply false
// 配置生成 BuildConfig 插件
id("com.github.gmazzo.buildconfig") version "3.0.3" apply false
id 'org.jetbrains.kotlin.jvm' version '1.6.10' apply false
}
plugin-gradle
接下来编写 Gradle 插件,此插件对应 KCP 架构中的 Plugin 和 Subplugin
首先配置下 build.gradle.kts 脚本
build.gradle.kts - module level
plugins {
id("java-gradle-plugin")
kotlin("jvm")
id("com.github.gmazzo.buildconfig")
}
dependencies {
implementation(kotlin("gradle-plugin-api"))
}
buildConfig {
// 配置 BuildConfig 的包名
packageName("com.guodong.android.mask.kcp.gradle")
// 设置 Kotlin 插件唯一 ID
buildConfigField("String", "KOTLIN_PLUGIN_ID", "\"${
rootProject.extra["kotlin_plugin_id"]}\"")
// 设置 Kotlin 插件 GroupId
buildConfigField("String", "KOTLIN_PLUGIN_GROUP", "\"com.guodong.android\"")
// 设置 Kotlin 插件 ArtifactId
buildConfigField("String", "KOTLIN_PLUGIN_NAME", "\"mask-kcp-kotlin-plugin\"")
// 设置 Kotlin 插件 Version
buildConfigField("String", "KOTLIN_PLUGIN_VERSION", "\"${
rootProject.extra["PLUGIN_VERSION"]}\"")
}
gradlePlugin {
plugins {
create("Mask") {
id = rootProject.extra["kotlin_plugin_id"] as String // `apply plugin: "com.guodong.android.mask.kcp"`
displayName = "Mask Kcp"
description = "Mask Kcp"
implementationClass = "com.guodong.android.mask.kcp.gradle.MaskGradlePlugin" // 插件入口类
}
}
}
tasks.withType<KotlinCompile

本文详细介绍了如何在Kotlin项目中利用Kotlin Compiler Plugin (KCP)搭建开发环境,通过插件实现对Java字节码的@Hide注解处理,以达到隐藏API的目的。从配置Gradle插件到编写Kotlin编译器插件,一步步展示了KCP的完整应用过程。
最低0.47元/天 解锁文章
1305

被折叠的 条评论
为什么被折叠?



