【问题标题】:Run gradle task only when called specifically仅在专门调用时运行 gradle 任务
【发布时间】:2019-01-24 12:54:11
【问题描述】:

我有一个 build.gradle 文件,它创建了一个 java WAR 文件。此文件用于 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()
}

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

gradle execFile -PmainClass=com.mysite.MyClass -Dsomeprop=somevalue

如果我想调试,我会运行:

gradle execFile -PmainClass=com.mysite.MyClass -Dsomeprop=somevalue -Ddebug=true

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

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

这很糟糕,我知道。

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

Why does gradle run every task in gradle.build

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

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

JavaExec 任务有一个执行 Java 程序的任务动作。 通过使用

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

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

(这样在运行其他任务时不会产生任何副作用)

【问题讨论】:

    标签: gradle


    【解决方案1】:

    您可以通过包装任务解决此问题,方法是在运行时在其 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()
        }
    }
    

    对于 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()
        }
    }
    

    请注意,在这两个示例中,对另一个任务的依赖项都应在包装任务中声明,而不是在 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()
        }
    }
    

    【讨论】:

    • 谢谢,这样execFileJavaExec 任务只会在execFile 被显式运行(因为它在doLast)。我能够以两种方式运行(正常的gradle build,并且还运行单个文件)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-17
    • 1970-01-01
    • 1970-01-01
    • 2015-06-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多