-
Notifications
You must be signed in to change notification settings - Fork 284
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
JVM 22+ support #876
base: main
Are you sure you want to change the base?
JVM 22+ support #876
Conversation
8c2a05f
to
dc45756
Compare
@@ -80,6 +80,10 @@ open class BuildInfo(project: Project) { | |||
|
|||
val isReleaseBuild: Boolean by lazy { java.lang.Boolean.getBoolean("releaseBuild") } | |||
|
|||
val isNativeArch: Boolean by lazy { java.lang.Boolean.getBoolean("nativeArch") } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pass gradlew ... -DnativeArch=true
to effectively pass -march=native
to native-image
@@ -80,6 +80,10 @@ open class BuildInfo(project: Project) { | |||
|
|||
val isReleaseBuild: Boolean by lazy { java.lang.Boolean.getBoolean("releaseBuild") } | |||
|
|||
val isNativeArch: Boolean by lazy { java.lang.Boolean.getBoolean("nativeArch") } | |||
|
|||
val isEnableOracleGraalvm: Boolean by lazy { java.lang.Boolean.getBoolean("oracleGraalvm") } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
execOperations.exec { | ||
val executableName = if (os.isWindows) "gu.cmd" else "gu" | ||
executable = distroBinDir.resolve(executableName).toString() | ||
args("install", "--no-progress", "native-image") | ||
val gvmVersionMajor = | ||
requireNotNull(graalVm.get().version.split(".").first().toIntOrNull()) { | ||
"Invalid GraalVM JDK version: ${graalVm.get().graalVmJdkVersion}" | ||
} | ||
if (gvmVersionMajor < 24) { | ||
execOperations.exec { | ||
val executableName = if (os.isWindows) "gu.cmd" else "gu" | ||
executable = distroBinDir.resolve(executableName).toString() | ||
args("install", "--no-progress", "native-image") | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
gu
is no longer applicable when using newer versions of GraalVM; in Pkl's case, no action is needed because native-image
now ships with GraalVM by default
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s | ||
' "$PWD" ) || exit | ||
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
applied after gradlew wrapper ...
add("-H:Name=${outputFile.get().asFile.name}") | ||
add("-o") | ||
add(outputFile.get().asFile.name) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
prefers stable options
add("-H:IncludeResources=org/pkl/core/stdlib/.*\\.pkl") | ||
add("-H:IncludeResources=org/jline/utils/.*") | ||
add("-H:IncludeResourceBundles=org.pkl.core.errorMessages") | ||
add("-H:IncludeResources=org/pkl/commons/cli/PklCARoots.pem") | ||
add("--macro:truffle") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(1) renamed version of this is now --macro:truffle-svm
(2) it is now applied automatically for builds with Truffle on the modulepath (see here)
val exclusions = listOf(libs.truffleApi, libs.graalSdk).map { it.get().module.name } | ||
val exclusions = listOf(libs.graalSdk).map { it.get().module.name } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the SDK is a virtual artifact anyway and is ignored by native-image
; truffleApi
must be on the modulepath due to the operating mechanism behind Truffle Unchained. otherwise, build errors surface
this is also why non-relocations must be added for truffle types
if (!buildInfo.isReleaseBuild) { | ||
add("-Ob") | ||
} else { | ||
add("-Os") | ||
} | ||
if (buildInfo.isNativeArch) { | ||
add("-march=native") | ||
} else { | ||
add("-march=compatibility") | ||
} | ||
if (buildInfo.isEnableOracleGraalvm) { | ||
add("--gc=G1") | ||
add("--enable-sbom=cyclonedx") | ||
} else { | ||
add("--gc=serial") | ||
} | ||
add("-march=compatibility") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changes here:
- when building a release...
-Os
is passed, which optimizes for size (this is a new feature supported bynative-image
)- under oracle graalvm...
--gc=G1 --enable-sbom=cyclonedx
are passed; the SBOM is embedded within the final binary
- when building with
-DnativeArch=true
...-march=native
is passed- otherwise,
-march=compatibility
is passed (no change)
- when building under graalvm CE...
--gc=serial
is passed; this is the only feasible option aside from epsilon (no-op)
- when not building a release...
-Ob
is passed to optimize build time (no change)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this test is broken for unclear reasons. the test output is:
> Task :pkl-core:test
errors > analyzeInvalidHttpModule.pkl FAILED
Changed content at line 2:
expecting:
["HTTP/1.1 header parser received no bytes"]
but was:
["parsing HTTP/1.1 status line, receiving [P], parser state [STATUS_LINE]"]
val testToolchain = | ||
javaToolchains.launcherFor { | ||
languageVersion = JavaLanguageVersion.of(21) | ||
vendor = JvmVendorSpec.GRAAL_VM | ||
} | ||
|
||
tasks.test { | ||
javaLauncher = testToolchain | ||
dependsOn(prepareTest) | ||
useJUnitPlatform() | ||
jvmArgumentProviders.add(CommandLineArgumentProvider { listOf("--add-modules=jdk.unsupported") }) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
note to self: clean up launcher configuration
This is great, thanks, Sam! I will do a review of this by next week. FYI: Pkl today supports Java 21. The range enabled here is Java 22+ (updated your PR title). |
@sgammon feel free to extract the toolchain support into another PR. Indeed, my PR is quited dated. I will close it... |
@StefMa roger, no worries :) I am a well known offender in that regard |
- feat: support for jvm21+/gvm jdk 23, latest truffle - feat: flag support for gvm, native arch, use new `-Os` optimization mode - feat: initial transitive native image flag support - fix: support up to graalvm/jdk 23 (latest) - fix: don't use `gu` tool for modern graalvm versions - fix: coordinate change for `shadow` plugin (`com.gradleup.shadow`) - fix: build with `--add-modules=jdk.unsupported` where needed - fix: use jdk21 to run the tests (needed for `Unsafe.ensureInitialized`) - fix: truffle svm dependency is required after graalvm `24.0.0` - fix: warnings for gvm flag usage, renamed truffle svm macro - chore: bump graalvm → `24.1.0` - chore: bump shadow → `8.3.5` - chore: update gradle → `8.12` Signed-off-by: Sam Gammon <[email protected]>
Signed-off-by: Sam Gammon <[email protected]>
dc45756
to
1982880
Compare
@bioball I dropped toolchain provisioning, but toolchains are still used to force JVM 21 for testing. I can centralize that code within This is a tricky one. GVM 23 is needed to use the latest Truffle API, or version checks must be disabled otherwise (since Truffle and GraalVM's versions need to line up). This is the support we need downstream to use Pkl in embedded form. But, GVM 21 is needed specifically because of deprecations in JDK 22, which are still in use by Truffle; so, JVM executions involving Truffle can't exceed JDK 21 (and this would include test runs). Thus, at least two toolchains are needed. It is easiest to declare these requirements using Gradle's toolchains feature; however, where those toolchains come from (dynamic provisioning or a static expectation) is another question. |
Wait, I guess it would make no difference to consolidate on GVM 21:
So, maybe it makes sense to update to the latest GVM/Truffle API, but only up to JDK 21. What do you think @bioball? Then there would be only one toolchain which simplifies things a lot. Ultimately our goal is just to get Pkl working in embedded form at latest Truffle API. JVM build toolchain is immaterial to the final product anyway since bytecode is pinned at JVM 17. |
Summary
This PR updates dependencies and build process for Pkl to bring GraalVM and Truffle support up to their latest versions; today, Pkl builds against Java 17+, and requires Java 17+ to run.
After merging this PR, Pkl would build against Java 23, test against Java 21, and imply no change to bytecode (i.e. still only requiring Java 17+ to run or transitively compile against Pkl).
Java 21 adds a lot of features, and JPMS enforcement (and related deprecations) are a concern. This PR takes care of those but does not modularize Pkl itself.
Test downstream here, via Github Actions. On that fork PR, the change set is expressed in full, with fixups.
Rationale
JVM 21 support: Needed for modern Java projects to embed Pkl; needed for modern GraalVM
native-image
binaries built with embedded Pkl.GVM 23 toolchain: Support for the latest release version of GraalVM and Truffle brings many improvements to the compiler and polyglot implementation
JVM 21-pinned test toolchain: Tests run under JVM 21. It's annoying to have two JDKs here, but JDK 23 is best, and JDK 21 is needed for JVM execution of Truffle implementation tests, due to a dependency on
sun.misc.Unsafe.ensureInitialized
, which was removed in JDK 22.Gradle
8.12
: Needed for Gradle to be able to understand class targets as high as65
, which corresponds to JVM 23.Shadow
8.3.5
: Necessitated by a plugin ID change (com.github.johnrengelman.shadow
→com.gradleup.shadow
), to enable support for JVM 21+Truffle SVM Dependency: Certain superclasses used by Pkl (notably,
AbstractTruffleException
andTruffleFeature
) have moved to the neworg.graalvm.nativeimage:truffle-runtime-svm
coordinate.Non-relocations for Truffle/GraalVM classes. After the Truffle Unchained transition, Truffle languages and runtime artifacts must be present on the Java module path. By definition, this precludes use in "relocated" form.
Known Issues
pkl-core
)analyzeInvalidHttpModule.pkl
:pkl-core:test:errors > analyzeInvalidHttpModule.pkl
:pkl-core:testJavaExecutable:errors > analyzeInvalidHttpModule.pkl
pkl-doc
)pkl-executor
)Pre-merge Checklist
Changelog
-Os
optimization modegu
tool for modern graalvm versionsshadow
plugin (com.gradleup.shadow
)--add-modules=jdk.unsupported
where neededUnsafe.ensureInitialized
)24.0.0
24.1.0
8.3.5
8.12