gradle WriteProperties任务不会创建属性文件,除非直接运行该任务

pzfprimi  于 2023-01-21  发布在  其他
关注(0)|答案(3)|浏览(174)

我尝试在非Android Java项目中生成属性文件,但由于某种原因,即使在使用./gradlew assembleDist构建项目或使用./gradlew foo:run运行项目时任务运行,也没有创建属性文件。任务在子项目中定义,如下所示:

task writeProperties(type: WriteProperties) {
    outputFile 'src/main/resources/foo.properties'
    property 'version', version
    property 'releaseType', releaseType
    property 'date', date
    println("task ran")
}

当我执行其他gradle任务时,task ran被打印出来,表明任务已运行,但指定路径中没有显示foo.properties文件。奇怪的是,如果我直接使用./gradlew foo:writeProperties运行writeProperties任务,文件会被创建并填充正确的变量。
我试着用doFirst{}doLast{} Package 上面的语句,但是我得到了如下错误:

Cause: path may not be null or empty string. path='null'

有人知道我做错了什么吗?我已经用头撞了好几个小时了,现在已经没有主意了。谢谢!

**更新:**我设法用已接受答案中提供的信息解决了这个问题。我不得不添加compileJava.finalizedBy(writeProperties)以使任务作为构建任务的一部分实际运行。正如上面提到的,println本质上是在骗我,因为它在配置阶段被打印出来,但任务操作没有运行。

tyg4sfes

tyg4sfes1#

代码的实际问题是println语句没有说明真相。任务配置闭包中的代码在任务配置时运行,而不是在任务执行时运行。因此,每次从命令行运行另一个任务时,任务都会配置好,println写入命令行,但是实际的任务动作并没有执行,你应该把你的println打包成一个doLast,这样它实际上是在.properties文件创建之后才运行的。

task myTask {
    println 'task configured'
    doLast {
        println 'task executed' 
    } 
}

如果希望任务在命令行上不指定的情况下运行,则需要使用dependsOnfinalizedBy设置任务依赖关系。

acruukt9

acruukt92#

所描述的问题不是问题。所发生的正是Gradle的工作原理。我也一直在努力理解为什么这种行为是正确的!我提供的答案有助于澄清正在发生的事情。Algebo并不是唯一一个试图理解Gradle工作原理的人。Algebo在描述他观察到的情况方面做得很好,希望我的答案能解开一些谜团。
首先要了解的是,gradle会在三个通道中评估代码:初始化、配置和执行。
在初始化过程中,gradle会指出构建中要包含哪些项目。
在配置过程中,任务将被创建、配置并添加到构建图中。配置任务时,您需要告知gradle任务的输入和输出是什么。Gradle使用该信息来了解它是否确实需要执行该任务。(即,如果任务的输入和输出是最新的,则您可以跳过该任务的执行)
在执行期间,gradle将执行与任务关联的操作。
通过以上解释,让我们看看Algebo的代码发生了什么。Algebo注意到的第一件事是他看到了"任务已运行"消息。这是为什么呢?这是因为该代码是在gradle配置阶段执行的。(Lukas的回答很好地解释了这一观察结果)因此,此时所做的一切就是配置"writeProperties"任务对象(类型为"WriteProperties")。当然,Algrebo正确地注意到"www.example.com"文件没有创建。foo.properties" file was not created. And that of course is because the task was only configured and not yet execute.
Algebo尝试的下一件事是将任务块中的代码放在doFirst和doLast块中。当Algebo尝试这样做时,他会得到错误消息,即路径可能为null或空。doFirst和doLast是定义任务操作的代码块。如我前面所述,它是在任务执行过程中执行的任务操作。那么为什么Algebo会得到这个错误呢?在"WriteProperties"任务的情况下,它要求配置"outputFile"。但是,Algebo将outputFile语句移到了任务操作块中。换句话说,在执行doFirst或doLast代码时,outputFile尚未定义。"WriteProperties"任务需要在执行任务操作之前进行定义。这就解释了观察到的行为。
那么,当他直接使用./gradlew foo:writeProperties directly执行任务时,为什么它会工作呢?这是因为任务配置正确,当他直接执行它时,它会执行与任务关联的任务操作。Algebo没有定义任何任务操作,因此没有要执行的操作,一旦任务操作完成(无),WriteProperies任务就会通过将定义的属性写入outputFile而结束。当然,这也是Algebo观察到的。
最后,代数注意到,他可以得到的任务做什么,他想通过添加声明:compileJava.finalizedBy(writeProperties)。在这种情况下,已配置了"写入属性"任务。此外,在配置过程中,已将该任务添加到构建图中。换句话说,已将该任务配置为在"compileJava"任务完成时运行。在执行"写入属性"任务时,已对其进行了正确配置。因此它执行任务的任务动作(在这种情况下没有),并且当完成时,"WriteProperties"任务通过将属性写入"outputFile"而结束。
尽管如此,定义的"writeProperties"任务仍存在另一个问题。Gradle现在希望用户定义所有任务的输入和输出。Gradle使用该信息来确定任务是否需要执行或跳过(如果该任务已经是最新的)。在Algebo的示例中,输入为:"版本"、"发布类型"和"日期",并且输出是文件"源/主/资源/www.example.com"。foo.propertiesgradle不知道"outputFile"是"output"的一部分)。"writeProperties"任务没有配置其输入和输出。因此,即使自上次执行以来没有任何更改,也将始终执行"writeProperties"。在代数最终工作解决方案中,如果例如"版本"改变并且compileJava任务已经是最新的,则他的属性文件将不会被重建。 gradle doesn't know that "outputFile" is part of "outputs"). The "writeProperties" task doesn't have its inputs and outputs configured. So "writeProperties" will always get executed even if nothing has changed since it was last executed. In Algebo final working solution, his properties file would not get rebuilt if for example "version" changed and the compileJava task was already up-to-date.
对于其他信息,我发现this很有帮助。

okxuctiv

okxuctiv3#

1.在build文件夹中生成新代码(非主源代码)
1.将生成的文件添加到源集中
1.将新任务链接到生成链

ext.genRes = 'build/generated_src/main/resources'
sourceSets {
    main {
        resources {
            srcDir(genRes)
        }
    }
}

ext.genResFoo = genRes + 'foo.properties'
ext.releaseType = 'test'
    
task genResources(type: WriteProperties) {
    outputFile genResFoo
    property 'version', version
    property 'releaseType', releaseType
    property 'date', new java.util.Date()
    doLast {
        println("writeProperties ran ${genResFoo}")
    }
}
processResources.dependsOn genResources

相关问题