gradle
gradle copied to clipboard
No longer possible to specify a executable which is not part of a Java toolchain for a JavaExec task
Expected Behavior
In 7.6.1 you were able to do this and it ran:
tasks.register<JavaExec>("LaunchWithCustomLauncher")
{
group = "run"
executable = file("customLauncher").absolutePath. // This is some launcher executable which loads a java runtime over JNI but it not part of that runtime
}
Current Behavior
in 8.0 to 8.1.1 I get the following error message:
Execution failed for task ':LaunchWithCustomLauncher'.
Failed to calculate the value of task ':LaunchWithCustomLauncher' property 'javaLauncher'. Toolchain installation '/Users/claes/IdeaProjects' could not be probed: A problem occurred starting process 'command '/Users/claes/IdeaProjects/bin/java''
It looks like it's caused by the changes in this PR: https://github.com/gradle/gradle/issues/21386
Context (optional)
It's a bit of an edge case, but because of various macOS + JNI reasons, we need to use a custom launcher to launch our (mostly) Java application for debugging (in IntelliJ). This launcher loads a JRE via JNI and passes on various command line arguments to it. This way we are able to use the functionality of the JavaExec interface (IDEA connecting up the debugger, passing the right class path & java arguments and so on).
So everything was fine for our use-case until 8.0 decided to be more strict. Which probably makes sense in most cases, but there should be some way to at least opt-out of this behaviour. I wasn't able to find a way to override it either by parameters or by subclassing JavaExec.
Steps to Reproduce
git clone https://github.com/kurasu/customlauncher
./gradlew LaunchWithCustomLauncher
Gradle version
8.1.1
Gradle version that used to work
7.6.1
Build scan URL (optional)
No response
Your Environment (optional)
No response
Given:
- #23990
- #24014
Could you see if the setup done for allowing ecj as a Java compiler can be used in your case?
I don't see how that would apply to the JavaExec task as it has no options object available (apart from debugOptions). Setting the setting on compileJava didn't have any effect, and I don't wee why it should either.
What I could see so far is that when the JavaExec constructor runs, it calls JavaExecExecutableUtils.getExecutableOverrideToolchainSpec, which in turn calls SpecificInstallationToolchainSpec.fromJavaExecutable to configure the JavaExec.javaLauncher property.
This is then somehow later pass through JavaToolchainQueryService.query method, which in turn calls asToolchainOrThrow which then throws the error that the Toolchain installation can't be probed. I'm not exactly familiar with the Gradle codebase but tried digging around a bit to see if it was possible to override the behaviour along these steps but couldn't find anything that worked.
Something is not right with the reproducer. It fails with the supposedly good versions too, just the same way. I've tried 7.6.1
and 7.5.1
. Please adjust it or provide a different one.
Hi, and thanks for getting back to me. You are correct, although my code reproduced the error, it also failed in quite similar way for the same task in the 7.x versions.
I updated the reproducer now to compile a cpp launcher with the native toolchain (which is closer to what we do in our real code) and this executable lists the arguments passed into it, and that launcher is then used to pretend-launch the JavaExec task. I didn't go through the hassle of actually starting the JVM using c++ in the launcher so the java code won't run, but it should be enough to highlight the regression.
The current state of https://github.com/kurasu/customlauncher (https://github.com/kurasu/customlauncher/commit/73e315f87fa6faab6f749ac48687c11b549a6620) should now run as its set to use 7.6.1, but changing it back to 8.0 or 8.3 will make it fail when I run it.
so again, with the command
./gradlew LaunchWithCustomLauncher
output with 7.6.1: (default)
> Task :LaunchWithCustomLauncher
CustomLauncher started
arguments:
/Users/claes/dev/customlauncher/launcher/build/exe/main/debug/launcher
-Dfile.encoding=UTF-8
-Duser.country=DE
-Duser.language=en
-Duser.variant
-cp
/Users/claes/dev/customlauncher/build/classes/java/main:/Users/claes/dev/customlauncher/build/resources/main
org.example.Main
output with 8.3:
`> Task :LaunchWithCustomLauncher FAILED
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':LaunchWithCustomLauncher'.
> Failed to calculate the value of task ':LaunchWithCustomLauncher' property 'javaLauncher'.
> Toolchain installation '/Users/claes/dev/customlauncher/launcher/build/exe/main' could not be probed: A problem occurred starting process 'command '/Users/claes/dev/customlauncher/launcher/build/exe/main/bin/java''`
Thank you for your interest in Gradle!
This issue needs a decision from the team responsible for that area. They have been informed. Response time may vary.
Instead of using JavaExec
, could you use Exec
instead?
Hi thanks for getting back to me.. If I did use Exec, i would need to replicate all the computation of the classpath to the command line argument list (probably manageable) but the bigger problem is probably getting java debugging to work properly. I assume (could be wrong) that IntelliJ and other IDEs recognize the JavaExec class and therefore know how to connect the debugger to it, but if we didn't have that ability afaik we'd need to set up debugging in IDE configurations using a special port.
As it is JavaExec is doing all the work we actually need, its just not letting us tweak the executable path.
@big-guy please could you make an example of using Exec
instead of JavaExec
for running a java application?