仅在专门调用时运行 gradle 任务

Luc*_*tto 4 gradle

我有一个build.gradle创建 javaWAR文件的文件。该文件用于 Docker 多阶段构建的一个阶段,以生成我在生产、暂存等中使用的 Docker 映像(配置文件/机密在映像之外)。

但是在开发中,虽然大部分时间我使用普通构建来生成WAR文件(或分解的WAR),并且它工作正常,但有时我只想在我的项目中执行带有主类的单个java文件

我实现了将以下内容添加到文件中:

task execFile(type: JavaExec) {
    main = mainClass

    classpath = sourceSets.main.runtimeClasspath

    if (System.getProperty('debug', 'false') == 'true') {
        jvmArgs "-Xdebug", "-agentlib:jdwp=transport=dt_socket,address=8788,server=y,suspend=y"
    }

    systemProperties System.getProperties()
}
Run Code Online (Sandbox Code Playgroud)

然后我可以执行文件传递系统属性:

gradle execFile -PmainClass=com.mysite.MyClass -Dsomeprop=somevalue
Run Code Online (Sandbox Code Playgroud)

如果我想调试我运行:

gradle execFile -PmainClass=com.mysite.MyClass -Dsomeprop=somevalue -Ddebug=true
Run Code Online (Sandbox Code Playgroud)

通过这种方式,我可以执行(和调试)单个文件,这在开发过程中的某些情况下非常有用,但问题是即使我没有execFile明确运行,也会执行此代码。

这会在构建和生成 WAR 文件时导致错误,所以我正在做的是注释这些行,在运行单个文件时取消注释,并在运行文件后再次注释(当我记得时),然后再推送git repo(否则docker 构建过程以错误告终)。

这很糟糕,我知道。

根据我的理解,该代码在配置阶段运行,为了使代码在任务执行中运行,我可以将代码包含在doLast方法中(或使用简写<<):

为什么 gradle 在 gradle.build 中运行每个任务

但在这种情况下,我得到了错误No main class specified,可能是由于本讨论中所述的相同原因:

https://discuss.gradle.org/t/javexec-error-no-main-class-specified/12731

JavaExec 任务具有执行 Java 程序的任务操作。通过使用 <<,您还可以将 main、classpath 和 args 的配置添加为任务操作。当 JavaExec 提供的任务操作运行时,配置这些值的第二个任务操作尚未运行。您可能希望在配置阶段配置这些值,而不是通过删除 << 在任务操作中配置这些值。

如果我删除该doLast方法,则不会发生该错误,但最初的问题仍未解决。

所以我想知道的是,是否有一种方法(以及如何)使execFile任务内部的内容仅在显式调用此任务时才运行。

(以便在运行其他任务时不会引起任何副作用)

Gia*_*ini 5

您可以使用包装任务解决这个问题,方法是在运行时在其doLast { }闭包中创建所需的 JavaExec 。

对于 Groovy DSL:

task myTask {
    group = 'MyGroup'
    description = 'Runs Hello.java'
    dependsOn 'build'

    doLast {
        tasks.create('myTaskExec', JavaExec) {
            main = 'com.example.Hello'
            args = ['foo', 'bar']
            classpath = sourceSets.main.runtimeClasspath
        }.exec()
    }
}
Run Code Online (Sandbox Code Playgroud)

对于 Kotlin DSL:

tasks.register("myTask") {
    group = "MyGroup"
    description = "Runs Hello.java"
    dependsOn(mutableListOf("build"))

    doLast {
        tasks.create<JavaExec>("myTaskExec") {
            main = "com.example.Hello" 
            args = mutableListOf("foo", "bar")
            classpath = sourceSets.main.get().runtimeClasspath
        }.exec()
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,在这两个示例中,应在包装任务中而不是在 JavaExec 中声明对另一个任务的依赖关系。

通过此更改,您的任务应仅在调用时运行:

task execFile {
    dependsOn 'build'

    doLast {
        tasks.create('execFileJavaExec', JavaExec) {
            main = mainClass
            classpath = sourceSets.main.runtimeClasspath

            if (System.getProperty('debug', 'false') == 'true') {
                jvmArgs "-Xdebug", "-agentlib:jdwp=transport=dt_socket,address=8788,server=y,suspend=y"
            }

            systemProperties System.getProperties()
        }.exec()
    }
}
Run Code Online (Sandbox Code Playgroud)