JDK-8198329 : Support FX build / test using JDK that doesn't include javafx.* modules
  • Type: Enhancement
  • Component: javafx
  • Sub-Component: build
  • Affected Version: openjfx11
  • Priority: P2
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2018-02-17
  • Updated: 2018-09-11
  • Resolved: 2018-04-27
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
openjfx11Fixed
Related Reports
Blocks :  
Blocks :  
Blocks :  
Blocks :  
Blocks :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Description
OpenJDK builds only include javafx.* modules if the configure step specifies to use javafx bits using the --with-import-modules option. Further, the OpenJDK 9 and 10 bundles do not include javafx.* modules.

The current FX build produces a bundle for inclusion in a JDK build. The subsequent build tasks for building apps, building tests, and running tests assume that the bootJDK already has javafx.* modules, and use scripts to patch these existing modules at compile time or runtime.

We can currently build the FX modules using a JDK without javafx.* modules (the "gradle sdk" step), but we cannot build or run apps or tests on such a JDK. We instead have to take those FX bits and build our own JDK including them.

This is a significant limitation, as it effectively requires FX developers to build their own OpenJDK + FX if they want to run an FX app with an OpenJDK build.

We need to enhance the build system to produce artifacts that can run on a boot JDK without javafx.* modules baked in.

NOTE: untill all of the internal dependencies are resolved (see JDK-8195798), we will need to specify the qualified exports on the command line. As a stop-gap we will generate the necessary @ args files with the needed "--add-exports" arguments.
Comments
Here are the newly-filed linked issues: JDK-8202277 : WebView image capture fails with standalone FX due to dependency on javafx.swing JDK-8202451 : Swing interop fails when run with a security manager with standalone SDK JDK-8202368 : Create jmods for standalone javafx modules JDK-8202446 : Update the scripts in rt/tools/scripts/ for standalone SDK
30-04-2018

Comment with linked issues moved below...
30-04-2018

I tested by building the proposed the changes with both OracleJDK 10.0.1 (has javafx modules) and OpenJDK 10.0.1 (does not have javafx modules) on Ubuntu. The changes look good. +1.
27-04-2018

Changeset: f29f3fbe6810 Author: kcr Date: 2018-04-27 05:19 -0700 URL: http://hg.openjdk.java.net/openjfx/jfx-dev/rt/rev/f29f3fbe6810 8198329: Support FX build / test using JDK that doesn't include javafx.* modules Reviewed-by: prr, jvos, aghaisas
27-04-2018

I've reviewed the code and also done a full build of rt on Windows 7 using OpenJDK10.0.1, which included building media and webkit and apps. I also ran -PFULL_TEST=true and saw only expected failures. So + 1 from me. -phil.
26-04-2018

Update webrev: http://cr.openjdk.java.net/~kcr/8198329/webrev.01/ Delta webrev between version .00 and .01 : http://cr.openjdk.java.net/~kcr/8198329/delta-webrev.00-01/ This version is intended to be the final version pending feedback. Changes from .00 are: 1. Removed the debug print statement from build.gradle 2. Implemented the "publicExports" and "zips" tasks to create the artifacts that will be needed for early access builds. These tasks are only executed if you run them explicitly or as part of "gradle all"
26-04-2018

I applied the patch to the github repository, and I could build the SDK with OpenJDK 10.0.1 I could compile and run a basic JavaFX program (using the instructions above) so I can confirm this approach is working.
25-04-2018

About * File a follow-on issue to create the jmods -- this will likely be done after the initial EA build As a follow-up of that issue, we can add the publish logic that allows the modules to be uploaded to e.g. maven central and jcenter. Gradle has a plugin for this, so I think it makes sense we include that as an additional (optional) task.
25-04-2018

Yes, that would be another follow-up issue. In order for applications to be able to use these bundles by declaring a gradle or maven dependency on them, we might need logic to handle unpacking native libraries, since AFAIK there is no builtin support for this.
25-04-2018

Webrev: http://cr.openjdk.java.net/~kcr/8198329/webrev.00/ EVALUATION ---------- The purpose of this RFE is to modify the build to create a standalone SDK as indicated above. Most of the modifications are in build.gradle to create a parallel "build/sdk" directory and to use that SDK when building and running apps and tests. Roughly, the following is done: if (boot JDK has javafx.* modules) { Create arg files that point "modular-sdk" (no change from today) } else { Create arg files that point "sdk" Use --module-path instead of --patch-module } I had to fix a few missing dependencies in build.gradle for compiling and running the system tests (these were latent bugs that cause the build to fail if the boot JDK doesn't have javafx.* modules already). The remaining changes are in support of this. I removed some unneeded build logic in Ensemble8 that was using the old ant-javafx.jar support (which is not present in the OpenJDK builds nor the standalone SDK). I fixed some logic in PlatformImpl that was assuming the presense of the javafx.swing module when a certain system property was set, I had to fix the ModuleLauncherTest since we now need --module-path for FX and the test application (so they need to be combined, since --module-path is a "last one wins" option). I also added a new test to verify that javafx.base is a proper named module. I have tested this on all three platforms with Oracle JDK 10 (has javafx modules) and OpenJDK 10 (does not have javafx modules) builds. NOTES TO REVIEWERS ------------------ * I left in some debug print statements in the gradle project config for my testing purposes, but will remove that for the final webrev. * When you test this, you will need OracleJDK 10 or 10.0.1 -- make sure that your boot JDK (JAVA_HOME) does not contain javafx modules. When you run your build, look for this line in the output: HAS_JAVAFX_MODULES: false BUGS / FOLLOW-ON ISSUES ----------------------- I ran into a few bugs while testing this: * javafx.web uses a utility method from the javafx.swing package, which throws an exception with the standalone FX unless javafx.swing is explicitly added and one of the qualified exports (sun.awt.image) is added on the comment line. I will file a bug to create a private utility method in javafx.web itself to break this unwanted (and now unworkable) dependency. * Swing interop needs 6 qualified exports on the command line when running with JDK 10 (and when running with 11-ea, until the jdk.unsupported.desktop module is added and we switch to building with 11) * Swing interop fails when run with a security manager NOTE: this is likely not something we will fix. Once we switch to the new public interop API it won't be a problem, and it isn't worth fixing in the interim. Additionaly, there is some needed follow-on work: * File a follow-on issue to create the zip bundles for the sdk or the docs -- the SDK at least is needed for the initial EA build * File a follow-on issue to create the jmods -- this will likely be done after the initial EA build * File a P5 bug to update the scripts in rt/tools/scripts/ for standalone SDK
24-04-2018

