Merge with Fabric 0.13, stage 2

This commit is contained in:
Juuz
2022-08-09 17:25:34 +03:00
27 changed files with 820 additions and 462 deletions

View File

@@ -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<Configuration> createLazyConfiguration(String name) {
return createLazyConfiguration(name, config -> {
});
}
NamedDomainObjectProvider<Configuration> createLazyConfiguration(String name, Action<? super Configuration> configurationAction);
NamedDomainObjectProvider<Configuration> getLazyConfigurationProvider(String name);
MappingSet getOrCreateSrcMappingCache(int id, Supplier<MappingSet> factory);
Mercury getOrCreateSrcMercuryCache(int id, Supplier<Mercury> factory);

View File

@@ -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

View File

@@ -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<ModSettings> getMods();
@ApiStatus.Experimental
NamedDomainObjectList<RemapConfigurationSettings> getRemapConfigurations();
@ApiStatus.Experimental
RemapConfigurationSettings addRemapConfiguration(String name, Action<RemapConfigurationSettings> action);
void createRemapConfigurations(SourceSet sourceSet);
default List<RemapConfigurationSettings> getCompileRemapConfigurations() {
return getRemapConfigurations().stream().filter(element -> element.getOnCompileClasspath().get()).toList();
}
default List<RemapConfigurationSettings> 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();

View File

@@ -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<String> 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<String> getClientTargetConfigurationName();
/**
* @return True if this configuration's artifacts should be exposed for compile operations.
*/
public abstract Property<Boolean> getOnCompileClasspath();
/**
* @return True if this configuration's artifacts should be exposed to runtime operations.
*/
public abstract Property<Boolean> getOnRuntimeClasspath();
/**
* @return the {@link PublishingMode} for the configuration.
*/
public abstract Property<PublishingMode> 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<String> outgoingConfigurations;
PublishingMode(String... outgoingConfigurations) {
this.outgoingConfigurations = Set.of(outgoingConfigurations);
}
public Set<String> outgoingConfigurations() {
return outgoingConfigurations;
}
}
@Inject
protected abstract Project getProject();
@ApiStatus.Internal
@Internal
public final String getRemappedConfigurationName() {
return getName() + "Mapped";
}
@ApiStatus.Internal
@Internal
public final NamedDomainObjectProvider<Configuration> getSourceConfiguration() {
return getConfigurationByName(getName());
}
@ApiStatus.Internal
@Internal
public final NamedDomainObjectProvider<Configuration> getRemappedConfiguration() {
return getConfigurationByName(getRemappedConfigurationName());
}
@ApiStatus.Internal
@Internal
public final NamedDomainObjectProvider<Configuration> getTargetConfiguration() {
return getConfigurationByName(getTargetConfigurationName().get());
}
@ApiStatus.Internal
@Internal
public final Provider<Configuration> 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<Configuration> getConfigurationByName(String name) {
return getProject().getConfigurations().named(name);
}
}

View File

@@ -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<String> 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<ModDependencyInfo> 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());
}
}
}

View File

@@ -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<Configuration> 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<Configuration> 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()));
});

View File

@@ -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();

View File

@@ -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<ConfigurationOption> 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<RemapConfigurationSettings> 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.
// <https://github.com/gradle/gradle/blob/v7.4.2/subprojects/plugins/src/main/java/org/gradle/api/plugins/BasePlugin.java#L104>
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<RemapConfigurationSettings> 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<SourceSet, String> mainOnly(Function<SourceSet, String> function) {
return sourceSet -> sourceSet.getName().equals(SourceSet.MAIN_SOURCE_SET_NAME) ? function.apply(sourceSet) : null;
}
private static Function<SourceSet, String> mainOnly(String name) {
return mainOnly(sourceSet -> name);
}
private static List<ConfigurationOption> 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<SourceSet, String> 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();
}
}
}

View File

@@ -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<String> outgoingConfigurations;
PublishingMode(String... outgoingConfigurations) {
this.outgoingConfigurations = Set.of(outgoingConfigurations);
}
public Set<String> outgoingConfigurations() {
return outgoingConfigurations;
}
}
}

