Task upToDate evaluation

Hey all,

I have a problem with upToDate evaluation in JavaExec task type .
“Task ‘name’ is not up-to-date because:
Value of input property ‘jvmArgs’ has changed for task ‘name’”

To reproduce:

  1. Run build in run configuration
  2. Run build in debug configuration
    Debug config adds “-agentlib:jdwp=transport=dt_socket,server=n,suspend=y,address=52141” to "jvmArgs " which invalidates the task.

Is it possible to exclude jvmArgs from upToDate evaluation?
JavaExecHandleBuilder unfortunately does not support setAllJvmArgs()

Yes, you can bypass input checking by using a CommandLineArgumentProvider. The value of the jvmArgs property is tracked as an input, so by implementing an argument provider we can pass arguments to the JVM and control how we consider those as inputs, to include ignoring them altogether. The simplest case would be something like this.

execTask.jvmArgumentProviders.add({ ['-agentlib:jdwp=transport=dt_socket,server=n,suspend=y,address=52141'] })

Should I build my custom implementation of the Interface?
Using your example presents me with
build_7qyrt64j7v8hgeazctqbddc52$_run_closure2$_closure5 cannot be cast to org.gradle.process.CommandLineArgumentProvider

If I understand the use of argument provider:

  • It will treat all arguments on the list as if they are on a special list which can always change and is internal and thus excluded from upToDate checks?

Use add as CommandLineArgumentProvider to the end of the closure. It’s seems SAM-coercion isn’t working properly here.

It will treat all arguments on the list as if they are on a special list which can always change and is internal and thus excluded from upToDate checks?

It’s actually simpler than that, the list returned here is just simply not tracked as an input at all. It’s up to the implementer to manually define these inputs if they want. In this case, we don’t do that, so effectively these items are ignored.

Makes sense, thanks for clarification.

Is there a way to generalize this, or is it limited to a string?
The address used in address=52141 is randomized incremented/randomized by IntelliJ Idea on every debug run.

There is also an issue that this adds the argument to normal, non-debug run configuration, which results in en errors and printout:

ERROR: transport error 202: connect failed: Connection refused
ERROR: JDWP Transport dt_socket failed to initialize, TRANSPORT_INIT(510)
JDWP exit error AGENT_ERROR_TRANSPORT_INIT(197): No transports initialized [debugInit.c:750]

It is possible to remove a part of jvmArgs receives by task?
Something like jvmArgs.filter{ it.matches("-agentlib*)}
I saw setAllJvmArgs is not supported by JavaExecHandleBuilder

And if I in debug configuration add jvmArg into argument provider like

doFirst {
jvmArgumentProviders.add({ getJvmArgs() } as CommandLineArgumentProvider)
}

Then it will complain that it is added twice

ERROR: Cannot load this JVM TI agent twice, check your java command line for duplicate jdwp options.

If I remove it from jvmArgs, then Gradle will say that jvmArg has changed in the next run.
Same will happen, if I just remove the argument with

doFirst {
setJvmArgs({[ ].iterator() })
}

Ah, so IntelliJ is adding this to the task somehow? Do you mind sharing your IntelliJ run configuration?

Yes.

Background:

  • Gradle 5.5.1
  • Project imported as Gradle into IntelliJ
  • Under Build/Build Tools/Gradle/Delegate Settings -> both are set to Gradle -> IntelliJ will use Gradle to build instead of its own javac.
  • Problem was first noticed when we tried to run some test files - debugging them would trigger a rebuild of all JavaExec tasks

Create run/debug configuration in IntelliJ under Gradle

Everything is default, with “Gradle Debug” having enabled for script debugging.

Please let me know if you need more details.

From JavaExec and Gradle phases standpoint:

  • Debug argument is not present during configuration/evaluation phase.
  • Debug argument “-agentlib:jdwp…” is present during execution phase

This sounds like something that the IDE is doing, so there might not be a lot we can do here. Is there are reason you would typically run this run configuration with debug enabled? This would simply debug the Gradle build itself, which typically isn’t necessary unless you’re trying to debug a build issue.

Since Idea uses Gradle to build, it invokes the build before running any other run configuration, for instance a Test class.

If I want to debug a test class, it will for some reason run whole build in debug configuration.

I can remove build to be run before the Test, but this would make it not ideal.

Is there a way to always disable debugging of Gradle?

Yeah, that doesn’t seem correct. Perhaps it’s worth opening an issue against IntelliJ for this. In my opinion, running a unit test from the IDE using the Gradle runner should enable debugging only on the Test task for that test execution.

https://youtrack.jetbrains.com/issues/IDEA

I changed Idea back to build and run with Idea instead of Gradle and it works now.
Funny part was that even when I disabled those task, Idea still attached the debugger and it just hanged the build.

Thanks for confirming my suspicion that this sounds wrong, but I am too lazy to register and report a bug.

Another workaround we have found: override JavaExec class with your own and filter default jmvArgs getter result