Skip to content

Commit

Permalink
chore: use Gradle toolchains for JDK provisioning
Browse files Browse the repository at this point in the history
It enables automatic JDK provisioning (e.g. download), and it enables
using different JDKs for executing Gradle and for building JMeter

Java version can be specified when building with -PjdkVersion=11

You could use ./gradlew -q javaToolchains to list the detected toolchains.

See https://docs.gradle.org/8.0/userguide/toolchains.html#sec:consuming

Fixes apache#5986
  • Loading branch information
vlsi committed Jun 18, 2023
1 parent e024bf3 commit 8e5122d
Show file tree
Hide file tree
Showing 7 changed files with 101 additions and 11 deletions.
16 changes: 15 additions & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,19 @@ jobs:
with:
fetch-depth: 50
- name: Set up Java ${{ matrix.java_version }}, ${{ matrix.java_distribution }}
if: ${{ matrix.oracle_java_website != '' }}
uses: oracle-actions/setup-java@1611a647972adb8b04779be3529a044d650fd510 # v1
with:
website: ${{ matrix.oracle_java_website }}
release: ${{ matrix.java_version }}
- name: Set up Java ${{ matrix.java_version }}, ${{ matrix.java_distribution }}
if: ${{ matrix.java_distribution != 'oracle' }}
uses: actions/setup-java@v3
with:
java-version: ${{ matrix.java_version }}
# The latest one will be the default, so we use Java 17 for launching Gradle
java-version: |
${{ matrix.non_ea_java_version }}
17
distribution: ${{ matrix.java_distribution }}
architecture: x64
- name: Steps to reproduce
Expand All @@ -68,6 +78,10 @@ jobs:
properties: |
testExtraJvmArgs=${{ matrix.testExtraJvmArgs }}
testDisableCaching=${{ matrix.testDisableCaching }}
jdkVersion=${{ matrix.java_version }}
jdkVendor=${{ matrix.java_distribution }}
# We provision JDKs with GitHub Actions for caching purposes, so Gradle should rather fail in case JDK is not found
org.gradle.java.installations.auto-download=false
env:
_JAVA_OPTIONS: ${{ matrix.extraJvmArgs }}
GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GE_ACCESS_TOKEN }}
Expand Down
12 changes: 11 additions & 1 deletion .github/workflows/matrix.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,16 @@ matrix.addAxis({
]
});

const eaJava = '21';

matrix.addAxis({
name: 'java_version',
// Strings allow versions like 18-ea
values: [
'8',
'11',
'17',
eaJava,
]
});

