chore: use Gradle toolchains for JDK provisioning

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 https://github.com/apache/jmeter/issues/5986
This commit is contained in:
Vladimir Sitnikov 2023-06-17 14:28:54 +03:00
parent 3670413302
commit 1ee08f4e28
21 changed files with 274 additions and 52 deletions

View File

@ -46,10 +46,19 @@ jobs:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
with: with:
fetch-depth: 50 fetch-depth: 50
- name: Set up Java ${{ matrix.java_version }}, ${{ matrix.java_distribution }} - name: Set up Java ${{ matrix.java_version }}, oracle
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 17 and ${{ matrix.non_ea_java_version }}, ${{ matrix.java_distribution }}
uses: actions/setup-java@v3 uses: actions/setup-java@v3
with: 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 }} distribution: ${{ matrix.java_distribution }}
architecture: x64 architecture: x64
- name: Steps to reproduce - name: Steps to reproduce
@ -68,6 +77,11 @@ jobs:
properties: | properties: |
testExtraJvmArgs=${{ matrix.testExtraJvmArgs }} testExtraJvmArgs=${{ matrix.testExtraJvmArgs }}
testDisableCaching=${{ matrix.testDisableCaching }} testDisableCaching=${{ matrix.testDisableCaching }}
jdkBuildVersion=17
jdkTestVersion=${{ matrix.java_version }}
jdkTestVendor=${{ matrix.java_vendor }}
# 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: env:
_JAVA_OPTIONS: ${{ matrix.extraJvmArgs }} _JAVA_OPTIONS: ${{ matrix.extraJvmArgs }}
GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GE_ACCESS_TOKEN }} GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GE_ACCESS_TOKEN }}

View File

