Message-ID: From: "vlsi (@vlsi)" To: "pgjdbc/pgjdbc" Date: Thu, 04 Jun 2026 07:03:58 +0000 Subject: [pgjdbc/pgjdbc] PR #4149: build: 42.2 compile with a Java 11 toolchain, run tests on multiple JDKs List-Id: X-GitHub-Additions: 62 X-GitHub-Author-Id: 213894 X-GitHub-Author-Login: vlsi X-GitHub-Base: release/42.2.x X-GitHub-Changed-Files: 4 X-GitHub-Commits: 1 X-GitHub-Deletions: 15 X-GitHub-Head-Branch: claude/jolly-merkle-d51ea7 X-GitHub-Head-SHA: 78e3dc04bc59cf4dd92b0472a6a658c0122bd8ac X-GitHub-Issue: 4149 X-GitHub-Merge-SHA: 93647193d7c8aafef969e1b6a7fb83c5526b8a30 X-GitHub-Merged-By: vlsi X-GitHub-Repo: pgjdbc/pgjdbc X-GitHub-State: merged X-GitHub-Type: pull_request X-GitHub-Url: https://github.com/pgjdbc/pgjdbc/pull/4149 Content-Type: text/plain; charset=utf-8 ## Why The 42.2.x build ties the compile JDK to the JVM that runs Gradle and sets the target through `sourceCompatibility`/`targetCompatibility`. That makes it hard to build on a fixed JDK while running the test suite against several Java versions, which is the model already used on `master`. ## What - Add a Gradle toolchain for the main modules. `jdkBuildVersion` (default 11) selects the compile JDK; the driver still produces Java 8 bytecode. - Replace `sourceCompatibility`/`targetCompatibility` with `javac --release 8`, guarded so it is only passed on `javac` 9+ (no effect on JDK 8). - Run the test task on a separate JDK via `-PjdkTestVersion` (0 reuses the build JVM), using a toolchain launcher. - Keep `postgresql-jre6`/`postgresql-jre7` off the toolchain; they manage their own `--release` (or `java6home`/`java7home`) handling. - Stop forwarding the build JVM's `java.*` system properties to the test JVM. Forwarding `java.home`/`java.version` broke a test JVM running on a different Java version; only `pgjdbc.*` is forwarded now, matching `master`. - CI: build on JDK 11 and run the `[8, 11]` test matrix through the toolchain launcher (`jdkTestVersion` + `org.gradle.java.installations.fromEnv`). ## How to verify ``` # Compiles on JDK 11, produces Java 8 bytecode ./gradlew :postgresql:compileJava # Driver.class major version = 52 # Runs the tests on JDK 8 while the build stays on JDK 11 ./gradlew :postgresql:test -PjdkTestVersion=8 ``` Verified locally: the main module compiles via the JDK 11 toolchain to Java 8 bytecode, unit tests pass on JDK 8 and on the default build JVM, and `postgresql-jre6`/`jre7` still produce Java 6/7 bytecode. ## Notes `jdkBuildVersion` defaults to 11, so the build now expects a JDK 11 toolchain. Pass `-PjdkBuildVersion=0` to compile with the current JVM instead. diff --git a/.github/workflows/buildcache.yml b/.github/workflows/buildcache.yml index ef103b0ab7..b093c87e96 100644 --- a/.github/workflows/buildcache.yml +++ b/.github/workflows/buildcache.yml @@ -11,7 +11,9 @@ jobs: strategy: matrix: os: [ubuntu, macos, windows] - jdk: [8, 11] + # build -x test does not run tests, so only the build JDK matters here. + # The driver compiles via a JDK 11 toolchain (still targeting Java 8 bytecode). + jdk: [11] name: '${{ matrix.os }}, ${{ matrix.jdk }} seed build cache' runs-on: ${{ matrix.os }}-latest @@ -20,8 +22,9 @@ jobs: with: fetch-depth: 50 - name: 'Set up JDK ${{ matrix.jdk }}' - uses: actions/setup-java@v1 + uses: actions/setup-java@v3 with: + distribution: zulu java-version: ${{ matrix.jdk }} - uses: burrunan/gradle-cache-action@v3 name: Build pgjdbc diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 8864070e0f..30207a2ded 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -19,11 +19,11 @@ jobs: - uses: actions/checkout@v4 with: fetch-depth: 50 - - name: 'Set up JDK 8' + - name: 'Set up JDK 11' uses: actions/setup-java@v3 with: distribution: zulu - java-version: 8 + java-version: 11 - uses: burrunan/gradle-cache-action@v3 name: Verify code style env: @@ -34,7 +34,7 @@ jobs: arguments: autostyleCheck checkstyleAll jandex ubuntu-latest: - name: 'Ubuntu, PG latest (JDK ${{ matrix.jdk }})' + name: 'Ubuntu, PG latest (build JDK 11, test JDK ${{ matrix.jdk }})' runs-on: ubuntu-latest strategy: fail-fast: false @@ -68,11 +68,15 @@ jobs: - name: Start PostgreSQL working-directory: docker run: docker compose up -d && docker compose logs - - name: 'Set up JDK ${{ matrix.jdk }}' + - name: 'Set up test JDK ${{ matrix.jdk }} and build JDK 11' uses: actions/setup-java@v3 with: distribution: zulu - java-version: ${{ matrix.jdk }} + # The last version becomes the default JAVA_HOME, so Gradle runs on JDK 11. + # The test task is launched on JDK ${{ matrix.jdk }} via the Gradle toolchain. + java-version: | + ${{ matrix.jdk }} + 11 - name: Prepare ssltest.local.properties run: echo enable_ssl_tests=true > ssltest.local.properties - name: Get Docker logs @@ -89,6 +93,8 @@ jobs: properties: | skipReplicationTests= port=${{ job.services.postgres.ports['5432'] }} + jdkTestVersion=${{ matrix.jdk }} + org.gradle.java.installations.fromEnv=JAVA_HOME_${{ matrix.jdk }}_X64,JAVA_HOME_11_X64 linux-checkerframework: name: 'CheckerFramework (JDK 11)' @@ -142,16 +148,16 @@ jobs: mvn --batch-mode --fail-at-end --show-version verify gss-encryption: - name: 'Ubuntu, gss encryption (JDK 8)' + name: 'Ubuntu, gss encryption (JDK 11)' runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - name: 'Set up JDK 8' + - name: 'Set up JDK 11' uses: actions/setup-java@v3 with: distribution: zulu - java-version: 8 + java-version: 11 - name: 'Install software' run: | sudo apt -y update diff --git a/build.gradle.kts b/build.gradle.kts index 9791676352..7caaba2a2f 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -14,6 +14,8 @@ import com.github.vlsi.gradle.publishing.dsl.simplifyXml import com.github.vlsi.gradle.publishing.dsl.versionFromResolution import de.thetaphi.forbiddenapis.gradle.CheckForbiddenApis import de.thetaphi.forbiddenapis.gradle.CheckForbiddenApisExtension +import org.gradle.jvm.toolchain.JavaLanguageVersion +import org.gradle.jvm.toolchain.JavaToolchainService import org.postgresql.buildtools.JavaCommentPreprocessorTask plugins { @@ -52,6 +54,10 @@ val skipJavadoc by props() val skipForbiddenApis by props() val enableMavenLocal by props() val enableGradleMetadata by props() +// Java version used to compile the driver via a toolchain. 0 falls back to the JVM that runs Gradle. +val jdkBuildVersion = props.int("jdkBuildVersion", 11) +// Java version used to run the test task via a toolchain. 0 reuses the build JVM. +val jdkTestVersion = props.int("jdkTestVersion", 0) // For instance -PincludeTestTags=!org.postgresql.test.SlowTests // or -PincludeTestTags=!org.postgresql.test.Replication val includeTestTags by props("") @@ -358,15 +364,18 @@ allprojects { } plugins.withType { - configure { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 - } configure { withSourcesJar() if (!skipJavadoc) { withJavadocJar() } + // postgresql-jre6/jre7 target older Java releases and manage their own + // compiler (java6home/java7home or --release), so keep them off the toolchain. + if (jdkBuildVersion != 0 && !project.path.startsWith(":postgresql-jre")) { + toolchain { + languageVersion.set(JavaLanguageVersion.of(jdkBuildVersion)) + } + } } val sourceSets: SourceSetContainer by project @@ -519,8 +528,26 @@ allprojects { configureEach { options.encoding = "UTF-8" + // Target Java 8 bytecode without referencing Java 9+ API. + // --release is only understood by javac 9+, so skip it on JDK 8. + // postgresql-jre6/jre7 set their own --release, so leave them alone. + if (!project.path.startsWith(":postgresql-jre")) { + options.release.set( + provider { + 8.takeIf { javaCompiler.get().metadata.languageVersion.asInt() > 9 } + } + ) + } } configureEach { + // Run tests on a specific Java version, independent of the build JVM. + if (jdkTestVersion != 0) { + javaLauncher.set( + project.the().launcherFor { + languageVersion.set(JavaLanguageVersion.of(jdkTestVersion)) + } + ) + } useJUnitPlatform { if (includeTestTags.isNotBlank()) { includeTags.add(includeTestTags) @@ -545,7 +572,10 @@ allprojects { passProperty("user.country", "tr") val props = System.getProperties() for (e in props.propertyNames() as `java.util`.Enumeration) { - if (e.startsWith("pgjdbc.") || e.startsWith("java")) { + // Forward only pgjdbc.* here. Forwarding the build JVM's java.* properties + // (java.home, java.version, ...) would break a test JVM on a different + // Java version selected via jdkTestVersion. + if (e.startsWith("pgjdbc.")) { passProperty(e) } } diff --git a/gradle.properties b/gradle.properties index b52bd98802..2b885c39d8 100644 --- a/gradle.properties +++ b/gradle.properties @@ -16,6 +16,14 @@ kotlin.parallel.tasks.in.project=true # Release version can be generated by using -Prelease or -Prc= arguments pgjdbc.version=42.2.30 +# Java version used to compile the driver via a Gradle toolchain. +# The driver still targets Java 8 bytecode (javac --release 8) regardless of this value. +# Set to 0 to compile with the JVM that runs Gradle instead of a toolchain. +jdkBuildVersion=11 +# Java version used to run the test task via a Gradle toolchain. +# 0 means "reuse the build JVM". Override per run, e.g. -PjdkTestVersion=8 +jdkTestVersion=0 + # The options below configures the use of local clone (e.g. testing development versions) # You can pass un-comment it, or pass option -PlocalReleasePlugins, or -PlocalReleasePlugins= # localReleasePlugins=../vlsi-release-plugins