第二章 开发环境搭建: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-embeddablekotlin-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」模式。配置步骤其实不复杂:

  1. 创建一个新的IntelliJ Platform Plugin项目
  2. plugin.xml 中声明你的编译器插件
  3. 配置运行配置为「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。每一步都有坑,但踩过一次就记住了。我刚开始做的时候,光环境就折腾了一周。现在回想起来,其实都是些小问题——版本不对、路径写错、依赖漏了。你按上面的步骤来,应该能省不少时间。

下一章咱们开始写真正的编译器插件逻辑,到时候你会觉得,环境搭建那点苦,值了。