From 63ecb88082f2e32c75d7854401cb1f52fd143955 Mon Sep 17 00:00:00 2001 From: modmuss50 Date: Mon, 16 Jan 2023 18:39:26 +0000 Subject: [PATCH] Gradle 8 tests, perf/memory optimisations (#796) * Add gradle 8 tests Reuse gradle home between tests Misc perf and mem optimisations * Fix build warning. * Added multi mc version test * Use server launcher in ServerRunner Co-authored-by: Luna <62033805+Luna5ama@users.noreply.github.com> --- build.gradle | 2 +- .../fabricmc/loom/LoomGradleExtension.java | 7 -- .../loom/api/processor/ProcessorContext.java | 3 + .../InterfaceInjectionProcessor.java | 24 +++---- .../processors/ProcessorContextImpl.java | 8 +++ .../extension/LoomGradleExtensionApiImpl.java | 2 +- .../extension/LoomGradleExtensionImpl.java | 15 ---- .../loom/task/PrepareJarRemapTask.java | 14 ++-- .../net/fabricmc/loom/task/RemapJarTask.java | 8 +-- .../task/service/LorenzMappingService.java | 69 +++++++++++++++++++ .../task/service/TinyRemapperService.java | 3 +- .../fabricmc/loom/util/SourceRemapper.java | 69 ++++++++----------- .../loom/test/LoomTestConstants.groovy | 10 ++- .../test/benchmark/FabricAPIBenchmark.groovy | 8 ++- .../test/integration/FabricAPITest.groovy | 11 +-- .../integration/MultiMcVersionTest.groovy | 61 ++++++++++++++++ .../test/util/GradleProjectTestTrait.groovy | 13 +--- .../loom/test/util/ServerRunner.groovy | 20 ++---- .../projects/multi-mc-versions/build.gradle | 56 +++++++++++++++ .../multi-mc-versions/gradle.properties | 9 +++ .../multi-mc-versions/settings.gradle | 9 +++ .../com/example/examplemod/ExampleMod.java | 19 +++++ .../src/main/resources/fabric.mod.json | 25 +++++++ 23 files changed, 339 insertions(+), 126 deletions(-) create mode 100644 src/main/java/net/fabricmc/loom/task/service/LorenzMappingService.java create mode 100644 src/test/groovy/net/fabricmc/loom/test/integration/MultiMcVersionTest.groovy create mode 100644 src/test/resources/projects/multi-mc-versions/build.gradle create mode 100644 src/test/resources/projects/multi-mc-versions/gradle.properties create mode 100644 src/test/resources/projects/multi-mc-versions/settings.gradle create mode 100644 src/test/resources/projects/multi-mc-versions/src/main/java/com/example/examplemod/ExampleMod.java create mode 100644 src/test/resources/projects/multi-mc-versions/src/main/resources/fabric.mod.json diff --git a/build.gradle b/build.gradle index ab444c93..e9b73af3 100644 --- a/build.gradle +++ b/build.gradle @@ -111,7 +111,6 @@ dependencies { testImplementation ('io.javalin:javalin:5.1.2') { exclude group: 'org.jetbrains.kotlin' } - testImplementation 'net.fabricmc:fabric-installer:0.9.0' testImplementation 'org.mockito:mockito-core:4.8.0' compileOnly 'org.jetbrains:annotations:23.0.0' @@ -194,6 +193,7 @@ jacocoTestReport { test { maxHeapSize = "2560m" + jvmArgs "-XX:+HeapDumpOnOutOfMemoryError" useJUnitPlatform() // Forward system prop onto tests. diff --git a/src/main/java/net/fabricmc/loom/LoomGradleExtension.java b/src/main/java/net/fabricmc/loom/LoomGradleExtension.java index aa74bab0..10ac4db9 100644 --- a/src/main/java/net/fabricmc/loom/LoomGradleExtension.java +++ b/src/main/java/net/fabricmc/loom/LoomGradleExtension.java @@ -26,10 +26,7 @@ package net.fabricmc.loom; import java.nio.file.Path; import java.util.List; -import java.util.function.Supplier; -import org.cadixdev.lorenz.MappingSet; -import org.cadixdev.mercury.Mercury; import org.gradle.api.Project; import org.gradle.api.file.ConfigurableFileCollection; import org.gradle.api.file.FileCollection; @@ -54,10 +51,6 @@ public interface LoomGradleExtension extends LoomGradleExtensionAPI { LoomFiles getFiles(); - MappingSet getOrCreateSrcMappingCache(int id, Supplier factory); - - Mercury getOrCreateSrcMercuryCache(int id, Supplier factory); - ConfigurableFileCollection getUnmappedModCollection(); void setInstallerData(InstallerData data); diff --git a/src/main/java/net/fabricmc/loom/api/processor/ProcessorContext.java b/src/main/java/net/fabricmc/loom/api/processor/ProcessorContext.java index a5152f9b..282dbf2f 100644 --- a/src/main/java/net/fabricmc/loom/api/processor/ProcessorContext.java +++ b/src/main/java/net/fabricmc/loom/api/processor/ProcessorContext.java @@ -27,6 +27,7 @@ package net.fabricmc.loom.api.processor; import net.fabricmc.loom.api.mappings.layered.MappingsNamespace; import net.fabricmc.loom.configuration.providers.minecraft.MinecraftJarConfiguration; import net.fabricmc.loom.util.LazyCloseable; +import net.fabricmc.mappingio.tree.MemoryMappingTree; import net.fabricmc.tinyremapper.TinyRemapper; public interface ProcessorContext { @@ -39,4 +40,6 @@ public interface ProcessorContext { boolean includesServer(); LazyCloseable createRemapper(MappingsNamespace from, MappingsNamespace to); + + MemoryMappingTree getMappings(); } diff --git a/src/main/java/net/fabricmc/loom/configuration/ifaceinject/InterfaceInjectionProcessor.java b/src/main/java/net/fabricmc/loom/configuration/ifaceinject/InterfaceInjectionProcessor.java index 77ba7403..ea0a7327 100644 --- a/src/main/java/net/fabricmc/loom/configuration/ifaceinject/InterfaceInjectionProcessor.java +++ b/src/main/java/net/fabricmc/loom/configuration/ifaceinject/InterfaceInjectionProcessor.java @@ -32,6 +32,7 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.function.Function; import java.util.stream.Collectors; import javax.inject.Inject; @@ -43,7 +44,6 @@ import org.jetbrains.annotations.Nullable; import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.ClassWriter; -import org.objectweb.asm.commons.Remapper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -56,6 +56,7 @@ import net.fabricmc.loom.util.Pair; import net.fabricmc.loom.util.ZipUtils; import net.fabricmc.loom.util.fmj.FabricModJson; import net.fabricmc.mappingio.tree.MappingTree; +import net.fabricmc.mappingio.tree.MemoryMappingTree; public abstract class InterfaceInjectionProcessor implements MinecraftJarProcessor { private static final Logger LOGGER = LoggerFactory.getLogger(InterfaceInjectionProcessor.class); @@ -98,16 +99,13 @@ public abstract class InterfaceInjectionProcessor implements MinecraftJarProcess @Override public void processJar(Path jar, Spec spec, ProcessorContext context) throws IOException { - final List remappedInjectedInterfaces; - // Remap from intermediary->named - try (var tinyRemapper = context.createRemapper(MappingsNamespace.INTERMEDIARY, MappingsNamespace.NAMED)) { - final Remapper remapper = tinyRemapper.get().getEnvironment().getRemapper(); - - remappedInjectedInterfaces = spec.injectedInterfaces().stream() - .map(injectedInterface -> remap(injectedInterface, remapper)) - .toList(); - } + final MemoryMappingTree mappings = context.getMappings(); + final int intermediaryIndex = mappings.getNamespaceId(MappingsNamespace.INTERMEDIARY.toString()); + final int namedIndex = mappings.getNamespaceId(MappingsNamespace.NAMED.toString()); + final List remappedInjectedInterfaces = spec.injectedInterfaces().stream() + .map(injectedInterface -> remap(injectedInterface, s -> mappings.mapClassName(s, intermediaryIndex, namedIndex))) + .toList(); try { ZipUtils.transform(jar, getTransformers(remappedInjectedInterfaces)); @@ -116,11 +114,11 @@ public abstract class InterfaceInjectionProcessor implements MinecraftJarProcess } } - private InjectedInterface remap(InjectedInterface in, Remapper remapper) { + private InjectedInterface remap(InjectedInterface in, Function remapper) { return new InjectedInterface( in.modId(), - remapper.map(in.className()), - remapper.map(in.ifaceName()) + remapper.apply(in.className()), + remapper.apply(in.ifaceName()) ); } diff --git a/src/main/java/net/fabricmc/loom/configuration/processors/ProcessorContextImpl.java b/src/main/java/net/fabricmc/loom/configuration/processors/ProcessorContextImpl.java index 15f2d3ca..484dc57e 100644 --- a/src/main/java/net/fabricmc/loom/configuration/processors/ProcessorContextImpl.java +++ b/src/main/java/net/fabricmc/loom/configuration/processors/ProcessorContextImpl.java @@ -24,12 +24,14 @@ package net.fabricmc.loom.configuration.processors; +import net.fabricmc.loom.LoomGradleExtension; import net.fabricmc.loom.api.mappings.layered.MappingsNamespace; import net.fabricmc.loom.api.processor.ProcessorContext; import net.fabricmc.loom.configuration.ConfigContext; import net.fabricmc.loom.configuration.providers.minecraft.MinecraftJar; import net.fabricmc.loom.configuration.providers.minecraft.MinecraftJarConfiguration; import net.fabricmc.loom.util.LazyCloseable; +import net.fabricmc.mappingio.tree.MemoryMappingTree; import net.fabricmc.tinyremapper.TinyRemapper; public record ProcessorContextImpl(ConfigContext configContext, MinecraftJar minecraftJar) implements ProcessorContext { @@ -57,4 +59,10 @@ public record ProcessorContextImpl(ConfigContext configContext, MinecraftJar min public LazyCloseable createRemapper(MappingsNamespace from, MappingsNamespace to) { return ContextImplHelper.createRemapper(configContext, from, to); } + + @Override + public MemoryMappingTree getMappings() { + LoomGradleExtension extension = LoomGradleExtension.get(configContext().project()); + return extension.getMappingConfiguration().getMappingsService(configContext().serviceManager()).getMappingTree(); + } } diff --git a/src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionApiImpl.java b/src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionApiImpl.java index 847fd3b5..17e54ec3 100644 --- a/src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionApiImpl.java +++ b/src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionApiImpl.java @@ -141,7 +141,7 @@ public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionA this.splitEnvironmentalSourceSet = project.getObjects().property(Boolean.class).convention(false); this.splitEnvironmentalSourceSet.finalizeValueOnRead(); - // Add main source set by default + // Enable dep iface injection by default interfaceInjection(interfaceInjection -> { interfaceInjection.getEnableDependencyInterfaceInjection().convention(true).finalizeValueOnRead(); }); diff --git a/src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionImpl.java b/src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionImpl.java index 0c2d7c8e..3748c043 100644 --- a/src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionImpl.java +++ b/src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionImpl.java @@ -29,10 +29,7 @@ import java.nio.file.Path; import java.util.ArrayList; import java.util.List; import java.util.Objects; -import java.util.function.Supplier; -import org.cadixdev.lorenz.MappingSet; -import org.cadixdev.mercury.Mercury; import org.gradle.api.Project; import org.gradle.api.file.ConfigurableFileCollection; import org.gradle.api.file.FileCollection; @@ -60,8 +57,6 @@ public class LoomGradleExtensionImpl extends LoomGradleExtensionApiImpl implemen private final LoomFiles loomFiles; private final ConfigurableFileCollection unmappedMods; - private final MappingSet[] srcMappingCache = new MappingSet[2]; - private final Mercury[] srcMercuryCache = new Mercury[2]; private final List transitiveAccessWideners = new ArrayList<>(); private LoomDependencyManager dependencyManager; @@ -167,16 +162,6 @@ public class LoomGradleExtensionImpl extends LoomGradleExtensionApiImpl implemen ); } - @Override - public MappingSet getOrCreateSrcMappingCache(int id, Supplier factory) { - return srcMappingCache[id] != null ? srcMappingCache[id] : (srcMappingCache[id] = factory.get()); - } - - @Override - public Mercury getOrCreateSrcMercuryCache(int id, Supplier factory) { - return srcMercuryCache[id] != null ? srcMercuryCache[id] : (srcMercuryCache[id] = factory.get()); - } - @Override public ConfigurableFileCollection getUnmappedModCollection() { return unmappedMods; diff --git a/src/main/java/net/fabricmc/loom/task/PrepareJarRemapTask.java b/src/main/java/net/fabricmc/loom/task/PrepareJarRemapTask.java index ab4c69c0..9569968a 100644 --- a/src/main/java/net/fabricmc/loom/task/PrepareJarRemapTask.java +++ b/src/main/java/net/fabricmc/loom/task/PrepareJarRemapTask.java @@ -57,14 +57,12 @@ public abstract class PrepareJarRemapTask extends AbstractLoomTask { getOutputs().upToDateWhen((o) -> false); getProject().getGradle().allprojects(project -> { - project.getTasks().configureEach(task -> { - if (task instanceof PrepareJarRemapTask otherTask) { - if (otherTask == this) return; + project.getTasks().withType(PrepareJarRemapTask.class, otherTask -> { + if (otherTask == this) return; - // Ensure that all other prepare tasks inputs have completed - dependsOn(otherTask.getInputs()); - mustRunAfter(otherTask.getInputs()); - } + // Ensure that all other prepare tasks inputs have completed + dependsOn(otherTask.getInputs()); + mustRunAfter(otherTask.getInputs()); }); }); } @@ -102,6 +100,6 @@ public abstract class PrepareJarRemapTask extends AbstractLoomTask { } static void prepare(TinyRemapperService tinyRemapperService, Path inputFile) { - tinyRemapperService.getTinyRemapperForInputs().readInputsAsync(tinyRemapperService.getOrCreateTag(inputFile), inputFile); + tinyRemapperService.getTinyRemapperForInputs().readInputs(tinyRemapperService.getOrCreateTag(inputFile), inputFile); } } diff --git a/src/main/java/net/fabricmc/loom/task/RemapJarTask.java b/src/main/java/net/fabricmc/loom/task/RemapJarTask.java index 6c52130b..872ce42e 100644 --- a/src/main/java/net/fabricmc/loom/task/RemapJarTask.java +++ b/src/main/java/net/fabricmc/loom/task/RemapJarTask.java @@ -33,13 +33,11 @@ import java.util.Collection; import java.util.List; import java.util.Objects; import java.util.Set; -import java.util.function.Supplier; import java.util.stream.Collectors; import java.util.stream.Stream; import javax.inject.Inject; -import com.google.common.base.Suppliers; import com.google.gson.JsonObject; import org.gradle.api.artifacts.Configuration; import org.gradle.api.file.ConfigurableFileCollection; @@ -90,13 +88,11 @@ public abstract class RemapJarTask extends AbstractRemapJarTask { public abstract Property getUseMixinAP(); private final Provider serviceManagerProvider; - private final Supplier tinyRemapperService; @Inject public RemapJarTask() { super(); serviceManagerProvider = BuildSharedServiceManager.createForTask(this, getBuildEventsListenerRegistry()); - tinyRemapperService = Suppliers.memoize(() -> TinyRemapperService.getOrCreate(serviceManagerProvider.get().get(), this)); getClasspath().from(getProject().getConfigurations().getByName(JavaPlugin.COMPILE_CLASSPATH_CONFIGURATION_NAME)); getAddNestedDependencies().convention(true).finalizeValueOnRead(); @@ -134,7 +130,7 @@ public abstract class RemapJarTask extends AbstractRemapJarTask { params.getNestedJars().from(getNestedJars()); } - params.getTinyRemapperBuildServiceUuid().set(UnsafeWorkQueueHelper.create(tinyRemapperService.get())); + params.getTinyRemapperBuildServiceUuid().set(UnsafeWorkQueueHelper.create(getTinyRemapperService())); params.getRemapClasspath().from(getClasspath()); params.getMultiProjectOptimisation().set(getLoomExtension().multiProjectOptimisation()); @@ -337,6 +333,6 @@ public abstract class RemapJarTask extends AbstractRemapJarTask { @Internal public TinyRemapperService getTinyRemapperService() { - return tinyRemapperService.get(); + return TinyRemapperService.getOrCreate(serviceManagerProvider.get().get(), this); } } diff --git a/src/main/java/net/fabricmc/loom/task/service/LorenzMappingService.java b/src/main/java/net/fabricmc/loom/task/service/LorenzMappingService.java new file mode 100644 index 00000000..953211c0 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/task/service/LorenzMappingService.java @@ -0,0 +1,69 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2023 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.task.service; + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.util.Objects; + +import org.cadixdev.lorenz.MappingSet; + +import net.fabricmc.loom.api.mappings.layered.MappingsNamespace; +import net.fabricmc.loom.configuration.providers.mappings.MappingConfiguration; +import net.fabricmc.loom.util.service.SharedService; +import net.fabricmc.loom.util.service.SharedServiceManager; +import net.fabricmc.lorenztiny.TinyMappingsReader; +import net.fabricmc.mappingio.tree.MemoryMappingTree; + +public final class LorenzMappingService implements SharedService { + private MappingSet mappings; + + public LorenzMappingService(MappingSet mappings) { + this.mappings = mappings; + } + + public static synchronized LorenzMappingService create(SharedServiceManager sharedServiceManager, MappingConfiguration mappingConfiguration, MappingsNamespace from, MappingsNamespace to) { + return sharedServiceManager.getOrCreateService(mappingConfiguration.getBuildServiceName("LorenzMappingService", from.toString(), to.toString()), () -> { + MemoryMappingTree m = mappingConfiguration.getMappingsService(sharedServiceManager).getMappingTree(); + + try { + try (var reader = new TinyMappingsReader(m, from.toString(), to.toString())) { + return new LorenzMappingService(reader.read()); + } + } catch (IOException e) { + throw new UncheckedIOException("Failed to read lorenz mappings", e); + } + }); + } + + @Override + public void close() throws IOException { + this.mappings = null; + } + + public MappingSet mappings() { + return Objects.requireNonNull(mappings); + } +} diff --git a/src/main/java/net/fabricmc/loom/task/service/TinyRemapperService.java b/src/main/java/net/fabricmc/loom/task/service/TinyRemapperService.java index ced8f239..38f7ad7d 100644 --- a/src/main/java/net/fabricmc/loom/task/service/TinyRemapperService.java +++ b/src/main/java/net/fabricmc/loom/task/service/TinyRemapperService.java @@ -181,12 +181,13 @@ public class TinyRemapperService implements SharedService { classpath.addAll(paths); } - tinyRemapper.readClassPathAsync(toRead.toArray(Path[]::new)); + tinyRemapper.readClassPath(toRead.toArray(Path[]::new)); } @Override public void close() throws IOException { if (tinyRemapper != null) { + tinyRemapper.getEnvironment(); tinyRemapper.finish(); tinyRemapper = null; } diff --git a/src/main/java/net/fabricmc/loom/util/SourceRemapper.java b/src/main/java/net/fabricmc/loom/util/SourceRemapper.java index 7812dd58..e3348689 100644 --- a/src/main/java/net/fabricmc/loom/util/SourceRemapper.java +++ b/src/main/java/net/fabricmc/loom/util/SourceRemapper.java @@ -50,9 +50,8 @@ import net.fabricmc.loom.LoomGradleExtension; import net.fabricmc.loom.api.RemapConfigurationSettings; import net.fabricmc.loom.api.mappings.layered.MappingsNamespace; import net.fabricmc.loom.configuration.providers.mappings.MappingConfiguration; +import net.fabricmc.loom.task.service.LorenzMappingService; import net.fabricmc.loom.util.service.SharedServiceManager; -import net.fabricmc.lorenztiny.TinyMappingsReader; -import net.fabricmc.mappingio.tree.MemoryMappingTree; public class SourceRemapper { private final Project project; @@ -167,51 +166,43 @@ public class SourceRemapper { LoomGradleExtension extension = LoomGradleExtension.get(project); MappingConfiguration mappingConfiguration = extension.getMappingConfiguration(); - MappingSet mappings = extension.getOrCreateSrcMappingCache(toNamed ? 1 : 0, () -> { - try { - MemoryMappingTree m = mappingConfiguration.getMappingsService(serviceManager).getMappingTree(); - project.getLogger().info(":loading " + (toNamed ? "intermediary -> named" : "named -> intermediary") + " source mappings"); - return new TinyMappingsReader(m, toNamed ? MappingsNamespace.INTERMEDIARY.toString() : MappingsNamespace.NAMED.toString(), toNamed ? MappingsNamespace.NAMED.toString() : MappingsNamespace.INTERMEDIARY.toString()).read(); - } catch (Exception e) { - throw new RuntimeException(e); + MappingSet mappings = LorenzMappingService.create(serviceManager, + mappingConfiguration, + toNamed ? MappingsNamespace.INTERMEDIARY : MappingsNamespace.NAMED, + toNamed ? MappingsNamespace.NAMED : MappingsNamespace.INTERMEDIARY + ).mappings(); + + Mercury mercury = createMercuryWithClassPath(project, toNamed); + mercury.setSourceCompatibilityFromRelease(getJavaCompileRelease(project)); + + for (File file : extension.getUnmappedModCollection()) { + Path path = file.toPath(); + + if (Files.isRegularFile(path)) { + mercury.getClassPath().add(path); } - }); + } - Mercury mercury = extension.getOrCreateSrcMercuryCache(toNamed ? 1 : 0, () -> { - Mercury m = createMercuryWithClassPath(project, toNamed); - m.setSourceCompatibilityFromRelease(getJavaCompileRelease(project)); + for (Path intermediaryJar : extension.getMinecraftJars(MappingsNamespace.INTERMEDIARY)) { + mercury.getClassPath().add(intermediaryJar); + } - for (File file : extension.getUnmappedModCollection()) { - Path path = file.toPath(); + for (Path intermediaryJar : extension.getMinecraftJars(MappingsNamespace.NAMED)) { + mercury.getClassPath().add(intermediaryJar); + } - if (Files.isRegularFile(path)) { - m.getClassPath().add(path); - } - } + Set files = project.getConfigurations() + .detachedConfiguration(project.getDependencies().create(Constants.Dependencies.JETBRAINS_ANNOTATIONS + Constants.Dependencies.Versions.JETBRAINS_ANNOTATIONS)) + .resolve(); - for (Path intermediaryJar : extension.getMinecraftJars(MappingsNamespace.INTERMEDIARY)) { - m.getClassPath().add(intermediaryJar); - } + for (File file : files) { + mercury.getClassPath().add(file.toPath()); + } - for (Path intermediaryJar : extension.getMinecraftJars(MappingsNamespace.NAMED)) { - m.getClassPath().add(intermediaryJar); - } - - Set files = project.getConfigurations() - .detachedConfiguration(project.getDependencies().create(Constants.Dependencies.JETBRAINS_ANNOTATIONS + Constants.Dependencies.Versions.JETBRAINS_ANNOTATIONS)) - .resolve(); - - for (File file : files) { - m.getClassPath().add(file.toPath()); - } - - m.getProcessors().add(MercuryRemapper.create(mappings)); - - return m; - }); + mercury.getProcessors().add(MercuryRemapper.create(mappings)); this.mercury = mercury; - return mercury; + return this.mercury; } public static int getJavaCompileRelease(Project project) { diff --git a/src/test/groovy/net/fabricmc/loom/test/LoomTestConstants.groovy b/src/test/groovy/net/fabricmc/loom/test/LoomTestConstants.groovy index 4e004e03..83e23162 100644 --- a/src/test/groovy/net/fabricmc/loom/test/LoomTestConstants.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/LoomTestConstants.groovy @@ -27,13 +27,19 @@ package net.fabricmc.loom.test import org.gradle.util.GradleVersion class LoomTestConstants { - private final static String NIGHTLY_VERSION = "8.1-20221229234322+0000" + private final static String NIGHTLY_VERSION = "8.1-20230109232704+0000" private final static boolean NIGHTLY_EXISTS = nightlyExists(NIGHTLY_VERSION) + // Test against the version of Gradle being used to build loom public final static String DEFAULT_GRADLE = GradleVersion.current().getVersion() + // Test against Gradle 8 + public final static String GRADLE_8 = "8.0-rc-1" // Tests that depend specifically on the nightly will run on the current version when the nightly is not available. public final static String PRE_RELEASE_GRADLE = NIGHTLY_EXISTS ? NIGHTLY_VERSION : DEFAULT_GRADLE - public final static String[] STANDARD_TEST_VERSIONS = NIGHTLY_EXISTS ? [DEFAULT_GRADLE, PRE_RELEASE_GRADLE] : [DEFAULT_GRADLE] + // Randomly sorted to ensure that all versions can run with a clean gradle home. + public final static String[] STANDARD_TEST_VERSIONS = (NIGHTLY_EXISTS ? [DEFAULT_GRADLE, GRADLE_8, PRE_RELEASE_GRADLE] : [DEFAULT_GRADLE, GRADLE_8]).shuffled().toArray() + + public static final File TEST_DIR = new File("./.gradle/test-files") /** * Nightly gradle versions get removed after a certain amount of time, lets check to see if its still online before running the tests. diff --git a/src/test/groovy/net/fabricmc/loom/test/benchmark/FabricAPIBenchmark.groovy b/src/test/groovy/net/fabricmc/loom/test/benchmark/FabricAPIBenchmark.groovy index 5acf17ee..1ede9916 100644 --- a/src/test/groovy/net/fabricmc/loom/test/benchmark/FabricAPIBenchmark.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/benchmark/FabricAPIBenchmark.groovy @@ -37,19 +37,21 @@ import net.fabricmc.loom.test.util.GradleProjectTestTrait class FabricAPIBenchmark implements GradleProjectTestTrait { def run(File dir) { def gradle = gradleProject( - version: LoomTestConstants.PRE_RELEASE_GRADLE, + version: LoomTestConstants.DEFAULT_GRADLE, projectDir: new File(dir, "project"), gradleHomeDir: new File(dir, "gradlehome"), allowExistingRepo: true, repo: "https://github.com/FabricMC/fabric.git", - commit: "5f243a8b7849eac4b30cd876a22a127797a1c406", + commit: "2facd446984085376bd23245410ebf2dc0881b02", patch: "fabric_api" ) + gradle.enableMultiProjectOptimisation() + def timeStart = new Date() - def result = gradle.run(tasks: ["clean"], args: []) + def result = gradle.run(tasks: ["clean", "build", "-x", "test", "-x", "check", "-x", ":fabric-data-generation-api-v1:runDatagen"], args: []) def timeStop = new Date() TimeDuration duration = TimeCategory.minus(timeStop, timeStart) diff --git a/src/test/groovy/net/fabricmc/loom/test/integration/FabricAPITest.groovy b/src/test/groovy/net/fabricmc/loom/test/integration/FabricAPITest.groovy index f5be694f..d67a1159 100644 --- a/src/test/groovy/net/fabricmc/loom/test/integration/FabricAPITest.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/integration/FabricAPITest.groovy @@ -44,7 +44,7 @@ class FabricAPITest extends Specification implements GradleProjectTestTrait { setup: def gradle = gradleProject( repo: "https://github.com/FabricMC/fabric.git", - commit: "5f243a8b7849eac4b30cd876a22a127797a1c406", + commit: "2facd446984085376bd23245410ebf2dc0881b02", version: version, patch: "fabric_api" ) @@ -54,7 +54,7 @@ class FabricAPITest extends Specification implements GradleProjectTestTrait { // Set the version to something constant gradle.buildGradle.text = gradle.buildGradle.text.replace('project.version + "+" + (ENV.GITHUB_RUN_NUMBER ? "" : "local-") + getBranch()', "\"$API_VERSION\"") - def server = ServerRunner.create(gradle.projectDir, "1.19.2") + def server = ServerRunner.create(gradle.projectDir, "1.19.3") .withMod(gradle.getOutputFile("fabric-api-${API_VERSION}.jar")) when: def result = gradle.run(tasks: ["build", "publishToMavenLocal"], args: ["--parallel", "-x", "check", "-x", "runDatagen", "-x", "runGametest"]) // Note: checkstyle does not appear to like being ran in a test runner @@ -65,12 +65,13 @@ class FabricAPITest extends Specification implements GradleProjectTestTrait { result.task(":build").outcome == SUCCESS result.task(":prepareRemapJar").outcome == SUCCESS - new File(gradle.mavenLocalDir, "net/fabricmc/fabric-api/fabric-biome-api-v1/9.0.17/fabric-biome-api-v1-9.0.17.jar").exists() - new File(gradle.mavenLocalDir, "net/fabricmc/fabric-api/fabric-biome-api-v1/9.0.17/fabric-biome-api-v1-9.0.17-sources.jar").exists() + new File(gradle.mavenLocalDir, "net/fabricmc/fabric-api/fabric-biome-api-v1/12.1.0/fabric-biome-api-v1-12.1.0.jar").exists() + new File(gradle.mavenLocalDir, "net/fabricmc/fabric-api/fabric-biome-api-v1/12.1.0/fabric-biome-api-v1-12.1.0-sources.jar").exists() serverResult.successful() serverResult.output.contains("- fabric-api $API_VERSION") where: - version << STANDARD_TEST_VERSIONS + //version << STANDARD_TEST_VERSIONS + version << [DEFAULT_GRADLE] } } diff --git a/src/test/groovy/net/fabricmc/loom/test/integration/MultiMcVersionTest.groovy b/src/test/groovy/net/fabricmc/loom/test/integration/MultiMcVersionTest.groovy new file mode 100644 index 00000000..c27db1df --- /dev/null +++ b/src/test/groovy/net/fabricmc/loom/test/integration/MultiMcVersionTest.groovy @@ -0,0 +1,61 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2016-2023 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.test.integration + +import net.fabricmc.loom.test.util.GradleProjectTestTrait +import spock.lang.Specification +import spock.lang.Unroll + +import static net.fabricmc.loom.test.LoomTestConstants.STANDARD_TEST_VERSIONS +import static org.gradle.testkit.runner.TaskOutcome.SUCCESS + +class MultiMcVersionTest extends Specification implements GradleProjectTestTrait { + @Unroll + def "build (gradle #version)"() { + setup: + def gradle = gradleProject(project: "multi-mc-versions", version: version) + + when: + def result = gradle.run(tasks: "build") + + then: + def versions = [ + 'fabric-1.14.4', + 'fabric-1.15', 'fabric-1.15.2', + 'fabric-1.16', 'fabric-1.16.5', + 'fabric-1.17', 'fabric-1.17.1', + 'fabric-1.18', 'fabric-1.18.2', + 'fabric-1.19', 'fabric-1.19.3' + ] + + result.task(":build").outcome == SUCCESS + versions.forEach { + result.task(":$it:build").outcome == SUCCESS + } + + where: + version << STANDARD_TEST_VERSIONS + } +} diff --git a/src/test/groovy/net/fabricmc/loom/test/util/GradleProjectTestTrait.groovy b/src/test/groovy/net/fabricmc/loom/test/util/GradleProjectTestTrait.groovy index 01d4e5b5..ad590af4 100644 --- a/src/test/groovy/net/fabricmc/loom/test/util/GradleProjectTestTrait.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/util/GradleProjectTestTrait.groovy @@ -37,22 +37,13 @@ trait GradleProjectTestTrait { @Lazy @Shared private static File sharedProjectDir = File.createTempDir() - @Lazy - @Shared - private static File sharedGradleHomeDir = File.createTempDir() + private static File gradleHomeDir = new File(LoomTestConstants.TEST_DIR, "integration/gradle_home") GradleProject gradleProject(Map options) { String gradleVersion = options.version as String ?: LoomTestConstants.DEFAULT_GRADLE String warningMode = options.warningMode as String ?: "fail" File projectDir = options.projectDir as File ?: options.sharedFiles ? sharedProjectDir : File.createTempDir() - File gradleHomeDir = options.gradleHomeDir as File ?: options.sharedFiles ? sharedGradleHomeDir : File.createTempDir() - - // Useful for faster local testing. - def homeDirOverride = System.getProperty("fabric.loom.test.homeDir") - - if (homeDirOverride) { - gradleHomeDir = new File(homeDirOverride) - } + File gradleHomeDir = gradleHomeDir setupProject(options, projectDir) diff --git a/src/test/groovy/net/fabricmc/loom/test/util/ServerRunner.groovy b/src/test/groovy/net/fabricmc/loom/test/util/ServerRunner.groovy index b2883abe..37862bf4 100644 --- a/src/test/groovy/net/fabricmc/loom/test/util/ServerRunner.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/util/ServerRunner.groovy @@ -25,11 +25,13 @@ package net.fabricmc.loom.test.util import groovy.transform.Immutable +import net.fabricmc.loom.util.download.Download import java.util.concurrent.TimeUnit class ServerRunner { - static final String LOADER_VERSION = "0.14.9" + static final String LOADER_VERSION = "0.14.12" + static final String INSTALLER_VERSION = "0.11.1" static final Map FABRIC_API_URLS = [ "1.16.5": "https://github.com/FabricMC/fabric/releases/download/0.37.1%2B1.16/fabric-api-0.37.1+1.16.jar", "1.17.1": "https://github.com/FabricMC/fabric/releases/download/0.37.1%2B1.17/fabric-api-0.37.1+1.17.jar" @@ -53,19 +55,9 @@ class ServerRunner { } def install() { - def args = [ - "server", - "-dir", - serverDir.absolutePath, - "-mcversion", - minecraftVersion, - "-loader", - LOADER_VERSION, - "-downloadMinecraft" - ] - - //noinspection UnnecessaryQualifiedReference - net.fabricmc.installer.Main.main(args as String[]) + def url = "https://meta.fabricmc.net/v2/versions/loader/${minecraftVersion}/${LOADER_VERSION}/${INSTALLER_VERSION}/server/jar" + Download.create(url) + .downloadPath(serverDir.toPath().resolve("fabric-server-launch.jar")) def eulaFile = new File(serverDir, "eula.txt") eulaFile << "eula=true" diff --git a/src/test/resources/projects/multi-mc-versions/build.gradle b/src/test/resources/projects/multi-mc-versions/build.gradle new file mode 100644 index 00000000..7d271f97 --- /dev/null +++ b/src/test/resources/projects/multi-mc-versions/build.gradle @@ -0,0 +1,56 @@ +import groovy.json.JsonSlurper + +plugins { + id "java" + id 'fabric-loom' apply false +} + +allprojects { + group = project.maven_group + version = project.mod_version +} + +ext { + yarnMeta = new JsonSlurper().parse(new URL("https://meta.fabricmc.net/v2/versions/yarn")) +} + +def getMappingVersion(String mcVersion) { + return rootProject.yarnMeta.find { it.gameVersion == mcVersion }.version +} + +subprojects { + apply plugin: "fabric-loom" + + archivesBaseName = rootProject.name + "-" + project.name + + def minecraft_version = project.name.substring(7) + def yarn_mappings = getMappingVersion(minecraft_version) + + dependencies { + // To change the versions see the gradle.properties files + minecraft "com.mojang:minecraft:$minecraft_version" + mappings "net.fabricmc:yarn:$yarn_mappings:v2" + modImplementation "net.fabricmc:fabric-loader:$loader_version" + } + + jar { + archiveClassifier.set "dev" + } + + // Just use the source from the root project + compileJava { + source(sourceSets.main.java.srcDirs) + } + + processResources { + from(rootProject.sourceSets.main.resources) + inputs.property 'version', project.version + + filesMatching("fabric.mod.json") { + expand 'version': project.version, 'minecraft_version': minecraft_version, 'loader_version': project.loader_version + } + } +} + +compileJava.enabled = false +processResources.enabled = false \ No newline at end of file diff --git a/src/test/resources/projects/multi-mc-versions/gradle.properties b/src/test/resources/projects/multi-mc-versions/gradle.properties new file mode 100644 index 00000000..ce3fa341 --- /dev/null +++ b/src/test/resources/projects/multi-mc-versions/gradle.properties @@ -0,0 +1,9 @@ +# The project should pass the build with these setting +org.gradle.jvmargs=-Xmx2560M +org.gradle.workers.max=3 + +mod_version = 1.0.0 +maven_group = com.example +archives_base_name = example-mod + +loader_version=0.14.12 \ No newline at end of file diff --git a/src/test/resources/projects/multi-mc-versions/settings.gradle b/src/test/resources/projects/multi-mc-versions/settings.gradle new file mode 100644 index 00000000..a7376582 --- /dev/null +++ b/src/test/resources/projects/multi-mc-versions/settings.gradle @@ -0,0 +1,9 @@ +rootProject.name = "multi-mc-versions" + +// Yes lot of mc version +include 'fabric-1.14.4' +include 'fabric-1.15', 'fabric-1.15.2' +include 'fabric-1.16', 'fabric-1.16.5' +include 'fabric-1.17', 'fabric-1.17.1' +include 'fabric-1.18', 'fabric-1.18.2' +include 'fabric-1.19', 'fabric-1.19.3' diff --git a/src/test/resources/projects/multi-mc-versions/src/main/java/com/example/examplemod/ExampleMod.java b/src/test/resources/projects/multi-mc-versions/src/main/java/com/example/examplemod/ExampleMod.java new file mode 100644 index 00000000..693e6e0c --- /dev/null +++ b/src/test/resources/projects/multi-mc-versions/src/main/java/com/example/examplemod/ExampleMod.java @@ -0,0 +1,19 @@ +package com.example.examplemod; + +import net.fabricmc.api.ModInitializer; +import net.minecraft.block.GrassBlock; +import net.minecraft.client.MinecraftClient; + +public class ExampleMod implements ModInitializer { + @Override + public void onInitialize() { + // class_2372 grassBlock = (class_2372) class_2246.field_10219; + GrassBlock grassBlock = (GrassBlock) net.minecraft.block.Blocks.GRASS_BLOCK; + // class_310 mincecraft = class_310.method_1551(); + MinecraftClient minecraft = MinecraftClient.getInstance(); + + System.out.println("Hello Fabric world!"); + System.out.println("This is a grass block: " + grassBlock); + System.out.println("This is minecraft client: " + minecraft); + } +} diff --git a/src/test/resources/projects/multi-mc-versions/src/main/resources/fabric.mod.json b/src/test/resources/projects/multi-mc-versions/src/main/resources/fabric.mod.json new file mode 100644 index 00000000..64ea821e --- /dev/null +++ b/src/test/resources/projects/multi-mc-versions/src/main/resources/fabric.mod.json @@ -0,0 +1,25 @@ +{ + "schemaVersion": 1, + "id": "example-mod", + "version": "${version}", + "name": "Example Mod", + "description": "This is an example description! Tell everyone what your mod is about!", + "authors": [ + "Me!" + ], + "contact": { + "homepage": "https://fabricmc.net/", + "sources": "https://github.com/FabricMC/fabric-example-mod" + }, + "license": "CC0-1.0", + "environment": "client", + "entrypoints": { + "main": [ + "com.example.examplemod.ExampleMod" + ] + }, + "depends": { + "fabricloader": ">=${loader_version}", + "minecraft": "${minecraft_version}" + } +}