Gradle javaexec task is ignoring jvmargs - gradle

I am trying to run my app using a Gradle javaexec task. However, jvmargs and args are not passed to the command execution. Why?
task runArgoDev(type: JavaExec) {
main = "org.app.ArgoDevRunner"
classpath = configurations.testRuntime
project.ext.jvmargs = ['-Xdock:name=Argo', '-Xmx512m', '-Dfile.encoding=UTF-8', '-Dapple.awt.textantialiasing=on', '-ea']
project.ext.args = ['-initParameter', 'implicit-scrollpane-support=true']
}

Above code doesn't have the desired effect because it sets extra properties on the project object, instead of configuring the task. Correct is jvmArgs = ... and args = .... (It's also possible to omit =, [, and ].)

Here is example, to pass program args and jvmargs to run task in gradle.
run {
args 'server', 'test.yml'
jvmArgs '-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005'
}

Related

Gradle task lines always getting executed

I have the following Gradle task:
task deploy(type: Exec) {
doFirst {
println 'Performing deployment'
}
final Map properties = project.getProperties()
if (!properties['tag']) {
throw new StopExecutionException("Need to pass a tag parameter")
}
commandLine "command", tag
}
If I run another task I get an error because properties['tag'] is undefined, I guess because Gradle is executing everything in the task except commandLine. Is there a better way to do this or a way to stop Gradle from executing parts of the task even when I'm running another task?
Using Gradle 6.6.1
I use this pattern:
// Groovy DSL
tasks.register("exec1", Exec) {
def tag = project.findProperty("tag") ?: ""
commandLine "echo", tag
doFirst {
if (!tag) {
throw new GradleException("Need to pass a tag parameter")
}
}
}
It adds the tag property if it exists.
If it does not exist, it adds an empty string but checks for this before it actually runs.
It would be great if the Exec task accepted providers as arguments so you could just give it providers.gradleProperty("tag"), but unfortunately it doesn't.

In gradle, what is the difference betweeen javaexec and a JavaExec task?

For example, I can have a JavaExec task:
task javaExecCaseA(type: JavaExec) {
javaLauncher = javaToolchains.launcherFor {
languageVersion = JavaLanguageVersion.of(11)
}
classpath = files("MySimpleProgram.jar")
}
or, inside a generic task:
task javaExecCaseB {
doLast {
javaexec {
classpath = files("MySimpleProgram.jar")
}
}
}
I haven't figured out how to specify the JavaLanguageVersion in the 2nd case (javaExecCaseB).
The bigger question though, is what is the difference?
I've tried various ways to set the version in javaExecCaseB, but I end up with an error like:
Could not set unknown property 'javaLauncher' for object of type org.gradle.process.internal.DefaultJavaExecAction_Decorated
I have found that the task is the gradle "JavaExec" task.
And the 2nd case, javaexec is a Project method.
I began this quest to find a way to run Java programs using a different JVM than gradle itself is using (set from an environment variable or command line when running gradle).
I was able to get it to work in both cases:
ext {
MyJvmVersion = 11
}
task SampleJavaExec1(type: JavaExec) {
// Example task for using a custom JVM version with a JavaExec task
javaLauncher = javaToolchains.launcherFor {
languageVersion = JavaLanguageVersion.of(MyJvmVersion as int)
}
environment['JAVA_HOME'] = javaLauncher.get().metadata.installationPath.asFile.absolutePath
classpath = files("MySimpleProgram.jar")
}
task SampleJavaExec2 {
// Example task for using a custom JVM version with the javaexec method
doLast {
javaexec {
environment['JAVA_HOME'] = "C:\\Program Files\\AdoptOpenJDK\\jdk-11.0.10.9-hotspot"
executable = "C:\\Program Files\\AdoptOpenJDK\\jdk-11.0.10.9-hotspot\\bin\\java.exe"
classpath = files("MySimpleProgram.jar")
}
}
}
In the 2nd case, javaexec() doesn't appear to have a "javaLauncher".
Instead of hardcoding a path, I also found that I can use javaLauncher to find it for me by adding this code inside the javaexec{} block:
javaLauncher = javaToolchains.launcherFor {
languageVersion = JavaLanguageVersion.of(MyJvmVersion as int)
}
environment['JAVA_HOME'] = javaLauncher.get().metadata.installationPath.asFile.absolutePath
This should invoke the auto download JVM resolution as well, but I've not tested that part.

Automatically pass unparsed arguments to JavaExec-type task in Gradle?

