ksp 配置篇

2,039 阅读3分钟

前言:并非所有的gradle版本都可以实现ksp,我尝试过最低的gradle版本是6.5.1-bin,插件版本则是对应的4.1.0,可以完美运行。而再低的6.1.1-bin,插件版本是4.0.2则会报错。而在gradle版本上到7之后。编译是没问题的,但是其需要的jdk版本是jdk11。所以使用什么样的gradle请根据实际情况选择

目录
ksp是什么
ksp的用途
配置ksp
使用poet生成文件
总结

1、ksp是什么

ksp全拼是:kotlin Symbols Process,kotlin符号处理。
你可以理解ksp是kotlin原生的类似java的APT(Annotation Processing Tool),但是功能更强的用于元编程的一种技术。

ksp的用途

ksp有什么用呢?
我现在也不知道他能用来干多少事情,但是我可以确定的是,ksp最起码可以充当注解处理器。这可能是他唯一的用处,也可能不是。

那同样是用来处理注解的,为什么我需要用ksp而不用以前的apt甚至kapt呢?
无论是apt还是kapt,都是以java的符号处理为基础而运行的。也就是说,我需要处理kotlin的符号,首先需要转成java,然后再处理,这其中就存在性能问题,也就是编译的时间会变长。于是ksp便应运而生了。
下面就进入本篇的正题——如何配置ksp

配置ksp

对于ksp配置影响较大的部分就是gradle。这里使用的版本是:
gradle version:6.5.1-bin
gradle 插件 version:4.1.0
kotlin version : 1.5.31

1、创建一个modue用于存放注解

04A0BE05-AA24-482B-A9D9-30BB0E0CBEAC.png

2、创建module用于存放符号处理器

84132745-219F-45B6-8B01-1898E041A294.png
2.1、修改build.gradle文件:

plugins {
    id 'kotlin'
    id 'org.jetbrains.kotlin.jvm' //jvm插件
}

compileKotlin {
      kotlinOptions {
        jvmTarget = "1.8"
		  //需要设置,否者可能无法生成文件
        freeCompilerArgs += "-Xuse-experimental=com.squareup.kotlinpoet.ksp.KotlinPoetKspPreview"
        freeCompilerArgs += "-Xuse-experimental=com.google.devtools.ksp.KspExperimental"
    }
}

dependencies {
    //ksp依赖
    implementation("com.google.devtools.ksp:symbol-processing-api:$ksp_version")//ksp_version = "1.5.31-1.0.0"
    //poet依赖,poet用于生成kotlin文件
    implementation("com.squareup:kotlinpoet:1.10.2")
    implementation("com.squareup:kotlinpoet-ksp:1.10.0")
    //注解依赖
    implementation project(":anno")
}

2.2、创建符号处理器

class TestSProcessor(private val environment: SymbolProcessorEnvironment) :
    SymbolProcessor {
    private val logger = environment.logger
    override fun process(resolver: Resolver): List<KSAnnotated> {
	//logging和info级别的log有可能无法在build中看见,请使用warn或error级别
        //logger.logging("test log run")
        //logger.info("test info run")
        logger.warn("test warn run")
        return emptyList()
    }
}

2.3、创建符号处理器提供者

class TestSProcessorProvider : SymbolProcessorProvider {
    override fun create(environment: SymbolProcessorEnvironment): SymbolProcessor {
		//返回值是符号处理器
        return TestSProcessor(environment)
    }
}

在main下创建resources文件夹,并按第二大点的截图添加文件。在文件中加入 com.erolc.complier.TestSProcessorProvider,是你符号处理器提供者的完整类名。

2.5、在app的build.gradle配置ksp

plugins {
	//...
    id 'com.google.devtools.ksp' version "$ksp_version" //加入ksp插件
}

dependencies {
ksp project(":complier")//使用符号处理器
implementation project(":anno")//加入注解
}

这样就可以进行调试了。如果在build中看到以下日志证明配置初步完成:

5694808E-1D9A-4EE3-B4B9-9867F01A93E7.png

使用poet生成文件

在符号处理器(TestSProcessor)的processs方法中加入以下简单代码用于测试:

override fun process(resolver: Resolver): List<KSAnnotated> {
    resolver.getSymbolsWithAnnotation(Test::class.qualifiedName!!)
    .filterIsInstance<KSClassDeclaration>()
    .toSet().forEach {
        FileSpec.builder(
            it.packageName.asString(),
            "${it.simpleName.asString()}$\$Test"
        ).addFunction(FunSpec.builder("test")
            .addStatement("return 12")
            .build())
            .build().writeTo(KspContext.environment.codeGenerator, false)
    }
}

现在不需要知道这段代码的具体意思,只需要知道这段代码是识别Test注解,并生成一个文件,文件中只有一个test方法即可。
然后我们在app模块中使用一下Test注解

@Test
class DataDemo

调试一下,如果在app模块的相应位置中生成对应文件代表生成文件也没问题了。

13973C43-36CC-479F-86B0-18075FF4123A.png

生成的文件内部是这样的:

0C11A42D-BC54-4DCA-9977-4742F2FAABED.png

但是这时我们去使用这个test方法会报错

398594B3-DC30-4501-BCE0-DF1719AF4DB7.png
这是因为并代码不知道怎么去找这个方法,所以需要在app模块中配置一下sourceSrc,让代码能找到它

android{
	//...
	buildTypes{
	//...
		debug{
		 sourceSets {
                main {
                    java {
                        srcDirs += ['build/generated/ksp/debug/kotlin']
                    }
//              gradle.7.0配置
//                    kotlin{
//                        srcDirs = ['build/generated/ksp/debug/kotlin']
//                    }
                }
            }

		}
	}
}

注意:如果是通过release的方式build,那么该文件就会出现在release文件夹内而不是debug。而sourceSets也需要设置在buildTypes为release中。
这时我们再看会生成的文件,会是这样的:
3A84801F-A74F-49F6-88DD-E2C3AFFCCB52.png
证明sourceSets已经起作用了,而我们使用的地方也不报错了:

640AECE1-5E95-4E49-A9D7-FE3B512E1501.png
到这里,ksp的配置就完成了。

总结

ksp可以像apt那样,识别kotlin代码,然后去解析,并通过kotlinpote去生成kotlin文件,是kotlin原生的符号处理技术。完整的源码已经上传到github上,希望对你有帮助。传送门