仅在明确调用时才运行gradle任务 [英] Run gradle task only when called specifically

查看:86
本文介绍了仅在明确调用时才运行gradle任务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个创建Java WAR文件的build.gradle文件.该文件在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方法中(或使用速记<<):

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

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

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

JavaExec任务具有执行Java程序的任务动作. 通过使用<< ;,您将添加主类路径的配置, 和args作为任务动作.当任务动作由 JavaExec运行时,第二个任务操作就是配置这些值 尚未运行.您可能需要在 配置阶段,而不是通过删除<<.

来执行任务.

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

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

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

解决方案

您可以通过在运行时在其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()
    }
}

I have a build.gradle file that creates a java WAR file. This file is used in one stage of a Docker multi stage build to generate a Docker Image that I use in production, staging, etc... (the configuration files / secrets are outside the image).

But in development, although most of the time I use the normal build to generate a WAR file (or an exploded WAR), and it works fine, sometimes I want to just execute a single java file with a main class in my project.

I achieved that adding the following to the file:

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

Then I'm able to execute the file passing system properties with:

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

And if I want to debug i run:

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

This way I can execute (and debug) single files, which is great in some cases during development, but the problem is that this code is executed even if I dont run execFile explicitly.

This causes errors when building and generating the WAR file, so what I'm doing is commenting these lines, uncommenting when I run single files, and commenting again (when I remember) after I run the files, before pushing the git repo (otherwise the docker build process ends up with errors).

This is very bad, I know.

Based on what I understand, that code is run during the configuration phase, and to make the code run in the execution of the task, I could include the code inside a doLast method (or use the shorthand <<):

Why does gradle run every task in gradle.build

But in this case I get the error No main class specified, probably due to the same reasons stated in this discussion:

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

The JavaExec task has a task action which executes the Java program. By using <<, you’re adding the configuration of the main, classpath, and args as a task action as well. When the task action provided by the JavaExec runs, the second task action to configure these values has not run yet. You likely want to configure these values in the configuration phase, not in a task action by removing the <<.

The error doesn't happen if I remove the doLast method, but the initial problem would remain unsolved.

So what I want to know is if there is a way (and how) to make what's inside the execFile task run only when this task is called explicitly.

(so that it won't cause any side effects when other tasks are run)

解决方案

You can solve this problem with a wrapping task, by creating at runtime the desired JavaExec one inside its doLast { } closure.

For 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()
    }
}

For 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()
    }
}

Note that in both examples the dependencies to another task should be declared in the wrapping task and not in the JavaExec one.

With this change your task should be running only when called:

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

这篇关于仅在明确调用时才运行gradle任务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