
org.gradle.jvm.plugins.JvmComponentPlugin Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of gradle-api Show documentation
Show all versions of gradle-api Show documentation
Gradle 6.9.1 API redistribution.
/*
* Copyright 2014 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.jvm.plugins;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Iterables;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Lists;
import org.gradle.api.Action;
import org.gradle.api.Incubating;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.Task;
import org.gradle.api.Transformer;
import org.gradle.internal.jvm.Jvm;
import org.gradle.internal.service.ServiceRegistry;
import org.gradle.jvm.JarBinarySpec;
import org.gradle.jvm.JvmBinarySpec;
import org.gradle.jvm.JvmLibrarySpec;
import org.gradle.jvm.internal.DefaultJarBinarySpec;
import org.gradle.jvm.internal.DefaultJvmBinarySpec;
import org.gradle.jvm.internal.DefaultJvmLibrarySpec;
import org.gradle.jvm.internal.JarBinarySpecInternal;
import org.gradle.jvm.internal.JarFile;
import org.gradle.jvm.internal.JavaPlatformResolver;
import org.gradle.jvm.internal.JvmAssembly;
import org.gradle.jvm.internal.JvmBinarySpecInternal;
import org.gradle.jvm.internal.JvmLibrarySpecInternal;
import org.gradle.jvm.internal.toolchain.JavaToolChainInternal;
import org.gradle.jvm.platform.JavaPlatform;
import org.gradle.jvm.platform.internal.DefaultJavaPlatform;
import org.gradle.jvm.tasks.Jar;
import org.gradle.jvm.tasks.api.ApiJar;
import org.gradle.jvm.toolchain.JavaToolChainRegistry;
import org.gradle.jvm.toolchain.LocalJava;
import org.gradle.jvm.toolchain.internal.DefaultJavaToolChainRegistry;
import org.gradle.jvm.toolchain.internal.InstalledJdk;
import org.gradle.jvm.toolchain.internal.InstalledJdkInternal;
import org.gradle.jvm.toolchain.internal.InstalledJre;
import org.gradle.jvm.toolchain.internal.JavaInstallationProbe;
import org.gradle.jvm.toolchain.internal.LocalJavaInstallation;
import org.gradle.language.base.internal.ProjectLayout;
import org.gradle.model.Defaults;
import org.gradle.model.Each;
import org.gradle.model.Model;
import org.gradle.model.ModelMap;
import org.gradle.model.Mutate;
import org.gradle.model.Path;
import org.gradle.model.RuleSource;
import org.gradle.model.internal.core.Hidden;
import org.gradle.platform.base.BinaryTasks;
import org.gradle.platform.base.ComponentBinaries;
import org.gradle.platform.base.ComponentType;
import org.gradle.platform.base.DependencySpec;
import org.gradle.platform.base.InvalidModelException;
import org.gradle.platform.base.TypeBuilder;
import org.gradle.platform.base.internal.BinaryNamingScheme;
import org.gradle.platform.base.internal.DefaultBinaryNamingScheme;
import org.gradle.platform.base.internal.DefaultPlatformRequirement;
import org.gradle.platform.base.internal.PlatformRequirement;
import org.gradle.platform.base.internal.PlatformResolvers;
import org.gradle.util.CollectionUtils;
import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import static org.apache.commons.lang.StringUtils.capitalize;
/**
* Base plugin for JVM component support. Applies the {@link org.gradle.language.base.plugins.ComponentModelBasePlugin}. Registers the {@link JvmLibrarySpec} library type for the components
* container.
*/
@Incubating
public class JvmComponentPlugin implements Plugin {
@Override
public void apply(Project project) {
}
@SuppressWarnings("UnusedDeclaration")
static class Rules extends RuleSource {
@ComponentType
public void register(TypeBuilder builder) {
builder.defaultImplementation(DefaultJvmLibrarySpec.class);
builder.internalView(JvmLibrarySpecInternal.class);
}
@ComponentType
public void registerJvmBinarySpec(TypeBuilder builder) {
builder.defaultImplementation(DefaultJvmBinarySpec.class);
builder.internalView(JvmBinarySpecInternal.class);
}
@ComponentType
public void registerJarBinarySpec(TypeBuilder builder) {
builder.defaultImplementation(DefaultJarBinarySpec.class);
builder.internalView(JarBinarySpecInternal.class);
}
@Model
@Hidden
public JavaToolChainRegistry javaToolChain(ServiceRegistry serviceRegistry) {
JavaToolChainInternal toolChain = serviceRegistry.get(JavaToolChainInternal.class);
return new DefaultJavaToolChainRegistry(toolChain);
}
@Model
public void javaInstallations(ModelMap jdks) {
}
@Model
@Hidden
public void javaToolChains(ModelMap javaInstallations, final JavaInstallationProbe probe) {
javaInstallations.create("currentGradleJDK", InstalledJdk.class, new Action() {
@Override
public void execute(InstalledJdk installedJdk) {
installedJdk.setJavaHome(Jvm.current().getJavaHome());
probe.current(installedJdk);
}
});
}
private static void validateNoDuplicate(ModelMap jdks) {
ListMultimap jdksByPath = indexByPath(jdks);
List errors = Lists.newArrayList();
for (String path : jdksByPath.keySet()) {
checkDuplicateForPath(jdksByPath, path, errors);
}
if (!errors.isEmpty()) {
throw new InvalidModelException(String.format("Duplicate Java installation found:\n%s", Joiner.on("\n").join(errors)));
}
}
@Mutate
public void registerPlatformResolver(PlatformResolvers platformResolvers) {
platformResolvers.register(new JavaPlatformResolver());
}
@Model
@Hidden
JavaInstallationProbe javaInstallationProbe(ServiceRegistry serviceRegistry) {
return serviceRegistry.get(JavaInstallationProbe.class);
}
@Defaults
public void resolveJavaToolChains(final ModelMap installedJdks, ModelMap localJavaInstalls, final JavaInstallationProbe probe) {
File currentJavaHome = canonicalFile(Jvm.current().getJavaHome());
// TODO:Cedric The following validation should in theory happen in its own rule, but it is not possible now because
// there's no way to iterate on the map as subject of a `@Validate` rule without Gradle thinking you're trying to mutate it
validateNoDuplicate(localJavaInstalls);
for (final LocalJava candidate : localJavaInstalls) {
final File javaHome = canonicalFile(candidate.getPath());
final JavaInstallationProbe.ProbeResult probeResult = probe.checkJdk(javaHome);
Class extends LocalJavaInstallation> clazz;
switch (probeResult.getInstallType()) {
case IS_JDK:
clazz = InstalledJdkInternal.class;
break;
case IS_JRE:
clazz = InstalledJre.class;
break;
case NO_SUCH_DIRECTORY:
throw new InvalidModelException(String.format("Path to JDK '%s' doesn't exist: %s", candidate.getName(), javaHome));
case INVALID_JDK:
default:
throw new InvalidModelException(String.format("JDK '%s' is not a valid JDK installation: %s\n%s", candidate.getName(), javaHome, probeResult.getError()));
}
if (!javaHome.equals(currentJavaHome)) {
installedJdks.create(candidate.getName(), clazz, new Action() {
@Override
public void execute(LocalJavaInstallation installedJdk) {
installedJdk.setJavaHome(javaHome);
probeResult.configure(installedJdk);
}
});
}
}
}
@ComponentBinaries
public void createBinaries(ModelMap binaries, PlatformResolvers platforms, final JvmLibrarySpecInternal jvmLibrary) {
List selectedPlatforms = resolvePlatforms(platforms, jvmLibrary);
final Set exportedPackages = exportedPackagesOf(jvmLibrary);
final Collection apiDependencies = apiDependenciesOf(jvmLibrary);
final Collection dependencies = componentDependenciesOf(jvmLibrary);
for (final JavaPlatform platform : selectedPlatforms) {
final BinaryNamingScheme namingScheme = namingSchemeFor(jvmLibrary, selectedPlatforms, platform);
binaries.create(namingScheme.getBinaryName(), new Action() {
@Override
public void execute(JarBinarySpec jarBinarySpec) {
JarBinarySpecInternal jarBinary = (JarBinarySpecInternal) jarBinarySpec;
jarBinary.setNamingScheme(namingScheme);
jarBinary.setTargetPlatform(platform);
jarBinary.setExportedPackages(exportedPackages);
jarBinary.setApiDependencies(apiDependencies);
jarBinary.setDependencies(dependencies);
}
});
}
}
private static File canonicalFile(File f) {
try {
return f.getCanonicalFile();
} catch (IOException e) {
return f;
}
}
private List resolvePlatforms(final PlatformResolvers platformResolver,
JvmLibrarySpecInternal jvmLibrarySpec) {
List targetPlatforms = jvmLibrarySpec.getTargetPlatforms();
if (targetPlatforms.isEmpty()) {
targetPlatforms = Collections.singletonList(
DefaultPlatformRequirement.create(DefaultJavaPlatform.current().getName()));
}
return CollectionUtils.collect(targetPlatforms, new Transformer() {
@Override
public JavaPlatform transform(PlatformRequirement platformRequirement) {
return platformResolver.resolve(JavaPlatform.class, platformRequirement);
}
});
}
private static Set exportedPackagesOf(JvmLibrarySpecInternal jvmLibrary) {
return jvmLibrary.getApi().getExports();
}
private static Collection apiDependenciesOf(JvmLibrarySpecInternal jvmLibrary) {
return jvmLibrary.getApi().getDependencies().getDependencies();
}
private static Collection componentDependenciesOf(JvmLibrarySpecInternal jvmLibrary) {
return jvmLibrary.getDependencies().getDependencies();
}
private BinaryNamingScheme namingSchemeFor(JvmLibrarySpec jvmLibrary, List selectedPlatforms, JavaPlatform platform) {
return DefaultBinaryNamingScheme.component(jvmLibrary.getName())
.withBinaryType("Jar")
.withRole("jar", true)
.withVariantDimension(platform, selectedPlatforms);
}
@BinaryTasks
public void createTasks(ModelMap tasks, final JarBinarySpecInternal binary, final @Path("buildDir") File buildDir) {
final File runtimeJarDestDir = binary.getJarFile().getParentFile();
final String runtimeJarArchiveName = binary.getJarFile().getName();
final String createRuntimeJar = "create" + capitalize(binary.getProjectScopedName());
final JvmAssembly assembly = binary.getAssembly();
final JarFile runtimeJarFile = binary.getRuntimeJar();
tasks.create(createRuntimeJar, Jar.class, new Action() {
@Override
public void execute(Jar jar) {
jar.setDescription("Creates the binary file for " + binary + ".");
jar.from(assembly.getClassDirectories());
jar.from(assembly.getResourceDirectories());
jar.getDestinationDirectory().set(runtimeJarDestDir);
jar.getArchiveFileName().set(runtimeJarArchiveName);
jar.dependsOn(assembly);
runtimeJarFile.setBuildTask(jar);
}
});
final JarFile apiJarFile = binary.getApiJar();
final Set exportedPackages = binary.getExportedPackages();
String apiJarTaskName = apiJarTaskName(binary);
tasks.create(apiJarTaskName, ApiJar.class, new Action() {
@Override
public void execute(ApiJar apiJarTask) {
apiJarTask.setDescription("Creates the API binary file for " + binary + ".");
apiJarTask.setOutputFile(apiJarFile.getFile());
apiJarTask.setExportedPackages(exportedPackages);
apiJarTask.source(assembly.getClassDirectories());
apiJarTask.dependsOn(assembly);
apiJarFile.setBuildTask(apiJarTask);
}
});
}
private String apiJarTaskName(JarBinarySpecInternal binary) {
String binaryName = binary.getProjectScopedName();
String libName = binaryName.endsWith("Jar")
? binaryName.substring(0, binaryName.length() - 3)
: binaryName;
return libName + "ApiJar";
}
private static void checkDuplicateForPath(ListMultimap index, String path, List errors) {
List localJavas = index.get(path);
if (localJavas.size() > 1) {
errors.add(String.format(" - %s are both pointing to the same JDK installation path: %s",
Joiner.on(", ").join(Iterables.transform(localJavas, new Function() {
@Override
public String apply(LocalJava input) {
return "'" + input.getName() + "'";
}
})), path));
}
}
private static ListMultimap indexByPath(ModelMap localJavaInstalls) {
final ListMultimap index = ArrayListMultimap.create();
for (LocalJava localJava : localJavaInstalls) {
try {
index.put(localJava.getPath().getCanonicalPath(), localJava);
} catch (IOException e) {
// ignore this installation for validation, it will be caught later
}
}
return index;
}
private static List toImmutableJdkList(ModelMap jdks) {
final List asImmutable = Lists.newArrayList();
jdks.afterEach(new Action() {
@Override
public void execute(LocalJava localJava) {
asImmutable.add(localJava);
}
});
return asImmutable;
}
@Defaults
void configureJvmBinaries(@Each JvmBinarySpecInternal jvmBinary, ProjectLayout projectLayout) {
File buildDir = projectLayout.getBuildDir();
BinaryNamingScheme namingScheme = jvmBinary.getNamingScheme();
jvmBinary.setClassesDir(namingScheme.getOutputDirectory(buildDir, "classes"));
jvmBinary.setResourcesDir(namingScheme.getOutputDirectory(buildDir, "resources"));
}
@Defaults
void configureJarBinaries(@Each JarBinarySpecInternal jarBinary, ProjectLayout projectLayout, JavaToolChainRegistry toolChains) {
String libraryName = jarBinary.getId().getLibraryName();
File jarsDir = jarBinary.getNamingScheme().getOutputDirectory(projectLayout.getBuildDir(), "jars");
jarBinary.setJarFile(new File(jarsDir, libraryName + ".jar"));
jarBinary.setApiJarFile(new File(jarsDir, "api/" + libraryName + ".jar"));
jarBinary.setToolChain(toolChains.getForPlatform(jarBinary.getTargetPlatform()));
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy