Resolving plugin problems with the configuration cache

Hi,

I am trying to make a Gradle plugin of mine (which is written in Kotlin) compatible with Gradle 6.8.3’s configuration cache. However, Gradle is complaining about not being able to serialize some fields, many of which look suspiciously like Kotlin lambdas that I require for lazy properties and task configuration avoidance!

Obviously, if it’s a choice between either task configuration avoidance or supporting the configuration cache, then I will choose task configuration avoidance. However, it would be “nice” to be able to support both features.

Here is what I think is my simplest remaining problem, where a customised Jar task wants to include some manifest tags that must be copied from another jar:

open class MyJar : Jar() {
    ...

    @get:PathSensitive(RELATIVE)
    @get:InputFile
    val sourceJar: RegularFileProperty = objects.fileProperty()

    private val myManifest: Provider<Manifest> = objects.property(Manifest::class.java)
        .value(sourceJar.map { JarFile(it.asFile).use(JarFile::getManifest) })
        .apply(Property<Manifest>::finalizeValueOnRead)

    private fun getAttribute(name: String): Provider<String?> = myManifest.map { man ->
        man.mainAttributes.getValue(name)
    }

    init {
        manifest {
            it.attributes(linkedMapOf(
                MY_TAG_NAME to getAttribute(OTHER_TAG_NAME),
                ...
            ))
        }
    }
}

However, this generates the following warning:

cannot serialize object of type java.io.ByteArrayOutputStream📋, a subtype of java.io.OutputStream📋, as these are not supported with the configuration cache. ?
    ⌄ field baos📋 of java.util.jar.JarVerifier📋
        ⌄ bean of type java.util.jar.JarVerifier📋
            ⌄ field jv📋 of java.util.jar.Manifest📋
                ⌄ bean of type java.util.jar.Manifest📋
                    ⌄ field myManifest📋 of com.example.MyJar📋

AFAIK there is no other way to configure a Jar task’s manifest lazily than to create providers like this. Can anyone suggest how to resolve this please?

Thanks,
Chris

I am only stumbling around in this area as well, so I might be totally wrong about this.

I think the issue is using Manifest as type for your provider, since its not cleanly serializable.
If you change that to - say - a Map and extract the manifest attributes in your providers value() method it might just work.

Hi, thanks for replying :slight_smile:.

My underlying requirement was only to “configure a Jar task’s manifest lazily”, and so I think I eventually solved this by throwing the Provider<Manifest> away and overriding the @TaskAction instead:

@TaskAction
override fun copy() {
    val extraAttributes = linkedMapOf(...)
    manifest.attributes(extraAttributes)
    super.copy()
}

Cheers,
Chris