Fix configuration cache test

This commit is contained in:
Juuz
2024-07-02 13:07:24 +03:00
parent 539a92f555
commit 3f27a84700
6 changed files with 190 additions and 56 deletions

View File

@@ -5,10 +5,12 @@ import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.List;
import java.util.StringJoiner;
import org.gradle.api.Project;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.Nullable;
import net.fabricmc.loom.LoomGradleExtension;
@@ -22,48 +24,44 @@ public final class ForgeLoggerConfig {
new ArtifactCoordinates("net.minecraftforge", "forge", "launcher")
);
public static void copyToPath(Project project, Path outputFile) {
try {
Files.deleteIfExists(outputFile);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
public static @Nullable File getForgeLoggerConfigSource(Project project) {
final List<String> libraries = LoomGradleExtension.get(project)
.getForgeUserdevProvider()
.getConfig()
.libraries();
boolean found = false;
for (String library : libraries) {
if (LOGGER_CONFIG_ARTIFACTS.stream().anyMatch(artifact -> artifact.matches(library))) {
final File libraryFile = project.getConfigurations()
return project.getConfigurations()
.detachedConfiguration(project.getDependencies().create(library))
.setTransitive(false)
.getSingleFile();
try (FileSystemUtil.Delegate fs = FileSystemUtil.getJarFileSystem(libraryFile, false)) {
final Path configPath = fs.getPath("log4j2.xml");
Files.copy(configPath, outputFile);
found = true;
break;
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
}
if (!found) {
StringBuilder sb = new StringBuilder("Could not find Forge dependency with logger config. Tried to find:");
return null;
}
for (ArtifactCoordinates artifact : LOGGER_CONFIG_ARTIFACTS) {
sb.append('\n').append(" - ").append(artifact);
}
throw new RuntimeException(sb.toString());
public static void copyToPath(Path libraryFile, Path outputFile) {
try (FileSystemUtil.Delegate fs = FileSystemUtil.getJarFileSystem(libraryFile, false)) {
final Path configPath = fs.getPath("log4j2.xml");
Files.copy(configPath, outputFile, StandardCopyOption.REPLACE_EXISTING);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
@Contract("-> fail")
public static void throwNotFound() {
StringBuilder sb = new StringBuilder("Could not find Forge dependency with logger config. Tried to find:");
for (ArtifactCoordinates artifact : LOGGER_CONFIG_ARTIFACTS) {
sb.append('\n').append(" - ").append(artifact);
}
throw new RuntimeException(sb.toString());
}
private record ArtifactCoordinates(String group, String name, @Nullable String classifier) {
boolean matches(String notation) {
final String[] parts = notation.split(":");

View File

@@ -1,7 +1,7 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2021-2023 FabricMC
* Copyright (c) 2021-2024 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
@@ -109,7 +109,10 @@ public interface ForgeExtensionAPI {
* This is disabled by default.
*
* @return the property
* @deprecated This API is not needed on newer Minecraft versions where Forge forces its own logger config.
*/
@ApiStatus.ScheduledForRemoval(inVersion = "2.0")
@Deprecated(forRemoval = true)
Property<Boolean> getUseForgeLoggerConfig();
/**

View File

@@ -1,7 +1,7 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2022-2023 FabricMC
* Copyright (c) 2022-2024 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
@@ -28,6 +28,7 @@ import org.gradle.api.Project;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.api.mappings.layered.MappingsNamespace;
import net.fabricmc.loom.util.ModPlatform;
public final class IntermediaryNamespaces {
/**
@@ -49,8 +50,14 @@ public final class IntermediaryNamespaces {
* Returns the intermediary namespace of the project.
*/
public static MappingsNamespace intermediaryNamespace(Project project) {
LoomGradleExtension extension = LoomGradleExtension.get(project);
return switch (extension.getPlatform().get()) {
return intermediaryNamespace(LoomGradleExtension.get(project).getPlatform().get());
}
/**
* Returns the intermediary namespace of the platform.
*/
public static MappingsNamespace intermediaryNamespace(ModPlatform platform) {
return switch (platform) {
case FABRIC, QUILT -> MappingsNamespace.INTERMEDIARY;
case FORGE -> MappingsNamespace.SRG;
case NEOFORGE -> MappingsNamespace.MOJANG;

View File

@@ -28,6 +28,8 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
@@ -117,4 +119,33 @@ public record ForgeRunTemplate(
settings.property(Constants.Forge.UNION_RELAUNCHER_MAIN_CLASS_PROPERTY, main);
}
}
public Resolved resolve(ConfigValue.Resolver configValueResolver) {
final Function<ConfigValue, String> resolve = value -> value.resolve(configValueResolver);
final Collector<Map.Entry<String, ConfigValue>, ?, Map<String, String>> resolveMap =
Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue().resolve(configValueResolver));
final List<String> args = this.args.stream().map(resolve).toList();
final List<String> jvmArgs = this.jvmArgs.stream().map(resolve).toList();
final Map<String, String> env = this.env.entrySet().stream().collect(resolveMap);
final Map<String, String> props = this.props.entrySet().stream().collect(resolveMap);
return new Resolved(
name,
main,
args,
jvmArgs,
env,
props
);
}
public record Resolved(
String name,
String main,
List<String> args,
List<String> jvmArgs,
Map<String, String> env,
Map<String, String> props
) { }
}

View File

@@ -26,26 +26,32 @@ package net.fabricmc.loom.task.launch;
import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.StringJoiner;
import java.util.stream.Collectors;
import org.apache.commons.io.FileUtils;
import org.gradle.api.Project;
import org.gradle.api.file.ConfigurableFileCollection;
import org.gradle.api.file.RegularFileProperty;
import org.gradle.api.logging.configuration.ConsoleOutput;
import org.gradle.api.provider.Property;
import org.gradle.api.provider.SetProperty;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.InputFile;
import org.gradle.api.tasks.InputFiles;
import org.gradle.api.tasks.Optional;
import org.gradle.api.tasks.OutputFile;
import org.gradle.api.tasks.TaskAction;
import org.jetbrains.annotations.ApiStatus;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.LoomGradlePlugin;
@@ -57,7 +63,7 @@ import net.fabricmc.loom.configuration.providers.minecraft.MinecraftVersionMeta;
import net.fabricmc.loom.configuration.providers.minecraft.mapped.MappedMinecraftProvider;
import net.fabricmc.loom.task.AbstractLoomTask;
import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.util.PropertyUtil;
import net.fabricmc.loom.util.ModPlatform;
import net.fabricmc.loom.util.gradle.SourceSetHelper;
public abstract class GenerateDLIConfigTask extends AbstractLoomTask {
@@ -103,6 +109,27 @@ public abstract class GenerateDLIConfigTask extends AbstractLoomTask {
@OutputFile
protected abstract RegularFileProperty getDevLauncherConfig();
@ApiStatus.Internal
@Input
protected abstract Property<ModPlatform> getPlatform();
@ApiStatus.Internal
@Input
@Optional
protected abstract Property<ForgeInputs> getForgeInputs();
@ApiStatus.Internal
@InputFile
protected abstract RegularFileProperty getPlatformMappingFile();
@ApiStatus.Internal
@InputFiles
protected abstract ConfigurableFileCollection getMappingJars();
@ApiStatus.Internal
@Input
protected abstract SetProperty<ForgeRunTemplate.Resolved> getRunTemplates();
public GenerateDLIConfigTask() {
getVersionInfoJson().set(LoomGradlePlugin.GSON.toJson(getExtension().getMinecraftProvider().getVersionInfo()));
getMinecraftVersion().set(getExtension().getMinecraftProvider().minecraftVersion());
@@ -124,6 +151,30 @@ public abstract class GenerateDLIConfigTask extends AbstractLoomTask {
getAssetsDirectoryPath().set(new File(getExtension().getFiles().getUserCache(), "assets").getAbsolutePath());
getNativesDirectoryPath().set(getExtension().getFiles().getNativesDirectory(getProject()).getAbsolutePath());
getDevLauncherConfig().set(getExtension().getFiles().getDevLauncherConfig());
getPlatform().set(getExtension().getPlatform());
getPlatform().finalizeValue();
getPlatformMappingFile().set(getProject().getLayout().file(getProject().provider(() -> getExtension().getPlatformMappingFile().toFile())));
getPlatformMappingFile().finalizeValue();
getMappingJars().from(getProject().getConfigurations().getByName(Constants.Configurations.MAPPINGS_FINAL));
if (getExtension().isForgeLike()) {
getRunTemplates().addAll(getProject().provider(() -> {
final ForgeRunsProvider forgeRunsProvider = getExtension().getForgeRunsProvider();
final ConfigValue.Resolver configResolver = forgeRunsProvider.getResolver(null);
return forgeRunsProvider.getTemplates()
.stream()
.map(template -> template.resolve(configResolver))
.toList();
}));
if (getExtension().isForge()) {
getForgeInputs().set(getProject().provider(() -> new ForgeInputs(getProject(), getExtension())));
}
} else {
getRunTemplates().empty();
}
}
@TaskAction
@@ -135,7 +186,8 @@ public abstract class GenerateDLIConfigTask extends AbstractLoomTask {
assetsDirectory = new File(assetsDirectory, "/legacy/" + versionInfo.id());
}
boolean quilt = getExtension().isQuilt();
final ModPlatform platform = getPlatform().get();
boolean quilt = platform == ModPlatform.QUILT;
final LaunchConfig launchConfig = new LaunchConfig()
.property(!quilt ? "fabric.development" : "loader.development", "true")
.property(!quilt ? "fabric.remapClasspathFile" : "loader.remapClasspathFile", getRemapClasspathFile().get().getAsFile().getAbsolutePath())
@@ -150,7 +202,7 @@ public abstract class GenerateDLIConfigTask extends AbstractLoomTask {
.property("client", "org.lwjgl.librarypath", nativesPath);
}
if (!getExtension().isForgeLike()) {
if (!platform.isForgeLike()) {
launchConfig
.argument("client", "--assetIndex")
.argument("client", versionInfo.assetIndex().fabricId(getMinecraftVersion().get()))
@@ -167,24 +219,23 @@ public abstract class GenerateDLIConfigTask extends AbstractLoomTask {
}
}
if (getExtension().isQuilt()) {
if (quilt) {
launchConfig
.argument("client", "--version")
.argument("client", "Architectury Loom");
}
if (getExtension().isForgeLike()) {
if (platform.isForgeLike()) {
// Find the mapping files for Unprotect to use for figuring out
// which classes are from Minecraft.
String unprotectMappings = getProject().getConfigurations()
.getByName(Constants.Configurations.MAPPINGS_FINAL)
.resolve()
String unprotectMappings = getMappingJars()
.getFiles()
.stream()
.map(File::getAbsolutePath)
.collect(Collectors.joining(File.pathSeparator));
final String intermediateNs = IntermediaryNamespaces.intermediary(getProject());
final String mappingsPath = getExtension().getPlatformMappingFile().toAbsolutePath().toString();
final String intermediateNs = IntermediaryNamespaces.intermediaryNamespace(platform).toString();
final String mappingsPath = getPlatformMappingFile().get().getAsFile().getAbsolutePath();
launchConfig
.property("unprotect.mappings", unprotectMappings)
@@ -192,31 +243,32 @@ public abstract class GenerateDLIConfigTask extends AbstractLoomTask {
.property("architectury.naming.sourceNamespace", intermediateNs)
.property("architectury.naming.mappingsPath", mappingsPath);
if (getExtension().isForge()) {
final List<String> dataGenMods = getExtension().getForge().getDataGenMods();
if (platform == ModPlatform.FORGE) {
final ForgeInputs forgeInputs = Objects.requireNonNull(getForgeInputs().getOrNull());
final List<String> dataGenMods = forgeInputs.dataGenMods();
// Only apply the hardcoded data arguments if the deprecated data generator API is being used.
if (!dataGenMods.isEmpty()) {
launchConfig
.argument("data", "--all")
.argument("data", "--mod")
.argument("data", String.join(",", getExtension().getForge().getDataGenMods()))
.argument("data", String.join(",", dataGenMods))
.argument("data", "--output")
.argument("data", getProject().file("src/generated/resources").getAbsolutePath());
.argument("data", forgeInputs.legacyDataGenDir());
}
launchConfig.property("mixin.env.remapRefMap", "true");
if (PropertyUtil.getAndFinalize(getExtension().getForge().getUseCustomMixin())) {
if (forgeInputs.useCustomMixin()) {
// See mixin remapper service in forge-runtime
launchConfig
.property("architectury.mixinRemapper.sourceNamespace", intermediateNs)
.property("architectury.mixinRemapper.mappingsPath", mappingsPath);
} else {
launchConfig.property("net.minecraftforge.gradle.GradleStart.srg.srg-mcp", getExtension().getMappingConfiguration().srgToNamedSrg.toAbsolutePath().toString());
launchConfig.property("net.minecraftforge.gradle.GradleStart.srg.srg-mcp", forgeInputs.srgToNamedSrg());
}
Set<String> mixinConfigs = PropertyUtil.getAndFinalize(getExtension().getForge().getMixinConfigs());
Set<String> mixinConfigs = forgeInputs.mixinConfigs();
if (!mixinConfigs.isEmpty()) {
for (String config : mixinConfigs) {
@@ -226,16 +278,13 @@ public abstract class GenerateDLIConfigTask extends AbstractLoomTask {
}
}
ForgeRunsProvider forgeRunsProvider = getExtension().getForgeRunsProvider();
ConfigValue.Resolver configResolver = forgeRunsProvider.getResolver(null);
for (ForgeRunTemplate template : forgeRunsProvider.getTemplates()) {
for (ConfigValue argument : template.args()) {
launchConfig.argument(template.name(), argument.resolve(configResolver));
for (ForgeRunTemplate.Resolved template : getRunTemplates().get()) {
for (String argument : template.args()) {
launchConfig.argument(template.name(), argument);
}
for (Map.Entry<String, ConfigValue> property : template.props().entrySet()) {
launchConfig.property(template.name(), property.getKey(), property.getValue().resolve(configResolver));
for (Map.Entry<String, String> property : template.props().entrySet()) {
launchConfig.property(template.name(), property.getKey(), property.getValue());
}
}
}
@@ -322,4 +371,23 @@ public abstract class GenerateDLIConfigTask extends AbstractLoomTask {
return stringJoiner.toString();
}
}
@ApiStatus.Internal
public record ForgeInputs(
List<String> dataGenMods,
String legacyDataGenDir,
Set<String> mixinConfigs,
boolean useCustomMixin,
String srgToNamedSrg
) implements Serializable {
public ForgeInputs(Project project, LoomGradleExtension extension) {
this(
extension.getForge().getDataGenMods(),
project.file("src/generated/resources").getAbsolutePath(),
extension.getForge().getMixinConfigs().get(),
extension.getForge().getUseCustomMixin().get(),
extension.getMappingConfiguration().srgToNamedSrg.toAbsolutePath().toString()
);
}
}
}

View File

@@ -32,9 +32,16 @@ import java.nio.file.Path;
import javax.inject.Inject;
import dev.architectury.loom.util.ForgeLoggerConfig;
import org.gradle.api.file.RegularFile;
import org.gradle.api.file.RegularFileProperty;
import org.gradle.api.provider.Property;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.InputFile;
import org.gradle.api.tasks.Optional;
import org.gradle.api.tasks.OutputFile;
import org.gradle.api.tasks.TaskAction;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Nullable;
import net.fabricmc.loom.task.AbstractLoomTask;
@@ -42,17 +49,37 @@ public abstract class GenerateLog4jConfigTask extends AbstractLoomTask {
@OutputFile
public abstract RegularFileProperty getOutputFile();
@ApiStatus.Internal
@Input
protected abstract Property<Boolean> getUseForgeLoggerConfig();
@ApiStatus.Internal
@InputFile
@Optional
protected abstract RegularFileProperty getForgeLoggerConfigSource();
@Inject
public GenerateLog4jConfigTask() {
getOutputFile().set(getExtension().getFiles().getDefaultLog4jConfigFile());
if (getExtension().isForge()) {
getUseForgeLoggerConfig().set(getProject().provider(() -> getExtension().getForge().getUseForgeLoggerConfig().get()));
getForgeLoggerConfigSource().set(getProject().getLayout().file(
getProject().provider(() -> ForgeLoggerConfig.getForgeLoggerConfigSource(getProject()))
));
} else {
getUseForgeLoggerConfig().set(false);
}
}
@TaskAction
public void run() {
Path outputFile = getOutputFile().get().getAsFile().toPath();
if (getExtension().isForge() && getExtension().getForge().getUseForgeLoggerConfig().get()) {
ForgeLoggerConfig.copyToPath(getProject(), outputFile);
if (getUseForgeLoggerConfig().get()) {
final @Nullable RegularFile source = getForgeLoggerConfigSource().getOrNull();
if (source == null) ForgeLoggerConfig.throwNotFound();
ForgeLoggerConfig.copyToPath(source.getAsFile().toPath(), outputFile);
return;
}