我怎样才能让Gradle扩展懒洋洋地评估由任务动态设置的属性? [英] How can I make Gradle extensions lazily evaluate properties that are set dynamically by tasks?

查看:103
本文介绍了我怎样才能让Gradle扩展懒洋洋地评估由任务动态设置的属性?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对使用Gradle非常新,我正在尝试开发一个帮助管理版本编号的插件。这个插件定义了一个任务来设置它应用到的项目的 project.version 属性。



m试图做的是让这个属性设置在每个Gradle构建的开始。使用彼得对另一个Gradle问题的回答,我设法让我的任务在任何其他人之前执行,方法是将 gradle.startParameter.taskNames = [:setProjectVersionNumber] + gradle.startParameter.taskNames 在我的插件的 apply 方法中。



然而,其他插件(特别是'Maven-publish')依赖于在配置阶段指定的版本:

出版物{
somePublication(MavenPublication){
version = project.version
}
}
}

我想知道的是,如果有一种方法可以对属性进行评估这些扩展中的 version 尽可能地延迟 - 这样它们才会被调用,直到调用依赖它们的任务为止,在这种情况下,它可能是:publishToMavenLocal

以下是一个SSCCE,展示了我希望实现的目标:

  //这将包含在插件中
class SetProjectVersionNumber extends DefaultTask {

@TaskAction
void start(){
//这将在执行阶段设置project.version
project.version =1.2.3
logger.info设置项目版本号:$ project.version
}
}

任务setProjectVersionNumber(类型:SetProjectVersionNumber)

//想象一下这个块被一个Maven的'发布'块(或者类似的东西)取代
ext {
version = project.version

//这将打印'unspecified',因为它在配置阶段被评估
println在扩展中,设置版本= $ 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)
}
}

在模拟项目中ct,我执行 build.gradle 如下:

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

group ='temp'

buildscript {
repositories {
mavenLocal )
jcenter()
}
依赖关系{
classpath'com.github.tagc:semver-plugin:0.2.2'
}
}

semver {
versionFilePath ='version.properties'
}

发布{
出版物{
testPublication(MavenPublication){
version = project.version
assert version
println设置发布版本为$版本
}
}
}

由于某些原因,这似乎起作用了。虽然版本字符串赋值逻辑封装在'afterEvaluate'结束中,并且测试发布版本分配不是,但前者仍然出现在后者之前:

 使用StatementExtractingScriptTransformer编译构建文件'/Users/davidfallah/Documents/semver/TestSemver2/build.gradle'。 
使用BuildScriptTransformer编译构建文件'/Users/davidfallah/Documents/semver/TestSemver2/build.gradle'。
VERSION FILE PATH = version.properties
当前Git分支:develop
将项目版本设置为0.2.1-SNAPSHOT
将发布版本设置为0.2.1-SNAPSHOT
所有项目评估。

由于我仍然想知道是否可以按照我最初的意图去做。另外,我希望能够解释为什么在项目版本设置之后分配发布版本,以及我是否可以依赖于这种情况,或者是否意外地发生了这种情况。

解决方案

您可以使用

  project.tasks。 =nofollow> GStrings的懒惰实例化在运行时评估属性: create(example_task,Exec.class,{
commandLine'echo',$ { - > project.someproperty}
})

请注意,您必须使用引号而不是撇号 - $ {...}可以工作,但'$ {...}'没有。


I'm pretty new to working with Gradle and I'm trying to develop a plugin that helps manage version numbering. This plugin defines a task that sets the project.version property of the project it's applied to.

What I'm trying to do is make it so that this property is set at the start of every Gradle build. Using Peter's answer to another Gradle question, I've managed to get my task to execute before any other by adding gradle.startParameter.taskNames = [":setProjectVersionNumber"] + gradle.startParameter.taskNames within my plugin's apply method.

However, other plugins (notably 'Maven-publish') rely on the version being specified during the configuration phase:

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

What I'd like to know is if there's a way that I can make the evaluation of properties like version within these extensions as lazy as possible - such that they're not evaluated until a task that depends upon them is called, which in this case might be :publishToMavenLocal.

Below is an SSCCE that demonstrates what I'm hoping to achieve:

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

If you can provide a way to make ext.version equal 1.2.3 in the example above, I believe you've resolved my issue.

If this is asking too much, it may be possible for me to make my plugin generate the version string at configuration-time rather than execution-time. It would be nice to know if I could do it this way, though.

EDIT

In an experimental branch, I tried moving all the version string assignment logic to the configuration-phase (by making it all happen during plugin application rather than during task execution), but I don't believe this will work as the plugin extension has not yet been processed and trying to refer to properties defined in it fail.

EDIT 2

Wrapping the version string assignment logic in a project.afterEvaluate closure seems to have worked:

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

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

In a mock project, I implement build.gradle as follows:

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

For some reason, this seems to work. Although the version string assignment logic is wrapped in an 'afterEvaluate' closure and the test publication version assignment isn't, the former still occurs before the latter:

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.

I'm leaving this question open and unresolved since I'd still like to know if it's possible to do it the way I originally intended. Additionally, I'd appreciate any explanation about why the publication version is assigned after the project version is set, and whether I can depend on that always being the case or whether that's just happening now by accident.

解决方案

You can use lazy instantiation of GStrings to evaluate properties at run time:

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

Note that you have to use quotation marks and not apostrophes - "${...}" works, but '${...}' does not.

这篇关于我怎样才能让Gradle扩展懒洋洋地评估由任务动态设置的属性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