Gradle 文档中的示例:配置和执行阶段

Example from Gradle documentation: Configuration and execution phase

Gradle 文档的“避免陷阱”一章有一个示例“配置和执行阶段”。 Link

It is important to keep in mind that Gradle has a distinct configuration and execution phase (see Build Lifecycle).

def classesDir = file('build/classes')
classesDir.mkdirs()
tasks.register('clean', Delete) {
    delete 'build'
}
tasks.register('compile') {
    dependsOn 'clean'
    doLast {
        if (!classesDir.isDirectory()) {
            println 'The class directory does not exist. I can not operate'
            // do something
        }
        // do something
    }
}

有 2 个任务,compileclean。构建目录是作为项目的一部分创建的。 clean 任务包含删除构建目录的命令。 compile 任务包含检查构建目录的子目录是否存在。

起初这似乎是一个容易理解的例子:一个目录不可用,因为它被较早地删除了。但后来我注意到一些我无法理解的东西。

As the creation of the directory happens during the configuration phase, the clean task removes the directory during the execution phase.

我理解第一部分,因为构建目录是在项目的配置阶段创建的。我不明白的是第二部分。文档说这发生在执行阶段。但是删除目录并没有包含在 doFirstdoLast 块中,因此这部分任务应该在配置阶段发生。

试图理解,第 1 轮

为了获得更好的概览,我添加了更多 println 并删除了仅供评论的行。

def classesDir = file('build/classes')
classesDir.mkdirs()
println "configuration phase of project";
tasks.register('clean', Delete) {
    println "step 1 in configuration phase of "+getName();
    delete 'build'
    println "step 3 in configuration phase of "+getName();
}
tasks.register('compile') {
    println "configuration phase of "+getName();
    dependsOn 'clean'
    doLast {
        if (!classesDir.isDirectory()) {
            println 'The class directory does not exist. I can not operate'
        }
    }
}

通过 ./gradlew compile --info 启动 gradle 提供了以下输出。

configuration phase of project
All projects evaluated.
configuration phase of compile
Selected primary task 'compile' from project :
step 1 in configuration phase of clean
step 3 in configuration phase of clean
Tasks to be executed: [task ':clean', task ':compile']
Tasks that were excluded: []
:clean (Thread[Execution worker for ':',5,main]) started.

> Task :clean
Caching disabled for task ':clean' because:
  Build cache is disabled
Task ':clean' is not up-to-date because:
  Task has not declared any outputs despite executing actions.
:clean (Thread[Execution worker for ':',5,main]) completed. Took 0.002 secs.
:compile (Thread[Execution worker for ':',5,main]) started.

> Task :compile
Caching disabled for task ':compile' because:
  Build cache is disabled
Task ':compile' is not up-to-date because:
  Task has not declared any outputs despite executing actions.
The class directory does not exist. I can not operate
:compile (Thread[Execution worker for ':',5,main]) completed. Took 0.0 secs.

关于我的问题,我没有从这个输出中得到更多信息。为什么目录在执行阶段被删除,尽管没有被包装在 doFirstdoLast 块中?这跟Delete有关系吗?

试图理解,第 2 轮

我想相信这是文档中的一个错误,但在稍微修改了代码之后,这不合适。

def classesDir = file('build/classes');
classesDir.mkdirs();

tasks.register('clean', Delete) {
    doFirst {
        delete 'build';
        println "[debug-print] ("+getName()+") build directory exists in doFirst: "+file("build").exists();
    }
    doLast {
        println "[debug-print] ("+getName()+") build directory exists in doLast: "+file("build").exists();
    }
}

tasks.register('compile') {
    dependsOn 'clean'
    doFirst {
        println "[debug-print] ("+getName()+") build directory exists in doFirst: "+file("build").exists();
    }
    doLast {
        println "[debug-print] ("+getName()+") build directory exists in doLast: "+file("build").exists();
    }
}

./gradlew compile的输出是:

> Task :clean
[debug-print] (clean) build directory exists in doFirst: true
[debug-print] (clean) build directory exists in doLast: false

> Task :compile
[debug-print] (compile) build directory exists in doFirst: false
[debug-print] (compile) build directory exists in doLast: false

这看起来 delete 并没有真正删除目录,或者至少没有立即删除。这与 Delete:

的 javadoc 匹配

Adds some files to be deleted by this task.

但话又说回来,我不明白实际的目录删除是什么时候发生的。在执行阶段,但不在 doFirst 中,也不在 doLast 中?这与我对执行阶段的理解不符。

tasks.register('clean', Delete) {
    println "step 1 in configuration phase of "+getName();
    delete 'build'
    println "step 3 in configuration phase of "+getName();
}

这个通过 Delete.delete() 配置 Delete 任务,它在配置期间排队要删除的内容,但任务的实际操作直到执行阶段才会发生。

tasks.register('clean', Delete) {
    doFirst {
        delete 'build';
        println "[debug-print] ("+getName()+") build directory exists in doFirst: "+file("build").exists();
    }
    doLast {
        println "[debug-print] ("+getName()+") build directory exists in doLast: "+file("build").exists();
    }
}

在执行阶段(修改任务配置 on-the-fly),在任务操作执行之前,这似乎正在排队通过 Delete.delete() 删除的目录。看起来是这样,因为 doFirst { } 在执行期间运行,而目录在 doLast { }.

期间消失了