Skip to content

Commit

Permalink
Allow to define vendor for the Daemon JVM criteria
Browse files Browse the repository at this point in the history
Signed-off-by: Madalin Valceleanu <vmadalin@google.com>
  • Loading branch information
vmadalin committed May 1, 2024
1 parent a450cc3 commit d6d7fa6
Show file tree
Hide file tree
Showing 24 changed files with 223 additions and 72 deletions.
Expand Up @@ -371,4 +371,13 @@ public boolean isIbmJvm() {
return false;
}

@Nullable
public String getVendor() {
for (String vendorProperty : VENDOR_PROPERTIES) {
if (System.getProperties().containsKey(vendorProperty) && !System.getProperty(vendorProperty).isEmpty()) {
return System.getProperty(vendorProperty);
}
}
return null;
}
}
Expand Up @@ -21,13 +21,14 @@ import org.gradle.api.JavaVersion
import org.gradle.buildconfiguration.tasks.UpdateDaemonJvm
import org.gradle.integtests.fixtures.AbstractIntegrationSpec
import org.gradle.integtests.fixtures.AvailableJavaHomes
import org.gradle.integtests.fixtures.jvm.JavaToolchainFixture
import org.gradle.internal.buildconfiguration.DaemonJvmPropertiesDefaults
import org.gradle.internal.buildconfiguration.fixture.DaemonJvmPropertiesFixture
import org.gradle.internal.jvm.Jvm
import org.gradle.test.precondition.Requires
import org.gradle.test.preconditions.IntegTestPreconditions