@ -8,16 +8,18 @@ const matrix = new MatrixBuilder();
matrix.addAxis({ matrix.addAxis({
name: 'java_distribution', name: 'java_distribution',
values: [ values: [
{value: 'corretto', weight: 1}, {value: 'corretto', vendor: 'amazon', weight: 1},
{value: 'liberica', weight: 1}, {value: 'liberica', vendor: 'bellsoft', weight: 1},
{value: 'microsoft', weight: 1}, {value: 'microsoft', vendor: 'microsoft', weight: 1},
{value: 'oracle', weight: 1}, {value: 'oracle', vendor: 'oracle', weight: 1},
{value: 'semeru', weight: 4}, {value: 'semeru', vendor: 'ibm', weight: 4},
{value: 'temurin', weight: 1}, {value: 'temurin', vendor: 'eclipse', weight: 1},
{value: 'zulu', weight: 1}, {value: 'zulu', vendor: 'azul', weight: 1},
] ]
}); });
const eaJava = '21';
matrix.addAxis({ matrix.addAxis({
name: 'java_version', name: 'java_version',
// Strings allow versions like 18-ea // Strings allow versions like 18-ea
@ -25,6 +27,7 @@ matrix.addAxis({
'8', '8',
'11', '11',
'17', '17',
eaJava,
] ]
}); });
@ -74,10 +77,13 @@ matrix.setNamePattern(['java_version', 'java_distribution', 'hash', 'os', 'tz',
// Semeru uses OpenJ9 jit which has no option for making hash codes the same // Semeru uses OpenJ9 jit which has no option for making hash codes the same
matrix.exclude({java_distribution: {value: 'semeru'}, hash: {value: 'same'}}); matrix.exclude({java_distribution: {value: 'semeru'}, hash: {value: 'same'}});
// Semeru 8 fails when Semeru 17 is on the PATH (we use 17 for build)
matrix.exclude({java_distribution: {value: 'semeru'}, java_version: '8'});
// Microsoft Java has no distribution for 8 // Microsoft Java has no distribution for 8
matrix.exclude({java_distribution: {value: 'microsoft'}, java_version: '8'}); matrix.exclude({java_distribution: {value: 'microsoft'}, java_version: '8'});
// Oracle JDK is only supported for JDK 17 and later // Oracle JDK is only supported for JDK 17 and later
matrix.exclude({java_distribution: {value: 'oracle'}, java_version: ['8', '11']}); 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 // Ensure at least one job with "same" hashcode exists
matrix.generateRow({hash: {value: 'same'}}); 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) // Ensure at least one Windows and at least one Linux job is present (macOS is almost the same as Linux)
@ -90,6 +96,8 @@ matrix.generateRow({java_version: "8"});
matrix.generateRow({java_version: "11"}); matrix.generateRow({java_version: "11"});
// Ensure there will be at least one job with Java 17 // Ensure there will be at least one job with Java 17
matrix.generateRow({java_version: "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); const include = matrix.generateRows(process.env.MATRIX_JOBS || 5);
if (include.length === 0) { if (include.length === 0) {
throw new Error('Matrix list is empty'); throw new Error('Matrix list is empty');
@ -124,9 +132,14 @@ include.forEach(v => {
jvmArgs.push(`-Duser.country=${v.locale.country}`); jvmArgs.push(`-Duser.country=${v.locale.country}`);
jvmArgs.push(`-Duser.language=${v.locale.language}`); jvmArgs.push(`-Duser.language=${v.locale.language}`);
v.java_distribution = v.java_distribution.value; v.java_distribution = v.java_distribution.value;
v.java_vendor = v.java_distribution.vendor;
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) { if (v.java_distribution !== 'semeru' && Math.random() > 0.5) {
// The following options randomize instruction selection in JIT compiler // 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.name += ', stress JIT';
v.testDisableCaching = 'JIT randomization should not be cached'; v.testDisableCaching = 'JIT randomization should not be cached';
jvmArgs.push('-XX:+UnlockDiagnosticVMOptions'); jvmArgs.push('-XX:+UnlockDiagnosticVMOptions');

View File

@ -18,7 +18,7 @@ class Axis {
} }
if (Array.isArray(filter)) { if (Array.isArray(filter)) {
// e.g. row={os: 'windows'}; filter=[{os: 'linux'}, {os: 'linux'}] // 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') { if (typeof filter === 'object') {
// e.g. row={jdk: {name: 'openjdk', version: 8}}; filter={jdk: {version: 8}} // e.g. row={jdk: {name: 'openjdk', version: 8}}; filter={jdk: {version: 8}}
@ -68,6 +68,7 @@ class MatrixBuilder {
this.duplicates = {}; this.duplicates = {};
this.excludes = []; this.excludes = [];
this.includes = []; this.includes = [];
this.implications = [];
this.failOnUnsatisfiableFilters = false; this.failOnUnsatisfiableFilters = false;
} }
@ -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 * @param filter
*/ */
exclude(filter) { exclude(filter) {
this.excludes.push(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}) { addAxis({name, title, values}) {
const axis = new Axis({name, title, values}); const axis = new Axis({name, title, values});
this.axes.push(axis); this.axes.push(axis);
@ -104,8 +115,10 @@ class MatrixBuilder {
* @returns {boolean} * @returns {boolean}
*/ */
matches(row) { matches(row) {
return (this.excludes.length === 0 || !this.excludes.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.find(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) { failOnUnsatisfiableFilters(value) {
@ -125,7 +138,7 @@ class MatrixBuilder {
let res; let res;
if (filter) { if (filter) {
// If matching row already exists, no need to generate more // 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) { if (res) {
return res; return res;
} }

View File

@ -175,7 +175,12 @@ systemProp.https.proxyPassword=your_password
### Test builds ### Test builds
JMeter is built using Gradle. JMeter is built using Gradle, and it uses [Gradle's Toolchains for JVM projects](https://docs.gradle.org/current/userguide/toolchains.html)
for provisioning JDKs. It means the code would search for the needed JDKs locally, or download them
if they are not found.
By default, the code would use JDK 17 for build purposes, however it would set the target release to 8,
so the resulting artifacts would be compatible with Java 8.
The following command builds and tests JMeter: The following command builds and tests JMeter:
@ -183,6 +188,15 @@ The following command builds and tests JMeter:
./gradlew build ./gradlew build
``` ```
If you want to use a custom JDK for building you can set `-PjdkBuildVersion=11`,
and you can select `-PjdkTestVersion=21` if you want to use a different JDK for testing.
You can list the available build parameters by executing
```sh
./gradlew parameters
```
If the system does not have a GUI display then: If the system does not have a GUI display then:
```sh ```sh
@ -196,7 +210,7 @@ The following command would compile the application and enable you to run `jmete
from the `bin` directory. from the `bin` directory.
> **Note** that it completely refreshes `lib/` contents, > **Note** that it completely refreshes `lib/` contents,
so it would remove custom plugins should you have them installed. so it would remove custom plugins should you have them installed to `lib/`. However, it would keep `lib/ext/` plugins intact.
```sh ```sh
./gradlew createDist ./gradlew createDist

View File

@ -18,3 +18,7 @@
plugins { plugins {
id("build-logic.kotlin-dsl-gradle-plugin") id("build-logic.kotlin-dsl-gradle-plugin")
} }
dependencies {
api(projects.buildParameters)
}

View File

@ -0,0 +1,37 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to you 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
*
* http://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.
*/
import buildparameters.BuildParametersExtension
import org.gradle.api.JavaVersion
class ToolchainProperties(
val version: Int,
val vendor: String?,
val implementation: String?,
)
val BuildParametersExtension.buildJdk: ToolchainProperties?
get() = jdkBuildVersion.takeIf { it != 0 }
?.let { ToolchainProperties(it, jdkBuildVendor.orNull, jdkBuildImplementation.orNull) }
val BuildParametersExtension.buildJdkVersion: Int
get() = buildJdk?.version ?: JavaVersion.current().majorVersion.toInt()
val BuildParametersExtension.testJdk: ToolchainProperties?
get() = jdkTestVersion.orNull?.takeIf { it != 0 }
?.let { ToolchainProperties(it, jdkTestVendor.orNull, jdkTestImplementation.orNull) }
?: buildJdk

View File

@ -0,0 +1,41 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to you 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
*
* http://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.
*/
import org.gradle.api.provider.Provider
import org.gradle.jvm.toolchain.JavaLanguageVersion
import org.gradle.jvm.toolchain.JavaLauncher
import org.gradle.jvm.toolchain.JavaToolchainService
import org.gradle.jvm.toolchain.JavaToolchainSpec
import org.gradle.jvm.toolchain.JvmImplementation
import org.gradle.jvm.toolchain.JvmVendorSpec
fun JavaToolchainService.launcherFor(jdk: ToolchainProperties): Provider<JavaLauncher> = launcherFor {
configureToolchain(jdk)
}
fun JavaToolchainSpec.configureToolchain(jdk: ToolchainProperties?) {
if (jdk == null) {
return
}
languageVersion.set(JavaLanguageVersion.of(jdk.version))
jdk.vendor?.let {
vendor.set(JvmVendorSpec.matching(it))
}
if (jdk.implementation.equals("J9", ignoreCase = true)) {
implementation.set(JvmImplementation.J9)
}
}

View File

@ -29,10 +29,39 @@ buildParameters {
defaultValue.set(true) defaultValue.set(true)
description.set("Add mavenLocal() to repositories") description.set("Add mavenLocal() to repositories")
} }
bool("enableJavaFx") {
defaultValue.set(false)
description.set("Build and include classes that depend on JavaFX. Disabled by default since JavaFX is not included in the default Java distributions")
}
bool("coverage") { bool("coverage") {
defaultValue.set(false) defaultValue.set(false)
description.set("Collect test coverage") description.set("Collect test coverage")
} }
integer("targetJavaVersion") {
defaultValue.set(8)
mandatory.set(true)
description.set("Java version for source and target compatibility")
}
integer("jdkBuildVersion") {
defaultValue.set(17)
mandatory.set(true)
description.set("JDK version to use for building JMeter. If the value is 0, then the current Java is used. (see https://docs.gradle.org/8.0/userguide/toolchains.html#sec:consuming)")
}
string("jdkBuildVendor") {
description.set("JDK vendor to use building JMeter (see https://docs.gradle.org/8.0/userguide/toolchains.html#sec:vendors)")
}
string("jdkBuildImplementation") {
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)")
}
integer("jdkTestVersion") {
description.set("JDK version to use for testing JMeter. If the value is 0, then the current Java is used. (see https://docs.gradle.org/8.0/userguide/toolchains.html#sec:consuming)")
}
string("jdkTestVendor") {
description.set("JDK vendor to use testing JMeter (see https://docs.gradle.org/8.0/userguide/toolchains.html#sec:vendors)")
}
string("jdkTestImplementation") {
description.set("Vendor-specific virtual machine implementation to use testing JMeter (see https://docs.gradle.org/8.0/userguide/toolchains.html#selecting_toolchains_by_virtual_machine_implementation)")
}
bool("spotbugs") { bool("spotbugs") {
defaultValue.set(false) defaultValue.set(false)
description.set("Run SpotBugs verifications") description.set("Run SpotBugs verifications")

View File

@ -15,8 +15,20 @@
* limitations under the License. * limitations under the License.
*/ */
import com.github.vlsi.gradle.dsl.configureEach
plugins { plugins {
id("java") id("java")
id("groovy") id("groovy")
id("build-logic.test-spock") id("build-logic.test-spock")
id("com.github.vlsi.gradle-extensions")
id("build-logic.build-params")
}
tasks.configureEach<GroovyCompile> {
buildParameters.testJdk?.let {
javaLauncher.convention(javaToolchains.launcherFor(it))
}
// Support jdk-release to configure the target Java release when compiling the bytecode
// See https://issues.apache.org/jira/browse/GROOVY-11105
} }

View File

@ -33,8 +33,9 @@ plugins {
} }
java { java {
sourceCompatibility = JavaVersion.VERSION_1_8 toolchain {
targetCompatibility = JavaVersion.VERSION_1_8 configureToolchain(buildParameters.buildJdk)
}
consistentResolution { consistentResolution {
useCompileClasspathVersions() useCompileClasspathVersions()
} }
@ -44,11 +45,25 @@ tasks.configureEach<JavaCompile> {
// Use --release=8 for Java 10+ so the generated bytecode does not include methods introduced in Java 9+ // Use --release=8 for Java 10+ so the generated bytecode does not include methods introduced in Java 9+
options.release.set( options.release.set(
provider { provider {
8.takeIf { javaCompiler.get().metadata.languageVersion.asInt() > 9 } buildParameters.targetJavaVersion.takeIf {
javaCompiler.get().metadata.languageVersion.asInt() > 9
}
} }
) )
} }
tasks.configureEach<JavaExec> {
buildParameters.testJdk?.let {
javaLauncher.convention(javaToolchains.launcherFor(it))
}
}
tasks.configureEach<Checkstyle> {
buildParameters.buildJdk?.let {
javaLauncher.convention(javaToolchains.launcherFor(it))
}
}
dependencies { dependencies {
findProject(":src:bom")?.let { findProject(":src:bom")?.let {
api(platform(it)) api(platform(it))
@ -116,7 +131,7 @@ tasks.configureEach<Javadoc> {
val lastEditYear: String by rootProject.extra val lastEditYear: String by rootProject.extra
bottom = bottom =
"Copyright &copy; 1998-$lastEditYear Apache Software Foundation. All Rights Reserved." "Copyright &copy; 1998-$lastEditYear Apache Software Foundation. All Rights Reserved."
if (JavaVersion.current() >= JavaVersion.VERSION_1_9) { if (buildParameters.buildJdkVersion > 8) {
addBooleanOption("html5", true) addBooleanOption("html5", true)
links("https://docs.oracle.com/en/java/javase/11/docs/api/") links("https://docs.oracle.com/en/java/javase/11/docs/api/")
} else { } else {

View File

@ -21,6 +21,7 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins { plugins {
id("java-library") id("java-library")
id("build-logic.build-params")
id("build-logic.java") id("build-logic.java")
id("build-logic.test-base") id("build-logic.test-base")
id("com.github.autostyle") id("com.github.autostyle")
@ -36,6 +37,9 @@ kotlin {
if (props.bool("kotlin.explicitApi", default = true)) { if (props.bool("kotlin.explicitApi", default = true)) {
explicitApi() explicitApi()
} }
jvmToolchain {
configureToolchain(buildParameters.buildJdk)
}
} }
tasks.configureEach<KotlinCompile> { tasks.configureEach<KotlinCompile> {
@ -44,7 +48,19 @@ tasks.configureEach<KotlinCompile> {
apiVersion = "kotlin.api".v apiVersion = "kotlin.api".v
} }
freeCompilerArgs += "-Xjvm-default=all" freeCompilerArgs += "-Xjvm-default=all"
jvmTarget = java.targetCompatibility.toString() val jdkRelease = buildParameters.targetJavaVersion.let {
when {
it < 9 -> "1.8"
else -> it.toString()
}
}
// jdk-release requires Java 9+
buildParameters.buildJdkVersion
.takeIf { it > 8 }
?.let {
freeCompilerArgs += "-Xjdk-release=$jdkRelease"
}
kotlinOptions.jvmTarget = jdkRelease
} }
} }

View File

@ -17,13 +17,12 @@
import com.github.vlsi.gradle.dsl.configureEach import com.github.vlsi.gradle.dsl.configureEach
import com.github.vlsi.gradle.properties.dsl.props import com.github.vlsi.gradle.properties.dsl.props
import org.gradle.api.JavaVersion
import org.gradle.api.tasks.testing.Test import org.gradle.api.tasks.testing.Test
import org.gradle.api.tasks.testing.logging.TestExceptionFormat import org.gradle.api.tasks.testing.logging.TestExceptionFormat
import org.gradle.kotlin.dsl.project
plugins { plugins {
id("java-library") id("java-library")
id("build-logic.build-params")
} }
dependencies { dependencies {
@ -37,6 +36,9 @@ tasks.configureEach<Test> {
exceptionFormat = TestExceptionFormat.FULL exceptionFormat = TestExceptionFormat.FULL
showStandardStreams = true showStandardStreams = true
} }
buildParameters.testJdk?.let {
javaLauncher.convention(javaToolchains.launcherFor(it))
}
// Pass the property to tests // Pass the property to tests
fun passProperty(name: String, default: String? = null) { fun passProperty(name: String, default: String? = null) {
val value = System.getProperty(name) ?: default val value = System.getProperty(name) ?: default
@ -57,9 +59,22 @@ tasks.configureEach<Test> {
} }
passProperty("java.awt.headless") passProperty("java.awt.headless")
passProperty("skip.test_TestDNSCacheManager.testWithCustomResolverAnd1Server") passProperty("skip.test_TestDNSCacheManager.testWithCustomResolverAnd1Server")
// Spock tests use cglib proxies that access ClassLoader.defineClass reflectively // Enable testing ByteBuddy with EA Java versions
passProperty("net.bytebuddy.experimental", "true")
// Spock tests use cglib proxies that access ClassLoader.defineClass reflectively,
// So we pass --add-opens
// See https://github.com/apache/jmeter/pull/5763 // See https://github.com/apache/jmeter/pull/5763
if (JavaVersion.current().isJava9Compatible) { jvmArgumentProviders += AddOpensArgumentsProvider(javaLauncher.map { it.metadata.languageVersion })
jvmArgs("--add-opens=java.base/java.lang=ALL-UNNAMED") }
}
class AddOpensArgumentsProvider(
@Input val javaLanguageVersion: Provider<JavaLanguageVersion>
): CommandLineArgumentProvider {
override fun asArguments(): Iterable<String> =
if (javaLanguageVersion.get().asInt() <= 8) {
// Jave 1.8 does not need add-opens, so we omit it
listOf()
} else {
listOf("--add-opens=java.base/java.lang=ALL-UNNAMED")
}
} }

View File

@ -66,3 +66,9 @@ if (buildParameters.coverage) {
} }
} }
} }
tasks.register("parameters") {
group = HelpTasksPlugin.HELP_GROUP
description = "Displays the supported build parameters."
dependsOn(gradle.includedBuild("build-logic").task(":build-parameters:parameters"))
}

View File

@ -15,10 +15,10 @@
* limitations under the License. * limitations under the License.
*/ */
import org.gradle.api.JavaVersion
import org.gradle.kotlin.dsl.dependencies import org.gradle.kotlin.dsl.dependencies
plugins { plugins {
id("build-logic.build-params")
id("org.checkerframework") id("org.checkerframework")
} }
@ -28,14 +28,14 @@ dependencies {
?.let { ?.let {
val checkerframeworkVersion = it.get() val checkerframeworkVersion = it.get()
"checkerFramework"("org.checkerframework:checker:$checkerframeworkVersion") "checkerFramework"("org.checkerframework:checker:$checkerframeworkVersion")
if (JavaVersion.current() == JavaVersion.VERSION_1_8) { if (buildParameters.buildJdkVersion == 8) {
// only needed for JDK 8 // only needed for JDK 8
"checkerFrameworkAnnotatedJDK"("org.checkerframework:jdk8:$checkerframeworkVersion") "checkerFrameworkAnnotatedJDK"("org.checkerframework:jdk8:$checkerframeworkVersion")
} }
} ?: run { } ?: run {
val checkerframeworkVersion = "3.34.0" val checkerframeworkVersion = "3.34.0"
"checkerFramework"("org.checkerframework:checker:$checkerframeworkVersion") "checkerFramework"("org.checkerframework:checker:$checkerframeworkVersion")
if (JavaVersion.current() == JavaVersion.VERSION_1_8) { if (buildParameters.buildJdkVersion == 8) {
// only needed for JDK 8 // only needed for JDK 8
"checkerFrameworkAnnotatedJDK"("org.checkerframework:jdk8:$checkerframeworkVersion") "checkerFrameworkAnnotatedJDK"("org.checkerframework:jdk8:$checkerframeworkVersion")
} }

View File

@ -28,7 +28,7 @@ if (!buildParameters.skipAutostyle) {
val skipCheckstyle = buildParameters.skipCheckstyle || run { val skipCheckstyle = buildParameters.skipCheckstyle || run {
logger.info("Checkstyle requires Java 11+") logger.info("Checkstyle requires Java 11+")
!JavaVersion.current().isJava11Compatible buildParameters.buildJdkVersion < 11
} }
if (!skipCheckstyle) { if (!skipCheckstyle) {

View File

@ -24,7 +24,7 @@ Useful commands (`gw` comes from https://github.com/dougborg/gdub, otherwise `./
## List available build parameters ## List available build parameters
# List all build parameters # List all build parameters
gw :build-logic:build-parameters:parameters gw parameters
## Cleaning build directories ## Cleaning build directories

View File

@ -27,6 +27,7 @@ pluginManagement {
plugins { plugins {
id("com.gradle.enterprise") version "3.13.2" id("com.gradle.enterprise") version "3.13.2"
id("com.gradle.common-custom-user-data-gradle-plugin") version "1.10" id("com.gradle.common-custom-user-data-gradle-plugin") version "1.10"
id("org.gradle.toolchains.foojay-resolver-convention") version "0.5.0"
} }
dependencyResolutionManagement { dependencyResolutionManagement {
@ -164,6 +165,10 @@ val expectedSha512 = mapOf(
to "okhttp-4.1.0.jar", to "okhttp-4.1.0.jar",
"93E7A41BE44CC17FB500EA5CD84D515204C180AEC934491D11FC6A71DAEA761FB0EECEF865D6FD5C3D88AAF55DCE3C2C424BE5BA5D43BEBF48D05F1FA63FA8A7" "93E7A41BE44CC17FB500EA5CD84D515204C180AEC934491D11FC6A71DAEA761FB0EECEF865D6FD5C3D88AAF55DCE3C2C424BE5BA5D43BEBF48D05F1FA63FA8A7"
to "okio-2.2.2.jar", 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() settings.extra["com.github.vlsi.checksum-dependency.sha512"].toString()
to "checksum-dependency-plugin.jar" to "checksum-dependency-plugin.jar"
) )

View File

@ -39,6 +39,7 @@ dependencies {
// to make runtime classpath consistent with the compile one. // to make runtime classpath consistent with the compile one.
api("com.github.tomakehurst:wiremock-jre8:2.35.0") api("com.github.tomakehurst:wiremock-jre8:2.35.0")
api("junit:junit:4.13.2") api("junit:junit:4.13.2")
api("net.bytebuddy:byte-buddy:1.14.5")
api("nl.jqno.equalsverifier:equalsverifier:3.14.1") api("nl.jqno.equalsverifier:equalsverifier:3.14.1")
// activemq-all should not be used as it provides secondary slf4j binding // activemq-all should not be used as it provides secondary slf4j binding
api("org.apache.activemq:activemq-broker:5.16.6") api("org.apache.activemq:activemq-broker:5.16.6")

View File

@ -16,6 +16,7 @@
*/ */
plugins { plugins {
id("build-logic.build-params")
id("build-logic.jvm-published-library") id("build-logic.jvm-published-library")
} }
@ -88,25 +89,7 @@ dependencies {
testImplementation(testFixtures(projects.src.testkitWiremock)) testImplementation(testFixtures(projects.src.testkitWiremock))
} }
fun String?.toBool(nullAs: Boolean, blankAs: Boolean, default: Boolean) = if (!buildParameters.enableJavaFx) {
when {
this == null -> nullAs
isBlank() -> blankAs
default -> !equals("false", ignoreCase = true)
else -> equals("true", ignoreCase = true)
}
fun classExists(name: String) =
try {
Class.forName(name)
true
} catch (e: Throwable) {
false
}
if (!(project.findProperty("enableJavaFx") as? String)
.toBool(nullAs = classExists("javafx.application.Platform"), blankAs = true, default = false)
) {
// JavaFX is not present in Maven Central, so exclude the file unless explicitly asked by // JavaFX is not present in Maven Central, so exclude the file unless explicitly asked by
// -PenableJavaFx // -PenableJavaFx
logger.lifecycle("RenderInBrowser is excluded from compilation. If you want to compile it, add -PenableJavaFx") logger.lifecycle("RenderInBrowser is excluded from compilation. If you want to compile it, add -PenableJavaFx")

View File

@ -632,6 +632,9 @@ val runGui by tasks.registering(JavaExec::class) {
group = "Development" group = "Development"
description = "Builds and starts JMeter GUI" description = "Builds and starts JMeter GUI"
dependsOn(createDist) dependsOn(createDist)
buildParameters.testJdk?.let {
javaLauncher.set(javaToolchains.launcherFor(it))
}
workingDir = File(project.rootDir, "bin") workingDir = File(project.rootDir, "bin")
mainClass.set("org.apache.jmeter.NewDriver") mainClass.set("org.apache.jmeter.NewDriver")

View File

@ -102,6 +102,7 @@ Summary
<ch_section>Non-functional changes</ch_section> <ch_section>Non-functional changes</ch_section>
<ul> <ul>
<li><pr>6000</pr>Add release-drafter for populating GitHub releases info based on the merged PRs</li> <li><pr>6000</pr>Add release-drafter for populating GitHub releases info based on the merged PRs</li>
<li><pr>5989</pr>Use Gradle toolchains for JDK provisioning, enable building and testing with different JDKs, start testing with Java 21</li>
</ul> </ul>
<!-- =================== Bug fixes =================== --> <!-- =================== Bug fixes =================== -->