diff --git a/src/main/java/net/fabricmc/loom/LoomGradleExtension.java b/src/main/java/net/fabricmc/loom/LoomGradleExtension.java index 8d7255d2..e6764ca4 100644 --- a/src/main/java/net/fabricmc/loom/LoomGradleExtension.java +++ b/src/main/java/net/fabricmc/loom/LoomGradleExtension.java @@ -1,7 +1,7 @@ /* * This file is part of fabric-loom, licensed under the MIT License (MIT). * - * Copyright (c) 2016-2021 FabricMC + * Copyright (c) 2016-2022 FabricMC * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -30,10 +30,7 @@ import java.util.function.Supplier; import org.cadixdev.lorenz.MappingSet; import org.cadixdev.mercury.Mercury; -import org.gradle.api.Action; -import org.gradle.api.NamedDomainObjectProvider; import org.gradle.api.Project; -import org.gradle.api.artifacts.Configuration; import org.gradle.api.file.ConfigurableFileCollection; import org.gradle.api.file.FileCollection; @@ -66,15 +63,6 @@ public interface LoomGradleExtension extends LoomGradleExtensionAPI { LoomFiles getFiles(); - default NamedDomainObjectProvider createLazyConfiguration(String name) { - return createLazyConfiguration(name, config -> { - }); - } - - NamedDomainObjectProvider createLazyConfiguration(String name, Action configurationAction); - - NamedDomainObjectProvider getLazyConfigurationProvider(String name); - MappingSet getOrCreateSrcMappingCache(int id, Supplier factory); Mercury getOrCreateSrcMercuryCache(int id, Supplier factory); diff --git a/src/main/java/net/fabricmc/loom/LoomGradlePlugin.java b/src/main/java/net/fabricmc/loom/LoomGradlePlugin.java index 85df3e9e..d9f78437 100644 --- a/src/main/java/net/fabricmc/loom/LoomGradlePlugin.java +++ b/src/main/java/net/fabricmc/loom/LoomGradlePlugin.java @@ -1,7 +1,7 @@ /* * This file is part of fabric-loom, licensed under the MIT License (MIT). * - * Copyright (c) 2016-2021 FabricMC + * Copyright (c) 2016-2022 FabricMC * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/net/fabricmc/loom/api/LoomGradleExtensionAPI.java b/src/main/java/net/fabricmc/loom/api/LoomGradleExtensionAPI.java index 7988ec78..40414ee3 100644 --- a/src/main/java/net/fabricmc/loom/api/LoomGradleExtensionAPI.java +++ b/src/main/java/net/fabricmc/loom/api/LoomGradleExtensionAPI.java @@ -29,6 +29,7 @@ import java.util.function.Consumer; import org.gradle.api.Action; import org.gradle.api.NamedDomainObjectContainer; +import org.gradle.api.NamedDomainObjectList; import org.gradle.api.artifacts.Dependency; import org.gradle.api.file.ConfigurableFileCollection; import org.gradle.api.file.RegularFileProperty; @@ -36,6 +37,7 @@ import org.gradle.api.provider.ListProperty; import org.gradle.api.provider.Property; import org.gradle.api.provider.Provider; import org.gradle.api.publish.maven.MavenPublication; +import org.gradle.api.tasks.SourceSet; import org.jetbrains.annotations.ApiStatus; import net.fabricmc.loom.api.decompilers.DecompilerOptions; @@ -103,6 +105,22 @@ public interface LoomGradleExtensionAPI { @ApiStatus.Experimental NamedDomainObjectContainer getMods(); + @ApiStatus.Experimental + NamedDomainObjectList getRemapConfigurations(); + + @ApiStatus.Experimental + RemapConfigurationSettings addRemapConfiguration(String name, Action action); + + void createRemapConfigurations(SourceSet sourceSet); + + default List getCompileRemapConfigurations() { + return getRemapConfigurations().stream().filter(element -> element.getOnCompileClasspath().get()).toList(); + } + + default List getRuntimeRemapConfigurations() { + return getRemapConfigurations().stream().filter(element -> element.getOnCompileClasspath().get()).toList(); + } + @ApiStatus.Experimental // TODO: move this from LoomGradleExtensionAPI to LoomGradleExtension once getRefmapName & setRefmapName is removed. MixinExtensionAPI getMixin(); diff --git a/src/main/java/net/fabricmc/loom/api/RemapConfigurationSettings.java b/src/main/java/net/fabricmc/loom/api/RemapConfigurationSettings.java new file mode 100644 index 00000000..b23e589d --- /dev/null +++ b/src/main/java/net/fabricmc/loom/api/RemapConfigurationSettings.java @@ -0,0 +1,154 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2022 FabricMC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package net.fabricmc.loom.api; + +import java.util.Set; + +import javax.inject.Inject; + +import com.google.common.base.Preconditions; +import org.gradle.api.Named; +import org.gradle.api.NamedDomainObjectProvider; +import org.gradle.api.Project; +import org.gradle.api.artifacts.Configuration; +import org.gradle.api.plugins.JavaPlugin; +import org.gradle.api.provider.Property; +import org.gradle.api.provider.Provider; +import org.gradle.api.tasks.Internal; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.NotNull; + +import net.fabricmc.loom.LoomGradleExtension; +import net.fabricmc.loom.configuration.providers.minecraft.MinecraftJarConfiguration; + +/** + * A {@link Named} object for configuring "proxy" configurations that remap artifacts. + */ +public abstract class RemapConfigurationSettings implements Named { + private final String name; + + @Inject + public RemapConfigurationSettings(String name) { + this.name = name; + + getTargetConfigurationName().finalizeValueOnRead(); + getClientTargetConfigurationName().finalizeValueOnRead(); + getOnCompileClasspath().finalizeValueOnRead(); + getOnRuntimeClasspath().finalizeValueOnRead(); + getPublishingMode().convention(PublishingMode.NONE).finalizeValueOnRead(); + } + + @Override + public @NotNull String getName() { + return name; + } + + /** + * @return The target configuration name + */ + public abstract Property getTargetConfigurationName(); + + /** + * Optional, only used when split sourcesets are enabled. + * When not present client only entries should go onto the target configuration. + * + * @return The client target configuration name + */ + public abstract Property getClientTargetConfigurationName(); + + /** + * @return True if this configuration's artifacts should be exposed for compile operations. + */ + public abstract Property getOnCompileClasspath(); + + /** + * @return True if this configuration's artifacts should be exposed to runtime operations. + */ + public abstract Property getOnRuntimeClasspath(); + + /** + * @return the {@link PublishingMode} for the configuration. + */ + public abstract Property getPublishingMode(); + + public enum PublishingMode { + NONE, + COMPILE_ONLY(JavaPlugin.API_ELEMENTS_CONFIGURATION_NAME), + RUNTIME_ONLY(JavaPlugin.RUNTIME_ELEMENTS_CONFIGURATION_NAME), + COMPILE_AND_RUNTIME(JavaPlugin.API_ELEMENTS_CONFIGURATION_NAME, JavaPlugin.RUNTIME_ELEMENTS_CONFIGURATION_NAME); + + private final Set outgoingConfigurations; + + PublishingMode(String... outgoingConfigurations) { + this.outgoingConfigurations = Set.of(outgoingConfigurations); + } + + public Set outgoingConfigurations() { + return outgoingConfigurations; + } + } + + @Inject + protected abstract Project getProject(); + + @ApiStatus.Internal + @Internal + public final String getRemappedConfigurationName() { + return getName() + "Mapped"; + } + + @ApiStatus.Internal + @Internal + public final NamedDomainObjectProvider getSourceConfiguration() { + return getConfigurationByName(getName()); + } + + @ApiStatus.Internal + @Internal + public final NamedDomainObjectProvider getRemappedConfiguration() { + return getConfigurationByName(getRemappedConfigurationName()); + } + + @ApiStatus.Internal + @Internal + public final NamedDomainObjectProvider getTargetConfiguration() { + return getConfigurationByName(getTargetConfigurationName().get()); + } + + @ApiStatus.Internal + @Internal + public final Provider getClientTargetConfiguration() { + return getProject().provider(() -> { + boolean split = LoomGradleExtension.get(getProject()).getMinecraftJarConfiguration().get() == MinecraftJarConfiguration.SPLIT; + Preconditions.checkArgument(split, "Cannot get client target configuration when project is not split"); + return getConfigurationByName(getClientTargetConfigurationName().get()).get(); + }); + } + + @Internal + private NamedDomainObjectProvider getConfigurationByName(String name) { + return getProject().getConfigurations().named(name); + } +} diff --git a/src/main/java/net/fabricmc/loom/build/ModCompileRemapper.java b/src/main/java/net/fabricmc/loom/build/ModCompileRemapper.java deleted file mode 100644 index 38250e25..00000000 --- a/src/main/java/net/fabricmc/loom/build/ModCompileRemapper.java +++ /dev/null @@ -1,203 +0,0 @@ -/* - * This file is part of fabric-loom, licensed under the MIT License (MIT). - * - * Copyright (c) 2019-2021 FabricMC - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package net.fabricmc.loom.build; - -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.function.Supplier; - -import com.google.common.io.Files; -import org.gradle.api.Project; -import org.gradle.api.artifacts.Configuration; -import org.gradle.api.artifacts.Dependency; -import org.gradle.api.artifacts.FileCollectionDependency; -import org.gradle.api.artifacts.ModuleDependency; -import org.gradle.api.artifacts.ResolvedArtifact; -import org.gradle.api.artifacts.dsl.DependencyHandler; -import org.gradle.api.artifacts.query.ArtifactResolutionQuery; -import org.gradle.api.artifacts.result.ArtifactResult; -import org.gradle.api.artifacts.result.ComponentArtifactsResult; -import org.gradle.api.artifacts.result.ResolvedArtifactResult; -import org.gradle.api.file.FileCollection; -import org.gradle.api.logging.Logger; -import org.gradle.api.plugins.JavaPlugin; -import org.gradle.jvm.JvmLibrary; -import org.gradle.language.base.artifact.SourcesArtifact; -import org.jetbrains.annotations.Nullable; - -import net.fabricmc.loom.LoomGradleExtension; -import net.fabricmc.loom.LoomGradlePlugin; -import net.fabricmc.loom.configuration.RemappedConfigurationEntry; -import net.fabricmc.loom.configuration.mods.ModProcessor; -import net.fabricmc.loom.configuration.processors.dependency.ModDependencyInfo; -import net.fabricmc.loom.configuration.processors.dependency.RemapData; -import net.fabricmc.loom.util.Checksum; -import net.fabricmc.loom.util.Constants; -import net.fabricmc.loom.util.ModUtils; -import net.fabricmc.loom.util.OperatingSystem; -import net.fabricmc.loom.util.SourceRemapper; - -@SuppressWarnings("UnstableApiUsage") -public class ModCompileRemapper { - // This is a placeholder that is used when the actual group is missing (null or empty). - // This can happen when the dependency is a FileCollectionDependency or from a flatDir repository. - private static final String MISSING_GROUP = "unspecified"; - - private static String replaceIfNullOrEmpty(@Nullable String s, Supplier fallback) { - return s == null || s.isEmpty() ? fallback.get() : s; - } - - public static void remapDependencies(Project project, String mappingsSuffix, LoomGradleExtension extension, SourceRemapper sourceRemapper) { - Logger logger = project.getLogger(); - DependencyHandler dependencies = project.getDependencies(); - boolean refreshDeps = LoomGradlePlugin.refreshDeps; - - final File modStore = extension.getFiles().getRemappedModCache(); - final RemapData remapData = new RemapData(mappingsSuffix, modStore); - - for (RemappedConfigurationEntry entry : Constants.MOD_COMPILE_ENTRIES) { - extension.getLazyConfigurationProvider(entry.getRemappedConfiguration()).configure(remappedConfig -> { - Configuration sourceConfig = project.getConfigurations().getByName(entry.sourceConfiguration()); - Configuration regularConfig = project.getConfigurations().getByName(entry.getTargetConfiguration(project.getConfigurations())); - - List modDependencies = new ArrayList<>(); - - for (ResolvedArtifact artifact : sourceConfig.getResolvedConfiguration().getResolvedArtifacts()) { - String group = replaceIfNullOrEmpty(artifact.getModuleVersion().getId().getGroup(), () -> MISSING_GROUP); - String name = artifact.getModuleVersion().getId().getName(); - String version = replaceIfNullOrEmpty(artifact.getModuleVersion().getId().getVersion(), () -> Checksum.truncatedSha256(artifact.getFile())); - - if (!ModUtils.shouldRemapMod(project.getLogger(), artifact.getFile(), artifact.getId(), extension.getPlatform().get(), sourceConfig.getName())) { - addToRegularCompile(project, regularConfig, artifact); - continue; - } - - ModDependencyInfo info = new ModDependencyInfo(group, name, version, artifact.getClassifier(), artifact.getFile(), remappedConfig, remapData); - modDependencies.add(info); - - File remappedSources = info.getRemappedOutput("sources"); - - if ((!remappedSources.exists() || refreshDeps) && !OperatingSystem.isCIBuild()) { - File sources = findSources(dependencies, artifact); - - if (sources != null) { - scheduleSourcesRemapping(project, sourceRemapper, sources, info.getRemappedNotation(), remappedSources); - } - } - } - - // FileCollectionDependency (files/fileTree) doesn't resolve properly, - // so we have to "resolve" it on our own. The naming is "abc.jar" => "unspecified:abc:unspecified". - for (FileCollectionDependency dependency : sourceConfig.getAllDependencies().withType(FileCollectionDependency.class)) { - String group = replaceIfNullOrEmpty(dependency.getGroup(), () -> MISSING_GROUP); - FileCollection files = dependency.getFiles(); - - // Create a mod dependency for each file in the file collection - for (File artifact : files) { - if (!ModUtils.shouldRemapMod(project.getLogger(), artifact, artifact.getName(), extension.getPlatform().get(), sourceConfig.getName())) { - dependencies.add(regularConfig.getName(), project.files(artifact)); - continue; - } - - String name = Files.getNameWithoutExtension(artifact.getAbsolutePath()); - String version = replaceIfNullOrEmpty(dependency.getVersion(), () -> Checksum.truncatedSha256(artifact)); - - ModDependencyInfo info = new ModDependencyInfo(group, name, version, null, artifact, remappedConfig, remapData); - modDependencies.add(info); - } - } - - for (ModDependencyInfo info : modDependencies) { - if (refreshDeps) { - info.forceRemap(); - } - - String remappedLog = info.getRemappedNotation() + " (" + mappingsSuffix + ")"; - project.getLogger().info(":providing " + remappedLog); - } - - try { - new ModProcessor(project).processMods(modDependencies); - } catch (IOException e) { - // Failed to remap, lets clean up to ensure we try again next time - modDependencies.forEach(info -> info.getRemappedOutput().delete()); - throw new RuntimeException("Failed to remap mods", e); - } - - // Add all of the remapped mods onto the config - for (ModDependencyInfo info : modDependencies) { - project.getLogger().info(":adding " + info.toString() + " into " + info.targetConfig.getName()); - project.getDependencies().add(info.targetConfig.getName(), info.getRemappedNotation()); - } - - // Export to other projects - if (entry.targetConfiguration().equals(JavaPlugin.API_CONFIGURATION_NAME)) { - project.getConfigurations().getByName(Constants.Configurations.NAMED_ELEMENTS).extendsFrom(remappedConfig); - } - }); - } - } - - private static void addToRegularCompile(Project project, Configuration regularCompile, ResolvedArtifact artifact) { - project.getLogger().info(":providing " + artifact); - DependencyHandler dependencies = project.getDependencies(); - Dependency dep = dependencies.module(artifact.getModuleVersion().toString() - + (artifact.getClassifier() == null ? "" : ':' + artifact.getClassifier())); // the owning module of the artifact - - if (dep instanceof ModuleDependency moduleDependency) { - moduleDependency.setTransitive(false); - } - - dependencies.add(regularCompile.getName(), dep); - } - - public static File findSources(DependencyHandler dependencies, ResolvedArtifact artifact) { - @SuppressWarnings("unchecked") ArtifactResolutionQuery query = dependencies.createArtifactResolutionQuery() - .forComponents(artifact.getId().getComponentIdentifier()) - .withArtifacts(JvmLibrary.class, SourcesArtifact.class); - - for (ComponentArtifactsResult result : query.execute().getResolvedComponents()) { - for (ArtifactResult srcArtifact : result.getArtifacts(SourcesArtifact.class)) { - if (srcArtifact instanceof ResolvedArtifactResult) { - return ((ResolvedArtifactResult) srcArtifact).getFile(); - } - } - } - - return null; - } - - private static void scheduleSourcesRemapping(Project project, SourceRemapper sourceRemapper, File sources, String remappedLog, File remappedSources) { - project.getLogger().debug(":providing " + remappedLog + " sources"); - - if (!remappedSources.exists() || sources.lastModified() <= 0 || sources.lastModified() > remappedSources.lastModified() || LoomGradlePlugin.refreshDeps) { - sourceRemapper.scheduleRemapSources(sources, remappedSources, false, true); // Depenedency sources are used in ide only so don't need to be reproducable - } else { - project.getLogger().info(remappedSources.getName() + " is up to date with " + sources.getName()); - } - } -} diff --git a/src/main/java/net/fabricmc/loom/configuration/CompileConfiguration.java b/src/main/java/net/fabricmc/loom/configuration/CompileConfiguration.java index 9345aea7..35a3f939 100644 --- a/src/main/java/net/fabricmc/loom/configuration/CompileConfiguration.java +++ b/src/main/java/net/fabricmc/loom/configuration/CompileConfiguration.java @@ -33,6 +33,7 @@ import java.util.Set; import org.gradle.api.NamedDomainObjectProvider; import org.gradle.api.Project; import org.gradle.api.artifacts.Configuration; +import org.gradle.api.artifacts.ConfigurationContainer; import org.gradle.api.plugins.JavaPlugin; import org.gradle.api.plugins.JavaPluginExtension; import org.gradle.api.tasks.AbstractCopyTask; @@ -73,13 +74,15 @@ import net.fabricmc.loom.extension.MixinExtension; import net.fabricmc.loom.util.Constants; import net.fabricmc.loom.util.ExceptionUtil; import net.fabricmc.loom.util.OperatingSystem; +import net.fabricmc.loom.util.gradle.SourceSetHelper; public final class CompileConfiguration { private CompileConfiguration() { } public static void setupConfigurations(Project project) { - LoomGradleExtension extension = LoomGradleExtension.get(project); + final ConfigurationContainer configurations = project.getConfigurations(); + final LoomGradleExtension extension = LoomGradleExtension.get(project); project.afterEvaluate(project1 -> { if (extension.shouldGenerateSrgTiny()) { @@ -93,27 +96,27 @@ public final class CompileConfiguration { } }); - extension.createLazyConfiguration(Constants.Configurations.MOD_COMPILE_CLASSPATH, configuration -> configuration.setTransitive(true)); - extension.createLazyConfiguration(Constants.Configurations.MOD_COMPILE_CLASSPATH_MAPPED, configuration -> configuration.setTransitive(false)); - NamedDomainObjectProvider serverDeps = extension.createLazyConfiguration(Constants.Configurations.MINECRAFT_SERVER_DEPENDENCIES, configuration -> configuration.setTransitive(false)); - extension.createLazyConfiguration(Constants.Configurations.MINECRAFT_RUNTIME_DEPENDENCIES, configuration -> configuration.setTransitive(false)); - extension.createLazyConfiguration(Constants.Configurations.MINECRAFT_DEPENDENCIES, configuration -> { + configurations.register(Constants.Configurations.MOD_COMPILE_CLASSPATH, configuration -> configuration.setTransitive(true)); + configurations.register(Constants.Configurations.MOD_COMPILE_CLASSPATH_MAPPED, configuration -> configuration.setTransitive(false)); + NamedDomainObjectProvider serverDeps = configurations.register(Constants.Configurations.MINECRAFT_SERVER_DEPENDENCIES, configuration -> configuration.setTransitive(false)); + configurations.register(Constants.Configurations.MINECRAFT_RUNTIME_DEPENDENCIES, configuration -> configuration.setTransitive(false)); + configurations.register(Constants.Configurations.MINECRAFT_DEPENDENCIES, configuration -> { configuration.extendsFrom(serverDeps.get()); configuration.setTransitive(false); }); - extension.createLazyConfiguration(Constants.Configurations.LOADER_DEPENDENCIES, configuration -> configuration.setTransitive(false)); - extension.createLazyConfiguration(Constants.Configurations.MINECRAFT, configuration -> configuration.setTransitive(false)); + configurations.register(Constants.Configurations.LOADER_DEPENDENCIES, configuration -> configuration.setTransitive(false)); + configurations.register(Constants.Configurations.MINECRAFT, configuration -> configuration.setTransitive(false)); if (extension.isForge()) { - extension.createLazyConfiguration(Constants.Configurations.FORGE).configure(configuration -> configuration.setTransitive(false)); - extension.createLazyConfiguration(Constants.Configurations.FORGE_USERDEV).configure(configuration -> configuration.setTransitive(false)); - extension.createLazyConfiguration(Constants.Configurations.FORGE_INSTALLER).configure(configuration -> configuration.setTransitive(false)); - extension.createLazyConfiguration(Constants.Configurations.FORGE_UNIVERSAL).configure(configuration -> configuration.setTransitive(false)); - extension.createLazyConfiguration(Constants.Configurations.FORGE_DEPENDENCIES); - extension.createLazyConfiguration(Constants.Configurations.FORGE_NAMED).configure(configuration -> configuration.setTransitive(false)); - extension.createLazyConfiguration(Constants.Configurations.FORGE_EXTRA).configure(configuration -> configuration.setTransitive(false)); - extension.createLazyConfiguration(Constants.Configurations.MCP_CONFIG).configure(configuration -> configuration.setTransitive(false)); - extension.createLazyConfiguration(Constants.Configurations.FORGE_RUNTIME_LIBRARY); + configurations.register(Constants.Configurations.FORGE).configure(configuration -> configuration.setTransitive(false)); + configurations.register(Constants.Configurations.FORGE_USERDEV).configure(configuration -> configuration.setTransitive(false)); + configurations.register(Constants.Configurations.FORGE_INSTALLER).configure(configuration -> configuration.setTransitive(false)); + configurations.register(Constants.Configurations.FORGE_UNIVERSAL).configure(configuration -> configuration.setTransitive(false)); + configurations.register(Constants.Configurations.FORGE_DEPENDENCIES); + configurations.register(Constants.Configurations.FORGE_NAMED).configure(configuration -> configuration.setTransitive(false)); + configurations.register(Constants.Configurations.FORGE_EXTRA).configure(configuration -> configuration.setTransitive(false)); + configurations.register(Constants.Configurations.MCP_CONFIG).configure(configuration -> configuration.setTransitive(false)); + configurations.register(Constants.Configurations.FORGE_RUNTIME_LIBRARY); extendsFrom(Constants.Configurations.MINECRAFT_SERVER_DEPENDENCIES, Constants.Configurations.FORGE_DEPENDENCIES, project); @@ -135,48 +138,24 @@ public final class CompileConfiguration { extendsFrom(JavaPlugin.TEST_RUNTIME_CLASSPATH_CONFIGURATION_NAME, Constants.Configurations.FORGE_EXTRA, project); } - extension.createLazyConfiguration(Constants.Configurations.INCLUDE, configuration -> configuration.setTransitive(false)); // Dont get transitive deps - - extension.createLazyConfiguration(Constants.Configurations.MAPPING_CONSTANTS); - extension.createLazyConfiguration(Constants.Configurations.NAMED_ELEMENTS, configuration -> { + configurations.register(Constants.Configurations.INCLUDE, configuration -> configuration.setTransitive(false)); // Dont get transitive deps + configurations.register(Constants.Configurations.MAPPING_CONSTANTS); + configurations.register(Constants.Configurations.NAMED_ELEMENTS, configuration -> { configuration.setCanBeConsumed(true); configuration.setCanBeResolved(false); - configuration.extendsFrom(project.getConfigurations().getByName(JavaPlugin.API_CONFIGURATION_NAME)); + configuration.extendsFrom(configurations.getByName(JavaPlugin.API_CONFIGURATION_NAME)); }); extendsFrom(JavaPlugin.COMPILE_ONLY_CONFIGURATION_NAME, Constants.Configurations.MAPPING_CONSTANTS, project); - extension.createLazyConfiguration(Constants.Configurations.MAPPINGS); - extension.createLazyConfiguration(Constants.Configurations.MAPPINGS_FINAL); - extension.createLazyConfiguration(Constants.Configurations.LOOM_DEVELOPMENT_DEPENDENCIES); - extension.createLazyConfiguration(Constants.Configurations.UNPICK_CLASSPATH); - extension.createLazyConfiguration(Constants.Configurations.LOCAL_RUNTIME); + configurations.register(Constants.Configurations.MAPPINGS); + configurations.register(Constants.Configurations.MAPPINGS_FINAL); + configurations.register(Constants.Configurations.LOOM_DEVELOPMENT_DEPENDENCIES); + configurations.register(Constants.Configurations.UNPICK_CLASSPATH); + configurations.register(Constants.Configurations.LOCAL_RUNTIME); extendsFrom(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME, Constants.Configurations.LOCAL_RUNTIME, project); - for (RemappedConfigurationEntry entry : Constants.MOD_COMPILE_ENTRIES) { - extension.createLazyConfiguration(entry.sourceConfiguration()) - .configure(configuration -> configuration.setTransitive(true)); - - // Don't get transitive deps of already remapped mods - extension.createLazyConfiguration(entry.getRemappedConfiguration()) - .configure(configuration -> configuration.setTransitive(false)); - - if (entry.compileClasspath()) { - extendsFrom(Constants.Configurations.MOD_COMPILE_CLASSPATH, entry.sourceConfiguration(), project); - extendsFrom(Constants.Configurations.MOD_COMPILE_CLASSPATH_MAPPED, entry.getRemappedConfiguration(), project); - extendsFrom(JavaPlugin.COMPILE_CLASSPATH_CONFIGURATION_NAME, entry.getRemappedConfiguration(), project); - extendsFrom(JavaPlugin.TEST_COMPILE_CLASSPATH_CONFIGURATION_NAME, entry.getRemappedConfiguration(), project); - } - - if (entry.runtimeClasspath()) { - extendsFrom(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME, entry.getRemappedConfiguration(), project); - extendsFrom(JavaPlugin.TEST_RUNTIME_CLASSPATH_CONFIGURATION_NAME, entry.getRemappedConfiguration(), project); - } - - for (String outgoingConfiguration : entry.publishingMode().outgoingConfigurations()) { - extendsFrom(outgoingConfiguration, entry.sourceConfiguration(), project); - } - } + extension.createRemapConfigurations(SourceSetHelper.getMainSourceSet(project)); extendsFrom(Constants.Configurations.LOADER_DEPENDENCIES, Constants.Configurations.MINECRAFT_DEPENDENCIES, project); @@ -206,7 +185,7 @@ public final class CompileConfiguration { LoomGradleExtension extension = LoomGradleExtension.get(p); p.getTasks().named(JavaPlugin.JAVADOC_TASK_NAME, Javadoc.class).configure(javadoc -> { - final SourceSet main = javaPluginExtension.getSourceSets().getByName(SourceSet.MAIN_SOURCE_SET_NAME); + final SourceSet main = SourceSetHelper.getMainSourceSet(p); javadoc.setClasspath(main.getOutput().plus(main.getCompileClasspath())); }); diff --git a/src/main/java/net/fabricmc/loom/configuration/LoomDependencyManager.java b/src/main/java/net/fabricmc/loom/configuration/LoomDependencyManager.java index 1e6a96fd..6d83be50 100644 --- a/src/main/java/net/fabricmc/loom/configuration/LoomDependencyManager.java +++ b/src/main/java/net/fabricmc/loom/configuration/LoomDependencyManager.java @@ -41,7 +41,7 @@ import org.gradle.api.artifacts.repositories.MavenArtifactRepository; import net.fabricmc.loom.LoomGradleExtension; import net.fabricmc.loom.LoomGradlePlugin; import net.fabricmc.loom.LoomRepositoryPlugin; -import net.fabricmc.loom.build.ModCompileRemapper; +import net.fabricmc.loom.configuration.mods.ModConfigurationRemapper; import net.fabricmc.loom.configuration.ide.idea.IdeaUtils; import net.fabricmc.loom.util.Constants; import net.fabricmc.loom.util.SourceRemapper; @@ -89,7 +89,7 @@ public class LoomDependencyManager { String platformSuffix = extension.isForge() ? "_forge" : extension.isQuilt() ? "_arch_quilt" : ""; String mappingsIdentifier = extension.getMappingsProvider().mappingsIdentifier() + platformSuffix; - ModCompileRemapper.remapDependencies(project, mappingsIdentifier, extension, sourceRemapper); + ModConfigurationRemapper.supplyModConfigurations(project, mappingsIdentifier, extension, sourceRemapper); sourceRemapper.remapAll(); diff --git a/src/main/java/net/fabricmc/loom/configuration/RemapConfigurations.java b/src/main/java/net/fabricmc/loom/configuration/RemapConfigurations.java new file mode 100644 index 00000000..149eb345 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/configuration/RemapConfigurations.java @@ -0,0 +1,174 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2022 FabricMC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package net.fabricmc.loom.configuration; + +import java.util.List; +import java.util.Locale; +import java.util.function.Function; + +import org.gradle.api.Action; +import org.gradle.api.NamedDomainObjectList; +import org.gradle.api.Project; +import org.gradle.api.artifacts.Configuration; +import org.gradle.api.plugins.JavaPlugin; +import org.gradle.api.tasks.SourceSet; + +import net.fabricmc.loom.LoomGradleExtension; +import net.fabricmc.loom.api.RemapConfigurationSettings; +import net.fabricmc.loom.util.Constants; +import net.fabricmc.loom.util.gradle.SourceSetHelper; + +public final class RemapConfigurations { + private static final List OPTIONS = List.of( + new ConfigurationOption(mainOnly(SourceSet::getApiConfigurationName), true, true, RemapConfigurationSettings.PublishingMode.COMPILE_AND_RUNTIME), + new ConfigurationOption(SourceSet::getImplementationConfigurationName, true, true, RemapConfigurationSettings.PublishingMode.RUNTIME_ONLY), + new ConfigurationOption(SourceSet::getCompileOnlyConfigurationName, true, false, RemapConfigurationSettings.PublishingMode.NONE), + new ConfigurationOption(mainOnly(SourceSet::getCompileOnlyApiConfigurationName), true, false, RemapConfigurationSettings.PublishingMode.COMPILE_ONLY), + new ConfigurationOption(SourceSet::getRuntimeOnlyConfigurationName, false, true, RemapConfigurationSettings.PublishingMode.RUNTIME_ONLY), + new ConfigurationOption(mainOnly(Constants.Configurations.LOCAL_RUNTIME), false, true, RemapConfigurationSettings.PublishingMode.NONE) + ); + + private RemapConfigurations() { + } + + public static void setupForSourceSet(Project project, SourceSet sourceSet) { + final LoomGradleExtension extension = LoomGradleExtension.get(project); + + for (ConfigurationOption option : getValidOptions(sourceSet)) { + extension.addRemapConfiguration(option.name(sourceSet), configure( + option.targetName(sourceSet), + option.compileClasspath(), + option.runtimeClasspath(), + option.publishingMode() + )); + } + } + + public static void configureClientConfigurations(Project project, SourceSet clientSourceSet) { + final LoomGradleExtension extension = LoomGradleExtension.get(project); + extension.createRemapConfigurations(clientSourceSet); + + final NamedDomainObjectList configurations = extension.getRemapConfigurations(); + SourceSet mainSourceSet = SourceSetHelper.getMainSourceSet(project); + + // Apply the client target names to the main configurations + for (ConfigurationOption option : getValidOptions(mainSourceSet)) { + configurations.getByName(option.name(mainSourceSet), settings -> { + settings.getClientTargetConfigurationName().convention(option.targetName(clientSourceSet)); + }); + } + } + + public static void applyToProject(Project project, RemapConfigurationSettings settings) { + // No point bothering to make it lazily, gradle realises configurations right away. + // + final Configuration remappedConfiguration = project.getConfigurations().create(settings.getRemappedConfigurationName()); + final Configuration configuration = project.getConfigurations().create(settings.getName()); + configuration.setTransitive(true); + // Don't get transitive deps of already remapped mods + remappedConfiguration.setTransitive(false); + + if (settings.getOnCompileClasspath().get()) { + extendsFrom(Constants.Configurations.MOD_COMPILE_CLASSPATH, configuration, project); + extendsFrom(Constants.Configurations.MOD_COMPILE_CLASSPATH_MAPPED, remappedConfiguration, project); + extendsFrom(JavaPlugin.COMPILE_CLASSPATH_CONFIGURATION_NAME, remappedConfiguration, project); + extendsFrom(JavaPlugin.TEST_COMPILE_CLASSPATH_CONFIGURATION_NAME, remappedConfiguration, project); + } + + if (settings.getOnRuntimeClasspath().get()) { + extendsFrom(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME, remappedConfiguration, project); + extendsFrom(JavaPlugin.TEST_RUNTIME_CLASSPATH_CONFIGURATION_NAME, remappedConfiguration, project); + } + + for (String outgoingConfigurationName : settings.getPublishingMode().get().outgoingConfigurations()) { + extendsFrom(outgoingConfigurationName, configuration, project); + } + } + + private static Action configure(String targetConfiguration, boolean compileClasspath, boolean runtimeClasspath, RemapConfigurationSettings.PublishingMode publishingMode) { + return configuration -> { + configuration.getTargetConfigurationName().convention(targetConfiguration); + configuration.getOnCompileClasspath().convention(compileClasspath); + configuration.getOnRuntimeClasspath().convention(runtimeClasspath); + configuration.getPublishingMode().convention(publishingMode); + }; + } + + private static void extendsFrom(String name, Configuration configuration, Project project) { + project.getConfigurations().named(name).configure(namedConfiguration -> { + namedConfiguration.extendsFrom(configuration); + }); + } + + private static Function mainOnly(Function function) { + return sourceSet -> sourceSet.getName().equals(SourceSet.MAIN_SOURCE_SET_NAME) ? function.apply(sourceSet) : null; + } + + private static Function mainOnly(String name) { + return mainOnly(sourceSet -> name); + } + + private static List getValidOptions(SourceSet sourceSet) { + return OPTIONS.stream().filter(option -> option.validFor(sourceSet)).toList(); + } + + private static String capitalise(String str) { + return str.substring(0, 1).toUpperCase(Locale.ROOT) + str.substring(1); + } + + private record ConfigurationOption(Function targetNameFunc, boolean compileClasspath, boolean runtimeClasspath, RemapConfigurationSettings.PublishingMode publishingMode) { + String targetName(SourceSet sourceSet) { + return targetNameFunc.apply(sourceSet); + } + + boolean validFor(SourceSet sourceSet) { + return targetName(sourceSet) != null; + } + + String name(SourceSet sourceSet) { + String targetName = targetName(sourceSet); + + if (targetName == null) { + throw new UnsupportedOperationException("Configuration option is not available for sourceset (%s)".formatted(sourceSet.getName())); + } + + final StringBuilder builder = new StringBuilder(); + + if (!SourceSet.MAIN_SOURCE_SET_NAME.equals(sourceSet.getName())) { + builder.append(sourceSet.getName()); + } + + if (builder.isEmpty()) { + builder.append("mod"); + } else { + builder.append("Mod"); + } + + builder.append(capitalise(targetName)); + + return builder.toString(); + } + } +} diff --git a/src/main/java/net/fabricmc/loom/configuration/RemappedConfigurationEntry.java b/src/main/java/net/fabricmc/loom/configuration/RemappedConfigurationEntry.java deleted file mode 100644 index dd373bdc..00000000 --- a/src/main/java/net/fabricmc/loom/configuration/RemappedConfigurationEntry.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * This file is part of fabric-loom, licensed under the MIT License (MIT). - * - * Copyright (c) 2019-2021 FabricMC - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package net.fabricmc.loom.configuration; - -import java.util.Set; - -import org.gradle.api.artifacts.ConfigurationContainer; -import org.gradle.api.plugins.JavaPlugin; - -public record RemappedConfigurationEntry(String sourceConfiguration, String targetConfiguration, boolean compileClasspath, boolean runtimeClasspath, PublishingMode publishingMode) { - public String getRemappedConfiguration() { - return sourceConfiguration + "Mapped"; - } - - public String getTargetConfiguration(ConfigurationContainer container) { - if (container.findByName(targetConfiguration) == null) { - return JavaPlugin.IMPLEMENTATION_CONFIGURATION_NAME; - } - - return targetConfiguration; - } - - public enum PublishingMode { - NONE, - COMPILE_ONLY(JavaPlugin.API_ELEMENTS_CONFIGURATION_NAME), - RUNTIME_ONLY(JavaPlugin.RUNTIME_ELEMENTS_CONFIGURATION_NAME), - COMPILE_AND_RUNTIME(JavaPlugin.API_ELEMENTS_CONFIGURATION_NAME, JavaPlugin.RUNTIME_ELEMENTS_CONFIGURATION_NAME); - - private final Set outgoingConfigurations; - - PublishingMode(String... outgoingConfigurations) { - this.outgoingConfigurations = Set.of(outgoingConfigurations); - } - - public Set outgoingConfigurations() { - return outgoingConfigurations; - } - } -} diff --git a/src/main/java/net/fabricmc/loom/configuration/accesswidener/TransitiveAccessWidenerJarProcessor.java b/src/main/java/net/fabricmc/loom/configuration/accesswidener/TransitiveAccessWidenerJarProcessor.java index 84791156..3847f793 100644 --- a/src/main/java/net/fabricmc/loom/configuration/accesswidener/TransitiveAccessWidenerJarProcessor.java +++ b/src/main/java/net/fabricmc/loom/configuration/accesswidener/TransitiveAccessWidenerJarProcessor.java @@ -47,10 +47,9 @@ import net.fabricmc.accesswidener.AccessWidenerRemapper; import net.fabricmc.accesswidener.AccessWidenerVisitor; import net.fabricmc.accesswidener.TransitiveOnlyFilter; import net.fabricmc.loom.LoomGradleExtension; +import net.fabricmc.loom.api.RemapConfigurationSettings; import net.fabricmc.loom.api.mappings.layered.MappingsNamespace; -import net.fabricmc.loom.configuration.RemappedConfigurationEntry; import net.fabricmc.loom.configuration.processors.JarProcessor; -import net.fabricmc.loom.util.Constants; import net.fabricmc.loom.util.TinyRemapperHelper; /** @@ -90,13 +89,9 @@ public class TransitiveAccessWidenerJarProcessor implements JarProcessor { final List accessWideners = new ArrayList<>(); final Set possibleModJars = new HashSet<>(); - for (RemappedConfigurationEntry entry : Constants.MOD_COMPILE_ENTRIES) { - // Only apply global AWs from mods that are part of the compile classpath - if (!entry.compileClasspath()) { - continue; - } - - final Configuration configuration = extension.getLazyConfigurationProvider(entry.sourceConfiguration()).get(); + // Only apply global AWs from mods that are part of the compile classpath + for (RemapConfigurationSettings entry : extension.getCompileRemapConfigurations()) { + final Configuration configuration = entry.getSourceConfiguration().get(); // Based off the logic in ModCompileRemapper. for (ResolvedArtifact artifact : configuration.getResolvedConfiguration().getResolvedArtifacts()) { diff --git a/src/main/java/net/fabricmc/loom/configuration/ide/RunConfigSettings.java b/src/main/java/net/fabricmc/loom/configuration/ide/RunConfigSettings.java index 5809ebf3..13a7f319 100644 --- a/src/main/java/net/fabricmc/loom/configuration/ide/RunConfigSettings.java +++ b/src/main/java/net/fabricmc/loom/configuration/ide/RunConfigSettings.java @@ -35,7 +35,6 @@ import java.util.function.Function; import org.gradle.api.Named; import org.gradle.api.Project; -import org.gradle.api.plugins.JavaPluginExtension; import org.gradle.api.tasks.SourceSet; import org.jetbrains.annotations.ApiStatus; @@ -43,6 +42,7 @@ import net.fabricmc.loom.LoomGradleExtension; import net.fabricmc.loom.configuration.providers.minecraft.MinecraftSourceSets; import net.fabricmc.loom.util.Constants; import net.fabricmc.loom.util.OperatingSystem; +import net.fabricmc.loom.util.gradle.SourceSetHelper; public final class RunConfigSettings implements Named { /** @@ -110,7 +110,7 @@ public final class RunConfigSettings implements Named { setSource(p -> { final String sourceSetName = MinecraftSourceSets.get(p).getSourceSetForEnv(getEnvironment()); - return p.getExtensions().getByType(JavaPluginExtension.class).getSourceSets().getByName(sourceSetName); + return SourceSetHelper.getSourceSetByName(sourceSetName, p); }); runDir("run"); @@ -252,7 +252,7 @@ public final class RunConfigSettings implements Named { } public void source(String source) { - setSource(proj -> project.getExtensions().getByType(JavaPluginExtension.class).getSourceSets().getByName(source)); + setSource(proj -> SourceSetHelper.getSourceSetByName(source, proj)); } public void ideConfigGenerated(boolean ideConfigGenerated) { diff --git a/src/main/java/net/fabricmc/loom/configuration/ifaceinject/InterfaceInjectionProcessor.java b/src/main/java/net/fabricmc/loom/configuration/ifaceinject/InterfaceInjectionProcessor.java index 082e3aa9..40be05c2 100644 --- a/src/main/java/net/fabricmc/loom/configuration/ifaceinject/InterfaceInjectionProcessor.java +++ b/src/main/java/net/fabricmc/loom/configuration/ifaceinject/InterfaceInjectionProcessor.java @@ -57,8 +57,8 @@ import org.objectweb.asm.commons.Remapper; import net.fabricmc.loom.LoomGradleExtension; import net.fabricmc.loom.LoomGradlePlugin; import net.fabricmc.loom.api.InterfaceInjectionExtensionAPI; +import net.fabricmc.loom.api.RemapConfigurationSettings; import net.fabricmc.loom.api.mappings.layered.MappingsNamespace; -import net.fabricmc.loom.configuration.RemappedConfigurationEntry; import net.fabricmc.loom.configuration.processors.JarProcessor; import net.fabricmc.loom.task.GenerateSourcesTask; import net.fabricmc.loom.util.Checksum; @@ -183,16 +183,9 @@ public class InterfaceInjectionProcessor implements JarProcessor, GenerateSource private List getDependencyInjectedInterfaces() { List result = new ArrayList<>(); - for (RemappedConfigurationEntry entry : Constants.MOD_COMPILE_ENTRIES) { - // Only apply injected interfaces from mods that are part of the compile and runtime classpath. - // Runtime is also required to ensure that the interface and it's impl is present when running the mc jar. - if (!(entry.compileClasspath() && entry.runtimeClasspath())) { - continue; - } - - Set artifacts = extension.getLazyConfigurationProvider(entry.sourceConfiguration()) - .get() - .resolve(); + // Only apply injected interfaces from mods that are part of the compile classpath + for (RemapConfigurationSettings entry : extension.getCompileRemapConfigurations()) { + final Set artifacts = entry.getSourceConfiguration().get().resolve(); for (File artifact : artifacts) { result.addAll(InjectedInterface.fromModJar(artifact.toPath())); diff --git a/src/main/java/net/fabricmc/loom/configuration/mods/ArtifactRef.java b/src/main/java/net/fabricmc/loom/configuration/mods/ArtifactRef.java new file mode 100644 index 00000000..1e6798d0 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/configuration/mods/ArtifactRef.java @@ -0,0 +1,111 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2022 FabricMC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package net.fabricmc.loom.configuration.mods; + +import static net.fabricmc.loom.configuration.mods.ModConfigurationRemapper.MISSING_GROUP; +import static net.fabricmc.loom.configuration.mods.ModConfigurationRemapper.replaceIfNullOrEmpty; + +import java.nio.file.Path; + +import org.gradle.api.Project; +import org.gradle.api.artifacts.Configuration; +import org.gradle.api.artifacts.Dependency; +import org.gradle.api.artifacts.ModuleDependency; +import org.gradle.api.artifacts.ResolvedArtifact; +import org.gradle.api.artifacts.dsl.DependencyHandler; +import org.jetbrains.annotations.Nullable; + +import net.fabricmc.loom.util.Checksum; + +public interface ArtifactRef { + Path path(); + + @Nullable Path sources(); + + String name(); + + String group(); + + String version(); + + @Nullable String classifier(); + + void applyToConfiguration(Project project, Configuration configuration); + + record ResolvedArtifactRef(ResolvedArtifact artifact, @Nullable Path sources) implements ArtifactRef { + @Override + public Path path() { + return artifact.getFile().toPath(); + } + + public String group() { + return replaceIfNullOrEmpty(artifact.getModuleVersion().getId().getGroup(), () -> MISSING_GROUP); + } + + public String name() { + return artifact.getModuleVersion().getId().getName(); + } + + public String version() { + return replaceIfNullOrEmpty(artifact.getModuleVersion().getId().getVersion(), () -> Checksum.truncatedSha256(artifact.getFile())); + } + + public String classifier() { + return artifact.getClassifier(); + } + + @Override + public void applyToConfiguration(Project project, Configuration configuration) { + final DependencyHandler dependencies = project.getDependencies(); + + Dependency dep = dependencies.module(artifact.getModuleVersion() + (artifact.getClassifier() == null ? "" : ':' + artifact.getClassifier())); // the owning module of the artifact + + if (dep instanceof ModuleDependency moduleDependency) { + moduleDependency.setTransitive(false); + } + + dependencies.add(configuration.getName(), dep); + } + } + + record FileArtifactRef(Path path, String group, String name, String version) implements ArtifactRef { + @Override + public @Nullable Path sources() { + return null; + } + + @Override + public @Nullable String classifier() { + return null; + } + + @Override + public void applyToConfiguration(Project project, Configuration configuration) { + final DependencyHandler dependencies = project.getDependencies(); + + dependencies.add(configuration.getName(), project.files(path.toFile())); + } + } +} diff --git a/src/main/java/net/fabricmc/loom/configuration/mods/ModConfigurationRemapper.java b/src/main/java/net/fabricmc/loom/configuration/mods/ModConfigurationRemapper.java new file mode 100644 index 00000000..8a2a2dbd --- /dev/null +++ b/src/main/java/net/fabricmc/loom/configuration/mods/ModConfigurationRemapper.java @@ -0,0 +1,196 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2019-2022 FabricMC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package net.fabricmc.loom.configuration.mods; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; +import java.util.function.Supplier; + +import com.google.common.io.Files; +import org.gradle.api.Project; +import org.gradle.api.artifacts.Configuration; +import org.gradle.api.artifacts.FileCollectionDependency; +import org.gradle.api.artifacts.ResolvedArtifact; +import org.gradle.api.artifacts.dsl.DependencyHandler; +import org.gradle.api.artifacts.query.ArtifactResolutionQuery; +import org.gradle.api.artifacts.result.ArtifactResult; +import org.gradle.api.artifacts.result.ComponentArtifactsResult; +import org.gradle.api.artifacts.result.ResolvedArtifactResult; +import org.gradle.api.file.FileCollection; +import org.gradle.api.plugins.JavaPlugin; +import org.gradle.jvm.JvmLibrary; +import org.gradle.language.base.artifact.SourcesArtifact; +import org.jetbrains.annotations.Nullable; + +import net.fabricmc.loom.LoomGradleExtension; +import net.fabricmc.loom.LoomGradlePlugin; +import net.fabricmc.loom.api.RemapConfigurationSettings; +import net.fabricmc.loom.configuration.processors.dependency.ModDependencyInfo; +import net.fabricmc.loom.configuration.processors.dependency.RemapData; +import net.fabricmc.loom.util.Checksum; +import net.fabricmc.loom.util.Constants; +import net.fabricmc.loom.util.ModUtils; +import net.fabricmc.loom.util.OperatingSystem; +import net.fabricmc.loom.util.SourceRemapper; + +@SuppressWarnings("UnstableApiUsage") +public class ModConfigurationRemapper { + // This is a placeholder that is used when the actual group is missing (null or empty). + // This can happen when the dependency is a FileCollectionDependency or from a flatDir repository. + public static final String MISSING_GROUP = "unspecified"; + + public static void supplyModConfigurations(Project project, String mappingsSuffix, LoomGradleExtension extension, SourceRemapper sourceRemapper) { + final DependencyHandler dependencies = project.getDependencies(); + final boolean refreshDeps = LoomGradlePlugin.refreshDeps; + + final File modStore = extension.getFiles().getRemappedModCache(); + final RemapData remapData = new RemapData(mappingsSuffix, modStore); + + for (RemapConfigurationSettings entry : extension.getRemapConfigurations()) { + entry.getRemappedConfiguration().configure(remappedConfig -> { + /* + sourceConfig - The source configuration where the intermediary named artifacts come from. i.e "modApi" + remappedConfig - an intermediate configuration where the remapped artifacts go + targetConfig - extends from the remappedConfig, such as "api" + */ + final Configuration sourceConfig = entry.getSourceConfiguration().get(); + final Configuration targetConfig = entry.getTargetConfiguration().get(); + final boolean hasClientTarget = entry.getClientTargetConfigurationName().isPresent(); + + Configuration clientRemappedConfig = null; + + if (hasClientTarget) { + clientRemappedConfig = entry.getClientTargetConfiguration().get(); + } + + final List modDependencies = new ArrayList<>(); + + for (ArtifactRef artifact : resolveArtifacts(project, sourceConfig)) { + if (!ModUtils.isMod(artifact.path())) { + artifact.applyToConfiguration(project, targetConfig); + continue; + } + + final ModDependencyInfo info = new ModDependencyInfo(artifact, remappedConfig, clientRemappedConfig, remapData); + + if (refreshDeps) { + info.forceRemap(); + } + + if (artifact.sources() != null) { + scheduleSourcesRemapping(project, sourceRemapper, artifact.sources().toFile(), info.getRemappedOutput("sources")); + } + + modDependencies.add(info); + } + + if (modDependencies.isEmpty()) { + return; + } + + try { + new ModProcessor(project, sourceConfig).processMods(modDependencies); + } catch (IOException e) { + // Failed to remap, lets clean up to ensure we try again next time + modDependencies.forEach(info -> info.getRemappedOutput().delete()); + throw new RuntimeException("Failed to remap mods", e); + } + + // Add all of the remapped mods onto the config + for (ModDependencyInfo info : modDependencies) { + project.getDependencies().add(info.targetConfig.getName(), info.getRemappedNotation()); + } + + // Export to other projects + if (entry.getTargetConfigurationName().get().equals(JavaPlugin.API_CONFIGURATION_NAME)) { + project.getConfigurations().getByName(Constants.Configurations.NAMED_ELEMENTS).extendsFrom(remappedConfig); + } + }); + } + } + + private static List resolveArtifacts(Project project, Configuration configuration) { + final List artifacts = new ArrayList<>(); + + for (ResolvedArtifact artifact : configuration.getResolvedConfiguration().getResolvedArtifacts()) { + final Path sources = findSources(project, artifact); + artifacts.add(new ArtifactRef.ResolvedArtifactRef(artifact, sources)); + } + + // FileCollectionDependency (files/fileTree) doesn't resolve properly, + // so we have to "resolve" it on our own. The naming is "abc.jar" => "unspecified:abc:unspecified". + for (FileCollectionDependency dependency : configuration.getAllDependencies().withType(FileCollectionDependency.class)) { + final String group = replaceIfNullOrEmpty(dependency.getGroup(), () -> MISSING_GROUP); + final FileCollection files = dependency.getFiles(); + + for (File artifact : files) { + final String name = Files.getNameWithoutExtension(artifact.getAbsolutePath()); + final String version = replaceIfNullOrEmpty(dependency.getVersion(), () -> Checksum.truncatedSha256(artifact)); + + artifacts.add(new ArtifactRef.FileArtifactRef(artifact.toPath(), group, name, version)); + } + } + + return artifacts; + } + + @Nullable + public static Path findSources(Project project, ResolvedArtifact artifact) { + final DependencyHandler dependencies = project.getDependencies(); + + @SuppressWarnings("unchecked") ArtifactResolutionQuery query = dependencies.createArtifactResolutionQuery() + .forComponents(artifact.getId().getComponentIdentifier()) + .withArtifacts(JvmLibrary.class, SourcesArtifact.class); + + for (ComponentArtifactsResult result : query.execute().getResolvedComponents()) { + for (ArtifactResult srcArtifact : result.getArtifacts(SourcesArtifact.class)) { + if (srcArtifact instanceof ResolvedArtifactResult) { + return ((ResolvedArtifactResult) srcArtifact).getFile().toPath(); + } + } + } + + return null; + } + + private static void scheduleSourcesRemapping(Project project, SourceRemapper sourceRemapper, File input, File output) { + if (OperatingSystem.isCIBuild()) { + return; + } + + if (!output.exists() || input.lastModified() <= 0 || input.lastModified() > output.lastModified() || LoomGradlePlugin.refreshDeps) { + sourceRemapper.scheduleRemapSources(input, output, false, true); // Depenedency sources are used in ide only so don't need to be reproducable + } else { + project.getLogger().info(output.getName() + " is up to date with " + input.getName()); + } + } + + public static String replaceIfNullOrEmpty(@Nullable String s, Supplier fallback) { + return s == null || s.isEmpty() ? fallback.get() : s; + } +} diff --git a/src/main/java/net/fabricmc/loom/configuration/mods/ModJavadocProcessor.java b/src/main/java/net/fabricmc/loom/configuration/mods/ModJavadocProcessor.java index 5de70544..be64e7a2 100644 --- a/src/main/java/net/fabricmc/loom/configuration/mods/ModJavadocProcessor.java +++ b/src/main/java/net/fabricmc/loom/configuration/mods/ModJavadocProcessor.java @@ -42,8 +42,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import net.fabricmc.loom.LoomGradleExtension; +import net.fabricmc.loom.api.RemapConfigurationSettings; import net.fabricmc.loom.api.mappings.layered.MappingsNamespace; -import net.fabricmc.loom.configuration.RemappedConfigurationEntry; import net.fabricmc.loom.configuration.processors.JarProcessor; import net.fabricmc.loom.task.GenerateSourcesTask; import net.fabricmc.loom.util.Constants; @@ -75,10 +75,8 @@ public final class ModJavadocProcessor implements JarProcessor, GenerateSourcesT final List javadocs = new ArrayList<>(); - for (RemappedConfigurationEntry entry : Constants.MOD_COMPILE_ENTRIES) { - Set artifacts = extension.getLazyConfigurationProvider(entry.sourceConfiguration()) - .get() - .resolve(); + for (RemapConfigurationSettings entry : extension.getRemapConfigurations()) { + final Set artifacts = entry.getSourceConfiguration().get().resolve(); for (File artifact : artifacts) { if (!ModUtils.isMod(artifact.toPath(), platform)) { diff --git a/src/main/java/net/fabricmc/loom/configuration/mods/ModProcessor.java b/src/main/java/net/fabricmc/loom/configuration/mods/ModProcessor.java index a8175582..86dde13d 100644 --- a/src/main/java/net/fabricmc/loom/configuration/mods/ModProcessor.java +++ b/src/main/java/net/fabricmc/loom/configuration/mods/ModProcessor.java @@ -44,14 +44,15 @@ import dev.architectury.tinyremapper.NonClassCopyMode; import dev.architectury.tinyremapper.OutputConsumerPath; import dev.architectury.tinyremapper.TinyRemapper; import org.gradle.api.Project; +import org.gradle.api.artifacts.Configuration; import org.objectweb.asm.commons.Remapper; import net.fabricmc.accesswidener.AccessWidenerReader; import net.fabricmc.accesswidener.AccessWidenerRemapper; import net.fabricmc.accesswidener.AccessWidenerWriter; import net.fabricmc.loom.LoomGradleExtension; +import net.fabricmc.loom.api.RemapConfigurationSettings; import net.fabricmc.loom.api.mappings.layered.MappingsNamespace; -import net.fabricmc.loom.configuration.RemappedConfigurationEntry; import net.fabricmc.loom.configuration.processors.dependency.ModDependencyInfo; import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl; import net.fabricmc.loom.task.RemapJarTask; @@ -70,9 +71,11 @@ public class ModProcessor { private static final String toM = MappingsNamespace.NAMED.toString(); private final Project project; + private final Configuration sourceConfiguration; - public ModProcessor(Project project) { + public ModProcessor(Project project, Configuration sourceConfiguration) { this.project = project; + this.sourceConfiguration = sourceConfiguration; } public void processMods(List processList) throws IOException { @@ -93,6 +96,7 @@ public class ModProcessor { } try { + project.getLogger().lifecycle(":remapping %d mods from %s".formatted(remapList.size(), sourceConfiguration.getName())); remapJars(remapList); } catch (Exception e) { project.getLogger().error("Failed to remap %d mods".formatted(remapList.size()), e); @@ -170,7 +174,6 @@ public class ModProcessor { .stream().map(File::toPath).toArray(Path[]::new); Stopwatch stopwatch = Stopwatch.createStarted(); - project.getLogger().lifecycle(":remapping " + remapList.size() + " mods (TinyRemapper, " + fromM + " -> " + toM + ")"); MemoryMappingTree mappings = (fromM.equals("srg") || toM.equals("srg")) && extension.isForge() ? mappingsProvider.getMappingsWithSrg() : mappingsProvider.getMappings(); LoggerFilter.replaceSystemOut(); @@ -200,8 +203,8 @@ public class ModProcessor { final Map outputConsumerMap = new HashMap<>(); final Map accessWidenerMap = new HashMap<>(); - for (RemappedConfigurationEntry entry : Constants.MOD_COMPILE_ENTRIES) { - for (File inputFile : project.getConfigurations().getByName(entry.sourceConfiguration()).getFiles()) { + for (RemapConfigurationSettings entry : extension.getRemapConfigurations()) { + for (File inputFile : entry.getSourceConfiguration().get().getFiles()) { if (remapList.stream().noneMatch(info -> info.getInputFile().equals(inputFile))) { project.getLogger().debug("Adding " + inputFile + " onto the remap classpath"); diff --git a/src/main/java/net/fabricmc/loom/configuration/processors/dependency/ModDependencyInfo.java b/src/main/java/net/fabricmc/loom/configuration/processors/dependency/ModDependencyInfo.java index 7108f65c..fd958c5d 100644 --- a/src/main/java/net/fabricmc/loom/configuration/processors/dependency/ModDependencyInfo.java +++ b/src/main/java/net/fabricmc/loom/configuration/processors/dependency/ModDependencyInfo.java @@ -40,16 +40,19 @@ import org.jetbrains.annotations.Nullable; import net.fabricmc.accesswidener.AccessWidenerReader; import net.fabricmc.loom.LoomGradlePlugin; import net.fabricmc.loom.api.mappings.layered.MappingsNamespace; +import net.fabricmc.loom.configuration.mods.ArtifactRef; import net.fabricmc.loom.util.ZipUtils; public class ModDependencyInfo { + private final ArtifactRef artifact; private final String group; public final String name; public final String version; @Nullable public final String classifier; - public final File inputFile; public final Configuration targetConfig; + @Nullable + public final Configuration targetClientConfig; public final RemapData remapData; @Nullable @@ -57,22 +60,27 @@ public class ModDependencyInfo { private boolean forceRemap = false; - public ModDependencyInfo(String group, String name, String version, @Nullable String classifier, File inputFile, Configuration targetConfig, RemapData remapData) { - this.group = group; - this.name = name; - this.version = version; - this.classifier = classifier; - this.inputFile = inputFile; + public ModDependencyInfo(ArtifactRef artifact, Configuration targetConfig, @Nullable Configuration targetClientConfig, RemapData remapData) { + this.artifact = artifact; + this.group = artifact.group(); + this.name = artifact.name(); + this.version = artifact.version(); + this.classifier = artifact.classifier(); this.targetConfig = targetConfig; + this.targetClientConfig = targetClientConfig; this.remapData = remapData; try { - this.accessWidenerData = tryReadAccessWidenerData(getInputFile().toPath()); + this.accessWidenerData = readAccessWidenerData(artifact.path()); } catch (IOException e) { - throw new UncheckedIOException("Failed to read access widener data from" + inputFile, e); + throw new UncheckedIOException("Failed to read access widener data from" + artifact.path(), e); } } + public ArtifactRef getArtifact() { + return artifact; + } + public String getRemappedNotation() { if (!hasClassifier()) { return String.format("%s:%s:%s", getGroup(), name, version); @@ -114,7 +122,7 @@ public class ModDependencyInfo { } public File getInputFile() { - return inputFile; + return artifact.path().toFile(); } private boolean outputHasInvalidAccessWidener() { @@ -127,7 +135,7 @@ public class ModDependencyInfo { final AccessWidenerData outputAWData; try { - outputAWData = tryReadAccessWidenerData(getRemappedOutput().toPath()); + outputAWData = readAccessWidenerData(getRemappedOutput().toPath()); } catch (IOException e) { throw new UncheckedIOException("Failed to read output access widener data from " + getRemappedOutput(), e); } @@ -142,11 +150,13 @@ public class ModDependencyInfo { } public boolean requiresRemapping() { - return !getRemappedOutput().exists() || inputFile.lastModified() <= 0 || inputFile.lastModified() > getRemappedOutput().lastModified() || forceRemap || !getRemappedPom().exists() || outputHasInvalidAccessWidener(); + final File inputFile = artifact.path().toFile(); + final long lastModified = inputFile.lastModified(); + return !getRemappedOutput().exists() || lastModified <= 0 || lastModified > getRemappedOutput().lastModified() || forceRemap || !getRemappedPom().exists() || outputHasInvalidAccessWidener(); } public void finaliseRemapping() { - getRemappedOutput().setLastModified(inputFile.lastModified()); + getRemappedOutput().setLastModified(artifact.path().toFile().lastModified()); savePom(); // Validate that the remapped AW is what we want. @@ -192,7 +202,7 @@ public class ModDependencyInfo { return accessWidenerData; } - private static AccessWidenerData tryReadAccessWidenerData(Path inputJar) throws IOException { + private static AccessWidenerData readAccessWidenerData(Path inputJar) throws IOException { String fieldName = "accessWidener"; byte[] modJsonBytes = ZipUtils.unpackNullable(inputJar, "fabric.mod.json"); @@ -211,7 +221,6 @@ public class ModDependencyInfo { } } } - JsonObject jsonObject = LoomGradlePlugin.GSON.fromJson(new String(modJsonBytes, StandardCharsets.UTF_8), JsonObject.class); if (!jsonObject.has(fieldName)) { diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftLibraryProvider.java b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftLibraryProvider.java index e88518b4..3d155030 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftLibraryProvider.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftLibraryProvider.java @@ -55,7 +55,7 @@ public class MinecraftLibraryProvider { } if (hasNativesToExtract) { - extension.createLazyConfiguration(Constants.Configurations.MINECRAFT_NATIVES, configuration -> configuration.setTransitive(false)); + project.getConfigurations().register(Constants.Configurations.MINECRAFT_NATIVES, configuration -> configuration.setTransitive(false)); } for (MinecraftVersionMeta.Library library : versionInfo.libraries()) { diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftSourceSets.java b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftSourceSets.java index 576a243e..7d058ea6 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftSourceSets.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftSourceSets.java @@ -32,13 +32,14 @@ import java.util.function.BiConsumer; import com.google.common.base.Preconditions; import org.gradle.api.Project; import org.gradle.api.plugins.JavaPlugin; -import org.gradle.api.plugins.JavaPluginExtension; import org.gradle.api.tasks.SourceSet; import org.gradle.jvm.tasks.Jar; import net.fabricmc.loom.LoomGradleExtension; +import net.fabricmc.loom.configuration.RemapConfigurations; import net.fabricmc.loom.task.AbstractRemapJarTask; import net.fabricmc.loom.util.Constants; +import net.fabricmc.loom.util.gradle.SourceSetHelper; public abstract sealed class MinecraftSourceSets permits MinecraftSourceSets.Single, MinecraftSourceSets.Split { public static MinecraftSourceSets get(Project project) { @@ -63,10 +64,8 @@ public abstract sealed class MinecraftSourceSets permits MinecraftSourceSets.Sin public abstract void afterEvaluate(Project project); protected void createSourceSets(Project project) { - final LoomGradleExtension extension = LoomGradleExtension.get(project); - for (String name : getAllSourceSetNames()) { - extension.createLazyConfiguration(name, configuration -> configuration.setTransitive(false)); + project.getConfigurations().register(name, configuration -> configuration.setTransitive(false)); // All the configurations extend the loader deps. extendsFrom(name, Constants.Configurations.LOADER_DEPENDENCIES, project); @@ -164,12 +163,9 @@ public abstract sealed class MinecraftSourceSets permits MinecraftSourceSets.Sin extendsFrom(MINECRAFT_COMBINED_NAMED, MINECRAFT_COMMON_NAMED, project); extendsFrom(MINECRAFT_COMBINED_NAMED, MINECRAFT_CLIENT_ONLY_NAMED, project); - final JavaPluginExtension javaExtension = project.getExtensions().getByType(JavaPluginExtension.class); - final LoomGradleExtension loomExtension = LoomGradleExtension.get(project); - // Register our new client only source set, main becomes common only, with their respective jars. - SourceSet mainSourceSet = javaExtension.getSourceSets().getByName(SourceSet.MAIN_SOURCE_SET_NAME); - SourceSet clientOnlySourceSet = javaExtension.getSourceSets().create(CLIENT_ONLY_SOURCE_SET_NAME); + SourceSet mainSourceSet = SourceSetHelper.getMainSourceSet(project); + SourceSet clientOnlySourceSet = SourceSetHelper.createSourceSet(CLIENT_ONLY_SOURCE_SET_NAME, project); extendsFrom(List.of( mainSourceSet.getCompileClasspathConfigurationName(), @@ -196,6 +192,8 @@ public abstract sealed class MinecraftSourceSets permits MinecraftSourceSets.Sin .plus(mainSourceSet.getOutput()) ); + RemapConfigurations.configureClientConfigurations(project, clientOnlySourceSet); + // Include the client only output in the jars project.getTasks().named(mainSourceSet.getJarTaskName(), Jar.class).configure(jar -> { jar.from(clientOnlySourceSet.getOutput().getClassesDirs()); @@ -227,9 +225,7 @@ public abstract sealed class MinecraftSourceSets permits MinecraftSourceSets.Sin public static SourceSet getClientSourceSet(Project project) { Preconditions.checkArgument(LoomGradleExtension.get(project).areEnvironmentSourceSetsSplit(), "Cannot get client only sourceset as project is not split"); - - final JavaPluginExtension javaExtension = project.getExtensions().getByType(JavaPluginExtension.class); - return javaExtension.getSourceSets().getByName(CLIENT_ONLY_SOURCE_SET_NAME); + return SourceSetHelper.getSourceSetByName(CLIENT_ONLY_SOURCE_SET_NAME, project); } } } diff --git a/src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionApiImpl.java b/src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionApiImpl.java index 3a1ab4c4..2a960235 100644 --- a/src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionApiImpl.java +++ b/src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionApiImpl.java @@ -34,11 +34,11 @@ import java.util.function.Consumer; import com.google.common.base.Suppliers; import org.gradle.api.Action; import org.gradle.api.NamedDomainObjectContainer; +import org.gradle.api.NamedDomainObjectList; import org.gradle.api.Project; import org.gradle.api.artifacts.Dependency; import org.gradle.api.file.ConfigurableFileCollection; import org.gradle.api.file.RegularFileProperty; -import org.gradle.api.plugins.JavaPluginExtension; import org.gradle.api.provider.ListProperty; import org.gradle.api.provider.Property; import org.gradle.api.provider.Provider; @@ -50,9 +50,11 @@ import net.fabricmc.loom.api.InterfaceInjectionExtensionAPI; import net.fabricmc.loom.api.LoomGradleExtensionAPI; import net.fabricmc.loom.api.MixinExtensionAPI; import net.fabricmc.loom.api.ModSettings; +import net.fabricmc.loom.api.RemapConfigurationSettings; import net.fabricmc.loom.api.decompilers.DecompilerOptions; import net.fabricmc.loom.api.mappings.intermediate.IntermediateMappingsProvider; import net.fabricmc.loom.api.mappings.layered.spec.LayeredMappingSpecBuilder; +import net.fabricmc.loom.configuration.RemapConfigurations; import net.fabricmc.loom.configuration.ide.RunConfig; import net.fabricmc.loom.configuration.ide.RunConfigSettings; import net.fabricmc.loom.configuration.launch.LaunchProviderSettings; @@ -66,6 +68,7 @@ import net.fabricmc.loom.configuration.providers.minecraft.MinecraftJarConfigura import net.fabricmc.loom.configuration.providers.minecraft.MinecraftSourceSets; import net.fabricmc.loom.util.DeprecationHelper; import net.fabricmc.loom.util.ModPlatform; +import net.fabricmc.loom.util.gradle.SourceSetHelper; /** * This class implements the public extension api. @@ -96,6 +99,7 @@ public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionA private final NamedDomainObjectContainer runConfigs; private final NamedDomainObjectContainer decompilers; private final NamedDomainObjectContainer mods; + private final NamedDomainObjectList remapConfigurations; // A common mistake with layered mappings is to call the wrong `officialMojangMappings` method, use this to keep track of when we are building a layered mapping spec. protected final ThreadLocal layeredSpecBuilderScope = ThreadLocal.withInitial(() -> false); @@ -142,6 +146,7 @@ public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionA baseName -> new RunConfigSettings(project, baseName)); this.decompilers = project.getObjects().domainObjectContainer(DecompilerOptions.class); this.mods = project.getObjects().domainObjectContainer(ModSettings.class); + this.remapConfigurations = project.getObjects().namedDomainObjectList(RemapConfigurationSettings.class); this.minecraftJarConfiguration = project.getObjects().property(MinecraftJarConfiguration.class).convention(MinecraftJarConfiguration.MERGED); this.minecraftJarConfiguration.finalizeValueOnRead(); @@ -159,8 +164,7 @@ public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionA // Add main source set by default interfaceInjection(interfaceInjection -> { - final JavaPluginExtension javaPluginExtension = project.getExtensions().getByType(JavaPluginExtension.class); - final SourceSet main = javaPluginExtension.getSourceSets().getByName(SourceSet.MAIN_SOURCE_SET_NAME); + final SourceSet main = SourceSetHelper.getMainSourceSet(project); interfaceInjection.getInterfaceInjectionSourceSets().add(main); interfaceInjection.getInterfaceInjectionSourceSets().finalizeValueOnRead(); @@ -372,6 +376,27 @@ public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionA return mods; } + @Override + public NamedDomainObjectList getRemapConfigurations() { + return remapConfigurations; + } + + @Override + public RemapConfigurationSettings addRemapConfiguration(String name, Action action) { + final RemapConfigurationSettings configurationSettings = getProject().getObjects().newInstance(RemapConfigurationSettings.class, name); + + action.execute(configurationSettings); + RemapConfigurations.applyToProject(getProject(), configurationSettings); + remapConfigurations.add(configurationSettings); + + return configurationSettings; + } + + @Override + public void createRemapConfigurations(SourceSet sourceSet) { + RemapConfigurations.setupForSourceSet(getProject(), sourceSet); + } + @Override public void silentMojangMappingsLicense() { this.silentMojangMappingsLicense = true; diff --git a/src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionImpl.java b/src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionImpl.java index 4951fe37..7710bd83 100644 --- a/src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionImpl.java +++ b/src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionImpl.java @@ -26,19 +26,14 @@ package net.fabricmc.loom.extension; import java.nio.file.Path; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.Objects; import java.util.function.Supplier; import com.google.common.base.Suppliers; import org.cadixdev.lorenz.MappingSet; import org.cadixdev.mercury.Mercury; -import org.gradle.api.Action; -import org.gradle.api.NamedDomainObjectProvider; import org.gradle.api.Project; -import org.gradle.api.artifacts.Configuration; import org.gradle.api.file.ConfigurableFileCollection; import org.gradle.api.file.FileCollection; @@ -68,7 +63,6 @@ public class LoomGradleExtensionImpl extends LoomGradleExtensionApiImpl implemen private final MappingSet[] srcMappingCache = new MappingSet[2]; private final Mercury[] srcMercuryCache = new Mercury[2]; - private final Map> lazyConfigurations = new HashMap<>(); private final List transitiveAccessWideners = new ArrayList<>(); private LoomDependencyManager dependencyManager; @@ -222,30 +216,6 @@ public class LoomGradleExtensionImpl extends LoomGradleExtensionApiImpl implemen return project.getRootProject() == project; } - @Override - public NamedDomainObjectProvider createLazyConfiguration(String name, Action configurationAction) { - NamedDomainObjectProvider provider = project.getConfigurations().register(name, configurationAction); - - if (lazyConfigurations.containsKey(name)) { - throw new IllegalStateException("Duplicate configuration name" + name); - } - - lazyConfigurations.put(name, provider); - - return provider; - } - - @Override - public NamedDomainObjectProvider getLazyConfigurationProvider(String name) { - NamedDomainObjectProvider provider = lazyConfigurations.get(name); - - if (provider == null) { - throw new NullPointerException("Could not find provider with name: " + name); - } - - return provider; - } - @Override public MixinExtension getMixin() { return this.mixinApExtension; diff --git a/src/main/java/net/fabricmc/loom/task/RemapTaskConfiguration.java b/src/main/java/net/fabricmc/loom/task/RemapTaskConfiguration.java index 07982cc7..69f304b6 100644 --- a/src/main/java/net/fabricmc/loom/task/RemapTaskConfiguration.java +++ b/src/main/java/net/fabricmc/loom/task/RemapTaskConfiguration.java @@ -33,8 +33,6 @@ import org.gradle.api.Task; import org.gradle.api.artifacts.Configuration; import org.gradle.api.plugins.BasePlugin; import org.gradle.api.plugins.JavaPlugin; -import org.gradle.api.plugins.JavaPluginExtension; -import org.gradle.api.tasks.SourceSet; import org.gradle.api.tasks.TaskContainer; import org.gradle.api.tasks.TaskProvider; import org.gradle.api.tasks.bundling.AbstractArchiveTask; @@ -44,6 +42,7 @@ import net.fabricmc.loom.LoomGradleExtension; import net.fabricmc.loom.util.Constants; import net.fabricmc.loom.util.PropertyUtil; import net.fabricmc.loom.util.aw2at.Aw2At; +import net.fabricmc.loom.util.gradle.SourceSetHelper; public class RemapTaskConfiguration { public static final String REMAP_JAR_TASK_NAME = "remapJar"; @@ -123,8 +122,7 @@ public class RemapTaskConfiguration { private static void trySetupSourceRemapping(Project project) { final TaskContainer tasks = project.getTasks(); final LoomGradleExtension extension = LoomGradleExtension.get(project); - final JavaPluginExtension javaExtension = project.getExtensions().getByType(JavaPluginExtension.class); - final String sourcesJarTaskName = javaExtension.getSourceSets().getByName(SourceSet.MAIN_SOURCE_SET_NAME).getSourcesJarTaskName(); + final String sourcesJarTaskName = SourceSetHelper.getMainSourceSet(project).getSourcesJarTaskName(); TaskProvider remapSourcesTask = tasks.register(REMAP_SOURCES_JAR_TASK_NAME, RemapSourcesJarTask.class, task -> { task.setDescription("Remaps the default sources jar to intermediary mappings."); diff --git a/src/main/java/net/fabricmc/loom/task/launch/GenerateRemapClasspathTask.java b/src/main/java/net/fabricmc/loom/task/launch/GenerateRemapClasspathTask.java index d97b5ab9..8077cd35 100644 --- a/src/main/java/net/fabricmc/loom/task/launch/GenerateRemapClasspathTask.java +++ b/src/main/java/net/fabricmc/loom/task/launch/GenerateRemapClasspathTask.java @@ -1,7 +1,7 @@ /* * This file is part of fabric-loom, licensed under the MIT License (MIT). * - * Copyright (c) 2021 FabricMC + * Copyright (c) 2021-2022 FabricMC * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -32,25 +32,40 @@ import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; +import org.gradle.api.artifacts.ConfigurationContainer; +import org.gradle.api.file.ConfigurableFileCollection; +import org.gradle.api.file.RegularFileProperty; +import org.gradle.api.tasks.InputFiles; +import org.gradle.api.tasks.OutputFile; import org.gradle.api.tasks.TaskAction; +import net.fabricmc.loom.api.RemapConfigurationSettings; import net.fabricmc.loom.api.mappings.layered.MappingsNamespace; -import net.fabricmc.loom.configuration.RemappedConfigurationEntry; import net.fabricmc.loom.task.AbstractLoomTask; import net.fabricmc.loom.util.Constants; public abstract class GenerateRemapClasspathTask extends AbstractLoomTask { + @InputFiles + public abstract ConfigurableFileCollection getRemapClasspath(); + + @OutputFile + public abstract RegularFileProperty getRemapClasspathFile(); + + public GenerateRemapClasspathTask() { + final ConfigurationContainer configurations = getProject().getConfigurations(); + + getRemapClasspath().from(configurations.named(Constants.Configurations.LOADER_DEPENDENCIES)); + getExtension().getRuntimeRemapConfigurations().stream() + .map(RemapConfigurationSettings::getName) + .map(configurations::named) + .forEach(getRemapClasspath()::from); + + getRemapClasspathFile().set(getExtension().getFiles().getRemapClasspathFile()); + } + @TaskAction public void run() { - List inputConfigurations = new ArrayList<>(); - inputConfigurations.add(Constants.Configurations.LOADER_DEPENDENCIES); - inputConfigurations.addAll(Constants.MOD_COMPILE_ENTRIES.stream().map(RemappedConfigurationEntry::sourceConfiguration).toList()); - - List remapClasspath = new ArrayList<>(); - - for (String inputConfiguration : inputConfigurations) { - remapClasspath.addAll(getProject().getConfigurations().getByName(inputConfiguration).getFiles()); - } + final List remapClasspath = new ArrayList<>(getRemapClasspath().getFiles()); for (Path minecraftJar : getExtension().getMinecraftJars(MappingsNamespace.INTERMEDIARY)) { remapClasspath.add(minecraftJar.toFile()); @@ -61,7 +76,7 @@ public abstract class GenerateRemapClasspathTask extends AbstractLoomTask { .collect(Collectors.joining(File.pathSeparator)); try { - Files.writeString(getExtension().getFiles().getRemapClasspathFile().toPath(), str); + Files.writeString(getRemapClasspathFile().getAsFile().get().toPath(), str); } catch (IOException e) { throw new RuntimeException("Failed to generate remap classpath", e); } diff --git a/src/main/java/net/fabricmc/loom/util/Constants.java b/src/main/java/net/fabricmc/loom/util/Constants.java index 5ec77011..10712160 100644 --- a/src/main/java/net/fabricmc/loom/util/Constants.java +++ b/src/main/java/net/fabricmc/loom/util/Constants.java @@ -24,16 +24,9 @@ package net.fabricmc.loom.util; -import java.util.List; - -import com.google.common.collect.ImmutableList; import org.eclipse.jdt.core.JavaCore; -import org.gradle.api.plugins.JavaPlugin; import org.objectweb.asm.Opcodes; -import net.fabricmc.loom.configuration.RemappedConfigurationEntry; -import net.fabricmc.loom.configuration.RemappedConfigurationEntry.PublishingMode; - public class Constants { public static final String PLUGIN_ID = "dev.architectury.loom"; public static final String LIBRARIES_BASE = "https://libraries.minecraft.net/"; @@ -46,15 +39,6 @@ public class Constants { public static final String MERCURY_SOURCE_VERSION = JavaCore.VERSION_15; // TODO: once we update Mercury: public static final String MERCURY_SOURCE_VERSION = JavaCore.VERSION_17; - public static final List MOD_COMPILE_ENTRIES = ImmutableList.of( - new RemappedConfigurationEntry("modApi", JavaPlugin.API_CONFIGURATION_NAME, true, true, PublishingMode.COMPILE_AND_RUNTIME), - new RemappedConfigurationEntry("modImplementation", JavaPlugin.IMPLEMENTATION_CONFIGURATION_NAME, true, true, PublishingMode.RUNTIME_ONLY), - new RemappedConfigurationEntry("modCompileOnly", JavaPlugin.COMPILE_ONLY_CONFIGURATION_NAME, true, false, PublishingMode.NONE), - new RemappedConfigurationEntry("modCompileOnlyApi", JavaPlugin.COMPILE_ONLY_API_CONFIGURATION_NAME, true, false, PublishingMode.COMPILE_ONLY), - new RemappedConfigurationEntry("modRuntimeOnly", JavaPlugin.RUNTIME_ONLY_CONFIGURATION_NAME, false, true, PublishingMode.RUNTIME_ONLY), - new RemappedConfigurationEntry("modLocalRuntime", Configurations.LOCAL_RUNTIME, false, true, PublishingMode.NONE) - ); - private Constants() { } diff --git a/src/main/java/net/fabricmc/loom/util/SourceRemapper.java b/src/main/java/net/fabricmc/loom/util/SourceRemapper.java index c93f8622..bc90fd1a 100644 --- a/src/main/java/net/fabricmc/loom/util/SourceRemapper.java +++ b/src/main/java/net/fabricmc/loom/util/SourceRemapper.java @@ -40,9 +40,9 @@ import org.gradle.api.Project; import org.slf4j.Logger; import net.fabricmc.loom.LoomGradleExtension; +import net.fabricmc.loom.api.RemapConfigurationSettings; import net.fabricmc.loom.api.mappings.layered.MappingsNamespace; import net.fabricmc.loom.build.IntermediaryNamespaces; -import net.fabricmc.loom.configuration.RemappedConfigurationEntry; import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl; import net.fabricmc.loom.util.gradle.ProgressLoggerHelper; import net.fabricmc.lorenztiny.TinyMappingsReader; @@ -260,8 +260,10 @@ public class SourceRemapper { classPath.add(file.toPath()); } } else { - for (RemappedConfigurationEntry entry : Constants.MOD_COMPILE_ENTRIES) { - for (File inputFile : project.getConfigurations().getByName(entry.sourceConfiguration()).getFiles()) { + final LoomGradleExtension extension = LoomGradleExtension.get(project); + + for (RemapConfigurationSettings entry : extension.getRemapConfigurations()) { + for (File inputFile : entry.getSourceConfiguration().get().getFiles()) { classPath.add(inputFile.toPath()); } } diff --git a/src/main/java/net/fabricmc/loom/util/gradle/SourceSetHelper.java b/src/main/java/net/fabricmc/loom/util/gradle/SourceSetHelper.java index 4c544669..1ff7b21e 100644 --- a/src/main/java/net/fabricmc/loom/util/gradle/SourceSetHelper.java +++ b/src/main/java/net/fabricmc/loom/util/gradle/SourceSetHelper.java @@ -71,6 +71,20 @@ public final class SourceSetHelper { .anyMatch(test -> test == sourceSet); // Ensure we have an identical reference } + public static SourceSet getSourceSetByName(String name, Project project) { + final JavaPluginExtension javaExtension = project.getExtensions().getByType(JavaPluginExtension.class); + return javaExtension.getSourceSets().getByName(name); + } + + public static SourceSet getMainSourceSet(Project project) { + return getSourceSetByName(SourceSet.MAIN_SOURCE_SET_NAME, project); + } + + public static SourceSet createSourceSet(String name, Project project) { + final JavaPluginExtension javaExtension = project.getExtensions().getByType(JavaPluginExtension.class); + return javaExtension.getSourceSets().create(name); + } + /** * Attempts to compute the owning project for the {@link SourceSet} * diff --git a/src/test/groovy/net/fabricmc/loom/test/LoomTestConstants.groovy b/src/test/groovy/net/fabricmc/loom/test/LoomTestConstants.groovy index ea5c33ec..e98e82a2 100644 --- a/src/test/groovy/net/fabricmc/loom/test/LoomTestConstants.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/LoomTestConstants.groovy @@ -27,7 +27,7 @@ package net.fabricmc.loom.test import org.gradle.util.GradleVersion class LoomTestConstants { - private final static String NIGHTLY_VERSION = "7.6-20220519002827+0000" + private final static String NIGHTLY_VERSION = "7.6-20220620222921+0000" private final static boolean NIGHTLY_EXISTS = nightlyExists(NIGHTLY_VERSION) public final static String DEFAULT_GRADLE = GradleVersion.current().getVersion()