(Note: Historically you also had to clone the top "jfx" repository in the forest that you cared about. However we have modified our approach, such that we no longer promote the use of a forest, and instead are putting all of our sources in a single repository, named "rt").
TODO KCR: FINISH THE ABOVE AND ADD MORE HERE
Using Gradle on The Command Line
Before diving directly into building OpenJFX, lets get our feet wet by learning what kinds of things we can call from the command line, and how to get help when we need it. The first command you should execute is tasks:
rbair$$ gradle tasks The CompileOptions.useAnt property has been deprecated and is scheduled to be removed in Gradle 2.0. There is no replacement for this property. :tasks ------------------------------------------------------------ All tasks runnable from root project ------------------------------------------------------------ Default tasks: assemblesdk Basic tasks ----------- buildModuleBaseLinux - creates javafx.base property files buildModuleGraphicsLinux - copies javafx.graphics native libraries buildModuleLibsLinux buildModuleMediaLinux - copies javafx.media native libraries buildModulePackagerExeLinux - copies jdk.packager executable buildModulePackagerLibsLinux - copies jdk.packager libraries buildModuleSWTLinux - copies SWT JAR buildModuleWebLinux - copies javafx.web native libraries clean - Deletes the build directory and the build directory of all sub projects cleanAll - Scrubs the repo of build artifacts javadoc - Generates the JavaDoc for all the public API jfxrtjavafxSwtLinux - Creates the jfxrtjavafx-swt.jar sdkfor -the Createslinux antarget SDKsdkLinux Build tasks ----------- antpluginClasses - Assembles antplugin classes. assemble - Assembles the outputs of this project. build - Assembles and tests this project. buildDependents - Assembles and tests this project and all projects that depend on it. buildJavaPackager buildModuleLinux buildModulesLinux buildModuleZipLinux buildNeeded - Assembles and tests this project and all projects it depends on. ccDecorabuildRunArgsLinux ccLinuxFont - Compiles native sources for Decorafont ccGlassfor linux ccLinuxFontFreetype - Compiles native sources for Glass ccPrismfontFreetype for linux ccLinuxFontPango - Compiles native sources for fontPango for linux ccLinuxGlassGlass - Compiles native sources for glass for linux for variant Glass ccLinuxGlassGlassgtk2 - Compiles native sources for Prismglass ccPrismSW for linux for variant Glassgtk2 ccLinuxGlassGlassgtk3 - Compiles native sources for PrismSW glass for linux for variant Glassgtk3 ccLinuxIio - Compiles native sources for iio for linux ccLinuxPrism - Compiles native sources for prism for linux ccLinuxPrismES2 - Compiles native sources for prismES2 for linux ccLinuxPrismSW - Compiles native sources for prismSW for linux classes - Assembles the main classes. clean - Deletes the build directory. cleanNative - Clean all native libraries and objects for Graphics cleanNativeDecora - Clean native objects for Decora cleanNativeFont - Clean native objects for font cleanNativeFontFreetype - Clean native objects for fontFreetype cleanNativeFontPango - Clean native objects for fontPango cleanNativeGlass - Clean native objects for glass cleanNativeIio - Clean native objects for iio cleanNativePrism - Clean native objects for prism cleanNativePrismES2 - Clean native objects for prismES2 cleanNativePrismSW - Clean native objects for prismSW compileLinuxLauncher - Compiles native sources for the application co-bundle launcher compileLinuxLibrary - Compiles native sources for the application co-bundle launcher library createMSPfile jar - Assembles a jar archive containing the main classes. javahDecorajslcClasses - GeneratesAssembles JNIjslc Headers classes. linkLinuxFont - Creates native dynamic library for Decorafont javahGlassfor linux linkLinuxFontFreetype - GeneratesCreates JNInative Headersdynamic library for Glass javahPrismfontFreetype for linux linkLinuxFontPango - Creates native dynamic library for fontPango for linux linkLinuxGlassGlass - Creates native dynamic library for glass for linux for variant Glass linkLinuxGlassGlassgtk2 - GeneratesCreates JNInative Headersdynamic library for Prismglass javahPrismSW for linux for variant Glassgtk2 linkLinuxGlassGlassgtk3 - GeneratesCreates JNInative Headersdynamic library for PrismSWglass linkDecora for linux for variant Glassgtk3 linkLinuxIio - Creates native dynamic library for Decoraiio linkGlassfor linux linkLinuxLauncher - Links native dynamic library for the application co-bundle launcher linkLinuxLibrary - Links native dynamic library for the application co-bundle launcher library linkLinuxPrism - Creates native dynamic library for Glassprism linkPrismfor linux linkLinuxPrismES2 - Creates native dynamic library for PrismprismES2 linkPrismSWfor linux linkLinuxPrismSW - Creates native dynamic library for PrismSWprismSW for linux native - Compiles and Builds all native libraries for Graphics nativeDecora - Generates JNI headers, compiles, and builds native dynamic library for Decora nativeFont - Generates JNI headers, compiles, and builds native dynamic library for font for all compile targets nativeFontFreetype - Generates JNI headers, compiles, and builds native dynamic library for fontFreetype for all compile targets nativeFontPango - Generates JNI headers, compiles, and builds native dynamic library for fontPango for all compile targets nativeGlass - Generates JNI headers, compiles, and builds native dynamic library for Glass glass for all compile targets nativeIio - Generates JNI headers, compiles, and builds native dynamic library for iio for all compile targets nativePrism - Generates JNI headers, compiles, and builds native dynamic library for Prism prism for all compile targets nativePrismES2 - Generates JNI headers, compiles, and builds native dynamic library for prismES2 for all compile targets nativePrismSW - Generates JNI headers, compiles, and builds native dynamic library for PrismSW prismSW for all compile targets shadersClasses - Assembles shaders classes. shimsClasses - Assembles shims classes. stubClasses - Assembles the stub classes. testapp1Classes - Assembles testapp1 classes. testapp2Classes - Assembles testapp2 classes. testapp3Classes - Assembles testapp3 classes. testapp4Classes - Assembles testapp4 classes. testapp5Classes - Assembles testapp5 classes. testapp6Classes - Assembles testapp6 classes. testClasses - Assembles the test classes. toolsClasses - Assembles tools classes. Build Setup tasks ----------------- init - Initializes a new Gradle build. wrapper - Generates Gradle wrapper files. Documentation tasks ------------------- javadoc - Generates Javadoc API documentation for the main source code. Help tasks ---------- buildEnvironment - Displays all buildscript dependencies declared in root project 'rt'. components - Displays the components produced by root project 'rt'. [incubating] dependencies - Displays all dependencies declared in root project 'javafxrt'. dependencyInsight - Displays the insight into a specific dependency in root project 'javafxrt'. dependentComponents - Displays the dependent components of components in root project 'rt'. [incubating] help - Displays a help message. model - Displays the configuration model of root project 'rt'. [incubating] projects - Displays the sub-projects of root project 'javafxrt'. properties - Displays the properties of root project 'javafxrt'. tasks - Displays the tasks runnable from root project 'javafxrt' (some of the displayed tasks may belong to subprojects). IDE tasks --------- cleanIdea - Cleans IDEA project files (IML, IPR) cleanIdeaWorkspace - Deletes the javafx.ipw file cleanNetBeans - Deletes generated NetBeans files idea - Generates IDEA project files (IML, IPR, IWS) netBeans - Creates the NetBeans project files for JavaFX Verification tasks ------------------ check - Runs all checks. test - Runs the unit tests. To see all tasks and more detail, run withgradle tasks --all. To see more detail about a task, run gradle help --task <task> BUILD SUCCESSFUL in 4s Total1 timeactionable task: 4.8831 secsexecuted
The tasks task is extremely helpful. You use it to discover all the other things you can do with this build file. You notice at the top of the output the phrase "All tasks runnable from root project". The "root" project is "javafx". That is, we are in the root project. Below the root project are a series of sub projects, some of which are referred to as modules or "components". But more about those later.
Gradle then tells us what the default tasks are. In this case, our default task is the 'sdk' task. This is the task that will be executed if you just call 'gradle' alone without providing any additional arguments. After this comes a listing of different tasks, broken out by group. The first group is the "Basic" group which contains the tasks you may find yourself using most often. These are all named and have a description provided. For example, if I wanted to execute the 'clean' task, then I would do so like this:
rbair$$ gradle clean
Finally, the tasks task gives us a useful hint that we can pass the --all argument in order to see all of the tasks in more detail. This produces a lot more output, but really gives an in depth look at what tasks are available for you to call.
I mentioned above that our root project is called "javafxrt", and that we have sub-projects in the gradle build. To see all of the projects available to you, execute the projects task (which you will notice was in the "Help tasks" group produced by the tasks task). This lists not just what projects are available, but what their name is, and what the project hierarchy is.
rbair$$ gradle projects The CompileOptions.useAnt property has been deprecated and is scheduled to be removed in Gradle 2.0. There is no replacement for this property. :projects ------------------------------------------------------------ Root project ------------------------------------------------------------ Root project 'javafxrt' +--- Project ':baseapps' +--- Project ':build-toolsbase' +--- Project ':controls' +--- Project ':designTimefxml' +--- Project ':fxmlfxpackager' +--- Project ':graphicsfxpackagerservices' |+--- Project ':graphics' +--- Project ':graphics:effects-jsljmx' |+--- Project \':media' +--- Project ':graphics:prism-jsl'swing' +--- Project ':swt' +--- Project ':swingsystemTests' \--- Project ':swtweb' To see a list of the tasks of a project, run gradle <project-path>:tasks For example, try running gradle :baseapps:tasks BUILD SUCCESSFUL in 1s Total1 timeactionable task: 4.194 secs1 executed kcr@beethoven:~/javafx/openjfx/jfx-kcr/rt$
Projects in gradle are named according to their depth. So the root project is simply named "javafx"rt" (or whatever your top directory is named). The immediate subprojects are all prefixed with a ":". Sub-subprojects have their parents in their name, for example, ":graphics:effects-jsl". When you execute a command such as gradle assemble what actually happens is that Gradle locates the assemble task on all projects and executes them. (TODO Is this entirely accurate?)
There are a couple other tricks-of-the-trade that you should be aware of. You can execute any gradle command with --info or --debug in order to get more output. Running in --info mode provides some additional debugging output that is very useful when things go wrong. In particular, our build system will output certain crucial variables that are being used to perform the build:
rbair$ gradle projects Starting Build Settings evaluated using settings file '/Users/rbair/Projects/JavaFX/graphics-8.0/javafx/settings.gradle'. Projects loaded. Root project using build file '/Users/rbair/Projects/JavaFX/graphics-8.0/javafx/build.gradle'. Included projects: [root project 'javafx', project ':base', project ':build-tools', project ':controls', project ':designTime', project ':fxml', project ':graphics', project ':swing', project ':swt', project ':graphics:effects-jsl', project ':graphics:prism-jsl'] Evaluating root project 'javafx' using build file '/Users/rbair/Projects/JavaFX/graphics-8.0/javafx/build.gradle'. OS_NAME: mac os x JAVA_HOME: /Library/Java/JavaVirtualMachines/jdk1.8.0.jdk_b81/Contents/Home/jre JDK_HOME: /Library/Java/JavaVirtualMachines/jdk1.8.0.jdk_b81/Contents/Home BINARY_STUB: file:///Library/Java/JavaVirtualMachines/jdk1.8.0.jdk_b81/Contents/Home/jre/lib/ext/jfxrt.jar HUDSON_JOB_NAME: not_hudson HUDSON_BUILD_NUMBER: 0000 PROMOTED_BUILD_NUMBER: 00 PRODUCT_NAME: OpenJFX RAW_VERSION: 8.0.0 RELEASE_NAME: 8.0 RELEASE_MILESTONE: ea The CompileOptions.useAnt property has been deprecated and is scheduled to be removed in Gradle 2.0. There is no replacement for this property. Evaluating project ':base' using empty build file. Evaluating project ':build-tools' using empty build file. Evaluating project ':controls' using empty build file. Evaluating project ':designTime' using empty build file. Evaluating project ':fxml' using empty build file. Evaluating project ':graphics' using empty build file. Evaluating project ':swing' using empty build file. Evaluating project ':swt' using empty build file. Evaluating project ':graphics:effects-jsl' using empty build file. Evaluating project ':graphics:prism-jsl' using empty build file. All projects evaluated. Selected primary task 'projects' Tasks to be executed: [task ':projects'] :projects ------------------------------------------------------------ Root project ------------------------------------------------------------ Root project 'javafx' +--- Project ':base' +--- Project ':build-tools' +--- Project ':controls' +--- Project ':designTime' +--- Project ':fxml' +--- Project ':graphics' | +--- Project ':graphics:effects-jsl' | \--- Project ':graphics:prism-jsl' +--- Project ':swing' \--- Project ':swt' To see a list of the tasks of a project, run gradle <project-path>:tasks For example, try running gradle :base:tasks BUILD SUCCESSFUL Total time: 4.194 secs
Among all this output is a list of several important properties, such as JDK_HOME. These properties are essential to the behavior of the build system, so if something goes wrong, you can check that you are building with the right binar stub and the right JDK (hint: nearly everything is based on JDK_HOME – if you have that set right, the rest of the Java build should just work).
One more trick is the --profile argument. You can perform any gradle task and use the --profile argument. This will cause gradle to keep track of how long various parts of the build took, and will produce an HTML report in build/reports/profile. The report breaks down how much time was spent in configuration, dependency resolution, and task execution. It further breaks it down by project. This gives useful metrics for tracking down which parts of the build take the longest and hopefully tighten up the build times.
Build and Test
There are three main things you may want to do on a regular basis when working on JavaFX: building, testing, and creating documentation. Lets look at each of these in turn.
The simplest basic task to build is the sdk task. The sdk task will compile all Java sources and all native sources for your target platform. It is the default task which is executed if you do not supply a specific task to run. It will create the appropriate sdk directory and populate it with the native dynamic libraries and the jfxrt.jar. Because the SDK is not distributed with documentation, the javadocs are not created as part of the sdk task by default. Once the sdk task has completed, you will have and SDK distribution which you could run against (modulo any closed-bits) or give to somebody else to run.
rbair$$ gradle The CompileOptions.useAnt property has been deprecated and is scheduled to be removed in Gradle 2.0. There is no replacement for this property. :base:processVersion :build-tools:generateGrammarSource :build-tools:compileJava :build-tools:processResources :build-tools:classes :build-tools:jar :base:compileJava [snip out a whole bunch of stuff] :jfxrt :sdk :buildModulesLinux :buildRunArgsLinux :buildModules :createTestArgfilesLinux :sdkLinux :sdk BUILD SUCCESSFUL in 1m Total48s time:127 1actionable mins 45.184 secstasks: 127 executed
You can find the built SDK in the build/modular-sdk directory:
rbair$$ pwd /Users/rbairkcr/openjfx-jfxdev/graphics/javafxrt rbair$$ ls -l build/ -rw-r--r-- 1 kcr kcr 1621 Dec 22 09:54 compile.args drwxr-xr-x 2 3kcr rbairkcr 4096 staffDec 22 102 Mar 23 17:39 sdk drwxr-xr-x 3 rbair staff 102 Mar 23 17:39 tmp rbair$ ls build/sdk/rt/lib/ ext/ libdecora-sse.dylib libprism-common.dylib javafx.properties libglass.dylib libprism-sw.dylib 09:54 libs/ -rw-r--r-- 1 kcr kcr 47 Dec 22 09:54 linux_freetype_tools.properties -rw-r--r-- 1 kcr kcr 681 Dec 22 09:54 linux_gtk2.properties -rw-r--r-- 1 kcr kcr 799 Dec 22 09:54 linux_gtk3.properties -rw-r--r-- 1 kcr kcr 255 Dec 22 09:54 linux_pango_tools.properties drwxr-xr-x 9 kcr kcr 4096 Dec 22 09:54 modular-sdk/ -rw-r--r-- 1 kcr kcr 1916 Dec 22 09:54 run.args -rw-r--r-- 1 kcr kcr 1379 Dec 22 09:54 run.java.policy -rw-r--r-- 1 kcr kcr 1304 Dec 22 09:54 test.java.policy -rw-r--r-- 1 kcr kcr 1551 Dec 22 09:54 testcompile.args -rw-r--r-- 1 kcr kcr 1846 Dec 22 09:54 testrun.args drwxr-xr-x 3 kcr kcr 4096 Dec 22 09:54 tmp/
The sdk task will build an OpenJFX SDK for your particular Operating System. The "host" build will be named sdk, and any cross builds will have a prefix like armv6hf-sdk. Multiple different sdks may be built concurrently, and all will reside within the build directory when completed (see <<Cross Builds>> for more information). platform. Gradle automatically handles the downloading of all dependencies (such as Antlr and SWT).
For more information on build properties, see Customizing the Build.
NOTE: cross-build support is currently untested in the mainline jfx-dev/rt repo
The build is configured to support cross builds, that is, the ability to build an SDK for a platform other than the one you are building from. There are multiple gradle files located in buildSrc which represent specific compile targets. These include:
By default, the OpenJFX build system will only build the SDK for the desktop platform you are building from. To ask it to build for a specific compile target, you must pass a COMPILE_TARGETS property to the build system, instructing it which to build. This is a comma separated list. Assuming you have already setup the prerequisites for building ARM (for example, when targeting the Raspberry PI), you would invoke gradle like this:
rbair$$ gradle -PCOMPILE_TARGETS=armv6hf
The build can be customized fairly extensively through the use of Gradle properties. Gradle provides many ways to supply properties to the build system. However the most common approach will be to use a gradle.properties file located in the rt directory. Simply make a copy of gradle.properties.template and then edit the resulting gradle.properties file to customize your build.
rbair$$ cp gradle.properties.template gradle.properties
The gradle.properties file that you have just created is heavily documented and contains information on all the different configuration options at your disposal.
- Enabling building of native source code (Prism, Glass, GStreamer, WebKit, etc)
- Specifying the build configuration (Release or Debug)
- Enabling building of JavaDoc
- Customizing the JDK_HOME
- Supplying compiler LINT options
Arguably the most important property in the build is the JDK_HOME property, which will be set to the value of $JAVA_HOME if you haven't explicitly set it. Almost all other properties are derived automatically from this one. The JDK_HOME is by default based on the java.home System property, which is set automatically by the JVM based on which version of Java is executed. Typically, then, the version of Java you will be using to compile with will be the version of Java you have setup on your path. You can of course specify the JDK_HOME yourself. Note also that on Windows, the version of the JDK you have set as JDK_HOME will determine whether you build 32 or 64 bit binaries.
The next basic task which you may want to perform is test. The test task will execute the unit tests. You generally will execute the top level test because unlike with Ant, Gradle will only re-execute those tests which have changed (or were dependent on code that was changed) on subsequent runs. You can of course execute gradle cleanTest in order to clean all the test results so they will run fresh. Or, if you want to execute only those tests related to a single project, you can do so in the normal fashion:
rbair$$ gradle :base:test The CompileOptions.useAnt property has been deprecated and is scheduled to be removed in Gradle 2.0. There is no replacement for this property. :base:processVersion UP-TO-DATE :build-tools:generateGrammarSource UP-TO-DATE :build-tools:compileJava UP-TO-DATE :build-tools:processResources UP-TO-DATE :build-tools:classes UP-TO-DATE :build-tools:jar UP-TO-DATE :base:compileJava UP-TO-DATE :base:processResources UP-TO-DATE :base:classes UP-TO-DATE :base:compileTestJava UP-TO-DATE :base:processTestResources UP-TO-DATE :base:testClasses UP-TO-DATE > Building > :base:test > 3411 tests completed, 45 skipped
For the sake of performance, most of the tests are configured to run in the same VM. However some tests by design cannot be run in the same VM, and others cannot yet run in the same VM due to bugs or issues in the test. In order to improve the quality of the project we need to run as many tests as possible in the same VM. The more tests we can run on pre-integration the less likely we are to see failures leak into master. Being able to run 20,000 tests in a minute is extremely useful, but not possible, unless they run in the same VM. Something to keep in mind.
Overlay - JDK 8
After a successful build, the final step could be copying the results, overlaying them over an existing JDK. This step will replace any JavaFX/OpenJFX binaries in that runtime with your newly built binaries.
First execute the gradle task which creates an overlay bundle.
rbair$ gradle [-PCOMPILE_TARGETS=armv6hf] zips # If you are cross compiling you will need the COMPILE_TARGETS flag # with the appropriate target # -PCOMPILE_TARGETS=armv6hf
This will create a zip bundle containing the OpenJFX binaries and is designed to be extracted into a JDK or JRE.
The created bundle is located in build/[platform-]bundles/javafx-sdk-overlay.zip. [platform-] will only be present for a cross build, and will be the name of the cross platform (for example armv6hf-bundles).
Please note that there might be some differences in the contents of the runtime found in build/[platform-]sdk/ and the contents of the bundles. The overlay bundle is designed to match JavaFX in a production JDK.
Within a JDK there is a directory that contains the Java Runtime Environment, "./jre". The zip bundle is designed to be extracted in the directory that contains "./jre".
As zip bundles do not always preserve permissions, sometimes it is necessary to modify the file permissions to match the others in the JRE. In particular, check the permissions on the extracted native libraries.
Sandbox Testing with JDK9
Testing with JDK 9 or JDK 10
Using the results of a modular JDK9 OpenJFX build is quite simple. A "run" args file can be used to point to the overriding modules that are in your build. (args file support for java was added in JDK9JDK 9) The file build/run.args and build/compile.args are created during the FX build process. The run.args file contains full paths to the overriding modules and shared libraries, and so must be recreated if you are using a copied or downloaded module set (for example from a nightly build). A script is provided that will recreate the xpatch.args file in the current directory:
The following can be used to set up an alias that can be used to launch a JFX application, but using the FX binaries from your development tree. This alias will override the modules built into JDK9.
export JFX_PATCH=$JFX_BUILD/build/run.args (or the path to one created by make_runargs.sh)
alias javafx='$JIGSAW$JAVA_HOME/bin/java @$JFX_PATCH'
In Windows, the paths for the alias can be a bit tricky to get right, as the JDK wants native Windows paths, and cygwin often works better with a Unix path. Here is an example that works with Cygwin:
export JIGSAWJAVA_HOME=`cygpath -m "/cygdrive/c/Program Files/Java/jdk-9/"`
export JFX_PATCH=`cygpath -m "$JFX_BUILD/build/run.args"`
alias javafx='"$JIGSAW$JAVA_HOME/bin/java" @$JFX_PATCH'
Integration with OpenJDK
With the module system in JDK 9 and later, it is not possible to easily overlay an OpenJFX build over an existing JDK as was possible with JDK 8. It is possible to build an OpenJDK that included the updated OpenJFX modules.
To create an integrated OpenJDK 9 with OpenJFX requires two builds:
- OpenJFX for JDK 9
- OpenJDK 9, with a configure reference that includes your OpenJFX build.
Build OpenJFX first.
Configure the JDK with the following addition:
Then build the JDK as normal.
Understanding a JDK
Modular world in our developer build
The export of module packages is governed by two sets of files:
Adding new packages in a modular world
JDK 9 Modules add The JDK Module System adds complexity to the development chain, but particularly when adding new API and especially packages. Adding a new package or changing package visibility will be a multi step task that will require at least two change sets to implement.