第二章 开发环境搭建:Gradle配置、Kotlin编译器源码编译、IDE插件开发环境配置
好,咱们直接进入正题。做编译器插件开发,环境搭不对,后面全是坑。我见过太多人卡在第一步,明明代码逻辑没问题,编译就是不通过。说白了,环境配置就是你的「工欲善其事」——这块花点时间,后面能省十倍精力。
2.1 Gradle配置:插件的构建基石
Kotlin编译器插件本质上是一个Gradle项目。你想想看,它要嵌入到编译流程里,自然得用Gradle来管理依赖和构建。我个人习惯用Kotlin DSL写构建脚本,类型安全,写起来也顺手。
先看一个最基础的 build.gradle.kts:
plugins {
kotlin("jvm") version "1.9.0"
id("org.jetbrains.kotlin.plugin.compiler") version "1.9.0"
}
repositories {
mavenCentral()
maven("https://maven.pkg.jetbrains.space/public/p/kotlin/dev")
}
dependencies {
// 编译器插件API
compileOnly("org.jetbrains.kotlin:kotlin-compiler-embeddable:1.9.0")
// 测试框架
testImplementation("org.jetbrains.kotlin:kotlin-test:1.9.0")
testImplementation("org.jetbrains.kotlin:kotlin-compiler:1.9.0")
}
tasks.withType<KotlinCompile> {
kotlinOptions.jvmTarget = "17"
}
关键点:kotlin-compiler-embeddable 和 kotlin-compiler 的区别。前者是嵌入版,适合插件开发;后者是完整版,测试时用。我在项目中遇到过把依赖搞反的情况,结果运行时类冲突,排查了半天。
嗯,这里要注意版本号必须一致。Kotlin编译器API在不同版本间可能有破坏性变更,我建议锁定一个稳定版本,比如1.9.x系列。
2.2 Kotlin编译器源码编译:从源码开始理解
为什么要自己编译Kotlin编译器?说白了,调试插件时你需要断点进编译器内部。光看文档不够,源码里藏着很多细节。
我建议你从GitHub上克隆Kotlin仓库:
git clone https://github.com/JetBrains/kotlin.git
cd kotlin
git checkout v1.9.0 # 切到对应版本
编译命令很简单,但耗时很长——我第一次编译等了将近40分钟。别急,这是正常的。
./gradlew :kotlin-compiler:dist
小技巧:如果你只需要编译器核心模块,可以只编译 :kotlin-compiler-embeddable:dist,能省一半时间。我曾经为了省时间试过只编译子模块,结果依赖没跟上,编译失败。后来学乖了,老老实实全量编译一次,后面增量编译就快了。
编译完成后,在 dist/kotlinc 目录下就能看到完整的编译器。你可以用 ./dist/kotlinc/bin/kotlinc 来测试你的插件。
2.3 IDE插件开发环境配置:调试才是王道
写编译器插件,最痛苦的是什么?调试。你不能像普通应用那样直接跑起来看效果。必须把插件加载到IDE里,然后观察编译过程。
我推荐用IntelliJ IDEA的「Plugin DevKit」模式。配置步骤其实不复杂:
- 创建一个新的IntelliJ Platform Plugin项目
- 在
plugin.xml中声明你的编译器插件 - 配置运行配置为「Plugin」类型
看一个 plugin.xml 的示例:
<idea-plugin>
<id>com.example.mycompilerplugin</id>
<name>My Compiler Plugin</name>
<version>1.0.0</version>
<vendor email="support@example.com">Example</vendor>
<depends>com.intellij.modules.platform</depends>
<depends>org.jetbrains.kotlin</depends>
<extensions defaultExtensionNs="org.jetbrains.kotlin">
<compilerPlugin implementation="com.example.MyCompilerPlugin"/>
</extensions>
</idea-plugin>
避坑指南:我曾经忘记在 plugin.xml 里声明 depends 依赖,结果插件加载了但编译器扩展没生效。IDE日志里没有任何错误提示,排查了整整两天。所以,org.jetbrains.kotlin 这个依赖一定要写上。
运行配置也很关键。在IDEA里新建一个「Plugin」运行配置,选择「Use classpath of module」为你的插件模块。然后点击调试按钮,IDEA会启动一个新的IDE实例,你的插件就在里面运行。
2.4 环境验证:确保一切就绪
配置完了怎么验证?写一个最简单的插件试试。我习惯写一个「Hello World」级别的编译器插件:
class HelloWorldPlugin : CompilerPlugin {
override fun process(module: Module, context: CompilerContext) {
println("Hello from compiler plugin!")
}
}
然后在测试代码里调用:
fun main() {
// 你的Kotlin代码
println("Hello, World!")
}
如果编译时控制台输出了「Hello from compiler plugin!」,说明环境搭建成功。如果没有,检查一下 plugin.xml 里的实现类路径是否正确。
个人经验:我建议在项目根目录放一个 local.properties 文件,指定Kotlin编译器的本地路径。这样调试时可以直接用你编译好的版本,不用每次都下载。配置如下:
kotlin.compiler.home=/path/to/your/kotlin/dist/kotlinc
2.5 常见问题与解决方案
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 编译时提示类找不到 | 依赖版本不匹配 | 检查所有Kotlin相关依赖版本是否一致 |
| 插件加载但没生效 | plugin.xml配置错误 | 检查extension的implementation类路径 |
| IDE启动后插件不显示 | 缺少depends声明 | 在plugin.xml中添加org.jetbrains.kotlin依赖 |
| 编译速度极慢 | 全量编译了所有模块 | 使用增量编译或只编译必要模块 |
嗯,环境搭建这块就这些。说白了,就是三个步骤:配Gradle、编译编译器、配IDE。每一步都有坑,但踩过一次就记住了。我刚开始做的时候,光环境就折腾了一周。现在回想起来,其实都是些小问题——版本不对、路径写错、依赖漏了。你按上面的步骤来,应该能省不少时间。
下一章咱们开始写真正的编译器插件逻辑,到时候你会觉得,环境搭建那点苦,值了。