diff --git a/.circleci/config.pkl b/.circleci/config.pkl index 006ea2b47..ebe9ae1c5 100644 --- a/.circleci/config.pkl +++ b/.circleci/config.pkl @@ -105,18 +105,13 @@ local buildNativeJobs: Mapping = new { } local gradleCheckJobs: Mapping = new { - ["gradle-check-jdk17"] { - javaVersion = "17.0" - isRelease = false - os = "linux" - } - ["gradle-check-jdk21"] { + ["gradle-check"] { javaVersion = "21.0" isRelease = false os = "linux" } - ["gradle-check-jdk17-windows"] { - javaVersion = "17.0" + ["gradle-check-windows"] { + javaVersion = "21.0" isRelease = false os = "windows" } diff --git a/.circleci/config.yml b/.circleci/config.yml index d0508b76f..87174960f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -12,7 +12,7 @@ jobs: - run: command: |- export PATH=~/staticdeps/bin:$PATH - ./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results -DreleaseBuild=true pkl-cli:macExecutableAmd64 pkl-core:testMacExecutableAmd64 pkl-server:testMacExecutableAmd64 + ./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results -DpklMultiJdkTesting=true -DreleaseBuild=true pkl-cli:macExecutableAmd64 pkl-core:testMacExecutableAmd64 pkl-server:testMacExecutableAmd64 name: gradle buildNative - persist_to_workspace: root: '.' @@ -88,7 +88,7 @@ jobs: - run: command: |- export PATH=~/staticdeps/bin:$PATH - ./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results -DreleaseBuild=true pkl-cli:linuxExecutableAmd64 pkl-core:testLinuxExecutableAmd64 pkl-server:testLinuxExecutableAmd64 + ./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results -DpklMultiJdkTesting=true -DreleaseBuild=true pkl-cli:linuxExecutableAmd64 pkl-core:testLinuxExecutableAmd64 pkl-server:testLinuxExecutableAmd64 name: gradle buildNative - persist_to_workspace: root: '.' @@ -108,7 +108,7 @@ jobs: - run: command: |- export PATH=~/staticdeps/bin:$PATH - ./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results -DreleaseBuild=true pkl-cli:macExecutableAarch64 pkl-core:testMacExecutableAarch64 pkl-server:testMacExecutableAarch64 + ./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results -DpklMultiJdkTesting=true -DreleaseBuild=true pkl-cli:macExecutableAarch64 pkl-core:testMacExecutableAarch64 pkl-server:testMacExecutableAarch64 name: gradle buildNative - persist_to_workspace: root: '.' @@ -168,7 +168,7 @@ jobs: - run: command: |- export PATH=~/staticdeps/bin:$PATH - ./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results -DreleaseBuild=true pkl-cli:linuxExecutableAarch64 pkl-core:testLinuxExecutableAarch64 pkl-server:testLinuxExecutableAarch64 + ./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results -DpklMultiJdkTesting=true -DreleaseBuild=true pkl-cli:linuxExecutableAarch64 pkl-core:testLinuxExecutableAarch64 pkl-server:testLinuxExecutableAarch64 name: gradle buildNative - persist_to_workspace: root: '.' @@ -245,7 +245,7 @@ jobs: - run: command: |- export PATH=~/staticdeps/bin:$PATH - ./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results -DreleaseBuild=true pkl-cli:alpineExecutableAmd64 pkl-core:testAlpineExecutableAmd64 pkl-server:testAlpineExecutableAmd64 + ./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results -DpklMultiJdkTesting=true -DreleaseBuild=true pkl-cli:alpineExecutableAmd64 pkl-core:testAlpineExecutableAmd64 pkl-server:testAlpineExecutableAmd64 name: gradle buildNative - persist_to_workspace: root: '.' @@ -277,7 +277,7 @@ jobs: - run: command: |- export PATH=~/staticdeps/bin:$PATH - ./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results -DreleaseBuild=true pkl-cli:windowsExecutableAmd64 pkl-core:testWindowsExecutableAmd64 pkl-server:testWindowsExecutableAmd64 + ./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results -DpklMultiJdkTesting=true -DreleaseBuild=true pkl-cli:windowsExecutableAmd64 pkl-core:testWindowsExecutableAmd64 pkl-server:testWindowsExecutableAmd64 name: gradle buildNative shell: bash.exe - persist_to_workspace: @@ -301,7 +301,7 @@ jobs: - run: command: |- export PATH=~/staticdeps/bin:$PATH - ./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results pkl-cli:macExecutableAmd64 pkl-core:testMacExecutableAmd64 pkl-server:testMacExecutableAmd64 + ./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results -DpklMultiJdkTesting=true pkl-cli:macExecutableAmd64 pkl-core:testMacExecutableAmd64 pkl-server:testMacExecutableAmd64 name: gradle buildNative - persist_to_workspace: root: '.' @@ -377,7 +377,7 @@ jobs: - run: command: |- export PATH=~/staticdeps/bin:$PATH - ./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results pkl-cli:linuxExecutableAmd64 pkl-core:testLinuxExecutableAmd64 pkl-server:testLinuxExecutableAmd64 + ./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results -DpklMultiJdkTesting=true pkl-cli:linuxExecutableAmd64 pkl-core:testLinuxExecutableAmd64 pkl-server:testLinuxExecutableAmd64 name: gradle buildNative - persist_to_workspace: root: '.' @@ -397,7 +397,7 @@ jobs: - run: command: |- export PATH=~/staticdeps/bin:$PATH - ./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results pkl-cli:macExecutableAarch64 pkl-core:testMacExecutableAarch64 pkl-server:testMacExecutableAarch64 + ./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results -DpklMultiJdkTesting=true pkl-cli:macExecutableAarch64 pkl-core:testMacExecutableAarch64 pkl-server:testMacExecutableAarch64 name: gradle buildNative - persist_to_workspace: root: '.' @@ -457,7 +457,7 @@ jobs: - run: command: |- export PATH=~/staticdeps/bin:$PATH - ./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results pkl-cli:linuxExecutableAarch64 pkl-core:testLinuxExecutableAarch64 pkl-server:testLinuxExecutableAarch64 + ./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results -DpklMultiJdkTesting=true pkl-cli:linuxExecutableAarch64 pkl-core:testLinuxExecutableAarch64 pkl-server:testLinuxExecutableAarch64 name: gradle buildNative - persist_to_workspace: root: '.' @@ -534,7 +534,7 @@ jobs: - run: command: |- export PATH=~/staticdeps/bin:$PATH - ./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results pkl-cli:alpineExecutableAmd64 pkl-core:testAlpineExecutableAmd64 pkl-server:testAlpineExecutableAmd64 + ./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results -DpklMultiJdkTesting=true pkl-cli:alpineExecutableAmd64 pkl-core:testAlpineExecutableAmd64 pkl-server:testAlpineExecutableAmd64 name: gradle buildNative - persist_to_workspace: root: '.' @@ -566,7 +566,7 @@ jobs: - run: command: |- export PATH=~/staticdeps/bin:$PATH - ./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results pkl-cli:windowsExecutableAmd64 pkl-core:testWindowsExecutableAmd64 pkl-server:testWindowsExecutableAmd64 + ./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results -DpklMultiJdkTesting=true pkl-cli:windowsExecutableAmd64 pkl-core:testWindowsExecutableAmd64 pkl-server:testWindowsExecutableAmd64 name: gradle buildNative shell: bash.exe - persist_to_workspace: @@ -581,23 +581,11 @@ jobs: resource_class: windows.large machine: image: windows-server-2022-gui:current - gradle-check-jdk17: + gradle-check: steps: - checkout - run: - command: ./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results check - name: gradle check - - store_test_results: - path: ~/test-results - environment: - LANG: en_US.UTF-8 - docker: - - image: cimg/openjdk:17.0 - gradle-check-jdk21: - steps: - - checkout - - run: - command: ./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results check + command: ./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results -DpklMultiJdkTesting=true check name: gradle check - store_test_results: path: ~/test-results @@ -605,14 +593,14 @@ jobs: LANG: en_US.UTF-8 docker: - image: cimg/openjdk:21.0 - gradle-check-jdk17-windows: + gradle-check-windows: steps: - checkout - run: command: |- # install jdk curl -Lf \ - https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.9%2B9.1/OpenJDK17U-jdk_x64_windows_hotspot_17.0.9_9.zip -o /tmp/jdk.zip + https://github.com/adoptium/temurin21-binaries/releases/download/jdk-21.0.5%2B11/OpenJDK21U-jdk_x64_windows_hotspot_21.0.5_11.zip -o /tmp/jdk.zip unzip /tmp/jdk.zip -d /tmp/jdk \ && cd /tmp/jdk/jdk-* \ @@ -621,7 +609,7 @@ jobs: name: Set up environment shell: bash.exe - run: - command: ./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results check + command: ./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results -DpklMultiJdkTesting=true check name: gradle check - store_test_results: path: ~/test-results @@ -635,7 +623,7 @@ jobs: steps: - checkout - run: - command: ./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results bench:jmh + command: ./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results -DpklMultiJdkTesting=true bench:jmh name: bench:jmh - store_test_results: path: ~/test-results @@ -648,7 +636,7 @@ jobs: - checkout - run: command: |- - ./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results :pkl-gradle:build \ + ./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results -DpklMultiJdkTesting=true :pkl-gradle:build \ :pkl-gradle:compatibilityTestReleases name: gradle compatibility - store_test_results: @@ -663,7 +651,7 @@ jobs: - attach_workspace: at: '.' - run: - command: ./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results publishToSonatype + command: ./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results -DpklMultiJdkTesting=true publishToSonatype - persist_to_workspace: root: '.' paths: @@ -680,7 +668,7 @@ jobs: - attach_workspace: at: '.' - run: - command: ./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results -DreleaseBuild=true publishToSonatype closeAndReleaseSonatypeStagingRepository + command: ./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results -DpklMultiJdkTesting=true -DreleaseBuild=true publishToSonatype closeAndReleaseSonatypeStagingRepository - persist_to_workspace: root: '.' paths: @@ -742,13 +730,10 @@ workflows: type: approval - pr-approval/authenticate: context: pkl-pr-approval - - gradle-check-jdk17: + - gradle-check: requires: - hold - - gradle-check-jdk21: - requires: - - hold - - gradle-check-jdk17-windows: + - gradle-check-windows: requires: - hold when: @@ -757,9 +742,8 @@ workflows: pattern: ^pull/\d+(/head)?$ main: jobs: - - gradle-check-jdk17 - - gradle-check-jdk21 - - gradle-check-jdk17-windows + - gradle-check + - gradle-check-windows - bench - gradle-compatibility - pkl-cli-macOS-amd64-snapshot @@ -770,9 +754,8 @@ workflows: - pkl-cli-windows-amd64-snapshot - deploy-snapshot: requires: - - gradle-check-jdk17 - - gradle-check-jdk21 - - gradle-check-jdk17-windows + - gradle-check + - gradle-check-windows - bench - gradle-compatibility - pkl-cli-macOS-amd64-snapshot @@ -793,19 +776,13 @@ workflows: - << pipeline.git.branch >> release: jobs: - - gradle-check-jdk17: - filters: - branches: - ignore: /.*/ - tags: - only: /^v?\d+\.\d+\.\d+$/ - - gradle-check-jdk21: + - gradle-check: filters: branches: ignore: /.*/ tags: only: /^v?\d+\.\d+\.\d+$/ - - gradle-check-jdk17-windows: + - gradle-check-windows: filters: branches: ignore: /.*/ @@ -861,9 +838,8 @@ workflows: only: /^v?\d+\.\d+\.\d+$/ - github-release: requires: - - gradle-check-jdk17 - - gradle-check-jdk21 - - gradle-check-jdk17-windows + - gradle-check + - gradle-check-windows - bench - gradle-compatibility - pkl-cli-macOS-amd64-release @@ -899,9 +875,8 @@ workflows: only: /^v?\d+\.\d+\.\d+$/ release-branch: jobs: - - gradle-check-jdk17 - - gradle-check-jdk21 - - gradle-check-jdk17-windows + - gradle-check + - gradle-check-windows - bench - gradle-compatibility - pkl-cli-macOS-amd64-release diff --git a/.circleci/jobs/GradleJob.pkl b/.circleci/jobs/GradleJob.pkl index 92621cebf..1620cd8bd 100644 --- a/.circleci/jobs/GradleJob.pkl +++ b/.circleci/jobs/GradleJob.pkl @@ -47,6 +47,7 @@ fixed gradleArgs = new Listing { "--info" "--stacktrace" "-DtestReportsDir=${HOME}/test-results" + "-DpklMultiJdkTesting=true" when (isRelease) { "-DreleaseBuild=true" } diff --git a/.java-version b/.java-version index 03b6389f3..aabe6ec39 100644 --- a/.java-version +++ b/.java-version @@ -1 +1 @@ -17.0 +21 diff --git a/DEVELOPMENT.adoc b/DEVELOPMENT.adoc index 2c9556fb5..61543f7e6 100644 --- a/DEVELOPMENT.adoc +++ b/DEVELOPMENT.adoc @@ -7,7 +7,7 @@ == Setup -. (mandatory) Install a JDK (any version between 17 - 21). +. (mandatory) Install a JDK (JDK 21+ required). . (recommended) Install {uri-intellij}[IntelliJ IDEA] + To import the project into IntelliJ, go to File->Open and select the project's root directory. If the project is opened but not imported, look for a popup in the lower right corner @@ -17,7 +17,7 @@ _gng_ enables to run Gradle commands with `gw` (instead of `./gradlew`) from any . (recommended) Set up Git ignore-revs + `git config blame.ignoreRevsFile .git-blame-ignore-revs` . (recommended) Install {uri-jenv}[jenv] and plugins + -_jenv_ use specific JDK versions in certain subdirectories. _Pkl_ comes with a `.java-version` file specifying JDK 17. + +_jenv_ use specific JDK versions in certain subdirectories. _Pkl_ comes with a `.java-version` file specifying JDK 21. + Enable _jenv_ plugins for better handling by `gradle`: + [source,shell] diff --git a/bench/gradle.lockfile b/bench/gradle.lockfile index 66a959fdc..dcfd6f7a0 100644 --- a/bench/gradle.lockfile +++ b/bench/gradle.lockfile @@ -7,9 +7,14 @@ net.sf.jopt-simple:jopt-simple:5.0.4=jmh,jmhCompileClasspath,jmhImplementationDe org.apache.commons:commons-math3:3.6.1=jmh,jmhCompileClasspath,jmhImplementationDependenciesMetadata,jmhRuntimeClasspath org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeOnlyDependenciesMetadata org.assertj:assertj-core:3.27.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -org.graalvm.compiler:compiler:23.0.6=graal -org.graalvm.sdk:graal-sdk:23.0.6=graal,jmh,jmhRuntimeClasspath,truffle -org.graalvm.truffle:truffle-api:23.0.6=graal,jmh,jmhRuntimeClasspath,truffle +org.graalvm.compiler:compiler:24.1.2=graal +org.graalvm.polyglot:polyglot:24.1.2=jmh,jmhRuntimeClasspath,truffle +org.graalvm.sdk:collections:24.1.2=graal,jmh,jmhRuntimeClasspath,truffle +org.graalvm.sdk:graal-sdk:24.1.2=jmh,jmhRuntimeClasspath +org.graalvm.sdk:nativeimage:24.1.2=jmh,jmhRuntimeClasspath,truffle +org.graalvm.sdk:word:24.1.2=graal,jmh,jmhRuntimeClasspath,truffle +org.graalvm.truffle:truffle-api:24.1.2=jmh,jmhRuntimeClasspath,truffle +org.graalvm.truffle:truffle-compiler:24.1.2=graal org.jetbrains.intellij.deps:trove4j:1.0.20200330=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinKlibCommonizerClasspath org.jetbrains.kotlin:kotlin-build-common:2.0.21=kotlinBuildToolsApiClasspath org.jetbrains.kotlin:kotlin-build-tools-api:2.0.21=kotlinBuildToolsApiClasspath diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 09576ef80..ea253c9bf 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -15,7 +15,13 @@ */ import org.jetbrains.kotlin.gradle.dsl.JvmTarget -plugins { `kotlin-dsl` } +plugins { + `kotlin-dsl` + `jvm-toolchains` +} + +// Keep this in sync with the constants in `BuildInfo.kt` (those are not addressable here). +val toolchainVersion = 21 dependencies { implementation(libs.downloadTaskPlugin) @@ -29,8 +35,16 @@ dependencies { } java { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 + sourceCompatibility = JavaVersion.toVersion(toolchainVersion) + targetCompatibility = JavaVersion.toVersion(toolchainVersion) + + toolchain { + languageVersion = JavaLanguageVersion.of(toolchainVersion) + vendor = JvmVendorSpec.ADOPTIUM + } } -kotlin { compilerOptions { jvmTarget = JvmTarget.JVM_17 } } +kotlin { + jvmToolchain(toolchainVersion) + compilerOptions { jvmTarget = JvmTarget.fromTarget(toolchainVersion.toString()) } +} diff --git a/buildSrc/settings.gradle.kts b/buildSrc/settings.gradle.kts index fce70fef5..399b53d29 100644 --- a/buildSrc/settings.gradle.kts +++ b/buildSrc/settings.gradle.kts @@ -1,5 +1,5 @@ /* - * Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved. + * Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,6 +24,8 @@ pluginManagement { } } +plugins { id("org.gradle.toolchains.foojay-resolver-convention") } + // makes ~/.gradle/init.gradle unnecessary and ~/.gradle/gradle.properties optional dependencyResolutionManagement { // use same version catalog as main build diff --git a/buildSrc/src/main/kotlin/BuildInfo.kt b/buildSrc/src/main/kotlin/BuildInfo.kt index df44e3902..06b4aea5d 100644 --- a/buildSrc/src/main/kotlin/BuildInfo.kt +++ b/buildSrc/src/main/kotlin/BuildInfo.kt @@ -1,5 +1,5 @@ /* - * Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved. + * Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,11 +19,56 @@ import java.io.File import org.gradle.api.Project import org.gradle.api.artifacts.VersionCatalog import org.gradle.api.artifacts.VersionCatalogsExtension -import org.gradle.kotlin.dsl.getByType +import org.gradle.api.attributes.Category +import org.gradle.api.plugins.JvmTestSuitePlugin +import org.gradle.api.plugins.jvm.JvmTestSuite +import org.gradle.api.provider.Provider +import org.gradle.api.tasks.TaskProvider +import org.gradle.api.tasks.testing.Test +import org.gradle.internal.extensions.stdlib.capitalized +import org.gradle.jvm.toolchain.* +import org.gradle.kotlin.dsl.* +import org.gradle.kotlin.dsl.support.serviceOf +import org.gradle.process.CommandLineArgumentProvider +import org.gradle.testing.base.TestingExtension + +/** + * JVM bytecode target; this is pinned at a reasonable version, because downstream JVM projects + * which consume Pkl will need a minimum Bytecode level at or above this one. + * + * Kotlin and Java need matching bytecode targets, so this is expressed as a build setting and + * constant default. To override, pass `-DpklJdkToolchain=X` to the Gradle command line, where X is + * a major Java version. + */ +const val PKL_JVM_TARGET_DEFAULT_MAXIMUM = 17 + +/** + * The Pkl build requires JDK 21+ to build, because JDK 17 is no longer within the default set of + * supported JDKs for GraalVM. This is a build-time requirement, not a runtime requirement. + */ +const val PKL_JDK_VERSION_MIN = 21 + +/** + * The JDK minimum is set to match the bytecode minimum, to guarantee that fat JARs work against the + * earliest supported bytecode target. + */ +const val PKL_TEST_JDK_MINIMUM = PKL_JVM_TARGET_DEFAULT_MAXIMUM + +/** + * Maximum JDK version which Pkl is tested with; this should be bumped when new JDK stable releases + * are issued. At the time of this writing, JDK 23 is the latest available release. + */ +const val PKL_TEST_JDK_MAXIMUM = 23 + +/** + * Test the full suite of JDKs between [PKL_TEST_JDK_MINIMUM] and [PKL_TEST_JDK_MAXIMUM]; if this is + * set to `false` (or overridden on the command line), only LTS releases are tested by default. + */ +const val PKL_TEST_ALL_JDKS = false // `buildInfo` in main build scripts // `project.extensions.getByType()` in precompiled script plugins -open class BuildInfo(project: Project) { +open class BuildInfo(private val project: Project) { inner class GraalVm(val arch: String) { val homeDir: String by lazy { System.getenv("GRAALVM_HOME") ?: "${System.getProperty("user.home")}/.graalvm" @@ -80,6 +125,220 @@ 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 jvmTarget: Int by lazy { + System.getProperty("pklJvmTarget")?.toInt() ?: PKL_JVM_TARGET_DEFAULT_MAXIMUM + } + + // JPMS exports for Truffle; needed on some versions of Java, and transitively within some JARs. + private val jpmsExports = + arrayOf( + "org.graalvm.truffle/com.oracle.truffle.api.exception=ALL-UNNAMED", + "org.graalvm.truffle/com.oracle.truffle.api=ALL-UNNAMED", + "org.graalvm.truffle/com.oracle.truffle.api.nodes=ALL-UNNAMED", + "org.graalvm.truffle/com.oracle.truffle.api.source=ALL-UNNAMED", + ) + + // Extra JPMS modules forced onto the module path via `--add-modules` in some cases. + private val jpmsAddModules = arrayOf("jdk.unsupported") + + // Formats `jpmsExports` for use in JAR manifest attributes. + val jpmsExportsForJarManifest: String by lazy { + jpmsExports.joinToString(" ") { it.substringBefore("=") } + } + + // Formats `jpmsExports` for use on the command line with `--add-exports`. + val jpmsExportsForAddExportsFlags: Collection by lazy { + jpmsExports.map { "--add-exports=$it" } + } + + // Formats `jpmsAddModules` for use on the command line with `--add-modules`. + val jpmsAddModulesFlags: Collection by lazy { jpmsAddModules.map { "--add-modules=$it" } } + + // JVM properties to set during testing. + val testProperties = + mapOf( + // @TODO: this should be removed once pkl supports JPMS as a true Java Module. + "polyglotimpl.DisableClassPathIsolation" to true + ) + + val jdkVendor: JvmVendorSpec = JvmVendorSpec.ADOPTIUM + + val jdkToolchainVersion: JavaLanguageVersion by lazy { + JavaLanguageVersion.of(System.getProperty("pklJdkToolchain")?.toInt() ?: PKL_JDK_VERSION_MIN) + } + + val jdkTestFloor: JavaLanguageVersion by lazy { JavaLanguageVersion.of(PKL_TEST_JDK_MINIMUM) } + + val jdkTestCeiling: JavaLanguageVersion by lazy { JavaLanguageVersion.of(PKL_TEST_JDK_MAXIMUM) } + + val testAllJdks: Boolean by lazy { + // By default, Pkl is tested against LTS JDK releases within the bounds of `PKL_TEST_JDK_TARGET` + // and `PKL_TEST_JDK_MAXIMUM`. To test against the full suite of JDK versions, past and present, + // set `-DpklTestAllJdks=true` on the Gradle command line. This results in non-LTS releases, old + // releases, and "experimental releases" (newer than the toolchain version) being included in + // the default `check` suite. + System.getProperty("pklTestAllJdks")?.toBoolean() ?: PKL_TEST_ALL_JDKS + } + + val testExperimentalJdks: Boolean by lazy { + System.getProperty("pklTestFutureJdks")?.toBoolean() ?: false + } + + val testJdkVendors: Sequence by lazy { + // By default, only OpenJDK is tested during multi-JDK testing. Flip `-DpklTestAllVendors=true` + // to additionally test against a suite of JDK vendors, including Azul, Oracle, and GraalVM. + when (System.getProperty("pklTestAllVendors")?.toBoolean()) { + true -> sequenceOf(JvmVendorSpec.ADOPTIUM, JvmVendorSpec.GRAAL_VM, JvmVendorSpec.ORACLE) + else -> sequenceOf(JvmVendorSpec.ADOPTIUM) + } + } + + // Assembles a collection of JDK versions which tests can be run against, considering ancillary + // parameters like `testAllJdks` and `testExperimentalJdks`. + val jdkTestRange: Collection by lazy { + JavaVersionRange.inclusive(jdkTestFloor, jdkTestCeiling).filter { version -> + // unless we are instructed to test all JDKs, tests only include LTS releases and + // versions above the toolchain version. + testAllJdks || (JavaVersionRange.isLTS(version) || version >= jdkToolchainVersion) + } + } + + private fun JavaToolchainSpec.pklJdkToolchain() { + languageVersion.set(jdkToolchainVersion) + vendor.set(jdkVendor) + } + + private fun labelForVendor(vendor: JvmVendorSpec): String = + when (vendor) { + JvmVendorSpec.AZUL -> "Zulu" + JvmVendorSpec.GRAAL_VM -> "GraalVm" + JvmVendorSpec.ORACLE -> "Oracle" + JvmVendorSpec.ADOPTIUM -> "Adoptium" + else -> error("Unrecognized JDK vendor: $vendor") + } + + private fun testNamer(baseName: () -> String): (JavaLanguageVersion, JvmVendorSpec?) -> String = + { jdkTarget, vendor -> + val targetToken = + when (vendor) { + null -> "Jdk${jdkTarget.asInt()}" + else -> "Jdk${jdkTarget.asInt()}${labelForVendor(vendor).capitalized()}" + } + if (jdkTarget > jdkToolchainVersion) { + // test targets above the toolchain target are considered "experimental". + "${baseName()}${targetToken}Experimental" + } else { + "${baseName()}${targetToken}" + } + } + + @Suppress("UnstableApiUsage") + fun multiJdkTestingWith( + templateTask: TaskProvider, + configurator: MultiJdkTestConfigurator = {}, + ): Iterable> = + with(project) { + // force the `jvm-test-suite` plugin to apply first + project.pluginManager.apply(JvmTestSuitePlugin::class.java) + + val isMultiVendor = testJdkVendors.count() > 1 + val baseNameProvider = { templateTask.get().name } + val namer = testNamer(baseNameProvider) + val applyConfig: MultiJdkTestConfigurator = { (version, jdk) -> + // 1) copy configurations from the template task + dependsOn(templateTask) + templateTask.get().let { template -> + classpath = template.classpath + testClassesDirs = template.testClassesDirs + jvmArgs.addAll(template.jvmArgs) + jvmArgumentProviders.addAll(template.jvmArgumentProviders) + forkEvery = template.forkEvery + maxParallelForks = template.maxParallelForks + minHeapSize = template.minHeapSize + maxHeapSize = template.maxHeapSize + exclude(template.excludes) + template.systemProperties.forEach { prop -> systemProperty(prop.key, prop.value) } + } + + // 2) assign launcher + javaLauncher = jdk + + // 3) dispatch the user's configurator + configurator(version to jdk) + } + + serviceOf().let { toolchains -> + jdkTestRange + .flatMap { targetVersion -> + // multiply out by jdk vendor + testJdkVendors.map { vendor -> (targetVersion to vendor) } + } + .filter { (jdkTarget, vendor) -> + // only include experimental tasks in the return suite if the flag is set. if the task + // is withheld from the returned list, it will not be executed by default with `gradle + // check`. + testExperimentalJdks || + (!namer(jdkTarget, vendor.takeIf { isMultiVendor }).contains("Experimental")) + } + .map { (jdkTarget, vendor) -> + if (jdkToolchainVersion == jdkTarget) + tasks.register(namer(jdkTarget, vendor)) { + // alias to `test` + dependsOn(templateTask) + group = Category.VERIFICATION + description = + "Alias for regular '${baseNameProvider()}' task, on JDK ${jdkTarget.asInt()}" + } + else + the().suites.register( + namer(jdkTarget, vendor.takeIf { isMultiVendor }), + JvmTestSuite::class, + ) { + targets.all { + testTask.configure { + group = Category.VERIFICATION + description = "Run tests against JDK ${jdkTarget.asInt()}" + applyConfig(jdkTarget to toolchains.launcherFor { languageVersion = jdkTarget }) + + // fix: on jdk17, we must force the polyglot module on to the modulepath + if (jdkTarget.asInt() == 17) + jvmArgumentProviders.add( + CommandLineArgumentProvider { + buildList { listOf("--add-modules=org.graalvm.polyglot") } + } + ) + } + } + } + } + .toList() + } + } + + val javaCompiler: Provider by lazy { + project.serviceOf().let { toolchainService -> + toolchainService.compilerFor { pklJdkToolchain() } + } + } + + val javaTestLauncher: Provider by lazy { + project.serviceOf().let { toolchainService -> + toolchainService.launcherFor { pklJdkToolchain() } + } + } + + val multiJdkTesting: Boolean by lazy { + // By default, Pkl is tested against a full range of JDK versions, past and present, within the + // supported bounds of `PKL_TEST_JDK_TARGET` and `PKL_TEST_JDK_MAXIMUM`. To opt-out of this + // behavior, set `-DpklMultiJdkTesting=false` on the Gradle command line. + // + // In CI, this defaults to `true` to catch potential cross-JDK compat regressions or other bugs. + // In local dev, this defaults to `false` to speed up the build and reduce contributor load. + System.getProperty("pklMultiJdkTesting")?.toBoolean() ?: isCiBuild + } + val hasMuslToolchain: Boolean by lazy { // see "install musl" in .circleci/jobs/BuildNativeJob.pkl File(System.getProperty("user.home"), "staticdeps/bin/x86_64-linux-musl-gcc").exists() @@ -136,3 +395,7 @@ open class BuildInfo(project: Project) { } } } + +// Shape of a function which is applied to configure multi-JDK testing. +private typealias MultiJdkTestConfigurator = + Test.(Pair>) -> Unit diff --git a/buildSrc/src/main/kotlin/InstallGraalVm.kt b/buildSrc/src/main/kotlin/InstallGraalVm.kt index 79acad0b1..8ab123567 100644 --- a/buildSrc/src/main/kotlin/InstallGraalVm.kt +++ b/buildSrc/src/main/kotlin/InstallGraalVm.kt @@ -1,5 +1,5 @@ /* - * Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved. + * Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,7 +30,7 @@ abstract class InstallGraalVm @Inject constructor( private val fileOperations: FileOperations, - private val execOperations: ExecOperations + private val execOperations: ExecOperations, ) : DefaultTask() { @get:Input abstract val graalVm: Property @@ -58,10 +58,16 @@ constructor( if (os.isMacOsX) distroDir.resolve("Contents/Home/bin") else distroDir.resolve("bin") println("Installing native-image into $distroDir") - 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") + } } println("Creating symlink ${graalVm.get().installDir} for $distroDir") diff --git a/buildSrc/src/main/kotlin/JavaVersionRange.kt b/buildSrc/src/main/kotlin/JavaVersionRange.kt new file mode 100644 index 000000000..c5f190327 --- /dev/null +++ b/buildSrc/src/main/kotlin/JavaVersionRange.kt @@ -0,0 +1,64 @@ +/* + * Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +@file:Suppress("MemberVisibilityCanBePrivate") + +import java.util.* +import org.gradle.jvm.toolchain.JavaLanguageVersion + +typealias JavaVersionPair = Pair + +// All LTS releases. +private val ltsReleases = + sortedSetOf( + JavaLanguageVersion.of(8), + JavaLanguageVersion.of(11), + JavaLanguageVersion.of(17), + JavaLanguageVersion.of(21), + ) + +/** Describes an inclusive range of JVM versions, based on the [JavaLanguageVersion] type. */ +@JvmInline +value class JavaVersionRange private constructor(private val bounds: JavaVersionPair) : + Iterable { + @Suppress("unused") + companion object { + fun isLTS(version: JavaLanguageVersion): Boolean = version in ltsReleases + + fun inclusive(floor: JavaLanguageVersion, ceiling: JavaLanguageVersion): JavaVersionRange = + JavaVersionRange(floor to ceiling) + + fun startingAt(floor: JavaLanguageVersion): JavaVersionRange = + inclusive(floor, JavaLanguageVersion.of(PKL_TEST_JDK_MAXIMUM)) + + fun upTo(ceiling: JavaLanguageVersion): JavaVersionRange = + inclusive(JavaLanguageVersion.of(PKL_TEST_JDK_MINIMUM), ceiling) + } + + operator fun contains(version: JavaLanguageVersion): Boolean = + version >= bounds.first && version <= bounds.second + + fun asSequence(): Sequence = sequence { + var current = bounds.first + while (current <= bounds.second) { + yield(current) + current = JavaLanguageVersion.of(current.asInt() + 1) + } + } + + fun asSortedSet(): SortedSet = asSequence().toSortedSet() + + override fun iterator(): Iterator = asSortedSet().iterator() +} diff --git a/buildSrc/src/main/kotlin/pklFatJar.gradle.kts b/buildSrc/src/main/kotlin/pklFatJar.gradle.kts index 9bd03faaa..15345809b 100644 --- a/buildSrc/src/main/kotlin/pklFatJar.gradle.kts +++ b/buildSrc/src/main/kotlin/pklFatJar.gradle.kts @@ -40,8 +40,6 @@ val relocations = mapOf( // pkl-core dependencies "org.antlr.v4." to "org.pkl.thirdparty.antlr.v4.", - "com.oracle.truffle" to "org.pkl.thirdparty.truffle", - "org.graalvm." to "org.pkl.thirdparty.graalvm.", "org.organicdesign.fp." to "org.pkl.thirdparty.paguro.", "org.snakeyaml.engine." to "org.pkl.thirdparty.snakeyaml.engine.", "org.msgpack." to "org.pkl.thirdparty.msgpack.", @@ -71,7 +69,7 @@ val relocations = "com.squareup.kotlinpoet." to "org.pkl.thirdparty.kotlinpoet.", ) -val nonRelocations = listOf("com/oracle/truffle/") +val nonRelocations = listOf("com/oracle/truffle/", "org/graalvm/") tasks.shadowJar { inputs.property("relocations", relocations) @@ -85,7 +83,23 @@ tasks.shadowJar { exclude("META-INF/maven/**") exclude("META-INF/upgrade/**") - exclude("META-INF/versions/19/**") + + val info = project.extensions.getByType() + val minimumJvmTarget = JavaVersion.toVersion(info.jvmTarget) + + manifest.attributes( + // Certain exports need to be added to the Java modulepath for Java 17 to work properly with + // shaded JARs. See the following link for an explanation of this syntax: + // https://bugs.openjdk.org/browse/JDK-8335225 + "Add-Exports" to info.jpmsExportsForJarManifest + ) + + // effectively, this results in calls excluding: + // `META-INF/versions/{18-25}/**` + // at the time of this writing; multi-release JARs beyond JDK 21 break the current + // version of the Shadow plugin, and aren't needed for Truffle's use by Pkl. + JavaVersionRange.startingAt(JavaLanguageVersion.of(minimumJvmTarget.majorVersion.toInt() + 1)) + .forEach { exclude("META-INF/versions/${it.asInt()}/**") } // org.antlr.v4.runtime.misc.RuleDependencyProcessor exclude("META-INF/services/javax.annotation.processing.Processor") diff --git a/buildSrc/src/main/kotlin/pklGradlePluginTest.gradle.kts b/buildSrc/src/main/kotlin/pklGradlePluginTest.gradle.kts index 6865cb058..d950d756a 100644 --- a/buildSrc/src/main/kotlin/pklGradlePluginTest.gradle.kts +++ b/buildSrc/src/main/kotlin/pklGradlePluginTest.gradle.kts @@ -87,7 +87,7 @@ tasks.addRule("Pattern: compatibilityTest[All|Releases|Latest|Candidate|Nightly| } } -fun createCompatibilityTestTask(versionInfo: GradleVersionInfo) = +fun createCompatibilityTestTask(versionInfo: GradleVersionInfo): TaskProvider = createCompatibilityTestTask(versionInfo.version, versionInfo.downloadUrl) fun createCompatibilityTestTask(version: String, downloadUrl: String): TaskProvider { diff --git a/buildSrc/src/main/kotlin/pklJavaLibrary.gradle.kts b/buildSrc/src/main/kotlin/pklJavaLibrary.gradle.kts index 7579a8521..d10156087 100644 --- a/buildSrc/src/main/kotlin/pklJavaLibrary.gradle.kts +++ b/buildSrc/src/main/kotlin/pklJavaLibrary.gradle.kts @@ -1,5 +1,5 @@ /* - * Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved. + * Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,25 +13,39 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -@file:Suppress("HttpUrlsUsage") +@file:Suppress("HttpUrlsUsage", "unused") import org.gradle.accessors.dm.LibrariesForLibs plugins { `java-library` + `jvm-toolchains` id("pklKotlinTest") id("com.diffplug.spotless") } // make sources Jar available to other subprojects -val sourcesJarConfiguration = configurations.register("sourcesJar") +val sourcesJarConfiguration: Provider = configurations.register("sourcesJar") // Version Catalog library symbols. val libs = the() +// Build configuration. +val info = project.extensions.getByType() + java { + val jvmTarget = JavaVersion.toVersion(info.jvmTarget) + withSourcesJar() // creates `sourcesJar` task withJavadocJar() + + sourceCompatibility = jvmTarget + targetCompatibility = jvmTarget + + toolchain { + languageVersion = info.jdkToolchainVersion + vendor = info.jdkVendor + } } artifacts { @@ -56,7 +70,11 @@ tasks.compileKotlin { enabled = false } tasks.jar { manifest { - attributes += mapOf("Automatic-Module-Name" to "org.${project.name.replace("-", ".")}") + attributes += + mapOf( + "Automatic-Module-Name" to "org.${project.name.replace("-", ".")}", + "Add-Exports" to info.jpmsExportsForJarManifest, + ) } } @@ -80,9 +98,48 @@ val workAroundKotlinGradlePluginBug by } } +val truffleJavacArgs = + listOf( + // TODO: determine correct limits for Truffle specializations + // (see https://graalvm.slack.com/archives/CNQSB2DHD/p1712380902746829) + "-Atruffle.dsl.SuppressWarnings=truffle-limit" + ) + tasks.compileJava { + javaCompiler = info.javaCompiler dependsOn(workAroundKotlinGradlePluginBug) - // TODO: determine correct limits for Truffle specializations - // (see https://graalvm.slack.com/archives/CNQSB2DHD/p1712380902746829) - options.compilerArgs.add("-Atruffle.dsl.SuppressWarnings=truffle-limit") + options.compilerArgs.addAll(truffleJavacArgs + info.jpmsAddModulesFlags) +} + +tasks.withType().configureEach { + val jvmTarget = JavaVersion.toVersion(info.jvmTarget) + javaCompiler = info.javaCompiler + sourceCompatibility = jvmTarget.majorVersion + targetCompatibility = jvmTarget.majorVersion +} + +tasks.withType().configureEach { jvmArgs(info.jpmsAddModulesFlags) } + +fun Test.configureJdkTestTask(launcher: Provider) { + useJUnitPlatform() + javaLauncher = launcher + systemProperties.putAll(info.testProperties) + jvmArgs.addAll(info.jpmsAddModulesFlags) } + +tasks.test { configureJdkTestTask(info.javaTestLauncher) } + +// Prepare test tasks for each JDK version which is within the test target suite for Pkl. Each task +// uses a pinned JDK toolchain version, and is named for the major version which is tested. +// +// Test tasks configured in this manner are executed manually by name, e.g. `./gradlew testJdk11`, +// and automatically as dependencies of `check`. +// +// We omit the current JDK from this list because it is already tested, in effect, by the default +// `test` task. +// +// Pkl subprojects may elect to further configure these tasks as needed; by default, each task +// inherits the configuration of the default `test` task (aside from an overridden launcher). +val jdkTestTasks = info.multiJdkTestingWith(tasks.test) { (_, jdk) -> configureJdkTestTask(jdk) } + +if (info.multiJdkTesting) tasks.check { dependsOn(jdkTestTasks) } diff --git a/buildSrc/src/main/kotlin/pklKotlinLibrary.gradle.kts b/buildSrc/src/main/kotlin/pklKotlinLibrary.gradle.kts index c66ec1ac9..49db35d15 100644 --- a/buildSrc/src/main/kotlin/pklKotlinLibrary.gradle.kts +++ b/buildSrc/src/main/kotlin/pklKotlinLibrary.gradle.kts @@ -1,5 +1,5 @@ /* - * Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved. + * Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,13 +14,15 @@ * limitations under the License. */ import org.gradle.accessors.dm.LibrariesForLibs +import org.jetbrains.kotlin.gradle.dsl.JvmTarget +import org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile plugins { id("pklJavaLibrary") - kotlin("jvm") } +// Build configuration. val buildInfo = project.extensions.getByType() // Version Catalog library symbols. @@ -38,3 +40,7 @@ dependencies { tasks.compileKotlin { enabled = true // disabled by pklJavaLibrary } + +tasks.withType().configureEach { + compilerOptions { jvmTarget = JvmTarget.fromTarget(buildInfo.jvmTarget.toString()) } +} diff --git a/buildSrc/src/main/kotlin/pklKotlinTest.gradle.kts b/buildSrc/src/main/kotlin/pklKotlinTest.gradle.kts index 1f9161eb1..75a2bf9ab 100644 --- a/buildSrc/src/main/kotlin/pklKotlinTest.gradle.kts +++ b/buildSrc/src/main/kotlin/pklKotlinTest.gradle.kts @@ -1,5 +1,5 @@ /* - * Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved. + * Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,7 +16,10 @@ import java.net.URI import org.gradle.api.tasks.testing.logging.TestExceptionFormat -plugins { kotlin("jvm") } +plugins { + `jvm-test-suite` + kotlin("jvm") +} val buildInfo = project.extensions.getByType() diff --git a/docs/gradle.lockfile b/docs/gradle.lockfile index 59f311dbc..323867115 100644 --- a/docs/gradle.lockfile +++ b/docs/gradle.lockfile @@ -6,8 +6,12 @@ io.leangen.geantyref:geantyref:1.3.16=testRuntimeClasspath net.bytebuddy:byte-buddy:1.15.11=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeOnlyDependenciesMetadata org.assertj:assertj-core:3.27.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -org.graalvm.sdk:graal-sdk:23.0.6=testRuntimeClasspath -org.graalvm.truffle:truffle-api:23.0.6=testRuntimeClasspath +org.graalvm.polyglot:polyglot:24.1.2=testRuntimeClasspath +org.graalvm.sdk:collections:24.1.2=testRuntimeClasspath +org.graalvm.sdk:graal-sdk:24.1.2=testRuntimeClasspath +org.graalvm.sdk:nativeimage:24.1.2=testRuntimeClasspath +org.graalvm.sdk:word:24.1.2=testRuntimeClasspath +org.graalvm.truffle:truffle-api:24.1.2=testRuntimeClasspath org.jetbrains.intellij.deps:trove4j:1.0.20200330=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinKlibCommonizerClasspath org.jetbrains.kotlin:kotlin-build-common:2.0.21=kotlinBuildToolsApiClasspath org.jetbrains.kotlin:kotlin-build-tools-api:2.0.21=kotlinBuildToolsApiClasspath diff --git a/docs/src/test/kotlin/DocSnippetTests.kt b/docs/src/test/kotlin/DocSnippetTests.kt index 03de67df7..14b9a2fb4 100644 --- a/docs/src/test/kotlin/DocSnippetTests.kt +++ b/docs/src/test/kotlin/DocSnippetTests.kt @@ -150,6 +150,7 @@ class DocSnippetTestsEngine : HierarchicalTestEngine) { var line = "" var prevLine = "" diff --git a/gradle.properties b/gradle.properties index 9a5ccdc48..f567cddf5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -5,6 +5,7 @@ version=0.28.0 # google-java-format requires jdk.compiler exports org.gradle.jvmargs= \ + -XX:+UseParallelGC \ -Dfile.encoding=UTF-8 \ --add-exports jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED \ --add-exports jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED \ @@ -15,4 +16,5 @@ org.gradle.jvmargs= \ org.gradle.parallel=true org.gradle.caching=true kotlin.stdlib.default.dependency=false +kotlin.daemon.jvmargs=-XX:+UseParallelGC #org.gradle.workers.max=1 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 8dccca073..d7eba50f3 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -9,14 +9,14 @@ geantyref = "1.+" googleJavaFormat = "1.25.2" # must not use `+` because used in download URL # 23.1.x requires JDK 20+ -graalVm = "23.0.6" -graalVmJdkVersion = "17.0.12" +graalVm = "24.1.2" +graalVmJdkVersion = "21.0.5" # slightly hacky but convenient place so we remember to update the checksum -graalVmSha256-macos-x64 = "3ecac1471f3fa95a56c5b75c65db9e60ac4551f56eda09eb9da95e6049ea77d7" -graalVmSha256-macos-aarch64 = "4cdfdc6c9395f6773efcd191b6605f1b7c8e1b78ab900ab5cff34720a3feffc5" -graalVmSha256-linux-x64 = "b6f3dace24cf1960ec790216f4c86f00d4f43df64e4e8b548f6382f04894713f" -graalVmSha256-linux-aarch64 = "bd991d486b92deb74337b881e0f13a764c9c1e90fc358819080f7321fa5175e8" -graalVmSha256-windows-x64 = "8b978e56dddc0edc60db99794b56975740d9c52293b31549cfc3f7516fc18b43" +graalVmSha256-macos-x64 = "2d9b09e28bc1bb6ff219bf62eacc4626c7740b4f1829ede9ea4450f33e9c0826" +graalVmSha256-macos-aarch64 = "cb68cb2c796f42f37a56fcd1385d8b86cca12e0b46c5618a5ed3ec7dd2260f6f" +graalVmSha256-linux-x64 = "c1960d4f9d278458bde1cd15115ac2f0b3240cb427d51cfeceb79dab91a7f5c9" +graalVmSha256-linux-aarch64 = "771b308852853cf93f7a3fc429741dd17502b8c5fa91930de6af8ded461e2dc3" +graalVmSha256-windows-x64 = "06f0edb4d7e6c0063ca0db696538652bbd3983b81f264171da2961873c5e9e6d" ideaExtPlugin = "1.1.9" javaPoet = "0.+" javaxInject = "1" @@ -93,6 +93,8 @@ spotlessPlugin = { group = "com.diffplug.spotless", name = "spotless-plugin-grad svm = { group = "org.graalvm.nativeimage", name = "svm", version.ref = "graalVm" } truffleApi = { group = "org.graalvm.truffle", name = "truffle-api", version.ref = "graalVm" } truffleDslProcessor = { group = "org.graalvm.truffle", name = "truffle-dsl-processor", version.ref = "graalVm" } +truffleSvm = { group = "org.graalvm.nativeimage", name = "truffle-runtime-svm", version.ref = "graalVm" } +truffleRuntime = { group = "org.graalvm.truffle", name = "truffle-runtime", version.ref = "graalVm" } wiremock = { group = "org.wiremock", name = "wiremock", version.ref = "wiremock" } [plugins] # ordered alphabetically diff --git a/pkl-cli/gradle.lockfile b/pkl-cli/gradle.lockfile index 2c33350aa..27f7e7c9a 100644 --- a/pkl-cli/gradle.lockfile +++ b/pkl-cli/gradle.lockfile @@ -54,13 +54,21 @@ org.eclipse.jetty:jetty-util:11.0.24=testCompileClasspath,testImplementationDepe org.eclipse.jetty:jetty-webapp:11.0.24=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath org.eclipse.jetty:jetty-xml:11.0.24=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath org.fusesource.jansi:jansi:2.4.1=compileClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -org.graalvm.compiler:compiler:23.0.6=compileClasspath,compileOnlyDependenciesMetadata -org.graalvm.nativeimage:native-image-base:23.0.6=compileClasspath,compileOnlyDependenciesMetadata -org.graalvm.nativeimage:objectfile:23.0.6=compileClasspath,compileOnlyDependenciesMetadata -org.graalvm.nativeimage:pointsto:23.0.6=compileClasspath,compileOnlyDependenciesMetadata -org.graalvm.nativeimage:svm:23.0.6=compileClasspath,compileOnlyDependenciesMetadata -org.graalvm.sdk:graal-sdk:23.0.6=compileClasspath,compileOnlyDependenciesMetadata,runtimeClasspath,testRuntimeClasspath -org.graalvm.truffle:truffle-api:23.0.6=compileClasspath,compileOnlyDependenciesMetadata,runtimeClasspath,testRuntimeClasspath +org.graalvm.compiler:compiler:24.1.2=compileClasspath,compileOnlyDependenciesMetadata +org.graalvm.nativeimage:native-image-base:24.1.2=compileClasspath,compileOnlyDependenciesMetadata +org.graalvm.nativeimage:objectfile:24.1.2=compileClasspath,compileOnlyDependenciesMetadata +org.graalvm.nativeimage:pointsto:24.1.2=compileClasspath,compileOnlyDependenciesMetadata +org.graalvm.nativeimage:svm:24.1.2=compileClasspath,compileOnlyDependenciesMetadata +org.graalvm.nativeimage:truffle-runtime-svm:24.1.2=compileClasspath,compileOnlyDependenciesMetadata +org.graalvm.polyglot:polyglot:24.1.2=compileClasspath,compileOnlyDependenciesMetadata,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.graalvm.sdk:collections:24.1.2=compileClasspath,compileOnlyDependenciesMetadata,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.graalvm.sdk:graal-sdk:24.1.2=compileClasspath,compileOnlyDependenciesMetadata,runtimeClasspath,testRuntimeClasspath +org.graalvm.sdk:jniutils:24.1.2=compileClasspath,compileOnlyDependenciesMetadata,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.graalvm.sdk:nativeimage:24.1.2=compileClasspath,compileOnlyDependenciesMetadata,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.graalvm.sdk:word:24.1.2=compileClasspath,compileOnlyDependenciesMetadata,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.graalvm.truffle:truffle-api:24.1.2=compileClasspath,compileOnlyDependenciesMetadata,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.graalvm.truffle:truffle-compiler:24.1.2=compileClasspath,compileOnlyDependenciesMetadata,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.graalvm.truffle:truffle-runtime:24.1.2=compileClasspath,compileOnlyDependenciesMetadata,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath org.hamcrest:hamcrest-core:2.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath org.hamcrest:hamcrest:2.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath org.jetbrains.intellij.deps:trove4j:1.0.20200330=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinKlibCommonizerClasspath diff --git a/pkl-cli/pkl-cli.gradle.kts b/pkl-cli/pkl-cli.gradle.kts index 253ea8144..8eed9acaf 100644 --- a/pkl-cli/pkl-cli.gradle.kts +++ b/pkl-cli/pkl-cli.gradle.kts @@ -13,6 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import java.io.ByteArrayOutputStream +import org.gradle.kotlin.dsl.support.serviceOf + plugins { pklAllProjects pklKotlinLibrary @@ -50,6 +53,9 @@ val stagedWindowsAmd64Executable: Configuration by configurations.creating dependencies { compileOnly(libs.svm) + compileOnly(libs.truffleSvm) + implementation(libs.truffleRuntime) + compileOnly(libs.graalSdk) // CliEvaluator exposes PClass api(projects.pklCore) @@ -81,7 +87,10 @@ dependencies { stagedWindowsAmd64Executable(executableDir("pkl-windows-amd64.exe")) } -tasks.jar { manifest { attributes += mapOf("Main-Class" to "org.pkl.cli.Main") } } +tasks.jar { + manifest.attributes += + mapOf("Main-Class" to "org.pkl.cli.Main", "Add-Exports" to buildInfo.jpmsExportsForJarManifest) +} tasks.javadoc { enabled = false } @@ -121,33 +130,95 @@ val testJavaExecutable by (configurations.testRuntimeClasspath.get() - configurations.runtimeClasspath.get()) } -tasks.check { dependsOn(testJavaExecutable) } +// Setup `testJavaExecutable` tasks for multi-JDK testing. +val testJavaExecutableOnOtherJdks = + if (buildInfo.multiJdkTesting) { + buildInfo.multiJdkTestingWith(testJavaExecutable) + } else { + emptyList() + } -// 0.14 Java executable was broken because javaExecutable.jvmArgs wasn't commented out. -// To catch this and similar problems, test that Java executable starts successfully. -val testStartJavaExecutable by - tasks.registering(Exec::class) { +// Prepare a run of the fat JAR, optionally with a specific Java launcher. +private fun setupJavaExecutableRun( + name: String, + args: Array, + launcher: Provider? = null, + configurator: Exec.() -> Unit = {}, +) = + tasks.register(name, Exec::class) { dependsOn(javaExecutable) - val outputFile = - layout.buildDirectory.file( - "testStartJavaExecutable" - ) // dummy output to satisfy up-to-date check + val outputFile = layout.buildDirectory.file(name) // dummy output to satisfy up-to-date check outputs.file(outputFile) - if (buildInfo.os.isWindows) { - executable = "java" - args("-jar", javaExecutable.get().outputs.files.singleFile.toString(), "--version") - } else { - executable = javaExecutable.get().outputs.files.singleFile.toString() - args("--version") - } + executable = + when (launcher) { + null -> "java" + else -> launcher.get().executablePath.asFile.absolutePath + } + + args("-jar", javaExecutable.get().outputs.files.singleFile.toString(), *args) doFirst { outputFile.get().asFile.delete() } doLast { outputFile.get().asFile.writeText("OK") } + + configurator() + } + +// 0.14 Java executable was broken because javaExecutable.jvmArgs wasn't commented out. +// To catch this and similar problems, test that Java executable starts successfully. +val testStartJavaExecutable by + setupJavaExecutableRun("testStartJavaExecutable", arrayOf("--version")) + +// Setup `testStartJavaExecutable` tasks for multi-JDK testing. +val testStartJavaExecutableOnOtherJdks = + if (buildInfo.multiJdkTesting) { + buildInfo.jdkTestRange.map { jdkTarget -> + setupJavaExecutableRun( + "testStartJavaExecutableJdk${jdkTarget.asInt()}", + arrayOf("--version"), + serviceOf().launcherFor { languageVersion = jdkTarget }, + ) + } + } else { + emptyList() } -tasks.check { dependsOn(testStartJavaExecutable) } +val evalTestFlags = arrayOf("eval", "./.circleci/config.pkl") + +fun Exec.useRootDirAndSuppressOutput() { + workingDir = rootProject.layout.projectDirectory.asFile + standardOutput = ByteArrayOutputStream() // we only care that this exec doesn't fail +} + +// 0.28 Preparing for JDK21 toolchains revealed that `testStartJavaExecutable` may pass, even though +// the evaluator fails. To catch this, we need to test the evaluator. We render the CircleCI config +// as a realistic test of the fat JAR. +val testEvalJavaExecutable by + setupJavaExecutableRun("testEvalJavaExecutable", evalTestFlags) { useRootDirAndSuppressOutput() } + +// Run the same evaluator tests on all configured JDK test versions. +val testEvalJavaExecutableOnOtherJdks = + buildInfo.jdkTestRange.map { jdkTarget -> + setupJavaExecutableRun( + "testEvalJavaExecutableJdk${jdkTarget.asInt()}", + evalTestFlags, + serviceOf().launcherFor { languageVersion = jdkTarget }, + ) { + useRootDirAndSuppressOutput() + } + } + +tasks.check { + dependsOn( + testJavaExecutable, + testStartJavaExecutable, + testJavaExecutableOnOtherJdks, + testStartJavaExecutableOnOtherJdks, + testEvalJavaExecutable, + testEvalJavaExecutableOnOtherJdks, + ) +} fun Exec.configureExecutable( graalVm: BuildInfo.GraalVm, @@ -174,11 +245,13 @@ fun Exec.configureExecutable( executable = "${graalVm.baseDir}/bin/$nativeImageCommandName" // JARs to exclude from the class path for the native-image build. - val exclusions = listOf(libs.truffleApi, libs.graalSdk).map { it.get().module.name } + val exclusions = listOf(libs.graalSdk).map { it.get().module.name } // https://www.graalvm.org/22.0/reference-manual/native-image/Options/ argumentProviders.add( CommandLineArgumentProvider { buildList { + // must be emitted before any experimental options are used + add("-H:+UnlockExperimentalVMOptions") // currently gives a deprecation warning, but we've been told // that the "initialize everything at build time" *CLI* option is likely here to stay add("--initialize-at-build-time=") @@ -189,9 +262,9 @@ fun Exec.configureExecutable( 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") add("-H:Class=org.pkl.cli.Main") - add("-H:Name=${outputFile.get().asFile.name}") + add("-o") + add(outputFile.get().asFile.name) // the actual limit (currently) used by native-image is this number + 1400 (idea is to // compensate for Truffle's own nodes) add("-H:MaxRuntimeCompileMethods=1800") @@ -206,7 +279,11 @@ fun Exec.configureExecutable( if (!buildInfo.isReleaseBuild) { add("-Ob") } - add("-march=compatibility") + if (buildInfo.isNativeArch) { + add("-march=native") + } else { + add("-march=compatibility") + } // native-image rejects non-existing class path entries -> filter add("--class-path") val pathInput = diff --git a/pkl-codegen-java/gradle.lockfile b/pkl-codegen-java/gradle.lockfile index b3cd061e5..43bb8834f 100644 --- a/pkl-codegen-java/gradle.lockfile +++ b/pkl-codegen-java/gradle.lockfile @@ -9,8 +9,12 @@ io.leangen.geantyref:geantyref:1.3.16=testRuntimeClasspath net.bytebuddy:byte-buddy:1.15.11=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeOnlyDependenciesMetadata org.assertj:assertj-core:3.27.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -org.graalvm.sdk:graal-sdk:23.0.6=runtimeClasspath,testRuntimeClasspath -org.graalvm.truffle:truffle-api:23.0.6=runtimeClasspath,testRuntimeClasspath +org.graalvm.polyglot:polyglot:24.1.2=runtimeClasspath,testRuntimeClasspath +org.graalvm.sdk:collections:24.1.2=runtimeClasspath,testRuntimeClasspath +org.graalvm.sdk:graal-sdk:24.1.2=runtimeClasspath,testRuntimeClasspath +org.graalvm.sdk:nativeimage:24.1.2=runtimeClasspath,testRuntimeClasspath +org.graalvm.sdk:word:24.1.2=runtimeClasspath,testRuntimeClasspath +org.graalvm.truffle:truffle-api:24.1.2=runtimeClasspath,testRuntimeClasspath org.jetbrains.intellij.deps:trove4j:1.0.20200330=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinKlibCommonizerClasspath org.jetbrains.kotlin:kotlin-build-common:2.0.21=kotlinBuildToolsApiClasspath org.jetbrains.kotlin:kotlin-build-tools-api:2.0.21=kotlinBuildToolsApiClasspath diff --git a/pkl-codegen-kotlin/gradle.lockfile b/pkl-codegen-kotlin/gradle.lockfile index 54048da71..a424ae81e 100644 --- a/pkl-codegen-kotlin/gradle.lockfile +++ b/pkl-codegen-kotlin/gradle.lockfile @@ -9,8 +9,12 @@ io.leangen.geantyref:geantyref:1.3.16=testRuntimeClasspath net.bytebuddy:byte-buddy:1.15.11=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeOnlyDependenciesMetadata org.assertj:assertj-core:3.27.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -org.graalvm.sdk:graal-sdk:23.0.6=runtimeClasspath,testRuntimeClasspath -org.graalvm.truffle:truffle-api:23.0.6=runtimeClasspath,testRuntimeClasspath +org.graalvm.polyglot:polyglot:24.1.2=runtimeClasspath,testRuntimeClasspath +org.graalvm.sdk:collections:24.1.2=runtimeClasspath,testRuntimeClasspath +org.graalvm.sdk:graal-sdk:24.1.2=runtimeClasspath,testRuntimeClasspath +org.graalvm.sdk:nativeimage:24.1.2=runtimeClasspath,testRuntimeClasspath +org.graalvm.sdk:word:24.1.2=runtimeClasspath,testRuntimeClasspath +org.graalvm.truffle:truffle-api:24.1.2=runtimeClasspath,testRuntimeClasspath org.jetbrains.intellij.deps:trove4j:1.0.20200330=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinKlibCommonizerClasspath,testRuntimeClasspath,testRuntimeOnlyDependenciesMetadata org.jetbrains.kotlin:kotlin-build-common:2.0.21=kotlinBuildToolsApiClasspath org.jetbrains.kotlin:kotlin-build-tools-api:2.0.21=kotlinBuildToolsApiClasspath diff --git a/pkl-commons-cli/gradle.lockfile b/pkl-commons-cli/gradle.lockfile index 5681fe0c6..8f7660276 100644 --- a/pkl-commons-cli/gradle.lockfile +++ b/pkl-commons-cli/gradle.lockfile @@ -7,8 +7,12 @@ com.tunnelvisionlabs:antlr4-runtime:4.9.0=runtimeClasspath,testRuntimeClasspath net.bytebuddy:byte-buddy:1.15.11=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeOnlyDependenciesMetadata org.assertj:assertj-core:3.27.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -org.graalvm.sdk:graal-sdk:23.0.6=runtimeClasspath,testRuntimeClasspath -org.graalvm.truffle:truffle-api:23.0.6=runtimeClasspath,testRuntimeClasspath +org.graalvm.polyglot:polyglot:24.1.2=runtimeClasspath,testRuntimeClasspath +org.graalvm.sdk:collections:24.1.2=runtimeClasspath,testRuntimeClasspath +org.graalvm.sdk:graal-sdk:24.1.2=runtimeClasspath,testRuntimeClasspath +org.graalvm.sdk:nativeimage:24.1.2=runtimeClasspath,testRuntimeClasspath +org.graalvm.sdk:word:24.1.2=runtimeClasspath,testRuntimeClasspath +org.graalvm.truffle:truffle-api:24.1.2=runtimeClasspath,testRuntimeClasspath org.jetbrains.intellij.deps:trove4j:1.0.20200330=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinKlibCommonizerClasspath org.jetbrains.kotlin:kotlin-build-common:2.0.21=kotlinBuildToolsApiClasspath org.jetbrains.kotlin:kotlin-build-tools-api:2.0.21=kotlinBuildToolsApiClasspath diff --git a/pkl-config-java/gradle.lockfile b/pkl-config-java/gradle.lockfile index 07f44ae29..590e18cbe 100644 --- a/pkl-config-java/gradle.lockfile +++ b/pkl-config-java/gradle.lockfile @@ -10,8 +10,12 @@ javax.inject:javax.inject:1=testCompileClasspath,testImplementationDependenciesM net.bytebuddy:byte-buddy:1.15.11=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeOnlyDependenciesMetadata org.assertj:assertj-core:3.27.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -org.graalvm.sdk:graal-sdk:23.0.6=pklCodegenJava,runtimeClasspath,testRuntimeClasspath -org.graalvm.truffle:truffle-api:23.0.6=pklCodegenJava,runtimeClasspath,testRuntimeClasspath +org.graalvm.polyglot:polyglot:24.1.2=pklCodegenJava,runtimeClasspath,testRuntimeClasspath +org.graalvm.sdk:collections:24.1.2=pklCodegenJava,runtimeClasspath,testRuntimeClasspath +org.graalvm.sdk:graal-sdk:24.1.2=pklCodegenJava,runtimeClasspath,testRuntimeClasspath +org.graalvm.sdk:nativeimage:24.1.2=pklCodegenJava,runtimeClasspath,testRuntimeClasspath +org.graalvm.sdk:word:24.1.2=pklCodegenJava,runtimeClasspath,testRuntimeClasspath +org.graalvm.truffle:truffle-api:24.1.2=pklCodegenJava,runtimeClasspath,testRuntimeClasspath org.jetbrains.intellij.deps:trove4j:1.0.20200330=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinKlibCommonizerClasspath org.jetbrains.kotlin:kotlin-build-common:2.0.21=kotlinBuildToolsApiClasspath org.jetbrains.kotlin:kotlin-build-tools-api:2.0.21=kotlinBuildToolsApiClasspath diff --git a/pkl-config-kotlin/gradle.lockfile b/pkl-config-kotlin/gradle.lockfile index d848baa8b..beba88d98 100644 --- a/pkl-config-kotlin/gradle.lockfile +++ b/pkl-config-kotlin/gradle.lockfile @@ -9,8 +9,12 @@ io.leangen.geantyref:geantyref:1.3.16=pklConfigJava,runtimeClasspath,testCompile net.bytebuddy:byte-buddy:1.15.11=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeOnlyDependenciesMetadata org.assertj:assertj-core:3.27.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -org.graalvm.sdk:graal-sdk:23.0.6=pklCodegenKotlin,pklConfigJava,runtimeClasspath,testRuntimeClasspath -org.graalvm.truffle:truffle-api:23.0.6=pklCodegenKotlin,pklConfigJava,runtimeClasspath,testRuntimeClasspath +org.graalvm.polyglot:polyglot:24.1.2=pklCodegenKotlin,pklConfigJava,runtimeClasspath,testRuntimeClasspath +org.graalvm.sdk:collections:24.1.2=pklCodegenKotlin,pklConfigJava,runtimeClasspath,testRuntimeClasspath +org.graalvm.sdk:graal-sdk:24.1.2=pklCodegenKotlin,pklConfigJava,runtimeClasspath,testRuntimeClasspath +org.graalvm.sdk:nativeimage:24.1.2=pklCodegenKotlin,pklConfigJava,runtimeClasspath,testRuntimeClasspath +org.graalvm.sdk:word:24.1.2=pklCodegenKotlin,pklConfigJava,runtimeClasspath,testRuntimeClasspath +org.graalvm.truffle:truffle-api:24.1.2=pklCodegenKotlin,pklConfigJava,runtimeClasspath,testRuntimeClasspath org.jetbrains.intellij.deps:trove4j:1.0.20200330=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinKlibCommonizerClasspath org.jetbrains.kotlin:kotlin-build-common:2.0.21=kotlinBuildToolsApiClasspath org.jetbrains.kotlin:kotlin-build-tools-api:2.0.21=kotlinBuildToolsApiClasspath diff --git a/pkl-core/gradle.lockfile b/pkl-core/gradle.lockfile index 6a22b6a72..7849b393c 100644 --- a/pkl-core/gradle.lockfile +++ b/pkl-core/gradle.lockfile @@ -12,9 +12,13 @@ org.antlr:ST4:4.3=antlr org.antlr:antlr-runtime:3.5.2=antlr org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeOnlyDependenciesMetadata org.assertj:assertj-core:3.27.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -org.graalvm.sdk:graal-sdk:23.0.6=compileClasspath,generatorCompileClasspath,generatorImplementationDependenciesMetadata,generatorRuntimeClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -org.graalvm.truffle:truffle-api:23.0.6=compileClasspath,generatorCompileClasspath,generatorImplementationDependenciesMetadata,generatorRuntimeClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -org.graalvm.truffle:truffle-dsl-processor:23.0.6=annotationProcessor +org.graalvm.polyglot:polyglot:24.1.2=compileClasspath,generatorCompileClasspath,generatorImplementationDependenciesMetadata,generatorRuntimeClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.graalvm.sdk:collections:24.1.2=compileClasspath,generatorCompileClasspath,generatorImplementationDependenciesMetadata,generatorRuntimeClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.graalvm.sdk:graal-sdk:24.1.2=compileClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.graalvm.sdk:nativeimage:24.1.2=compileClasspath,generatorCompileClasspath,generatorImplementationDependenciesMetadata,generatorRuntimeClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.graalvm.sdk:word:24.1.2=compileClasspath,generatorCompileClasspath,generatorImplementationDependenciesMetadata,generatorRuntimeClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.graalvm.truffle:truffle-api:24.1.2=compileClasspath,generatorCompileClasspath,generatorImplementationDependenciesMetadata,generatorRuntimeClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.graalvm.truffle:truffle-dsl-processor:24.1.2=annotationProcessor org.jetbrains.intellij.deps:trove4j:1.0.20200330=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinKlibCommonizerClasspath org.jetbrains.kotlin:kotlin-build-common:2.0.21=kotlinBuildToolsApiClasspath org.jetbrains.kotlin:kotlin-build-tools-api:2.0.21=kotlinBuildToolsApiClasspath diff --git a/pkl-core/src/main/java/org/pkl/core/EvaluatorImpl.java b/pkl-core/src/main/java/org/pkl/core/EvaluatorImpl.java index 336b321df..f97f03976 100644 --- a/pkl-core/src/main/java/org/pkl/core/EvaluatorImpl.java +++ b/pkl-core/src/main/java/org/pkl/core/EvaluatorImpl.java @@ -1,5 +1,5 @@ /* - * Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved. + * Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -324,7 +324,7 @@ private T doEvaluate(Supplier supplier) { var error = new ExceptionInInitializerError(pklException); error.setStackTrace(e.getStackTrace()); throw new PklBugException(error); - } catch (ThreadDeath e) { + } catch (Throwable e) { if (e.getClass() .getName() .equals("com.oracle.truffle.polyglot.PolyglotEngineImpl$CancelExecution")) { diff --git a/pkl-core/src/test/kotlin/org/pkl/core/LanguageSnippetTestsEngine.kt b/pkl-core/src/test/kotlin/org/pkl/core/LanguageSnippetTestsEngine.kt index 1baa61103..99cf94795 100644 --- a/pkl-core/src/test/kotlin/org/pkl/core/LanguageSnippetTestsEngine.kt +++ b/pkl-core/src/test/kotlin/org/pkl/core/LanguageSnippetTestsEngine.kt @@ -34,6 +34,18 @@ import org.pkl.core.http.HttpClient import org.pkl.core.project.Project import org.pkl.core.util.IoUtils +// @TODO: this test fails on JDK 22+, because of an output mismatch +private val excludedOnJvm22Plus = listOf(Regex(".*analyzeInvalidHttpModule.*")) + +private fun currentMajorJavaVersion(): Int = + System.getProperty("java.version").substringBefore('.').toInt() + +private fun exclusionsForThisJvm(): List = + when { + currentMajorJavaVersion() >= 22 -> excludedOnJvm22Plus + else -> emptyList() + } + abstract class AbstractLanguageSnippetTestsEngine : InputOutputTestEngine() { private val lineNumberRegex = Regex("(?m)^(( ║ )*)(\\d+) \\|") private val hiddenExtensionRegex = Regex(".*[.]([^.]*)[.]pkl") @@ -61,6 +73,9 @@ abstract class AbstractLanguageSnippetTestsEngine : InputOutputTestEngine() { if (IoUtils.isWindows()) { addAll(windowsExcludedTests) } + + // on experimental JVM versions, exclude tests which are known to be incompatible + addAll(exclusionsForThisJvm()) } override val inputDir: Path = snippetsDir.resolve("input") @@ -201,7 +216,7 @@ abstract class AbstractNativeLanguageSnippetTestsEngine : AbstractLanguageSnippe Regex(".*/import1b\\.pkl"), // URIs get rendered slightly differently (percent-encoded vs raw) Regex(".*日本語_error\\.pkl"), - ) + ) + exclusionsForThisJvm() /** Avoid running tests for native binaries when those native binaries have not been built. */ override fun discover( diff --git a/pkl-doc/gradle.lockfile b/pkl-doc/gradle.lockfile index 99156228e..e6fb76fdd 100644 --- a/pkl-doc/gradle.lockfile +++ b/pkl-doc/gradle.lockfile @@ -11,7 +11,6 @@ com.google.guava:guava:32.1.1-jre=testCompileClasspath,testImplementationDepende com.google.j2objc:j2objc-annotations:2.8=testCompileClasspath,testImplementationDependenciesMetadata com.google.jimfs:jimfs:1.3.0=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath com.ibm.icu:icu4j:58.2=validator -com.ibm.icu:icu4j:72.1=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath com.shapesecurity:salvation:2.7.2=validator com.tunnelvisionlabs:antlr4-runtime:4.9.0=runtimeClasspath,testRuntimeClasspath commons-codec:commons-codec:1.10=validator @@ -37,10 +36,22 @@ org.commonmark:commonmark-ext-gfm-tables:0.24.0=compileClasspath,implementationD org.commonmark:commonmark:0.24.0=compileClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath org.eclipse.jetty:jetty-util-ajax:9.4.18.v20190429=validator org.eclipse.jetty:jetty-util:9.4.18.v20190429=validator -org.graalvm.js:js:23.0.6=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -org.graalvm.regex:regex:23.0.6=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -org.graalvm.sdk:graal-sdk:23.0.6=runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -org.graalvm.truffle:truffle-api:23.0.6=runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.graalvm.js:js-community:24.1.2=testRuntimeClasspath +org.graalvm.js:js-language:24.1.2=testRuntimeClasspath +org.graalvm.js:js:24.1.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.graalvm.polyglot:polyglot:24.1.2=runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.graalvm.regex:regex:24.1.2=testRuntimeClasspath +org.graalvm.sdk:collections:24.1.2=runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.graalvm.sdk:graal-sdk:24.1.2=runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.graalvm.sdk:jniutils:24.1.2=testRuntimeClasspath +org.graalvm.sdk:nativebridge:24.1.2=testRuntimeClasspath +org.graalvm.sdk:nativeimage:24.1.2=runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.graalvm.sdk:word:24.1.2=runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.graalvm.shadowed:icu4j:24.1.2=testRuntimeClasspath +org.graalvm.truffle:truffle-api:24.1.2=runtimeClasspath,testRuntimeClasspath +org.graalvm.truffle:truffle-compiler:24.1.2=testRuntimeClasspath +org.graalvm.truffle:truffle-enterprise:24.1.2=testRuntimeClasspath +org.graalvm.truffle:truffle-runtime:24.1.2=testRuntimeClasspath org.jetbrains.intellij.deps:trove4j:1.0.20200330=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinKlibCommonizerClasspath org.jetbrains.kotlin:kotlin-build-common:2.0.21=kotlinBuildToolsApiClasspath org.jetbrains.kotlin:kotlin-build-tools-api:2.0.21=kotlinBuildToolsApiClasspath diff --git a/pkl-executor/gradle.lockfile b/pkl-executor/gradle.lockfile index d62231456..bf8034285 100644 --- a/pkl-executor/gradle.lockfile +++ b/pkl-executor/gradle.lockfile @@ -5,8 +5,12 @@ com.tunnelvisionlabs:antlr4-runtime:4.9.0=testRuntimeClasspath net.bytebuddy:byte-buddy:1.15.11=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeOnlyDependenciesMetadata org.assertj:assertj-core:3.27.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -org.graalvm.sdk:graal-sdk:23.0.6=testRuntimeClasspath -org.graalvm.truffle:truffle-api:23.0.6=testRuntimeClasspath +org.graalvm.polyglot:polyglot:24.1.2=testRuntimeClasspath +org.graalvm.sdk:collections:24.1.2=testRuntimeClasspath +org.graalvm.sdk:graal-sdk:24.1.2=testRuntimeClasspath +org.graalvm.sdk:nativeimage:24.1.2=testRuntimeClasspath +org.graalvm.sdk:word:24.1.2=testRuntimeClasspath +org.graalvm.truffle:truffle-api:24.1.2=testRuntimeClasspath org.jetbrains.intellij.deps:trove4j:1.0.20200330=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinKlibCommonizerClasspath org.jetbrains.kotlin:kotlin-build-common:2.0.21=kotlinBuildToolsApiClasspath org.jetbrains.kotlin:kotlin-build-tools-api:2.0.21=kotlinBuildToolsApiClasspath diff --git a/pkl-server/gradle.lockfile b/pkl-server/gradle.lockfile index 314693dcc..0142ad905 100644 --- a/pkl-server/gradle.lockfile +++ b/pkl-server/gradle.lockfile @@ -5,8 +5,12 @@ com.tunnelvisionlabs:antlr4-runtime:4.9.0=compileClasspath,implementationDepende net.bytebuddy:byte-buddy:1.15.11=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeOnlyDependenciesMetadata org.assertj:assertj-core:3.27.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -org.graalvm.sdk:graal-sdk:23.0.6=compileClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -org.graalvm.truffle:truffle-api:23.0.6=compileClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.graalvm.polyglot:polyglot:24.1.2=compileClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.graalvm.sdk:collections:24.1.2=compileClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.graalvm.sdk:graal-sdk:24.1.2=runtimeClasspath,testRuntimeClasspath +org.graalvm.sdk:nativeimage:24.1.2=compileClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.graalvm.sdk:word:24.1.2=compileClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.graalvm.truffle:truffle-api:24.1.2=compileClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath org.jetbrains.intellij.deps:trove4j:1.0.20200330=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinKlibCommonizerClasspath org.jetbrains.kotlin:kotlin-build-common:2.0.21=kotlinBuildToolsApiClasspath org.jetbrains.kotlin:kotlin-build-tools-api:2.0.21=kotlinBuildToolsApiClasspath diff --git a/pkl-server/pkl-server.gradle.kts b/pkl-server/pkl-server.gradle.kts index 147667e75..8be9e5fda 100644 --- a/pkl-server/pkl-server.gradle.kts +++ b/pkl-server/pkl-server.gradle.kts @@ -1,5 +1,5 @@ /* - * Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved. + * Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/pkl-server/src/test/kotlin/org/pkl/server/AbstractServerTest.kt b/pkl-server/src/test/kotlin/org/pkl/server/AbstractServerTest.kt index 00a7ab513..05eb94fbc 100644 --- a/pkl-server/src/test/kotlin/org/pkl/server/AbstractServerTest.kt +++ b/pkl-server/src/test/kotlin/org/pkl/server/AbstractServerTest.kt @@ -25,6 +25,7 @@ import kotlin.io.path.outputStream import kotlin.io.path.writeText import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.AfterAll +import org.junit.jupiter.api.BeforeAll import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Test import org.junit.jupiter.api.io.TempDir @@ -38,13 +39,18 @@ abstract class AbstractServerTest { companion object { /** Set to `true` to bypass messagepack serialization when running [JvmServerTest]. */ internal const val USE_DIRECT_TRANSPORT = false + lateinit var executor: ExecutorService - val executor: ExecutorService = - if (USE_DIRECT_TRANSPORT) { - createDirectExecutor() - } else { - Executors.newCachedThreadPool() - } + @BeforeAll + @JvmStatic + fun beforeAll() { + executor = + if (USE_DIRECT_TRANSPORT) { + createDirectExecutor() + } else { + Executors.newCachedThreadPool() + } + } @AfterAll @JvmStatic diff --git a/pkl-tools/gradle.lockfile b/pkl-tools/gradle.lockfile index 6c205ae2c..64b141b63 100644 --- a/pkl-tools/gradle.lockfile +++ b/pkl-tools/gradle.lockfile @@ -10,8 +10,15 @@ io.leangen.geantyref:geantyref:1.3.16=runtimeClasspath,testRuntimeClasspath org.commonmark:commonmark-ext-gfm-tables:0.24.0=runtimeClasspath,testRuntimeClasspath org.commonmark:commonmark:0.24.0=runtimeClasspath,testRuntimeClasspath org.fusesource.jansi:jansi:2.4.1=runtimeClasspath,testRuntimeClasspath -org.graalvm.sdk:graal-sdk:23.0.6=runtimeClasspath,testRuntimeClasspath -org.graalvm.truffle:truffle-api:23.0.6=runtimeClasspath,testRuntimeClasspath +org.graalvm.polyglot:polyglot:24.1.2=runtimeClasspath,testRuntimeClasspath +org.graalvm.sdk:collections:24.1.2=runtimeClasspath,testRuntimeClasspath +org.graalvm.sdk:graal-sdk:24.1.2=runtimeClasspath,testRuntimeClasspath +org.graalvm.sdk:jniutils:24.1.2=runtimeClasspath,testRuntimeClasspath +org.graalvm.sdk:nativeimage:24.1.2=runtimeClasspath,testRuntimeClasspath +org.graalvm.sdk:word:24.1.2=runtimeClasspath,testRuntimeClasspath +org.graalvm.truffle:truffle-api:24.1.2=runtimeClasspath,testRuntimeClasspath +org.graalvm.truffle:truffle-compiler:24.1.2=runtimeClasspath,testRuntimeClasspath +org.graalvm.truffle:truffle-runtime:24.1.2=runtimeClasspath,testRuntimeClasspath org.jetbrains.kotlin:kotlin-reflect:2.0.21=runtimeClasspath,testRuntimeClasspath org.jetbrains.kotlin:kotlin-stdlib-common:2.0.21=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath org.jetbrains.kotlin:kotlin-stdlib-jdk7:2.0.21=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath diff --git a/settings.gradle.kts b/settings.gradle.kts index 5f97fee35..2ba218904 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,5 +1,5 @@ /* - * Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved. + * Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -56,13 +56,9 @@ pluginManagement { } } -@Suppress("UnstableApiUsage") dependencyResolutionManagement { repositories { mavenCentral() } } - -val javaVersion = JavaVersion.current() +plugins { id("org.gradle.toolchains.foojay-resolver-convention") version ("0.8.0") } -require(javaVersion.isCompatibleWith(JavaVersion.VERSION_17)) { - "Project requires Java 17 or higher, but found ${javaVersion.majorVersion}." -} +@Suppress("UnstableApiUsage") dependencyResolutionManagement { repositories { mavenCentral() } } if ( gradle.startParameter.taskNames.contains("updateDependencyLocks") ||