Как я могу заставить расширения Gradle лениво оценивать свойства, которые динамически устанавливаются задачами?

Я новичок в работе с Gradle и пытаюсь разработать плагин, который помогает управлять нумерацией версий. Этот подключаемый модуль определяет задачу, которая устанавливает свойство project.version проекта, к которому он применяется.

Я пытаюсь сделать так, чтобы это свойство устанавливалось в начале каждой сборки Gradle. Используя ответ Питера на другой вопрос Gradle, мне удалось выполнить свою задачу раньше любой другой, добавив gradle.startParameter.taskNames = [":setProjectVersionNumber"] + gradle.startParameter.taskNames в свой метод apply плагина.

Однако другие плагины (особенно «Maven-publish») полагаются на версию, указанную на этапе настройки:

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

Я хотел бы знать, есть ли способ сделать оценку таких свойств, как version в этих расширениях, максимально ленивой, чтобы они не оценивались до тех пор, пока не будет вызвана задача, которая зависит от них, что в этом случай может быть :publishToMavenLocal.

Ниже приведен SSCCE, демонстрирующий, чего я надеюсь достичь:

// 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"
}

Если вы можете предоставить способ сделать ext.version равным 1.2.3 в приведенном выше примере, я думаю, вы решили мою проблему.

Если это требует слишком многого, я могу заставить мой плагин генерировать строку версии во время настройки, а не во время выполнения. Хотя было бы неплохо узнать, смогу ли я сделать это таким образом.

ИЗМЕНИТЬ

В экспериментальной ветке я попытался перенести всю логику назначения строки версии на фазу конфигурации (заставив все это происходить во время приложения плагина, а не во время выполнения задачи), но я не верю, что это будет работать, поскольку расширение плагина не еще не был обработан, и попытка сослаться на свойства, определенные в нем, не удалась.

ИЗМЕНИТЬ 2

Кажется, сработало закрытие логики назначения строки версии в замыкании project.afterEvaluate:

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

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

В фиктивном проекте я реализую build.gradle следующим образом:

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"
        }
    }
}

Почему-то кажется, что это работает. Хотя логика присвоения строки версии заключена в замыкание afterEvaluate, а присвоение версии тестовой публикации — нет, первое все равно происходит перед вторым:

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.

Я оставляю этот вопрос открытым и нерешенным, так как мне все еще хотелось бы знать, возможно ли сделать это так, как я изначально планировал. Кроме того, я был бы признателен за любое объяснение того, почему версия публикации назначается после установки версии проекта, и могу ли я полагаться на то, что это всегда так, или это происходит случайно сейчас.


person Tagc    schedule 29.12.2014    source источник


Ответы (1)


Вы можете использовать отложенное создание экземпляров GString для оценки свойства во время выполнения:

project.tasks.create("example_task", Exec.class, {
    commandLine 'echo', "${-> project.someproperty}"
})

Обратите внимание, что вы должны использовать кавычки, а не апострофы — "${...}" работает, а '${...}' — нет.

person Rob Watts    schedule 15.07.2016
comment
Ваше здоровье. Я спрашивал об этом так давно, что я наполовину забыл язык, не говоря уже о том, чтобы все еще работать над этим проектом, чтобы проверить это, но кажется правдоподобным, что он должен работать. - person Tagc; 16.07.2016