diff --git a/subprojects/core/src/main/java/org/gradle/api/tasks/JavaExec.java b/subprojects/core/src/main/java/org/gradle/api/tasks/JavaExec.java index 588553aa35323..83ff46eaadd19 100644 --- a/subprojects/core/src/main/java/org/gradle/api/tasks/JavaExec.java +++ b/subprojects/core/src/main/java/org/gradle/api/tasks/JavaExec.java @@ -16,6 +16,8 @@ package org.gradle.api.tasks; +import org.apache.tools.ant.types.Commandline; +import org.gradle.api.Incubating; import org.gradle.api.file.FileCollection; import org.gradle.api.internal.ConventionTask; import org.gradle.api.tasks.options.Option; @@ -31,6 +33,7 @@ import java.io.File; import java.io.InputStream; import java.io.OutputStream; +import java.util.Arrays; import java.util.List; import java.util.Map; @@ -279,6 +282,18 @@ public List getArgs() { return javaExecHandleBuilder.getArgs(); } + /** + * Command line arguments passed to the main class. + * @param args the command line arguments as a single string. Will be parsed to argument list. + * @return this + * @since 4.9 + */ + @Incubating + @Option(option = "args", description = "Command line arguments passed to the main class. [INCUBATING]") + public JavaExec setArgsString(String args) { + return setArgs(Arrays.asList(Commandline.translateCommandline(args))); + } + /** * {@inheritDoc} */ diff --git a/subprojects/docs/src/docs/release/notes.md b/subprojects/docs/src/docs/release/notes.md index b0be5e0bfa1a6..41988e7530f07 100644 --- a/subprojects/docs/src/docs/release/notes.md +++ b/subprojects/docs/src/docs/release/notes.md @@ -2,6 +2,11 @@ Here are the new features introduced in this Gradle release. +### Command line args supported by JavaExec + +Since Gradle 4.9, the command line arguments can be passed to `JavaExec` with `--args`. For example, if you want to launch the application with command line arguments `foo --bar`, +you don't need to hardcode it into the build script - you can just run `gradle run --args 'foo --bar'` (see [application plugin](userguide/application_plugin.html) for more information). + diff --git a/subprojects/docs/src/docs/userguide/applicationPlugin.adoc b/subprojects/docs/src/docs/userguide/applicationPlugin.adoc index 4a3355d2abee2..62c35bd4dd83f 100644 --- a/subprojects/docs/src/docs/userguide/applicationPlugin.adoc +++ b/subprojects/docs/src/docs/userguide/applicationPlugin.adoc @@ -43,6 +43,8 @@ The only mandatory configuration for the plugin is the specification of the main You can run the application by executing the `run` task (type: api:org.gradle.api.tasks.JavaExec[]). This will compile the main source set, and launch a new JVM with its classes (along with all runtime dependencies) as the classpath and using the specified main class. You can launch the application in debug mode with `gradle run --debug-jvm` (see api:org.gradle.api.tasks.JavaExec#setDebug(boolean)[]). +Since Gradle 4.9, the command line arguments can be passed with `--args`. For example, if you want to launch the application with command line arguments `foo --bar`, you can use `gradle run --args 'foo --bar'` (see api:org.gradle.api.tasks.JavaExec#setArgsString(java.lang.String)[]). + If your application requires a specific set of JVM settings or system properties, you can configure the `applicationDefaultJvmArgs` property. These JVM arguments are applied to the `run` task and also considered in the generated start scripts of your distribution. ++++ diff --git a/subprojects/plugins/src/integTest/groovy/org/gradle/api/tasks/JavaExecIntegrationTest.groovy b/subprojects/plugins/src/integTest/groovy/org/gradle/api/tasks/JavaExecIntegrationTest.groovy index 014f0dd2d3a0a..933a0cb546ad9 100644 --- a/subprojects/plugins/src/integTest/groovy/org/gradle/api/tasks/JavaExecIntegrationTest.groovy +++ b/subprojects/plugins/src/integTest/groovy/org/gradle/api/tasks/JavaExecIntegrationTest.groovy @@ -31,7 +31,10 @@ class JavaExecIntegrationTest extends AbstractIntegrationSpec { file("src/main/java/Driver.java").text = mainClass(""" try { FileWriter out = new FileWriter("out.txt"); - out.write(args[0]); + for (String arg: args) { + out.write(arg); + out.write("\\n"); + } out.close(); } catch (IOException e) { throw new RuntimeException(e); @@ -65,7 +68,7 @@ class JavaExecIntegrationTest extends AbstractIntegrationSpec { """ } - @IgnoreIf({GradleContextualExecuter.parallel}) + @IgnoreIf({ GradleContextualExecuter.parallel }) def "java exec is not incremental by default"() { when: run "run" @@ -80,6 +83,30 @@ class JavaExecIntegrationTest extends AbstractIntegrationSpec { executedAndNotSkipped ":run" } + def 'arguments passed via command line take precedence and is not incremental by default'() { + when: + run("run", "--args", "2 '3' \"4\"") + + then: + executedAndNotSkipped ":run" + assertOutputFileIs('''\ + 2 + 3 + 4 + '''.stripIndent()) + + when: + run("run", "--args", "2 '3' \"4\"") + + then: + executedAndNotSkipped ":run" + assertOutputFileIs('''\ + 2 + 3 + 4 + '''.stripIndent()) + } + @Issue(["GRADLE-1483", "GRADLE-3528"]) def "when the user declares outputs it becomes incremental"() { given: @@ -109,6 +136,36 @@ class JavaExecIntegrationTest extends AbstractIntegrationSpec { executedAndNotSkipped ":run" } + def 'arguments passed via command line matter in incremental check'() { + given: + buildFile << """ + run.outputs.file "out.txt" + """ + + when: + run("run", "--args", "2") + + then: + executedAndNotSkipped ":run" + assertOutputFileIs("2\n") + + when: + run("run", "--args", "2") + + then: + skipped ":run" + + when: + file("out.txt").delete() + + and: + run("run", "--args", "2") + + then: + executedAndNotSkipped ":run" + assertOutputFileIs("2\n") + } + def "arguments can be passed by using argument providers"() { given: def inputFile = file("input.txt") @@ -176,4 +233,8 @@ class JavaExecIntegrationTest extends AbstractIntegrationSpec { executedAndNotSkipped ":run" outputFile.text == "different" } + + private void assertOutputFileIs(String text) { + assert file("out.txt").text == text + } }