Skip to content

Commit

Permalink
Merge pull request #23095 Backport recent toolchain related fixes
Browse files Browse the repository at this point in the history
Fixes #23025

Co-authored-by: József Bartók <jbartok@gradle.com>
  • Loading branch information
bot-gradle and jbartok committed Dec 14, 2022
2 parents b668172 + d832983 commit ceb9f1d
Show file tree
Hide file tree
Showing 20 changed files with 607 additions and 76 deletions.
Expand Up @@ -43,6 +43,7 @@
import org.gradle.internal.Actions;
import org.gradle.internal.deprecation.DeprecationLogger;
import org.gradle.internal.management.DependencyResolutionManagementInternal;
import org.gradle.internal.management.ToolchainManagementInternal;
import org.gradle.internal.resource.TextUriResourceLoader;
import org.gradle.internal.service.ServiceRegistry;
import org.gradle.internal.service.scopes.ServiceRegistryFactory;
Expand Down Expand Up @@ -77,6 +78,8 @@ public abstract class DefaultSettings extends AbstractPluginAware implements Set
private final List<IncludedBuildSpec> includedBuildSpecs = new ArrayList<>();
private final DependencyResolutionManagementInternal dependencyResolutionManagement;

private final ToolchainManagementInternal toolchainManagement;

