Search code examples
androidkotlingradlegradle-kotlin-dsl

How to access custom code generated by Kotlin DSL?


I have created a default Empty Views Activity project in Android Studio with Kotlin as language and Kotlin DSL as build configuration language. Then I appended the following code to the app level build.gradle.kts.

abstract class CustomTask : DefaultTask() {
    @get:Input
    var generatedCodePath = ""

    @TaskAction
    fun run() {
        val path = File(generatedCodePath).resolve(
            "custom_code/debug/out/com/example/app/CustomCode.kt"
        )
        path.parentFile.mkdirs()
        path.writeText("""
            #package com.example.app
            #
            #public fun customCode() {
            #    println("Hello from custom code!")
            #}
        """.trimMargin("#"))
    }
}

tasks.register<CustomTask>("customTask") {
    generatedCodePath = "$buildDir/generated"
}

tasks.named("preBuild").configure {
    dependsOn("customTask")
}

The idea is that the new CustomTask will generate a file on each build. After sync & rebuild I have checked that indeed the file CustomCode.kt has been correctly generated in app\build\generated\custom_code\debug\out\com\example\app\CustomCode.kt.

Now I have tried to import the function customCode from the generated file to the MainActivity but I have run into unresolved references.

package com.example.gradlegenerate

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.example.app.* // Unresolved reference: app
import com.example.app.CustomCodeKt // Unresolved reference: app

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }
}

Note that the generated file is in package app and the activity in gradlegenerate so there is no name collision.

I tried to add the generated file in the source sets in app level build.gradle.kts and repeat the sync & rebuild & import but no luck.

android {
    sourceSets {
        named("main") {
            java.srcDir("$buildDir/generated/debug/out")
        }
    }
}

What am I missing?


Solution

  • The problem was that the path of the generated code did not match the path added to the source sets.

    In app/build.gradle.kts I've corrected the source sets.

    sourceSets {
        named("main") {
            java.srcDir("$buildDir/generated/custom_code/debug/out")
        }
    }
    

    Note the string custom_code that was missing in the question text.

    Now I could finally import and use the customCode function in the MainActivity.

    package com.example.gradlegenerate
    
    import androidx.appcompat.app.AppCompatActivity
    import android.os.Bundle
    import com.example.app.customCode
    
    class MainActivity : AppCompatActivity() {
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
            customCode()
        }
    }
    

    When I build and run the app the output is then registered by Logcat.

    System.out    com.example.gradlegenerate    I    Hello from custom code!