跳转至

Kotlin 编译器源码阅读

产物构建

通过执行 ./gradlew dist 命令,可以将编译器分发到 dist/kotlinc/ 目录下。

如何调试 Kotlin 编译器

java_version="$(findJavaVersion)"
if [[ $java_version -ge 9 ]]; then
    # Workaround the illegal reflective access warning from ReflectionUtil to ResourceBundle.setParent, see IDEA-248785.
    java_args=("${java_args[@]}" "--add-opens" "java.base/java.util=ALL-UNNAMED")
fi

if [ -n "$KOTLIN_RUNNER" ]; then
    java_args=("${java_args[@]}" "-Dkotlin.home=${KOTLIN_HOME}")
    kotlin_app=("${KOTLIN_HOME}/lib/kotlin-runner.jar" "org.jetbrains.kotlin.runner.Main")
else
    [ -n "$KOTLIN_COMPILER" ] || KOTLIN_COMPILER=org.jetbrains.kotlin.cli.jvm.K2JVMCompiler

    if [[ $java_version < 13 ]]; then
        java_args=("${java_args[@]}" "-noverify")
    fi

    declare additional_classpath=""
    if [ -n "$KOTLIN_TOOL" ]; then
        additional_classpath=":${KOTLIN_HOME}/lib/${KOTLIN_TOOL}"
    fi

    kotlin_app=("${KOTLIN_HOME}/lib/kotlin-preloader.jar" "org.jetbrains.kotlin.preloading.Preloader" "-cp" "${KOTLIN_HOME}/lib/kotlin-compiler.jar${additional_classpath}" $KOTLIN_COMPILER)
fi

"${JAVACMD:=java}" $JAVA_OPTS "${java_args[@]}" -cp "${kotlin_app[@]}" "${kotlin_args[@]}"

通过查看 kotlinc 源码可知,org.jetbrains.kotlin.preloading.Preloader 类是编译器的预加载器,它会加载编译器的主类 org.jetbrains.kotlin.cli.jvm.K2JVMCompiler。因此我们修改Preloader类,运行它的main方法,即可启动与调试编译器,示例如下所示:

String[] testArgs = {"-cp",  "./dist/kotlinc/lib/kotlin-compiler.jar", "org.jetbrains.kotlin.cli.jvm.K2JVMCompiler",
                    "./compilerTestData/Test.kt", "-include-runtime",
                    "-d", "./compilerTestData/Test.jar"
            };
            run(testArgs);

Kotlin/JS 编译器调试

export KOTLIN_COMPILER=org.jetbrains.kotlin.cli.js.K2JSCompiler

DIR="${BASH_SOURCE[0]%/*}"
: ${DIR:="."}

"${DIR}"/kotlinc "$@"

通过以上代码可知,org.jetbrains.kotlin.cli.js.K2JSCompiler 是 Kotlin/JS 编译器的主类,我们可以通过修改K2JSCompiler类,运行它的main方法,即可启动与调试 Kotlin/JS 编译器。

需要注意的是,K2 版本编译器不还不支持直接把 Kotlin 代码编译成 JS 代码,因此需要先把代码编译成 Klib,再把 Klib 编译成 JS 代码,同时 outputDir 不支持相对路径,只支持绝对路径,如下所示

#!/bin/sh

set -e

KOTLIN_HOME= # it should point to Kotlin home directory
BUILD_DIR=`pwd`/build # it must be absolute path

rm -rf $BUILD_DIR
mkdir -p $BUILD_DIR/libs # there should be two separate directories for KLIBs and JS
mkdir -p $BUILD_DIR/app

## first, build KLIB
$KOTLIN_HOME/bin/kotlinc-js \
  -Xir-produce-klib-file \
  -libraries $KOTLIN_HOME/lib/kotlin-stdlib-js.klib \
  -ir-output-dir $BUILD_DIR/libs \
  -ir-output-name main \
  main.kt

## then, build JS
$KOTLIN_HOME/bin/kotlinc-js \
  -Xir-produce-js \
  -libraries $KOTLIN_HOME/lib/kotlin-stdlib-js.klib \
  -Xinclude=$BUILD_DIR/libs/main.klib \
  -ir-output-dir $BUILD_DIR/app \
  -ir-output-name app

因此我们可以通过修改 preloader 类,运行它的 main 方法,即可启动与调试 Kotlin/JS 编译器。

String[] testArgs = {"-cp",  "./dist/kotlinc/lib/kotlin-compiler.jar", "org.jetbrains.kotlin.cli.js.K2JSCompiler",
                    "-libraries","./dist/kotlinc/lib/kotlin-stdlib-js.klib",
                    "-ir-output-dir","/Users/xxx/AndroidProject/leo/kotlin/compilerTestData","-ir-output-name","TestKotlin",
                    "-Xir-produce-klib-file",
                    "./compilerTestData/Test.kt",
            };
            run(testArgs);

最后更新: November 17, 2024