10

我对使用 Gradle 很陌生,我正在尝试开发一个有助于管理版本编号的插件。这个插件定义了一个任务来设置project.version它所应用的项目的属性。

我要做的是让它在每个 Gradle 构建开始时设置此属性。使用Peter 对另一个 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.

我将这个问题悬而未决,因为我仍然想知道是否有可能按照我最初的意图去做。此外,我希望能解释一下为什么在设置项目版本之后分配发布版本,以及我是否可以依赖这种情况总是如此,或者这是否只是偶然发生的。

4

1 回答 1

4

您可以使用GStrings 的惰性实例化来在运行时评估属性:

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

请注意,您必须使用引号而不是撇号 -"${...}"有效,但'${...}'无效。

于 2016-07-15T22:57:27.690 回答