So, I have a couple of build convention plugins th...
# community-support
t
So, I have a couple of build convention plugins that have a custom extension and I want to read the actual values that the consumer of the plugin configures with that extension and set the values onto an "upstream" Gradle plugin's extension. What I did so far (and what worked in a whacky way) was always to configure the upstream's extension in an
afterEvaluate {}
block, because only then my
build.gradle.kts
/ custom extension configured values became available, but for a specific upstream plugin this no longer works, because I have to configure things early. Is there a better way of achieving this, i.e. another callback that is run in configuration phase after the build script has been evaluated?
m
Add a function to your extension:
Copy code
abstract class MyExtension {
  fun doStuff(action: Action<MySpec>) {
    // ...
  }
}
This way you can run your logic when the user sets the values
e
or just expose the upstream plugin's properties as your own
1
Copy code
abstract class MyExtension @Inject constructor(
    private val upstreamExtension: UpstreamExtension
) {
    val upstreamLazyProperty: Property<Foo>
        get() = upstreamExtension.lazyProperty
    var upstreamNonLazyProperty: Foo by upstreamExtension::nonLazyProperty
m
Assuming everything is lazy, you can also use
pluginManager.withId()
:
Copy code
val myExtension = extensions.create(...)
pluginManager.withId("myupstream.plugin") {
  // 
  upstreamExtension.property.set(myExtension.property)
}
t
Ok, thanks for the pointers!
v
The question is, why you ever needed
afterEvaluate
, assuming your extension uses
Property
and the upstream extension uses
Property
, you can just wire them together anytime, when the value is set is pointless. That's exactly the reason
Property
exists
If one of them of course still uses the legacy way of primitive types, then yes, what @ephemient said if it is the upstream one, use a function on the extension instead of properties, or change yours if it is only yours.
Besides that the upstream plugin needing eager configuration also sounds like a smell already. 🙂
t
Well, I could reconfigure it in a way to work now. The culprit was actually that I need the
project.version
property being configured as an output of my build convention, but since this has no lazy-set equivalent as of now (https://github.com/gradle/gradle/issues/13672), I figured I just need to wrap this particular part into an
afterEvaluate
. This is basically what I'm doing now, the rest of the plugin is configured as it should (
VersionConfig
comes from the Axion Release Plugin):
Copy code
afterEvaluate {
    val pluginVersion =
        try {
            lateinit var version: String
            configure<VersionConfig> {
                version = this.version
            }
            version
        } catch (e: FileNotFoundException) {
            logger.warn("Skipping application of version plugin, because we're in a git worktree which is unsupported")
            "0.0.1-unknown"
        }

    project.version = pluginVersion
}
e
why not just unconditionally set
project.version
?
Copy code
project.version = object {
    override fun toString() = try {
        lateinit var version: String
        configure<VersionConfig> {
            version = this.version
        }
        version
    } catch (e: FileNotFoundException) {
        logger.warn("Skipping application of version plugin, because we're in a git worktree which is unsupported")
        "0.0.1-unknown"
    }
}
👍 1