¿Cómo puedo hacer que las extensiones de Gradle evalúen perezosamente las propiedades que las tareas establecen dinámicamente?

Soy bastante nuevo en trabajar con Gradle y estoy tratando de desarrollar un complemento que ayude a administrar la numeración de versiones. Este complemento define una tarea que establece elproject.version propiedad del proyecto al que se aplica.

Lo que intento hacer es hacer que esta propiedad se establezca al comienzo de cada compilación de Gradle. UtilizandoLa respuesta de Peter a otra pregunta de Gradle, Logré ejecutar mi tarea antes que ninguna otra agregandogradle.startParameter.taskNames = [":setProjectVersionNumber"] + gradle.startParameter.taskNames dentro de mi pluginapply método.

Sin embargo, otros complementos (especialmente 'Maven-Publish') dependen de la versión que se especifica durante la fase de configuración:

publishing {
    publications {
        somePublication(MavenPublication) {
            version = project.version
        }
    }
}

Lo que me gustaría saber es si hay una forma en que pueda hacer la evaluación de propiedades comoversion dentro de estas extensiones lo más vago posible, de modo que no se evalúen hasta que se llame una tarea que depende de ellas, que en este caso podría ser:publishToMavenLocal.

A continuación se muestra un SSCCE que demuestra lo que espero lograr:

// This would be included within the plugin
class SetProjectVersionNumber extends DefaultTask {

    @TaskAction
    void start() {
        // This will set project.version during execution phase
        project.version = "1.2.3"
        logger.info "Set project version number: $project.version"
    }
}

task setProjectVersionNumber(type: SetProjectVersionNumber)

// Imagine this block being replaced by a maven 'publishing' block (or something similar)
ext {
    version = project.version

    // This will print 'unspecified', as it's evaluated during configuration phase
    println "In extension, setting version=$project.version"
}

Si puedes proporcionar una manera de hacerext.version igual1.2.3 En el ejemplo anterior, creo que has resuelto mi problema.

Si esto es pedir demasiado, es posible que mi plugin genere la cadena de versión en el momento de la configuración en lugar del tiempo de ejecución. Sin embargo, sería bueno saber si pudiera hacerlo de esta manera.

EDITAR

En una rama experimental, intenté mover toda la lógica de asignación de cadenas de versión a la fase de configuración (haciendo que todo suceda durante la aplicación del complemento en lugar de durante la ejecución de la tarea), pero no creo que esto funcione ya que la extensión del complemento no sin embargo, se ha procesado e intenta hacer referencia a las propiedades definidas en él fallan.

EDITAR 2

Envolviendo la lógica de asignación de cadena de versión en unproject.afterEvaluate el cierre parece haber funcionado:

@Override
public void apply(Project project) {
    logger = project.logger
    project.extensions.create(EXTENSION_NAME, SemVerPluginExtension)

    project.afterEvaluate {
        setVersionProjectNumber(project)
        addTasks(project)
    }
}

En un proyecto simulado, implementobuild.gradle como sigue:

apply plugin: 'semver'
apply plugin: 'maven-publish'

group = 'temp'

buildscript {
    repositories {
        mavenLocal()
        jcenter()
    }
    dependencies {
        classpath 'com.github.tagc:semver-plugin:0.2.2'
    }
}

semver {
    versionFilePath = 'version.properties'
}

publishing {
    publications {
        testPublication(MavenPublication) {
            version = project.version
            assert version
            println "Set publication version to $version"
        }
    }
}

Por alguna razón, esto parece funcionar. Aunque la lógica de asignación de cadena de versión está envuelta en un cierre 'afterEvaluate' y la asignación de versión de publicación de prueba no lo es, la primera todavía ocurre antes de la segunda:

Compiling build file '/Users/davidfallah/Documents/semver/TestSemver2/build.gradle' using StatementExtractingScriptTransformer.
Compiling build file '/Users/davidfallah/Documents/semver/TestSemver2/build.gradle' using BuildScriptTransformer.
VERSION FILE PATH=version.properties
Current Git branch: develop
Set project version to 0.2.1-SNAPSHOT
Set publication version to 0.2.1-SNAPSHOT
All projects evaluated.

Dejo esta pregunta abierta y sin resolver ya que todavía me gustaría saber si es posible hacerlo de la manera que originalmente pretendía. Además, agradecería cualquier explicación sobre por qué se asigna la versión de publicación después de configurar la versión del proyecto, y si puedo confiar en que ese sea siempre el caso o si eso está sucediendo ahora por accidente.

Respuestas a la pregunta(1)

Su respuesta a la pregunta