Nucleus
Performance & nativeGraalVM Native Image

Configuration

Reference for the graalvm { } DSL block that configures GraalVM native-image builds, including toolchain, image name, build arguments, metadata repository, and per-OS settings.

The graalvm { } block inside nucleus.application { } configures GraalVM native-image builds: the toolchain, the output binary, the arguments passed to native-image, the reachability metadata, and the macOS and Windows settings. Every property is lazy and Property-typed. The block is defined on JvmApplication, so it sits alongside mainClass and nativeDistributions.

Enable a native image

Set isEnabled = true and pick a toolchain. A minimal configuration looks like this:

build.gradle.kts
nucleus.application {
    mainClass = "com.example.MainKt"

    graalvm {
        isEnabled = true
        imageName = "myapp"

        // Download the full BellSoft Liberica NIK 25 yourself and install it locally —
        // Gradle's toolchain auto-provisioning does not fetch the NIK variant.
        // In CI, set up the JDK with graalvm/setup-graalvm@v1 first.
        javaLanguageVersion = 25

        buildArgs.addAll(
            "-H:+AddAllCharsets",
            "-Djava.awt.headless=false",
            "-Os",
            "-H:-IncludeMethodData",
        )

        metadataRepository {
            enabled = true           // default
            version = "0.10.6"       // default
            excludedModules.add("com.example:my-lib")
        }
    }
}

graalvm reference

PropertyTypeDefaultNotes
isEnabledProperty<Boolean>falseMaster switch for the native-image build.
javaLanguageVersionProperty<Int>25Toolchain language version; triggers Gradle's toolchain download.
imageNameProperty<String>package nameOutput binary name.
marchProperty<String>"native"native targets the current CPU; compatibility targets older CPUs.
buildArgsListProperty<String>emptyExtra arguments passed to native-image.
nativeImageConfigBaseDirDirectoryPropertyDirectory of app-specific reachability-metadata.json. Rarely needed.
macOSGraalvmMacOSSettingsmacOS sub-block (see below).
windowsGraalvmWindowsSettingsWindows sub-block (see below).
metadataRepositoryMetadataRepositorySettingsenabledOracle Reachability Metadata Repository (see below).

Set build arguments

buildArgs are forwarded verbatim to native-image. These are the arguments most desktop apps need:

ArgumentPurpose
-H:+AddAllCharsetsIncludes every charset, required for text I/O.
-Djava.awt.headless=falseEnables GUI support, required for desktop apps.
-OsOptimizes for binary size.
-H:-IncludeMethodDataDrops method metadata, reducing binary size by several MB.

Configure the metadata repository

The Nucleus plugin downloads the Oracle GraalVM Reachability Metadata Repository and resolves entries for every runtime dependency on the classpath. The metadataRepository { } sub-block maps to MetadataRepositorySettings.

PropertyTypeDefaultNotes
enabledProperty<Boolean>trueSet to false to skip the repository entirely.
versionProperty<String>"0.10.6"Repository artifact version.
excludedModulesSetProperty<String>emptygroup:artifact coordinates to skip.
moduleToConfigVersionMapProperty<String, String>emptyPins the metadata directory version for a given module.
build.gradle.kts
metadataRepository {
    moduleToConfigVersion.put("io.ktor:ktor-client-core", "3.0.0")
    excludedModules.add("group:noisy-lib")
}

Configure macOS settings

The macOS { } sub-block maps to GraalvmMacOSSettings.

PropertyTypeDefaultNotes
cStubsSrcRegularFilePropertyFile of additional C stubs linked into the binary.
minimumSystemVersionProperty<String>"12.0"Patches the Mach-O LC_VERSION_MIN_MACOSX load command.
macOsSdkVersionProperty<String>"26.0"SDK version stamped into the launcher's Mach-O headers, which controls Liquid Glass eligibility.

Configure Windows settings

The windows { } sub-block maps to GraalvmWindowsSettings. GraalVM native images on Windows are dynamically linked against the Visual C++ runtime, which is not part of a clean Windows install. Bundling the runtime DLLs next to the executable lets the app start without the Visual C++ Redistributable.

PropertyTypeDefaultNotes
bundleCRuntimeProperty<Boolean>trueCopies the MSVC runtime DLLs next to the .exe.
dllsListProperty<String>vcruntime140.dll, vcruntime140_1.dll, msvcp140.dllDLL file names copied when bundleCRuntime is enabled.
sourceDirDirectoryPropertytoolchain binDirectory the DLLs are copied from. Point it at the MSVC redistributable if a DLL is missing from the toolchain.
build.gradle.kts
graalvm {
    windows {
        bundleCRuntime = true
        dlls.add("vcruntime140.dll")
    }
}

No release variant

Unlike the JVM build types, GraalVM has no release variant: there is no packageReleaseGraalvmNative and no runReleaseGraalvmNative. The native tasks are packageGraalvmNative and runGraalvmNative. This is intentional:

  • ProGuard's dead-code elimination is redundant. native-image already does closed-world dead-code elimination at compile time.
  • ProGuard can rename classes that are still referenced by reachability-metadata.json, which breaks the build silently.

Use -Os in buildArgs for size optimization instead of ProGuard.

nativeImageConfigBaseDir is usually empty

Nucleus ships all generic and platform-specific metadata automatically. You only need nativeImageConfigBaseDir for app-specific entries the automatic layers don't cover, which is rare. See Automatic metadata for the five layers.

What's next