How to apply kotlin serialization in buildscript

I want to use kotlin serialization in the build script itself (build.gradle.kts).
So I added the plugin to the “plugins” block:

plugins {
val kotlinVersion = “1.5.31”
java
application
kotlin(“jvm”) version kotlinVersion
kotlin(“plugin.serialization”) version kotlinVersion
}

I also added the dependency in “buildscript” block:

buildscript {
dependencies {
classpath(group = “com.typesafe”, name = “config”, version = “1.4.1”)
classpath(group = “org.jetbrains.kotlinx”, name = “kotlinx-serialization-hocon”, version = “1.3.0”)
}
}

Then I defined my data classes and I use “@Serializable” annotation on them.
Then I try to extract configuration like this:

tasks {

register(“testConfig”) {
println(“Task testConfig”)
val typesafeConf = com.typesafe.config.ConfigFactory.parseFile(File(“src/env.conf”))
val envConf = Hocon.decodeFromConfig(typesafeConf)
println(envConf)
}
}

The “decodeFromConfig” fails with the following error:

Serializer for class ‘Configuration’ is not found.
Mark the class as @Serializable or provide the serializer explicitly.

But I do use @Serializable. When I hover the mouse over it, I see this:

kotlinx.serialization compiler plugin is not applied to the module, so this annotation would not be processed. Make sure that you’ve setup your buildscript correctly and re-import project.

So the problem is, the plugin is not applied to the buildscript itself.
I tried to put the “apply” inside the buildscript block, could not make it work. It doesn’t like the “plugins” block there; the “apply” statements could not find the plugin anywhere.

How can I make it work?

What you need, is to have the Kotlin Compile plugin added when the serializable class is compiled so that the boilerplate can be generated.

If you define your serializable class within the build script, I don’t think it is possible because afair you cannot influence which compiler plugins are in use to compile the build scripts.

You need to put your serializable classes into an included build or buildSrc where you can make them normal Kotlin classes and control the Kotlin compiler, giving it the compiler plugin it needs.

@Vampire Thanks Björn, the buildSrc solution worked for me.

@Vampire Two more questions, maybe you can help.
First, since I use internal company nexus for repository, with authentication, etc., I want to define it in one place.
So I read Declaring repositories about defining it in settings.gradle.kts. However, the buildSrc still wants to see the repositories defined in its own build script. Why is that? Do I need to resort to use the “allprojects” block?

Another related question. For defining the repository, I need to fetch a few parameters from $HOME/.gradle/gradle.properties. Here is my definition:

val nexusHost: String by project
val nexusUsername: String by project
val nexusPassword: String by project
repositories {
    val nexusRepoUrl = "http://${nexusHost}/repository/public"
    maven {
        isAllowInsecureProtocol = true
        url = uri(nexusRepoUrl)
        credentials {
            username = nexusUsername
            password = nexusPassword
        }
    }
}

It works fine in the main build.gradle.kts, but not in settings.gradle.kts. How can I fix it? This is important because the credentials are different when my projects are built in the build server.

@Vampire Never mind, I solved both issues by putting the repositories definition in buildSrc/build.gradle.kts. Then it magically was applied to the main project too.

@Vampire Sorry, the previous statement appears to be wrong. When I tried distTar task, the main project
could not get some dependencies until I specified repositories in the main build.gradle.kts. So I still don’t know how to minimize the repetition of the code for specifying repositories.

Similar to included builds, a buildSrc build is a complete standalone multi-project build with own settings script and neither does modifying the buildSrc build modify the main build, nor the other way around.

You could for example change buildSrc to an included build, for example build-logic and make another included build that provides a settings plugin configuring the repositories. This build you can then include in the build-logic build and in the main build and apply the settings plugin in both. This way I think you should be able to use the same central respository declaration in for both.