hydraulic-software / conveyor

Gradle plugin, user guide and discussion forums for Conveyor
https://conveyor.hydraulic.dev
Apache License 2.0
123 stars 9 forks source link

Behavioral differences between conveyor run and conveyor make app #56

Closed ennerf closed 1 year ago

ennerf commented 1 year ago

Describe the bug I'm trying to package an FXSampler based app (see chart-fx#580). conveyor run behaves as expected, but conveyor make windows-app and running the executable doesn't find the samples (uses reflection).

Can you think of anything that would be different between the run and make app commands?

To Reproduce Steps to reproduce the behavior:

  1. checkout the branch in chart-fx#580
  2. clean package -DskipTests --projects chartfx-samples -am (using JDK 15)
  3. cd chartfx-samples
  4. conveyor run (works)
  5. conveyor make windows-app and double-click the .exe (does not work)

Expected behavior Both versions should act the same.

Screenshots conveyor run conveyor make windows-app
image image

Desktop (please complete the following information):

mikehearn commented 1 year ago

That's very weird. Off hand I can't think of what could cause that. The run command is extremely simple. It literally just triggers the build of the app task, and then locates the first entry point and runs it.

What's the exception?

Random things to try:

ennerf commented 1 year ago

How are you running the exe? Is it possible there's a dependency on argv[0] being relative/absolute or something like that?

Good call. That "fixed" it. It seems to execute correctly when the working directory is anything other than bin. It makes no difference whether the execution path is absolute or relative.

The code is just calling into ControlsFX, so I have a feeling this will be a pain to debug... 😠

import fxsampler.FXSampler;

public class ChartFxSampler {
    public static void main(String[] args) {
        FXSampler.main(args);
    }
}

It doesn't look like a Conveyor issue, so I'll go ahead and close it.

mikehearn commented 1 year ago

It might still be an issue - maybe when argv[0] isn't a path our custom JNI launcher code isn't doing something that the java binary would and that's an appcompat issue. When you find the difference let us know. It could be as simple as a one line fix on our end.

ennerf commented 1 year ago

I found nothing on the app side 😔

mikehearn commented 1 year ago

OK, I'll take a look when I get a chance. What's the stack trace?

ennerf commented 1 year ago

There is only a lack of samples, so there is no stack trace. I just found the issue though:

It's using an older version of FXSampler that searches for jars/directories at or below the working directory: SampleScanner.java#L173-L197.

The latest version unfortunately only loads examples on the module path, so that one doesn't work at all.

ennerf commented 1 year ago

Afaik there is no way to change the working directory post VM startup, so besides fixing it upstream (the right thing to do), I can think of a few workarounds:

Update I worked around it by placing a custom version that gets loaded by the classloader before the original one. That should work until there is a fix upstream.

mikehearn commented 1 year ago

I'm not sure overriding user.dir would work, but you could try this:

app.jvm.system-properties.user.dir = &&/../

and see if it affects the working directory. && is a special token that means "the place where the exe is found".

Presumably you can't use the existing samples as auto modules?

A couple of alternatives that spring to mind:

  1. If there's no console attached, set the default working directory to the root of the app package in the C++ EXE we provide that runs before the JVM starts up.
  2. A tool that auto-module-ifies a classpath (i.e. combines jars, computes a module descriptor for them all)

I've been meaning to do (2) for ages but never got around to it. Like, give it a Maven coordinate or some inputs and it'd spit out a "real" module, so like auto-mods but better because they'd have real dependency data and jlink would accept them.

ennerf commented 1 year ago

Thanks, the &&/.. works and is a nicer workaround 👍

It's not my project, so modularizing it is out of scope. I figured I could quickly add a conveyor configuration, but I completely underestimated the brittleness of the ControlsFX Sampler project.

RE (2) I've run into so many issues with modules that I stopped trying to have fully-modularized projects. I've also tried adding a combined module descriptor with moditect to a shaded/shrunk jar, but I ran into some issues with that too. It'd be nice to have a tool that reliable takes care of it, but please add a flag to disable it in case something goes wrong.