https://kotlinlang.org logo
#gradle
Title
# gradle
g

Guilherme Delgado

06/20/2022, 2:10 PM
I want to create a custom plugin as follow:
Copy code
class KotlinJvmOptionsPlugin : Plugin<Project> {
    override fun apply(target: Project) {
        with(target) {
            extensions.configure<KotlinJvmOptions> {
                jvmTarget = "11"
                freeCompilerArgs = freeCompilerArgs + listOf("-Xopt-in=kotlin.RequiresOptIn")
            }
        }
    }
}
but it will fail with:
Copy code
Caused by: org.gradle.api.UnknownDomainObjectException: Extension of type 'KotlinJvmOptions' does not exist. Currently registered extension types: [ExtraPropertiesExtension, BasePluginExtension, DefaultArtifactPublicationSet, SourceSetContainer, ReportingExtension, JavaPluginExtension, JavaToolchainService, NamedDomainObjectContainer<BaseVariantOutput>, LibraryExtension, LibraryAndroidComponentsExtension]
How can I solve this and have access to
kotlinOptions
? Thanks 🙂
h

hfhbd

06/20/2022, 2:20 PM
or use
project.configure<FooExtension> { }
v

Vampire

06/20/2022, 2:37 PM
KotlinJvmOptions
simply is not an extension, so you cannot configure it. I guess
LibraryExtension
or
CommonExtension
is the extension you want to configure. You also don't need
extensions.
, you can call
configure
on the project directly and thus just call
configure
as the project is
this
in that lambda anyway. But one important thing to notice, if you write it like that, you introduce an ordering constraint for plugins. Your plugin will onyl work if it is applied after the Kotlin plugin. Such ordering constraints for plugins are bad practice. Better use
pluginManager.withPlugin
to react to the Kotlin plugin being applied for configuring it.
👍 1
g

Guilherme Delgado

06/20/2022, 2:44 PM
I’ve manage to make it work like this:
Copy code
class KotlinJvmOptionsPlugin : Plugin<Project> {
    override fun apply(target: Project) {
        with(target) {
            configure<LibraryExtension> {
                (this as ExtensionAware).extensions.configure<KotlinJvmOptions>("kotlinOptions") {
                    jvmTarget = "11"
                    freeCompilerArgs = freeCompilerArgs + listOf("-Xopt-in=kotlin.RequiresOptIn")
                }
            }
        }
    }
}
But one important thing to notice, if you write it like that, you introduce an ordering constraint for plugins. Your plugin will onyl work if it is applied after the Kotlin plugin. Such ordering constraints for plugins are bad practice. Better use
pluginManager.withPlugin
to react to the Kotlin plugin being applied for configuring it.
This is a good advice because i was having this problem and I didn’t knew what it was. 🙌
Regarding plugin
pluginManager.withPlugin
your suggestion is to do something like this:
Copy code
@Suppress("UnstableApiUsage", "unused")
class KotlinJvmOptionsPlugin : Plugin<Project> {
    override fun apply(target: Project) {
        with(target) {
            with(pluginManager) {
                apply("com.android.library")
                apply("org.jetbrains.kotlin.android")
            }
            
            configure<LibraryExtension> {
                (this as ExtensionAware).extensions.configure<KotlinJvmOptions>("kotlinOptions") {
                    jvmTarget = "11"
                    freeCompilerArgs = freeCompilerArgs + listOf("-Xopt-in=kotlin.RequiresOptIn")
                }
            }
        }
    }
}
?
(if I create more plugins, should I always add this pluginManager logic before, just to make sure I don’t run into ordering problems?)
v

Vampire

06/20/2022, 3:19 PM
Regarding plugin
pluginManager.withPlugin
your suggestion is to do something like this:
No, I did not say
pluginManager.apply
, I said
pluginManager.withPlugin
. But if you want to
apply
you can also do it of course, but you don't need to do it on
pluginManager
, you can do it on the
Project
directly. If you use
apply
you apply the plugin if it is not applied yet (multiple application is prevented automatically). If you use
pluginManager.withPlugin
you are reacting to a plugin being applied. So if your plugin is only sensible with that other plugin applied, so it is kind of a pre-requisite, then yes, apply it. If your plugin can optionally do some work in case another plugin is applied but not do it if that plugin does not get applied, use
pluginManager.withPlugin
.
And yes, in every plugin where you interact with another plugin you should either apply that other plugin or react to it being applied or you have ordering constraints.
g

Guilherme Delgado

06/20/2022, 3:24 PM
Thanks 🙏
👌 1
122 Views