I want to use 3d party library in my project build process. Library methods requires ScriptEngine. When I'm trying to instantiate it i got an error:
java.lang.IllegalArgumentException: Unable to construct script definition: Unable to load base class kotlin.script.experimental.api.KotlinType@42842bb8
at kotlin.script.experimental.host.ConfigurationFromTemplateKt.getTemplateClass(configurationFromTemplate.kt:189)
at kotlin.script.experimental.host.ConfigurationFromTemplateKt.createScriptDefinitionFromTemplate(configurationFromTemplate.kt:36)
at kotlin.script.experimental.jsr223.KotlinJsr223DefaultScriptEngineFactory.<init>(KotlinJsr223DefaultScriptEngineFactory.kt:74)
at ce.domain.usecase.load.LoadMetaFilesForTargetUseCase.invoke(LoadMetaFilesUseCase.kt:17)
at ce.domain.usecase.entry.BuildProjectUseCase.invoke(BuildProjectUseCase.kt:24)
at ce.domain.usecase.entry.BuildProjectUseCase.invoke$default(BuildProjectUseCase.kt:18)
at Build_gradle$$$result$1.invoke(build.gradle.kts:68)
at Build_gradle$$$result$1.invoke(build.gradle.kts:60)
at org.gradle.kotlin.dsl.ProjectExtensionsKt$sam$org_gradle_api_Action$0.execute(ProjectExtensions.kt)
at org.gradle.api.internal.tasks.DefaultTaskContainer.create(DefaultTaskContainer.java:368)
at org.gradle.kotlin.dsl.ProjectExtensionsKt.task(ProjectExtensions.kt:147)
at Build_gradle.<init>(build.gradle.kts:60)
...
I've reproduced issue with simple grdale project: Sample project gradle:
import kotlin.script.experimental.jsr223.KotlinJsr223DefaultScriptEngineFactory
plugins {
kotlin("jvm") version "1.8.21"
application
}
repositories {
mavenCentral()
}
buildscript {
repositories {
mavenCentral()
google()
}
dependencies {
classpath("org.jetbrains.kotlin:kotlin-scripting-jsr223:1.8.10")
classpath("org.jetbrains.kotlin:kotlin-scripting-common:1.8.10")
classpath("org.jetbrains.kotlin:kotlin-compiler-embeddable:1.8.10")
classpath("org.jetbrains.kotlin:kotlin-reflect")
}
}
dependencies {
testImplementation(kotlin("test"))
}
abstract class TestProjectTask : DefaultTask() {
@get: InputFile
abstract val projectFile: RegularFileProperty
@TaskAction
fun execute() {
try {
val eng2 = KotlinJsr223DefaultScriptEngineFactory().getScriptEngine()
println("Project file = ${projectFile.get()} $eng2")
val worker = Worker()
worker.doWork(eng2, projectFile.asFile.get().absolutePath)
} catch (err: Throwable) {
err.printStackTrace()
}
}
}
task("hello2", TestProjectTask::class) {
projectFile.set(File("./project.kts"))
}
KotlinJsr223DefaultScriptEngineFactory().getScriptEngine() always throws same exception.
Thanks to work done by contributors in this issue and the linked comment thread, the answer is relative simple, even if discovering how to do it was not! I've cleaned up the provided workaround.
Summary:
K2JVMCompilerto generate the sourcesI recommend using a buildSrc convention plugin to set up the requisite logic. It helps keep the build scripts cleaner and more declarative, and setup-logic is contained within buildSrc.
Kotlin dependencies
First, make sure that the
K2JVMCompilerclass is available.If you're working in a single
build.gradle.kts, then this can be achieved by applying the Kotlin plugin:Or if writing a plugin/pre-compiled script plugin, add a dependency on the Kotlin Gradle Plugin in the project's
build.gradle.kts.A compile-time dependency on
kotlin-compiler-embeddableis required for accessing theK2JVMCompilerclass.Run task
Next, let's create the task that will be used to run the
.main.ktsfiles.In order to run a Kotlin script, we need a few things:
In order to follow Gradle best practices, tracking task's input and output files is also important (but is not strictly required).
(As previously mentioned, it's best to do this in a buildSrc directory, but you can paste this task into a regular
build.gradle.ktstoo.)Compile and Runtime dependencies
Let's use a pre-compiled convention plugin to define how to fetch the dependencies needed to compile and run a Kotlin script.
We now have two Configurations that contain the requisite dependencies. In the same convention plugin, let's add those dependencies to all RunKotlinScript tasks.
Creating run tasks
This convention plugin can be applied to any script in the project:
and then you can create a task, which will be correctly configured
and can be run, using Gradle