I'm trying to pass a lot of arguments to a JavaExec task in Gradle. Right now I'm doing something like:
task foo(type: JavaExec) {
if (project.hasProperty('prop1')) {
args += ["--prop1"]
}
if (project.hasProperty('foo2')) {
args += ["--foo3"]
}
...
if (project.hasProperty('flagn')) {
args += ["--flagn"]
}
}
And then when I execute this I do something like ./gradlew :foo -Pprop1 -Pfoo2 ... -Pflagn. This works but is really tedious since I need to literally pass the same string arguments from Gradle to JVM. Is there an easier way - like automatically pass all the unparsed arguments or something simpler?
You can access the project properties from the command line via the StartParameter object.
So, for your example, you could use:
task foo(type: JavaExec) {
args gradle.startParameter.projectProperties.keySet().collect { "--$it" }
}
However, this will add any command line project property to the JavaExec args. Maybe you could think about filtering for properties with a specific prefix.

Run executable jar with parameters from gradle

I wish to run executable jar from my gradle file. I have tied:
task runJar(dependsOn:jar) << {
javaexec {
main="-jar"; args "C:/Development/AndroidStudioProjects/AndroidDev/Test.jar"
}
}
But I get "Could not find property 'jar' on project ':MyProj"
I also tried:
task runScheduleReader << {
javaexec {
main = "MainClass"
classpath = "C:/Development/AndroidStudioProjects/AndroidDev/Test.jar"
args('1')
}
}
I am relatively new to groovy, can you please help me with that?
P.S... I put those function outside of android {}
In your first code snippet dependsOn in task declaration means, that task runJar should be executed only after the jar task. Exception you get, says, that your current project doesn't have such a task. So, if you really don't need to execute jar task just before, you can simply not declere this task dependency:
task runJar() << {
javaexec {
main="-jar"; args "C:/Development/AndroidStudioProjects/AndroidDev/Test.jar"
}
}
Though, this is a little bit strange case, when you have to execute some jar without relative path, this solution should work.
The second snippet should pass the jar as the argument too, but this time, it should be an arguments array, something like this:
task runScheduleReader() << {
javaexec {
main="-jar";
args = [
"C:/Development/AndroidStudioProjects/AndroidDev/Test.jar",
"1"
]
}
}

Gradle task should not execute automatically

I'm defining a task in gradle:
task releaseCandidate(type: Exec) {
commandLine 'git', 'checkout', 'develop'
// Increment version code in Manifest
String manifest = new File('AndroidManifest.xml').getText('UTF-8')
Pattern pattern = Pattern.compile('android:versionCode="([0-9]+)"')
Matcher matcher = pattern.matcher(manifest)
matcher.find()
int newVersionCode = Integer.parseInt(matcher.group(1)) + 1
manifest = manifest.replaceAll(
"android:versionCode=\"([0-9]+)\"", "android:versionCode=\"$newVersionCode\""
)
new File('AndroidManifest.xml').write(manifest, 'UTF-8')
commandLine 'git', 'diff'
}
Which I want to execute only when I explicitly call it as gradle releaseCandidate. However, when I run any other task, such as gradle assembleDebug, it also runs task releaseCandidate. I don't want that behaviour to happen. There is no task depending on releaseCandidate or vice-versa.
My project is an Android app, so I am using android gradle plugin.
A common pitfall. Add an action to the task otherwise code will run at configuration phase. Sample task with action:
task sample << {
}
As I see You'd rather need to write a custom task than using Exec type. I suppose it's not valid to define commandLine twice.
EDIT
You can read this post to get the general idea how it all works.
You are mixing Task configuration and groovy code. Everything that is part of the main body of a task definition will be executed in the configuration phase. The task task1 << { code } is a shorthand for
task task1 {
doLast {
code
}
}
commandLine is part of the Exec Task but your other code is not and should be wrapped into a doLast this will execute the commandline first and then execute your additional code. If you need another exec commandLine then you'll need another task.
task releaseCandidate(type: Exec) {
commandLine 'git', 'checkout', 'develop'
doLast {
// Increment version code in Manifest
String manifest = new File('AndroidManifest.xml').getText('UTF-8')
Pattern pattern = Pattern.compile('android:versionCode="([0-9]+)"')
Matcher matcher = pattern.matcher(manifest)
matcher.find()
int newVersionCode = Integer.parseInt(matcher.group(1)) + 1
manifest = manifest.replaceAll(
"android:versionCode=\"([0-9]+)\"", "android:versionCode=\"$newVersionCode\""
)
new File('AndroidManifest.xml').write(manifest, 'UTF-8')
}
}
Just to complete #Opal answer for cases when Exec is really used (for example CommandLine reference) :
task task1 << {
exec {
List<String> arguments = new ArrayList<String>()
//..
commandLine arguments
}
}

Resources