Gradle and Maven Plugins for Native Image with Initial JUnit 5 Testing Support
--
We are pleased to announce the release of the new official GraalVM Native Image Gradle and Maven plugins. The plugins aim to make GraalVM Native Image a first-class citizen in the JVM ecosystem: it makes building, testing, and running Java applications as native executables a breeze. The key new feature is the out-of-the-box support for native JUnit 5 testing.
The native JUnit support allows libraries in the JVM ecosystem to run their test suites via GraalVM Native Image. With integrated testing, library configuration should be always up to date and ready for the end user. We believe that this is the biggest step towards making the Java ecosystem native-ready.
Complete examples are available here.
Native Testing: The Way You Are Used to It
We’ve made it: testing Java code with JUnit 5 behaves exactly the same* in native execution as with the JVM. To make this work, we implemented a custom junit-platform-native
feature that logs tests that are discovered during the previous execution of the standard JVM test
task and registers them for native compilation and reflection. Based on this information, special test executable that contains all the tests (and their metadata) is built, and then invoked when using the corresponding build-tool task.
Collection of metadata imposes the dependency to the JVM test
task execution. The downside of this is increased testing time, but it also provides a suitable entry point for users to enable native-image-agent
invocation that can be used to generate missing reflection configuration for the project. Note that the agent invocation is independent from the test-metadata collection — the test metadata is always collected.
In the future we intend to work on removing the dependency on the JVM
test
execution. For this, we need modifications in the testing frameworks that will allow metadata collection without the execution of individual tests (a.k.a., dry-run support).
For more information users should consult the plugin documentation for Maven or Gradle.
* Given proper configuration, and given that the project under test doesn’t include native-specific code (e.g., build-time initialization, substitutions, and plugins).
Gradle Plugin
Adding native-gradle-plugin
to an existing Gradle project is as simple as including following to the plugins
section of the build.gradle
as well as adding the following to the settings.gradle
:
After that, we can configure the image build by using a nativeBuild
configuration block:
The plugin then adds nativeBuild
and nativeRun
tasks that build and run the main class (as one might expect ☺). If the reflection configuration is necessary for the Native Image building, this plugin also provides a simple option that activates the native-image-agent
without any additional user setup. More information (and Kotlin configuration syntax) is available in the documentation.
To help ease the community transition, at the moment we support a subset of the configuration syntax and aliased task names from the most popular unofficial GraalVM Gradle plugins (
io.micronaut.application
andcom.palantir.graal
). Note that this behavior might eventually be deprecated.
Testing in Gradle
User can start Native Image testing by invoking the nativeTest
task (with the ability to add additional native-image
configuration using a nativeTest
configuration block).
Note that the native testing depends on running the standard
test
task in the JVM mode beforehand.
Maven Plugin
We are releasing our existing plugin under the new maven coordinates — org.graalvm.buildtools:native-maven-plugin
. This change was motivated by our intention to move faster with the plugin development by decoupling it from the GraalVM release cycle. Users of our existing native-image-maven-plugin
only need to change the plugin's groupId
, artifactId
and version
in their pom.xml
, as the new plugin is backwards compatible with the old one. Versioning of the new plugin will start at 0.9.0
.
Adding our new plugin to the existing Maven project requires adding the following to thepom.xml
:
After that, the user can build native images by running:
mvn -Pnative -DskipTests package
Testing in Maven
The user can start Native Image testing by running:
mvn -Pnative test
Maven plugin currently requires an extra step in order to enable said listener: The user needs to add a dependency to org.graalvm.buildtools:junit-platform-native
in their pom.xml
. This step will not be necessary once JUnit 5.8 lands.
Note that the native testing depends on running the standard test task in the JVM mode beforehand.
Documentation and more configuration options are available here.
Future Goals
The next step is creating a standardized repository with configuration that would be automatically added for legacy libraries. This should make the development for Native Image feels more frictionless even for libraries that don’t support it yet. We intend to follow up with patches and PRs for original libraries, working closely with the community in order to bring first party support to the most of the ecosystem.
Built with Love Through Collaboration
Our testing support was developed in collaboration with JUnit, Micronaut, and Spring teams. Many thanks to Sam Brannen, Graeme Rocher, and Sébastien Deleuze for their contributions and advice. Moving forward, our new plugins are already landing in Spring Native 0.10.0, and hopefully soon many more projects will follow.
We are looking forwards to hearing about your experiences and/or potential issues. Contributions are also very welcome.
The project repository is available at github.com/graalvm/native-build-tools.
All projects mentioned here are released under the Universal Permissive License.