gradle icon indicating copy to clipboard operation
gradle copied to clipboard

No longer possible to specify a executable which is not part of a Java toolchain for a JavaExec task

Open kurasu opened this issue 1 year ago • 9 comments

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

kurasu avatar Jun 09 '23 13:06 kurasu

Given:

  • #23990
  • #24014

Could you see if the setup done for allowing ecj as a Java compiler can be used in your case?

ljacomet avatar Jun 12 '23 08:06 ljacomet

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.

kurasu avatar Jun 13 '23 11:06 kurasu

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.

jbartok avatar Aug 22 '23 12:08 jbartok

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''`

kurasu avatar Aug 23 '23 13:08 kurasu

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.

ljacomet avatar Aug 30 '23 12:08 ljacomet

Instead of using JavaExec, could you use Exec instead?

big-guy avatar Nov 20 '23 17:11 big-guy

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.

kurasu avatar Nov 21 '23 16:11 kurasu

@big-guy please could you make an example of using Exec instead of JavaExec for running a java application?

abique avatar Feb 20 '24 09:02 abique