View File

@@ -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<AccessWidenerFile> accessWideners = new ArrayList<>();
final Set<Path> 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()) {

View File

@@ -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) {

View File

@@ -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<InjectedInterface> getDependencyInjectedInterfaces() {
List<InjectedInterface> 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<File> 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<File> artifacts = entry.getSourceConfiguration().get().resolve();
for (File artifact : artifacts) {
result.addAll(InjectedInterface.fromModJar(artifact.toPath()));

View File

@@ -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()));
}
}
}

View File

@@ -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<ModDependencyInfo> 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<ArtifactRef> resolveArtifacts(Project project, Configuration configuration) {
final List<ArtifactRef> 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<String> fallback) {
return s == null || s.isEmpty() ? fallback.get() : s;
}
}

View File

@@ -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<ModJavadoc> javadocs = new ArrayList<>();
for (RemappedConfigurationEntry entry : Constants.MOD_COMPILE_ENTRIES) {
Set<File> artifacts = extension.getLazyConfigurationProvider(entry.sourceConfiguration())
.get()
.resolve();
for (RemapConfigurationSettings entry : extension.getRemapConfigurations()) {
final Set<File> artifacts = entry.getSourceConfiguration().get().resolve();
for (File artifact : artifacts) {
if (!ModUtils.isMod(artifact.toPath(), platform)) {

View File

@@ -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<ModDependencyInfo> 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<ModDependencyInfo, OutputConsumerPath> outputConsumerMap = new HashMap<>();
final Map<ModDependencyInfo, byte[]> 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");

View File

@@ -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)) {

View File

@@ -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()) {

View File

@@ -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);
}
}
}

View File

@@ -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<RunConfigSettings> runConfigs;
private final NamedDomainObjectContainer<DecompilerOptions> decompilers;
private final NamedDomainObjectContainer<ModSettings> mods;
private final NamedDomainObjectList<RemapConfigurationSettings> 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<Boolean> 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<RemapConfigurationSettings> getRemapConfigurations() {
return remapConfigurations;
}
@Override
public RemapConfigurationSettings addRemapConfiguration(String name, Action<RemapConfigurationSettings> 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;

View File

@@ -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<String, NamedDomainObjectProvider<Configuration>> lazyConfigurations = new HashMap<>();
private final List<AccessWidenerFile> transitiveAccessWideners = new ArrayList<>();
private LoomDependencyManager dependencyManager;
@@ -222,30 +216,6 @@ public class LoomGradleExtensionImpl extends LoomGradleExtensionApiImpl implemen
return project.getRootProject() == project;
}
@Override
public NamedDomainObjectProvider<Configuration> createLazyConfiguration(String name, Action<? super Configuration> configurationAction) {
NamedDomainObjectProvider<Configuration> 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<Configuration> getLazyConfigurationProvider(String name) {
NamedDomainObjectProvider<Configuration> 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;

View File

@@ -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<RemapSourcesJarTask> remapSourcesTask = tasks.register(REMAP_SOURCES_JAR_TASK_NAME, RemapSourcesJarTask.class, task -> {
task.setDescription("Remaps the default sources jar to intermediary mappings.");

View File

@@ -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<String> inputConfigurations = new ArrayList<>();
inputConfigurations.add(Constants.Configurations.LOADER_DEPENDENCIES);
inputConfigurations.addAll(Constants.MOD_COMPILE_ENTRIES.stream().map(RemappedConfigurationEntry::sourceConfiguration).toList());
List<File> remapClasspath = new ArrayList<>();
for (String inputConfiguration : inputConfigurations) {
remapClasspath.addAll(getProject().getConfigurations().getByName(inputConfiguration).getFiles());
}
final List<File> 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);
}

View File

@@ -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<RemappedConfigurationEntry> 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() {
}

View File

@@ -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());
}
}

View File

@@ -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}
*

View File

@@ -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()