class UpdateDaemonJvmIntegrationTest extends AbstractIntegrationSpec implements DaemonJvmPropertiesFixture {
class UpdateDaemonJvmIntegrationTest extends AbstractIntegrationSpec implements DaemonJvmPropertiesFixture, JavaToolchainFixture {

def "root project has an updateDaemonJvm task only"() {
buildFile << """
Expand Down Expand Up @@ -104,10 +105,9 @@ class UpdateDaemonJvmIntegrationTest extends AbstractIntegrationSpec implements
succeeds( "updateDaemonJvm", "--jvm-version=10000")
}

@NotYetImplemented
def "When execute updateDaemonJvm for valid vendor option Then build properties are populated with expected values"() {
when:
run "updateDaemonJvm", "--toolchain-vendor=$vendor"
run "updateDaemonJvm", "--jvm-vendor=$vendor"

then:
assertJvmCriteria(DaemonJvmPropertiesDefaults.TOOLCHAIN_VERSION, vendor)
Expand All @@ -128,33 +128,29 @@ class UpdateDaemonJvmIntegrationTest extends AbstractIntegrationSpec implements
implementation << ["VENDOR_SPECIFIC", "J9"]
}

@NotYetImplemented
def "When execute updateDaemonJvm specifying different options Then build properties are populated with expected values"() {
when:
run "updateDaemonJvm", "--jvm-version=17", "--toolchain-vendor=IBM", "--toolchain-implementation=J9"
run "updateDaemonJvm", "--jvm-version=17", "--jvm-vendor=IBM"

then:
assertJvmCriteria(JavaVersion.VERSION_17, "IBM", "J9")
assertJvmCriteria(JavaVersion.VERSION_17, "IBM")
}

@NotYetImplemented
def "When execute updateDaemonJvm specifying different options in lower case Then build properties are populated with expected values"() {
when:
run "updateDaemonJvm", "--jvm-version=17", "--toolchain-vendor=ibm", "--toolchain-implementation=j9"
run "updateDaemonJvm", "--jvm-version=17", "--jvm-vendor=ibm"

then:
assertJvmCriteria(JavaVersion.VERSION_17, "IBM", "J9")
assertJvmCriteria(JavaVersion.VERSION_17, "IBM")
}

@NotYetImplemented
def "When execute updateDaemonJvm with unexpected --toolchain-vendor option Then fails with expected exception message"() {
def "When execute updateDaemonJvm with unexpected --jvm-vendor option Then fails with expected exception message"() {
when:
fails "updateDaemonJvm", "--toolchain-vendor=unknown-vendor"
fails "updateDaemonJvm", "--jvm-vendor=unknown-vendor"

then:
failureDescriptionContains("Problem configuring option 'toolchain-vendor' on task ':updateDaemonJvm' from command line.")
failureHasCause("Cannot convert string value 'unknown-vendor' to an enum value of type 'org.gradle.internal.jvm.inspection.JvmVendor\$KnownJvmVendor' " +
"(valid case insensitive values: ADOPTIUM, ADOPTOPENJDK, AMAZON, APPLE, AZUL, BELLSOFT, GRAAL_VM, HEWLETT_PACKARD, IBM, JETBRAINS, MICROSOFT, ORACLE, SAP, TENCENT, UNKNOWN)")
failureDescriptionContains("Value 'unknown-vendor' given for toolchainVendor is an invalid Java vendor. " +
"Possible values are [ADOPTIUM, ADOPTOPENJDK, AMAZON, APPLE, AZUL, BELLSOFT, GRAAL_VM, HEWLETT_PACKARD, IBM, JETBRAINS, MICROSOFT, ORACLE, SAP, TENCENT, UNKNOWN]")
}

@NotYetImplemented
Expand All @@ -180,29 +176,31 @@ class UpdateDaemonJvmIntegrationTest extends AbstractIntegrationSpec implements
assertJvmCriteria(otherJvm.javaVersion)
}

@NotYetImplemented
def "Given defined invalid criteria When execute updateDaemonJvm with different criteria Then criteria get modified using java home"() {
def currentJvm = JavaVersion.current()

given:
writeJvmCriteria(currentJvm, "invalidVendor")
captureJavaHome()

expect:
succeeds("updateDaemonJvm", "--jvm-version=20", "--toolchain-vendor=AZUL")
succeeds("updateDaemonJvm", "--jvm-version=20", "--jvm-vendor=AZUL")
assertJvmCriteria(JavaVersion.VERSION_20, "AZUL")
assertDaemonUsedJvm(Jvm.current())
}

@NotYetImplemented
@Requires(IntegTestPreconditions.JavaHomeWithDifferentVersionAvailable)
def "Given defined valid criteria matching with local toolchain When execute updateDaemonJvm with different criteria Then criteria get modified using the expected local toolchain"() {
def otherJvm = AvailableJavaHomes.differentVersion
def otherMetadata = AvailableJavaHomes.getJvmInstallationMetadata(otherJvm)

given:
writeJvmCriteria(otherJvm.javaVersion, otherMetadata.vendor.knownVendor.name())
captureJavaHome()

expect:
succeeds("updateDaemonJvm", "--jvm-version=20", "--toolchain-vendor=AZUL")
withInstallations(otherJvm).succeeds("updateDaemonJvm", "--jvm-version=20", "--jvm-vendor=AZUL")
assertJvmCriteria(JavaVersion.VERSION_20, "AZUL")
assertDaemonUsedJvm(otherJvm)
}
}
Expand Up @@ -28,10 +28,15 @@
import org.gradle.api.tasks.options.Option;
import org.gradle.internal.buildconfiguration.DaemonJvmPropertiesDefaults;
import org.gradle.internal.buildconfiguration.tasks.UpdateDaemonJvmModifier;
import org.gradle.internal.jvm.inspection.JvmVendor;
import org.gradle.jvm.toolchain.JvmVendorSpec;
import org.gradle.jvm.toolchain.internal.DefaultJvmVendorSpec;
import org.gradle.util.internal.GUtil;
import org.gradle.util.internal.IncubationLogger;
import org.gradle.work.DisableCachingByDefault;

import javax.inject.Inject;
import java.util.Arrays;

/**
* Generates or updates the Gradle Daemon JVM criteria.
Expand All @@ -43,6 +48,9 @@
@DisableCachingByDefault(because = "Not worth caching")
@Incubating
public abstract class UpdateDaemonJvm extends DefaultTask {

private final Property<JvmVendorSpec> jvmVendorSpec = getProject().getObjects().property(JvmVendorSpec.class);

/**
* Constructor.
*
Expand All @@ -56,10 +64,15 @@ public UpdateDaemonJvm() {
@TaskAction
void generate() {
IncubationLogger.incubatingFeatureUsed("Daemon JVM criteria");

JvmVendor jvmVendor = null;
if (jvmVendorSpec.isPresent()) {
jvmVendor = JvmVendor.KnownJvmVendor.valueOf(jvmVendorSpec.get().toString()).asJvmVendor();
}
UpdateDaemonJvmModifier.updateJvmCriteria(
getPropertiesFile().get().getAsFile(),
getJvmVersion().get(),
null,
jvmVendor,
null
);
}
Expand All @@ -85,4 +98,32 @@ void generate() {
@Option(option = "jvm-version", description = "The version of the JVM required to run the Gradle Daemon.")
@Incubating
public abstract Property<JavaVersion> getJvmVersion();

/**
* The vendor of Java required to run the Gradle Daemon.
*
* @since 8.9
*/
@Input
@Optional
@Incubating
public Property<JvmVendorSpec> getJvmVendor() {
return jvmVendorSpec;
}

/**
* The vendor of Java required to run the Gradle Daemon.
*
* @since 8.9
*/
@Option(option = "jvm-vendor", description = "The vendor of Java required to run the Gradle Daemon.")
@Incubating
public void setJvmVendor(String vendor) {
try {
JvmVendor.KnownJvmVendor jvmVendor = GUtil.toEnum(JvmVendor.KnownJvmVendor.class, vendor);
jvmVendorSpec.set(DefaultJvmVendorSpec.of(jvmVendor));
} catch (Exception e) {
throw new IllegalArgumentException(String.format("Value '%s' given for %s is an invalid Java vendor. Possible values are %s", vendor, DaemonJvmPropertiesDefaults.TOOLCHAIN_VENDOR_PROPERTY, Arrays.toString(JvmVendor.KnownJvmVendor.values())));
}
}
}
Expand Up @@ -22,6 +22,7 @@ import org.gradle.integtests.fixtures.AvailableJavaHomes
import org.gradle.integtests.fixtures.jvm.JavaToolchainFixture
import org.gradle.internal.buildconfiguration.fixture.DaemonJvmPropertiesFixture
import org.gradle.internal.jvm.Jvm
import org.gradle.internal.os.OperatingSystem
import org.gradle.test.precondition.Requires
import org.gradle.test.preconditions.IntegTestPreconditions
import org.junit.Assume
Expand All @@ -47,15 +48,29 @@ class DaemonToolchainIntegrationTest extends AbstractIntegrationSpec implements
def "Given other daemon toolchain version When executing any task Then daemon jvm was set up with expected configuration"() {
given:
def otherJvm = AvailableJavaHomes.differentVersion
writeJvmCriteria(otherJvm)
writeJvmCriteria(otherJvm.javaVersion)
captureJavaHome()

expect:
withInstallations(otherJvm).succeeds("help")
assertDaemonUsedJvm(otherJvm)
}

def "Given daemon toolchain criteria that doesn't match installed ones When executing any task Then fails with the expected message"() {
@Requires(IntegTestPreconditions.JavaHomeWithDifferentVersionAvailable)
def "Given other daemon toolchain version and vendor When executing any task Then daemon jvm was set up with expected configuration"() {
given:
def otherJvm = AvailableJavaHomes.differentVersion
def otherMetadata = AvailableJavaHomes.getJvmInstallationMetadata(otherJvm)

writeJvmCriteria(otherJvm.javaVersion, otherMetadata.vendor.knownVendor.name())
captureJavaHome()

expect:
withInstallations(otherJvm).succeeds("help")
assertDaemonUsedJvm(otherJvm)
}

def "Given daemon toolchain criteria with version that doesn't match installed ones When executing any task Then fails with the expected message"() {
given:
// Java 10 is not available
def java10 = AvailableJavaHomes.getAvailableJdks(JavaVersion.VERSION_1_10)
Expand All @@ -65,6 +80,19 @@ class DaemonToolchainIntegrationTest extends AbstractIntegrationSpec implements

expect:
fails("help")
failure.assertHasDescription("Cannot find a Java installation on your machine")
failure.assertHasDescription("Cannot find a Java installation on your machine (${OperatingSystem.current()}) matching the Daemon JVM defined requirements: JVM version '10' vendor 'any'")
}

def "Given daemon toolchain criteria with version and vendor that doesn't match installed ones When executing any task Then fails with the expected message"() {
given:
// Java 10 is not available
def java10 = AvailableJavaHomes.getAvailableJdks(JavaVersion.VERSION_1_10)
Assume.assumeTrue(java10.isEmpty())
writeJvmCriteria(JavaVersion.VERSION_1_10, "ibm")
captureJavaHome()

expect:
fails("help")
failure.assertHasDescription("Cannot find a Java installation on your machine (${OperatingSystem.current()}) matching the Daemon JVM defined requirements: JVM version '10' vendor 'IBM'")
}
}
Expand Up @@ -53,7 +53,6 @@ class DaemonToolchainInvalidCriteriaIntegrationTest extends AbstractIntegrationS
failure.assertHasDescription("Value '-1' given for toolchainVersion is an invalid Java version")
}

@NotYetImplemented
def "Given unexpected toolchain vendor When execute any task Then fails with expected exception message"() {
given:
writeJvmCriteria(JavaVersion.VERSION_17, "unexpectedVendor")
Expand All @@ -62,7 +61,7 @@ class DaemonToolchainInvalidCriteriaIntegrationTest extends AbstractIntegrationS
fails 'help'

then:
failureDescriptionContains("Option toolchainVendor doesn't accept value 'unexpectedVendor'. Possible values are " +
failureDescriptionContains("Value 'unexpectedVendor' given for toolchainVendor is an invalid Java vendor. Possible values are " +
"[ADOPTIUM, ADOPTOPENJDK, AMAZON, APPLE, AZUL, BELLSOFT, GRAAL_VM, HEWLETT_PACKARD, IBM, JETBRAINS, MICROSOFT, ORACLE, SAP, TENCENT, UNKNOWN]")
}

Expand Down
Expand Up @@ -36,6 +36,7 @@
import org.gradle.internal.concurrent.CompositeStoppable;
import org.gradle.internal.concurrent.Stoppable;
import org.gradle.internal.jvm.Jvm;
import org.gradle.internal.jvm.inspection.JvmVendor;
import org.gradle.internal.jvm.inspection.JvmVersionDetector;
import org.gradle.internal.logging.console.GlobalUserInputReceiver;
import org.gradle.internal.nativeintegration.services.NativeServices;
Expand Down Expand Up @@ -193,6 +194,7 @@ static DaemonContext buildDaemonContextForCurrentProcess(DaemonRequestContext re
UUID.randomUUID().toString(),
currentProcess.getJvm().getJavaHome(),
JavaVersion.current(),
JvmVendor.KnownJvmVendor.parse(Jvm.current().getVendor()),
null, 0L, 0,
// The gradle options aren't being properly checked.
requestContext.getDaemonOpts(),
Expand Down
Expand Up @@ -16,12 +16,15 @@

package org.gradle.launcher.cli;

import org.gradle.StartParameter;
import org.gradle.TaskExecutionRequest;
import org.gradle.api.internal.StartParameterInternal;
import org.gradle.api.internal.file.FileCollectionFactory;
import org.gradle.cli.CommandLineArgumentException;
import org.gradle.cli.CommandLineParser;
import org.gradle.cli.ParsedCommandLine;
import org.gradle.initialization.layout.BuildLayoutFactory;
import org.gradle.internal.buildconfiguration.DaemonJvmPropertiesConfigurator;
import org.gradle.jvm.toolchain.internal.ToolchainConfiguration;
import org.gradle.launcher.cli.converter.BuildLayoutConverter;
import org.gradle.launcher.cli.converter.BuildOptionBackedConverter;
Expand All @@ -38,6 +41,7 @@
import javax.annotation.Nullable;
import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class BuildEnvironmentConfigurationConverter {
Expand Down Expand Up @@ -87,13 +91,21 @@ public Parameters convertParameters(ParsedCommandLine args, @Nullable File curre
DaemonParameters daemonParameters = new DaemonParameters(buildLayout, fileCollectionFactory, properties.getRequestedSystemProperties());
daemonParametersConverter.convert(args, properties.getProperties(), daemonParameters);

// This is a workaround to maintain existing behavior that allowed
// toolchain-specific properties to be specified with -P instead of -D
Map<String, String> gradlePropertiesAsSeenByToolchains = new HashMap<>();
gradlePropertiesAsSeenByToolchains.putAll(properties.getProperties());
gradlePropertiesAsSeenByToolchains.putAll(startParameter.getProjectProperties());
toolchainConfigurationBuildOptionBackedConverter.convert(args, gradlePropertiesAsSeenByToolchains, daemonParameters.getToolchainConfiguration());
daemonParameters.setRequestedJvmCriteria(properties.getDaemonJvmProperties());
try {
// This is a workaround to maintain existing behavior that allowed
// toolchain-specific properties to be specified with -P instead of -D
Map<String, String> gradlePropertiesAsSeenByToolchains = new HashMap<>();
gradlePropertiesAsSeenByToolchains.putAll(properties.getProperties());
gradlePropertiesAsSeenByToolchains.putAll(startParameter.getProjectProperties());
toolchainConfigurationBuildOptionBackedConverter.convert(args, gradlePropertiesAsSeenByToolchains, daemonParameters.getToolchainConfiguration());
daemonParameters.setRequestedJvmCriteria(properties.getDaemonJvmProperties());
} catch (Exception exception) {
// When executing updateDaemonJvm with an invalid jvm criteria the validation will be ignored
// and instead the JAVA_HOME will be used to update the daemon-jvm.properties
if (!isExecutingUpdateDaemonJvmTask(startParameter)) {
throw exception;
}
}

return new Parameters(startParameter, daemonParameters, properties);
}
Expand All @@ -104,4 +116,9 @@ public void configure(CommandLineParser parser) {
startParameterConverter.configure(parser);
daemonParametersConverter.configure(parser);
}

private boolean isExecutingUpdateDaemonJvmTask(StartParameter startParameters) {
List<TaskExecutionRequest> taskExecutionRequests = startParameters.getTaskRequests();
return taskExecutionRequests.size() == 1 && taskExecutionRequests.get(0).getArgs().contains(DaemonJvmPropertiesConfigurator.TASK_NAME);
}
}

0 comments on commit d6d7fa6

Please sign in to comment.