Expand Down Expand Up @@ -78,6 +81,7 @@ matrix.exclude({java_distribution: {value: 'semeru'}, hash: {value: 'same'}});
matrix.exclude({java_distribution: {value: 'microsoft'}, java_version: '8'});
// Oracle JDK is only supported for JDK 17 and later
matrix.exclude({java_distribution: {value: 'oracle'}, java_version: ['8', '11']});
matrix.imply({java_version: eaJava}, {java_distribution: {value: 'oracle'}})
// Ensure at least one job with "same" hashcode exists
matrix.generateRow({hash: {value: 'same'}});
// Ensure at least one Windows and at least one Linux job is present (macOS is almost the same as Linux)
Expand All @@ -90,6 +94,8 @@ matrix.generateRow({java_version: "8"});
matrix.generateRow({java_version: "11"});
// Ensure there will be at least one job with Java 17
matrix.generateRow({java_version: "17"});
// Ensure there will be at least one job with Java EA
matrix.generateRow({java_version: eaJava});
const include = matrix.generateRows(process.env.MATRIX_JOBS || 5);
if (include.length === 0) {
throw new Error('Matrix list is empty');
Expand Down Expand Up @@ -124,9 +130,13 @@ include.forEach(v => {
jvmArgs.push(`-Duser.country=${v.locale.country}`);
jvmArgs.push(`-Duser.language=${v.locale.language}`);
v.java_distribution = v.java_distribution.value;
if (v.java_distribution === 'oracle') {
v.oracle_java_website = v.java_version === eaJava ? 'jdk.java.net' : 'oracle.com';
}
v.non_ea_java_version = v.java_version === eaJava ? '' : v.java_version;
if (v.java_distribution !== 'semeru' && Math.random() > 0.5) {
// The following options randomize instruction selection in JIT compiler
// so it might reveal missing synchronization in TestNG code
// so it might reveal missing synchronization
v.name += ', stress JIT';
v.testDisableCaching = 'JIT randomization should not be cached';
jvmArgs.push('-XX:+UnlockDiagnosticVMOptions');
Expand Down
23 changes: 18 additions & 5 deletions .github/workflows/matrix_builder.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class Axis {
}
if (Array.isArray(filter)) {
// e.g. row={os: 'windows'}; filter=[{os: 'linux'}, {os: 'linux'}]
return filter.find(v => Axis.matches(row, v));
return filter.some(v => Axis.matches(row, v));
}
if (typeof filter === 'object') {
// e.g. row={jdk: {name: 'openjdk', version: 8}}; filter={jdk: {version: 8}}
Expand Down Expand Up @@ -68,6 +68,7 @@ class MatrixBuilder {
this.duplicates = {};
this.excludes = [];
this.includes = [];
this.implications = [];
this.failOnUnsatisfiableFilters = false;
}

Expand All @@ -80,13 +81,23 @@ class MatrixBuilder {
}

/**
* Specifies exclude filter (e.g. exclude a forbidden combination)
* Specifies exclude filter (e.g. exclude a forbidden combination).
* @param filter
*/
exclude(filter) {
this.excludes.push(filter);
}

/**
* Adds implication like `antecedent -> consequent`.
* In other words, if `antecedent` holds, then `consequent` must also hold.
* @param antecedent
* @param consequent
*/
imply(antecedent, consequent) {
this.implications.push({antecedent: antecedent, consequent: consequent});
}

addAxis({name, title, values}) {
const axis = new Axis({name, title, values});
this.axes.push(axis);
Expand All @@ -104,8 +115,10 @@ class MatrixBuilder {
* @returns {boolean}
*/
matches(row) {
return (this.excludes.length === 0 || !this.excludes.find(f => Axis.matches(row, f))) &&
(this.includes.length === 0 || this.includes.find(f => Axis.matches(row, f)));
return (this.excludes.length === 0 || !this.excludes.some(f => Axis.matches(row, f))) &&
(this.includes.length === 0 || this.includes.some(f => Axis.matches(row, f))) &&
(this.implications.length === 0 || (
this.implications.every(i => !Axis.matches(row, i.antecedent) || Axis.matches(row, i.consequent))));
}

failOnUnsatisfiableFilters(value) {
Expand All @@ -125,7 +138,7 @@ class MatrixBuilder {
let res;
if (filter) {
// If matching row already exists, no need to generate more
res = this.rows.find(v => Axis.matches(v, filter));
res = this.rows.some(v => Axis.matches(v, filter));
if (res) {
return res;
}
Expand Down
16 changes: 16 additions & 0 deletions build-logic/build-parameters/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,22 @@ buildParameters {
defaultValue.set(false)
description.set("Collect test coverage")
}
integer("targetJavaVersion") {
defaultValue.set(8)
mandatory.set(true)
description.set("Java version for source and target compatibility")
}
integer("jdkVersion") {
defaultValue.set(17)
mandatory.set(true)
description.set("JDK version to use for building JMeter. If the value is 0, then current Java is used. (see https://docs.gradle.org/8.0/userguide/toolchains.html#sec:consuming)")
}
string("jdkVendor") {
description.set("JDK vendor to use building JMeter (see https://docs.gradle.org/8.0/userguide/toolchains.html#sec:vendors)")
}
string("jdkImplementation") {
description.set("Vendor-specific virtual machine implementation to use building JMeter (see https://docs.gradle.org/8.0/userguide/toolchains.html#selecting_toolchains_by_virtual_machine_implementation)")
}
bool("spotbugs") {
defaultValue.set(false)
description.set("Run SpotBugs verifications")
Expand Down
19 changes: 16 additions & 3 deletions build-logic/jvm/src/main/kotlin/build-logic.java.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,19 @@ plugins {
}

java {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
buildParameters.jdkVersion.takeIf { it > 0 }?.let { jdkVersion ->
toolchain {
languageVersion.set(JavaLanguageVersion.of(jdkVersion))
buildParameters.jdkVendor.orNull?.let {
vendor.set(JvmVendorSpec.matching(it))
}
buildParameters.jdkImplementation.orNull?.let {
if (it.equals("J9", ignoreCase = true)) {
implementation.set(JvmImplementation.J9)
}
}
}
}
consistentResolution {
useCompileClasspathVersions()
}
Expand All @@ -44,7 +55,9 @@ tasks.configureEach<JavaCompile> {
// Use --release=8 for Java 10+ so the generated bytecode does not include methods introduced in Java 9+
options.release.set(
provider {
8.takeIf { javaCompiler.get().metadata.languageVersion.asInt() > 9 }
buildParameters.targetJavaVersion.takeIf {
javaCompiler.get().metadata.languageVersion.asInt() > 9
}
}
)
}
Expand Down
21 changes: 20 additions & 1 deletion build-logic/jvm/src/main/kotlin/build-logic.kotlin.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
id("java-library")
id("build-logic.build-params")
id("build-logic.java")
id("build-logic.test-base")
id("com.github.autostyle")
Expand All @@ -36,6 +37,19 @@ kotlin {
if (props.bool("kotlin.explicitApi", default = true)) {
explicitApi()
}
buildParameters.jdkVersion.takeIf { it > 0 }?.let { jdkVersion ->
jvmToolchain {
languageVersion.set(JavaLanguageVersion.of(jdkVersion))
buildParameters.jdkVendor.orNull?.let {
vendor.set(JvmVendorSpec.matching(it))
}
buildParameters.jdkImplementation.orNull?.let {
if (it.equals("J9", ignoreCase = true)) {
implementation.set(JvmImplementation.J9)
}
}
}
}
}

tasks.configureEach<KotlinCompile> {
Expand All @@ -44,7 +58,12 @@ tasks.configureEach<KotlinCompile> {
apiVersion = "kotlin.api".v
}
freeCompilerArgs += "-Xjvm-default=all"
jvmTarget = java.targetCompatibility.toString()
kotlinOptions.jvmTarget = buildParameters.targetJavaVersion.let {
when {
it < 9 -> "1.8"
else -> it.toString()
}
}
}
}

Expand Down
5 changes: 5 additions & 0 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ pluginManagement {
plugins {
id("com.gradle.enterprise") version "3.13.2"
id("com.gradle.common-custom-user-data-gradle-plugin") version "1.10"
id("org.gradle.toolchains.foojay-resolver-convention") version "0.5.0"
}

dependencyResolutionManagement {
Expand Down Expand Up @@ -164,6 +165,10 @@ val expectedSha512 = mapOf(
to "okhttp-4.1.0.jar",
"93E7A41BE44CC17FB500EA5CD84D515204C180AEC934491D11FC6A71DAEA761FB0EECEF865D6FD5C3D88AAF55DCE3C2C424BE5BA5D43BEBF48D05F1FA63FA8A7"
to "okio-2.2.2.jar",
"B9F87DECE28EABCCEDA58C77C3B602AEAE7A8AEF3D30DA838F4924A620B18C05D9DF86C5876BDE8AB5597C8C0CE808AD083CAF89C3A5AAC60C1E980C6C144A17"
to "foojay-resolver-0.5.0.jar",
"10BF91C79AB151B684834E3CA8BA7D7E19742A3EEB580BDE690FBA433F9FFFE3ABBD79ED3FE3F97986C3A2BADC4D14E28835A8EF89167B4B9CC6014242338769"
to "gson-2.9.1.jar",
settings.extra["com.github.vlsi.checksum-dependency.sha512"].toString()
to "checksum-dependency-plugin.jar"
)
Expand Down

0 comments on commit 8e5122d

Please sign in to comment.