public DefaultSettings(
ServiceRegistryFactory serviceRegistryFactory,
GradleInternal gradle,
Expand All @@ -97,6 +100,7 @@ public DefaultSettings(
this.services = serviceRegistryFactory.createFor(this);
this.rootProjectDescriptor = createProjectDescriptor(null, settingsDir.getName(), settingsDir);
this.dependencyResolutionManagement = services.get(DependencyResolutionManagementInternal.class);
this.toolchainManagement = services.get(ToolchainManagementInternal.class);
}

@Override
Expand Down Expand Up @@ -370,13 +374,14 @@ public void enableFeaturePreview(String name) {
}

@Override
public void dependencyResolutionManagement(Action<? super DependencyResolutionManagement> dependencyResolutionConfiguration) {
dependencyResolutionConfiguration.execute(dependencyResolutionManagement);
public void preventFromFurtherMutation() {
dependencyResolutionManagement.preventFromFurtherMutation();
toolchainManagement.preventFromFurtherMutation();
}

@Override
public void preventFromFurtherMutation() {
dependencyResolutionManagement.preventFromFurtherMutation();
public void dependencyResolutionManagement(Action<? super DependencyResolutionManagement> dependencyResolutionConfiguration) {
dependencyResolutionConfiguration.execute(dependencyResolutionManagement);
}

@Override
Expand All @@ -385,13 +390,12 @@ public DependencyResolutionManagementInternal getDependencyResolutionManagement(
}

@Override
@Inject
public ToolchainManagement getToolchainManagement() {
throw new UnsupportedOperationException();
return toolchainManagement;
}

@Override
public void toolchainManagement(Action<? super ToolchainManagement> toolchainManagementConfiguration) {
toolchainManagementConfiguration.execute(getToolchainManagement());
toolchainManagementConfiguration.execute(toolchainManagement);
}
}
Expand Up @@ -16,7 +16,19 @@

package org.gradle.initialization;

import org.gradle.api.toolchain.management.ToolchainManagement;
import org.gradle.api.internal.plugins.ExtensionContainerInternal;
import org.gradle.internal.FinalizableValue;
import org.gradle.internal.management.ToolchainManagementInternal;

public abstract class DefaultToolchainManagement implements ToolchainManagementInternal {

@Override
public void preventFromFurtherMutation() {
ExtensionContainerInternal extensions = (ExtensionContainerInternal) getExtensions();
extensions.getAsMap().values().stream()
.filter(ext -> ext instanceof FinalizableValue)
.map(ext -> (FinalizableValue) ext)
.forEach(FinalizableValue::preventFromFurtherMutation);
}

public abstract class DefaultToolchainManagement implements ToolchainManagement {
}
@@ -0,0 +1,35 @@
/*
* Copyright 2022 the original author or authors.
*
* 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
*
* 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.
*/

package org.gradle.internal;

/**
* Mutable value type for which mutation can be disabled at a certain point in time,
* by calling the {@code disableFurtherMutations()} method.
* <p>
* After {@code disableFurtherMutations()} has been called, any subsequent calls to methods that mutate
* the value in any way will fail by throwing an {@code IllegalStateException}.
*/
public interface FinalizableValue {

/**
* Disallows further changes to the value represented by this type.
* <p>
* Subsequent calls to methods that mutate the value in any way will fail by throwing an {@code IllegalStateException}.
*/
void preventFromFurtherMutation();

}
Expand Up @@ -22,18 +22,17 @@
import org.gradle.api.initialization.resolve.RulesMode;
import org.gradle.api.internal.project.ProjectInternal;
import org.gradle.api.provider.Property;
import org.gradle.internal.FinalizableValue;
import org.gradle.internal.service.scopes.Scopes;
import org.gradle.internal.service.scopes.ServiceScope;

import java.util.List;

@ServiceScope(Scopes.Build.class)
public interface DependencyResolutionManagementInternal extends DependencyResolutionManagement {
public interface DependencyResolutionManagementInternal extends DependencyResolutionManagement, FinalizableValue {

void configureProject(ProjectInternal project);

void preventFromFurtherMutation();

void applyRules(ComponentMetadataHandler target);

RepositoriesModeInternal getConfiguredRepositoriesMode();
Expand Down
@@ -0,0 +1,26 @@
/*
* Copyright 2022 the original author or authors.
*
* 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
*
* 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.
*/

package org.gradle.internal.management;

import org.gradle.api.toolchain.management.ToolchainManagement;
import org.gradle.internal.FinalizableValue;
import org.gradle.internal.service.scopes.Scopes;
import org.gradle.internal.service.scopes.ServiceScope;

@ServiceScope(Scopes.Build.class)
public interface ToolchainManagementInternal extends ToolchainManagement, FinalizableValue {
}
Expand Up @@ -261,6 +261,21 @@ public Throwable getErrorCause() {
public boolean isValidInstallation() {
return true;
}

@Override
public String toString() {
return "DefaultJvmInstallationMetadata{" +
"languageVersion=" + languageVersion +
", javaVersion='" + javaVersion + '\'' +
", javaVendor='" + javaVendor + '\'' +
", runtimeName='" + runtimeName + '\'' +
", runtimeVersion='" + runtimeVersion + '\'' +
", jvmName='" + jvmName + '\'' +
", jvmVersion='" + jvmVersion + '\'' +
", jvmVendor='" + jvmVendor + '\'' +
", architecture='" + architecture + '\'' +
'}';
}
}

class FailureInstallationMetadata implements JvmInstallationMetadata {
Expand Down
Expand Up @@ -17,8 +17,6 @@
package org.gradle.jvm.toolchain.internal;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import org.gradle.api.GradleException;
import org.gradle.api.logging.Logger;
import org.gradle.api.logging.Logging;
Expand All @@ -37,12 +35,13 @@
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Collectors;


public class JavaInstallationRegistry {
private final BuildOperationExecutor executor;
private final Supplier<Set<InstallationLocation>> installations;
private final Installations installations;
private final Logger logger;
private final OperatingSystem os;

Expand All @@ -54,7 +53,7 @@ public JavaInstallationRegistry(List<InstallationSupplier> suppliers, BuildOpera
private JavaInstallationRegistry(List<InstallationSupplier> suppliers, Logger logger, BuildOperationExecutor executor, OperatingSystem os) {
this.logger = logger;
this.executor = executor;
this.installations = Suppliers.memoize(() -> collectInBuildOperation(suppliers));
this.installations = new Installations(() -> collectInBuildOperation(suppliers));
this.os = os;
}

Expand All @@ -71,6 +70,10 @@ public Set<InstallationLocation> listInstallations() {
return installations.get();
}

public void addInstallation(InstallationLocation installation) {
installations.add(installation);
}

private Set<InstallationLocation> collectInstallations(List<InstallationSupplier> suppliers) {
return suppliers.parallelStream()
.map(InstallationSupplier::get)
Expand Down Expand Up @@ -146,4 +149,32 @@ public BuildOperationDescriptor.Builder description() {
}
}

private static class Installations {

private final Supplier<Set<InstallationLocation>> initializer;

private Set<InstallationLocation> locations = null;

Installations(Supplier<Set<InstallationLocation>> initializer) {
this.initializer = initializer;
}

synchronized Set<InstallationLocation> get() {
initIfNeeded();
return locations;
}

synchronized void add(InstallationLocation location) {
initIfNeeded();
locations.add(location);
}

private void initIfNeeded() {
if (locations == null) {
locations = initializer.get();
}
}

}

}
Expand Up @@ -82,7 +82,8 @@ class JavaToolchainDownloadSpiAuthenticationIntegrationTest extends AbstractJava
.assertHasCause("Error while evaluating property 'javaCompiler' of task ':compileJava'.")
.assertHasCause("Failed to calculate the value of task ':compileJava' property 'javaCompiler'.")
.assertHasCause("Unable to download toolchain matching the requirements ({languageVersion=99, vendor=matching('exotic'), implementation=vendor-specific}) from '" + archiveUri + "'.")
.assertHasCause("Provisioned toolchain '" + temporaryFolder.testDirectory.file("user-home", "jdks", "toolchain") + "' could not be probed.")
.assertHasCause("Provisioned toolchain '" + temporaryFolder.testDirectory.file("user-home", "jdks", "toolchain") + "' could not be probed: " +
"A problem occurred starting process 'command '")
}

@ToBeFixedForConfigurationCache(because = "Fails the build with an additional error")
Expand Down Expand Up @@ -135,7 +136,8 @@ class JavaToolchainDownloadSpiAuthenticationIntegrationTest extends AbstractJava
.assertHasCause("Error while evaluating property 'javaCompiler' of task ':compileJava'")
.assertHasCause("Failed to calculate the value of task ':compileJava' property 'javaCompiler'.")
.assertHasCause("Unable to download toolchain matching the requirements ({languageVersion=99, vendor=matching('exotic'), implementation=vendor-specific}) from '" + archiveUri + "'.")
.assertHasCause("Provisioned toolchain '" + temporaryFolder.testDirectory.file("user-home", "jdks", "toolchain") + "' could not be probed.")
.assertHasCause("Provisioned toolchain '" + temporaryFolder.testDirectory.file("user-home", "jdks", "toolchain") + "' could not be probed: " +
"A problem occurred starting process 'command '")
}

private static String customToolchainResolverCode(String uri) {
Expand Down
Expand Up @@ -369,7 +369,7 @@ class JavaToolchainDownloadSpiIntegrationTest extends AbstractJavaToolchainDownl
}
}
println(\"\"\"Explicitly requested toolchains: \${toolchainManagement.jvm.getJavaRepositories().collect { it.getName() }}.\"\"\")
println(\"\"\"Explicitly requested toolchains: \${toolchainManagement.jvm.getJavaRepositories().getAsList().collect { it.getName() }}.\"\"\")
"""

buildFile << """
Expand All @@ -395,6 +395,81 @@ class JavaToolchainDownloadSpiIntegrationTest extends AbstractJavaToolchainDownl
failure.getOutput().contains("Explicitly requested toolchains: [useless3, useless1].")
}

@ToBeFixedForConfigurationCache(because = "Fails the build with an additional error")
def "created repository can be removed"() {
settingsFile << """
${applyToolchainResolverPlugin("UselessToolchainResolver1", uselessToolchainResolverCode("UselessToolchainResolver1"))}
${applyToolchainResolverPlugin("UselessToolchainResolver2", uselessToolchainResolverCode("UselessToolchainResolver2"))}
${applyToolchainResolverPlugin("UselessToolchainResolver3", uselessToolchainResolverCode("UselessToolchainResolver3"))}
toolchainManagement {
jvm {
javaRepositories {
repository('useless1') {
resolverClass = UselessToolchainResolver1
}
repository('useless2') {
resolverClass = UselessToolchainResolver2
}
repository('useless3') {
resolverClass = UselessToolchainResolver3
}
}
}
}
toolchainManagement.jvm.javaRepositories.remove('useless2')
println(\"\"\"Explicitly requested toolchains: \${toolchainManagement.jvm.getJavaRepositories().getAsList().collect { it.getName() }}.\"\"\")
"""

buildFile << """
apply plugin: "java"
java {
toolchain {
languageVersion = JavaLanguageVersion.of(99)
}
}
"""

file("src/main/java/Foo.java") << "public class Foo {}"

when:
failure = executer
.withTasks("compileJava")
.requireOwnGradleUserHomeDir()
.withToolchainDownloadEnabled()
.runWithFailure()

then:
failure.getOutput().contains("Explicitly requested toolchains: [useless1, useless3].")
}

def "cannot mutate repository rules after settings have been evaluated"() {
settingsFile << """
${applyToolchainResolverPlugin("UselessToolchainResolver", uselessToolchainResolverCode("UselessToolchainResolver"))}
toolchainManagement {
jvm {
javaRepositories {
repository('useless') {
resolverClass = UselessToolchainResolver
}
}
}
}
"""

buildFile << """
gradle.settings.toolchainManagement.jvm.javaRepositories.remove('useless')
"""

when:
fails ":help"

then:
failure.assertHasCause("Mutation of toolchain repositories declared in settings is only allowed during settings evaluation")
}

private static String customToolchainResolverCode() {
"""
import java.util.Optional;
Expand Down Expand Up @@ -455,13 +530,13 @@ class JavaToolchainDownloadSpiIntegrationTest extends AbstractJavaToolchainDownl
SystemInfo systemInfo = NativeServices.getInstance().get(SystemInfo.class)
switch (systemInfo.architecture) {
case SystemInfo.Architecture.i386:
return "x32";
return "x32"
case SystemInfo.Architecture.amd64:
return "x64";
return "x64"
case SystemInfo.Architecture.aarch64:
return "aarch64";
return "aarch64"
default:
return "unknown";
return "unknown"
}
}

Expand Down

0 comments on commit ceb9f1d

Please sign in to comment.