Skip to content

Latest commit

 

History

History
206 lines (161 loc) · 9.03 KB

announcement.adoc

File metadata and controls

206 lines (161 loc) · 9.03 KB

Gradle and Maven Plugins for Native Image with Initial JUnit 5 Testing Support

1*xyDPne0XE1sK69i4wyHC6Q

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 of 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

plugins {
  id 'org.graalvm.buildtools.native' version "0.9.0"  // or a newer version
}

as well as adding the following to the settings.gradle:

pluginManagement {
  repositories {
    mavenCentral()
    gradlePluginPortal()
  }
}

(this step will be redundant once this plugin is published to the Gradle Plugin Portal).

After that, we can configure the image build by using a graalvmNative configuration block:

graalvmNative {
    binaries {
        main {
            imageName = "my-app"
            mainClass = "org.test.Main"
            verbose = true
            fallback = false
        }
    }
}

The plugin then adds nativeCompile and nativeRun tasks that respectively creates a native executable and runs 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.

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).

$ ./gradlew nativeTest

> Task :nativeTest
JUnit Platform on Native Image - report
----------------------------------------
org.graalvm.buildtools.example.App2Test > appHasAGreeting() SUCCESSFUL
org.graalvm.buildtools.example.AppTest > appHasAGreeting() SUCCESSFUL

Test run finished after 3 ms
[         3 containers found      ]
[         0 containers skipped    ]
[         3 containers started    ]
[         0 containers aborted    ]
[         3 containers successful ]
[         0 containers failed     ]
[         2 tests found           ]
[         0 tests skipped         ]
[         2 tests started         ]
[         0 tests aborted         ]
[         2 tests successful      ]
[         0 tests failed          ]


BUILD SUCCESSFUL in 771ms
5 actionable tasks: 1 executed, 4 up-to-date

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 the pom.xml:

<profiles>
  <profile>
    <id>native</id>
    <build>
      <plugins>
        <plugin>
          <groupId>org.graalvm.buildtools</groupId>
          <artifactId>native-maven-plugin</artifactId>
          <version>0.9.0</version> <!-- or newer version -->
          <executions>
            <execution>
              <id>test-native</id>
              <goals>
                <goal>test</goal>
              </goals>
              <phase>test</phase>
            </execution>
            <execution>
              <id>build-native</id>
              <goals>
                <goal>compile-no-fork</goal>
              </goals>
              <phase>package</phase>
            </execution>
          </executions>
          <configuration>
            <imageName>my-app</imageName>
            <mainClass>org.test.Main</mainClass>
            <buildArgs>
            --no-fallback
            --verbose
            </buildArgs>
          </configuration>
        </plugin>
      </plugins>
    </build>
  </profile>
</profiles>

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

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 _PR_s 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.