beryx / badass-runtime-plugin

Create a custom runtime image of your non-modular application
https://badass-runtime-plugin.beryx.org
Apache License 2.0
162 stars 21 forks source link

Linking with JavaFX #66

Open dresch86 opened 4 years ago

dresch86 commented 4 years ago

Firstly, great plugin! I spent a day experimenting with numerous options and this has gotten me the closest to what I need. I am trying to package an app, DocxToBB, that uses JavaFX but the runtime image doesn't launch until I manually edit the .bat and include --module-path and --add-modules. In the JavaFX example I saw for this plugin I didn't see any additional config being needed to make this work. I am not sure what I am missing. Also, suggestModules doesn't show JavaFX in the list either. Few questions:

  1. How is JavaFX detected?
  2. Does the plugin automatically copy the JavaFX modules to the runtime?
  3. Is --module-path and --add-modules supposed to be automatically included in the .bat file?

Thanks!

siordache commented 4 years ago
  1. That's the job of the org.openjfx.javafxplugin. It takes care of choosing the right JavaFX dependencies for your platform.
  2. The plugin copies the JavaFX JARs into the runtime. Note that all your program's dependencies (including the JavaFX ones) are treated as non-modular. Only JDK modules are allowed in the modules list of the runtimeblock. That's why suggestModules doesn't display any JavaFX modules.
  3. This plugin is for non-modular applications, so --module-path or --add-modules should not appear in the .bat file.

To fix your build, you need to remove the following lines from the runtime block:

additive = true
modules = ['javafx.controls', 'javafx.fxml', 'javafx.graphics']

After doing this and executing gradlew jpackage, I was able to start your application with both:

build\image\bin\docxtobb.bat

and

build\jpackage\docxtobb-java\docxtobb-java.exe
dresch86 commented 4 years ago

I got it working now....sort of! I took out the lines you referenced above, but there was another issue. I did not have the JavaFX SDK on my Path environment variable. There are .dll files that JavaFX needs since it is dependent on native access.

build\image\bin\docxtobb.bat Works now but...

build\jpackage\docxtobb-java\docxtobb-java.exe Doesn't presumably because the JavaFX .dll files are not being copied into the runtime

dresch86 commented 4 years ago

Ok, I got it working now.... I had to add the following to grab the JavaFX natives and put them in the fat jar.

jar {
    manifest {
        attributes 'Main-Class': 'org.ose.docxtobb.Launcher'
    }
    from {
        configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
    }
}
siordache commented 4 years ago

Great! I'm just a bit surprised that you needed to add this piece of code.

dresch86 commented 4 years ago

Great! I'm just a bit surprised that you needed to add this piece of code.

Yeah, I am not sure what the deal was. I do have the environment variables PATH_TO_FX and PATH_TO_FX_MODS defined since I installed the OpenJFX SDK. I wonder if the OpenJFX plugin just references those locations so code hinting works, but doesn't pull the required files into the project....

When I have some time I will investigate

JornVernee commented 3 years ago

Note that all your program's dependencies (including the JavaFX ones) are treated as non-modular

This is problematic in the case of JavaFX, since it expects to be loaded from the module path. See e.g. https://bugs.openjdk.java.net/browse/JDK-8256362

I was trying this plugin out together with JavaFX 15, but running into an error saying JavaFX runtime components were missing. However, adding them to the module path manually by moving the JavaFX jars into the app/mods directory of the generated image, and adding:

runtime {
    ...
    launcher {
        jvmArgs = ["--add-modules=javafx.base,javafx.controls,javafx.fxml"]
    }
}

And then also removing the app.classpath entries for the JavaFX jars from the app/{app name}.cfg file made the generated executable work. I don't think that will fix the installer though. (There's probably a better way to do it automatically from build.gradle as well).

siordache commented 3 years ago

My workaround for this problem is to call the main method of the class that extends Application from a Launcher class. (I am aware that this is not the right way to do it.)

hakanai commented 1 year ago

Is this ticket closable now?