Notes for developers of JavaFX: We need to add this support in such a way that a developer can still build and test the existing javafx-exports.zip for importing into a JDK build. My proposed fix is to build both the existing bundled sdk (in the "modular-sdk" dir) and javafx-exports.zip file as well as the new standalone sdk (in the "sdk" dir) The one that will be used for building and running apps and tests will depend on whether or not the boot JDK contains javafx.* modules. The build.gradle "HAS_JAVAFX_MODULES" flag, which is true if and only if the boot JDK contains javafx.* modules, will be used as follows: false : the standalone variant : build / test using the standalone set of JavaFX modules true : the bundled variant : build / test the set of javafx.* modules for inclusion into the JDK NOTE: even though it is somewhat misleading, I plan to retain the "modular-sdk" directory name, at least during the transition. This reduces the effort and the risk to the existing builds for as long as we need to support both. NOTE: Switching the boot JDK from one that has javafx modules (e.g., an Oracle JDK 10 build) to one without javafx modules (e.g., an OpenJDK 10 build) requires removing the "build" directory, either manually or by running "gradle clean". Here is the proposed layout of the build directory when building the standalone variant. Note that "compile.args", "run.args", etc. files serve a similar purpose as with the bundled variant. build/ compile.args :: modified to use --module-path instead of --patch-module run.args :: modified to use --module-path instead of --patch-module run.java.policy :: similar to bundled variant test.java.policy :: similar to bundled variant testcompile.args :: modified to use --module-path instead of --patch-module testrun.args :: modified to use --module-path instead of --patch-module sdk/ :: standlone layout as defined above shims/ :: similar to bundled variant (with the addition of the module-info.class files) See the previous comment for the planned layout of the JavaFX SDK (which will be built in the build dir and zipped up as javafx-sdk-$VER-$PLATFORM.zip for distribution). We also plan to produce a separate javafx-jmods-$VER-$PLATFORM.zip bundle for distributing the jmods, since they are only needed to jlink your application, and are not needed to run your application using --module-path. Other than qualified exports (most of which will go away soon), the only command line options needed to compile and run a JavaFX application are "--module-path" to point to the JAVAFX_SDK/lib dir, and for applications in the unnamed module, "--add-modules" to add the needed javafx.* modules to the module graph. For example, to compile and run an application that uses javafx.controls: javac --module-path JAVAFX_SDK/lib --add-modules javafx.controls my/pkg/MyApp java --module-path JAVAFX_SDK/lib --add-modules javafx.controls my.pkg.MyApp Or for a modular app, you don't need to specify the --add-modules as long as your application's module-info.java "requires" the necessary modules: java --module-path JAVAFX_SDK/lib --module-path . -m mymod/my.pgk.MyApp For developer convenience (and for use by gradle build / test), you can use the @ args files as follows: javac @JFX_BUILD/compile.args my/pkg/MyApp java @JFX_BUILD/run.args my.pkg.MyApp
24-04-2018

Here is the proposed layout of the standalone JavaFX SDK: 1. Standalone SDK (used via module-path to compile / run applications) javafx-sdk-$VER-$PLATFORM.zip <JAVAFX_SDK_DIR>/ legal/ ${module}/ *.md lib/ javafx.base.jar javafx.controls.jar javafx.fxml.jar javafx.graphics.jar javafx.media.jar javafx.swing.jar javafx.web.jar javafx-swt.jar javafx.properties src.zip *.so (Linux) *.dylib (Mac) bin/ *.dll (Windows) 2. JavaFX jmods (used via jlink) javafx-jmods-$VER-$PLATFORM.zip <JAVAFX_SDK_DIR>/ jmods/ javafx.base.jmod javafx.controls.jmod javafx.fxml.jmod javafx.graphics.jmod javafx.media.jmod javafx.swing.jmod javafx.web.jmod
24-04-2018

Yes, those are good points.
26-03-2018

An SDK is good, but I think the most common usecase will be via the existing distribution channels (e.g. maven central, jcenter). In that case, a developer simply declares a dependency on the required modules, and his build tools (maven or gradle) will communicate with the distribution channels to download and install the required modules and their dependencies. That means the jmods should also have the native libs included.
26-03-2018