@@ -283,6 +283,24 @@ tasks.register('generateNativeImageMetadata') {
283283 }
284284}
285285
286+ // native-image and the tracing agent only exist in a GraalVM JDK. Prefer the
287+ // JDK the build is running on when it is one -- that covers CI and any GraalVM
288+ // distribution -- and otherwise have Gradle locate an installation, so a local
289+ // build does not have to be invoked with GraalVM as its JAVA_HOME.
290+ def currentJavaHome = file(System . getProperty(' java.home' ))
291+ def currentJdkIsGraalvm = new File (currentJavaHome, ' bin/native-image' ). exists()
292+
293+ def graalvmLauncher = javaToolchains. launcherFor {
294+ languageVersion = JavaLanguageVersion . of(21 )
295+ vendor = JvmVendorSpec . matching(' Oracle Corporation' )
296+ }
297+
298+ def graalvmJava = {
299+ currentJdkIsGraalvm
300+ ? new File (currentJavaHome, ' bin/java' ). absolutePath
301+ : graalvmLauncher. get(). executablePath. asFile. absolutePath
302+ }
303+
286304task generateNativeImageConfig (type : Exec ) {
287305 description = ' Generate native-image configuration using tracing agent'
288306 group = ' native'
@@ -298,32 +316,33 @@ task generateNativeImageConfig(type: Exec) {
298316
299317 doFirst {
300318 agentOutputDir. mkdirs()
319+ commandLine ' bash' , ' -c' , """
320+ ${ simulateScript.absolutePath} | ${ graalvmJava()} \\
321+ -agentlib:native-image-agent=config-output-dir=${ agentOutputDir.absolutePath} \\
322+ -cp ${ shadowJar.archiveFile.get().asFile.absolutePath} \\
323+ nextflow.lsp.NextflowLanguageServer
324+ """
301325 }
302-
303- commandLine ' bash' , ' -c' , """
304- ${ simulateScript.absolutePath} | java \\
305- -agentlib:native-image-agent=config-output-dir=${ agentOutputDir.absolutePath} \\
306- -cp ${ shadowJar.archiveFile.get().asFile.absolutePath} \\
307- nextflow.lsp.NextflowLanguageServer
308- """
309- }
310-
311- tasks. named(' nativeCompile' ) {
312- // native-image reads all three config directories via
313- // -H:ConfigurationFileDirectories, which Gradle cannot see. Without these
314- // declarations a metadata change reports UP-TO-DATE and silently ships the
315- // previously built binary. Passing the producing tasks as file inputs both
316- // registers their outputs and creates the task dependency.
317- inputs. files(tasks. named(' generateNativeImageMetadata' ))
318- inputs. files(tasks. named(' generateNativeImageConfig' ))
319- inputs. dir(" $projectDir /native/conf" )
320326}
321327
322328graalvmNative {
323329 binaries {
324330 main {
325331 imageName = ' nextflow-lsp'
326332 mainClass = ' nextflow.lsp.NextflowLanguageServer'
333+
334+ // static metadata first, then the traced metadata for the tail that
335+ // genuinely cannot be enumerated (Groovy indy call sites, JDK internals).
336+ // Declared through the plugin rather than as a raw
337+ // -H:ConfigurationFileDirectories so that Gradle tracks the directories
338+ // as task inputs -- otherwise a metadata change reports nativeCompile
339+ // UP-TO-DATE and silently ships the previously built binary.
340+ configurationFileDirectories. from(
341+ tasks. named(' generateNativeImageMetadata' ),
342+ tasks. named(' generateNativeImageConfig' ),
343+ file(" $projectDir /native/conf" ),
344+ )
345+
327346 buildArgs. addAll([
328347 ' --no-fallback' ,
329348 ' --enable-url-protocols=http,https' ,
@@ -339,11 +358,19 @@ graalvmNative {
339358 ' --initialize-at-build-time=groovyjarjarantlr4' ,
340359 ' --initialize-at-build-time=java.beans' ,
341360 ' --initialize-at-build-time=com.sun.beans' ,
342- // static metadata first, then the traced metadata for the tail that
343- // genuinely cannot be enumerated (Groovy indy call sites, JDK internals)
344- " -H:ConfigurationFileDirectories=$buildDir /native-image-static,$buildDir /native-image-agent,$projectDir /native/conf"
345361 ])
362+
363+ // native-image defaults to -march=x86-64-v3 on AMD64, which requires
364+ // AVX2 and faults with an illegal instruction on anything older than
365+ // Haswell. AArch64 already defaults to the armv8-a baseline.
366+ if ( System . getProperty(' os.arch' ) in [' amd64' , ' x86_64' ] )
367+ buildArgs. add(' -march=compatibility' )
368+
369+ if ( ! currentJdkIsGraalvm )
370+ javaLauncher = graalvmLauncher
346371 }
347372 }
348- toolchainDetection = false
373+ // when the current JDK is GraalVM the plugin uses it directly; detection is
374+ // only needed for the fallback above
375+ toolchainDetection = ! currentJdkIsGraalvm
349376}
0 commit comments