From cc43cfc1dcc933c1ff5619299bc965afbcbc2e99 Mon Sep 17 00:00:00 2001 From: modmuss50 Date: Thu, 6 Oct 2022 21:42:45 +0100 Subject: [PATCH] Major steps towards config caching support :) --- .../mixin/AnnotationProcessorInvoker.java | 18 +++- .../configuration/CompileConfiguration.java | 21 +++-- .../configuration/LoomDependencyManager.java | 5 +- .../mods/ModConfigurationRemapper.java | 5 +- .../loom/configuration/mods/ModProcessor.java | 7 +- .../mappings/GradleMappingContext.java | 7 +- .../mappings/IntermediateMappingsService.java | 4 +- .../mappings/MappingsProviderImpl.java | 6 +- .../loom/task/AbstractRemapJarTask.java | 12 ++- .../loom/task/PrepareJarRemapTask.java | 2 +- .../net/fabricmc/loom/task/RemapJarTask.java | 24 +++-- .../loom/task/RemapSourcesJarTask.java | 7 +- .../loom/task/service/JarManifestService.java | 43 ++++----- .../loom/task/service/MappingsService.java | 8 +- .../task/service/MixinMappingsService.java | 70 --------------- .../task/service/SourceRemapperService.java | 7 +- .../task/service/TinyRemapperService.java | 32 +++++-- .../fabricmc/loom/util/DeprecationHelper.java | 7 -- .../loom/util/gradle/GradleUtils.java | 11 +++ .../loom/util/gradle/SourceSetHelper.java | 15 ++-- .../util/kotlin/KotlinClasspathService.java | 7 +- .../service/BuildSharedServiceManager.java | 90 +++++++++++++++++++ .../service/ScopedSharedServiceManager.java | 35 ++++++++ .../util/service/SharedServiceManager.java | 28 ++---- .../util/service/UnsafeWorkQueueHelper.java | 5 +- 25 files changed, 295 insertions(+), 181 deletions(-) delete mode 100644 src/main/java/net/fabricmc/loom/task/service/MixinMappingsService.java create mode 100644 src/main/java/net/fabricmc/loom/util/service/BuildSharedServiceManager.java create mode 100644 src/main/java/net/fabricmc/loom/util/service/ScopedSharedServiceManager.java diff --git a/src/main/java/net/fabricmc/loom/build/mixin/AnnotationProcessorInvoker.java b/src/main/java/net/fabricmc/loom/build/mixin/AnnotationProcessorInvoker.java index 0a79dab8..3415f7bd 100644 --- a/src/main/java/net/fabricmc/loom/build/mixin/AnnotationProcessorInvoker.java +++ b/src/main/java/net/fabricmc/loom/build/mixin/AnnotationProcessorInvoker.java @@ -45,7 +45,7 @@ import net.fabricmc.loom.LoomGradleExtension; import net.fabricmc.loom.configuration.ide.idea.IdeaUtils; import net.fabricmc.loom.configuration.providers.minecraft.MinecraftSourceSets; import net.fabricmc.loom.extension.MixinExtension; -import net.fabricmc.loom.task.service.MixinMappingsService; +import net.fabricmc.loom.task.PrepareJarRemapTask; import net.fabricmc.loom.util.Constants; /** @@ -94,7 +94,7 @@ public abstract class AnnotationProcessorInvoker { String refmapName = Objects.requireNonNull(MixinExtension.getMixinInformationContainer(sourceSet)).refmapNameProvider().get(); Map args = new HashMap<>() {{ put(Constants.MixinArguments.IN_MAP_FILE_NAMED_INTERMEDIARY, loom.getMappingsProvider().tinyMappings.toFile().getCanonicalPath()); - put(Constants.MixinArguments.OUT_MAP_FILE_NAMED_INTERMEDIARY, MixinMappingsService.getMixinMappingFile(project, sourceSet).getCanonicalPath()); + put(Constants.MixinArguments.OUT_MAP_FILE_NAMED_INTERMEDIARY, getMixinMappingsForSourceSet(project, sourceSet).getCanonicalPath()); put(Constants.MixinArguments.OUT_REFMAP_FILE, getRefmapDestination(task, refmapName)); put(Constants.MixinArguments.DEFAULT_OBFUSCATION_ENV, "named:" + loom.getMixin().getRefmapTargetNamespace().get()); put(Constants.MixinArguments.QUIET, "true"); @@ -111,6 +111,9 @@ public abstract class AnnotationProcessorInvoker { args.put("AMSG_" + key, value); }); + // Ensure that all of the mixin mappings have been generated before we create the mixin mappings. + runBeforePrepare(project, task); + project.getLogger().debug("Outputting refmap to dir: " + getRefmapDestinationDir(task) + " for compile task: " + task); args.forEach((k, v) -> passArgument(task, k, v)); } catch (IOException e) { @@ -143,6 +146,12 @@ public abstract class AnnotationProcessorInvoker { } } + private void runBeforePrepare(Project project, Task compileTask) { + project.getGradle().allprojects(otherProject -> { + otherProject.getTasks().withType(PrepareJarRemapTask.class, prepareRemapTask -> prepareRemapTask.mustRunAfter(compileTask)); + }); + } + private static void checkPattern(String input, Pattern pattern) { final Matcher matcher = pattern.matcher(input); @@ -150,4 +159,9 @@ public abstract class AnnotationProcessorInvoker { throw new IllegalArgumentException("Mixin argument (%s) does not match pattern (%s)".formatted(input, pattern.toString())); } } + + public static File getMixinMappingsForSourceSet(Project project, SourceSet sourceSet) { + final LoomGradleExtension extension = LoomGradleExtension.get(project); + return new File(extension.getFiles().getProjectBuildCache(), "mixin-map-" + extension.getMappingsProvider().mappingsIdentifier() + "." + sourceSet.getName() + ".tiny"); + } } diff --git a/src/main/java/net/fabricmc/loom/configuration/CompileConfiguration.java b/src/main/java/net/fabricmc/loom/configuration/CompileConfiguration.java index 09afc19a..b4fc5ff2 100644 --- a/src/main/java/net/fabricmc/loom/configuration/CompileConfiguration.java +++ b/src/main/java/net/fabricmc/loom/configuration/CompileConfiguration.java @@ -30,6 +30,7 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.util.List; +import java.util.function.Consumer; import org.gradle.api.NamedDomainObjectProvider; import org.gradle.api.Project; @@ -63,6 +64,8 @@ import net.fabricmc.loom.util.Constants; import net.fabricmc.loom.util.ExceptionUtil; import net.fabricmc.loom.util.gradle.GradleUtils; import net.fabricmc.loom.util.gradle.SourceSetHelper; +import net.fabricmc.loom.util.service.ScopedSharedServiceManager; +import net.fabricmc.loom.util.service.SharedServiceManager; public final class CompileConfiguration { private CompileConfiguration() { @@ -126,7 +129,7 @@ public final class CompileConfiguration { javadoc.setClasspath(main.getOutput().plus(main.getCompileClasspath())); }); - GradleUtils.afterSuccessfulEvaluation(project, () -> { + afterEvaluationWithService(project, (serviceManager) -> { MinecraftSourceSets.get(project).afterEvaluate(project); final boolean previousRefreshDeps = extension.refreshDeps(); @@ -137,14 +140,14 @@ public final class CompileConfiguration { } try { - setupMinecraft(project); + setupMinecraft(project, serviceManager); } catch (Exception e) { throw ExceptionUtil.createDescriptiveWrapper(RuntimeException::new, "Failed to setup Minecraft", e); } LoomDependencyManager dependencyManager = new LoomDependencyManager(); extension.setDependencyManager(dependencyManager); - dependencyManager.handleDependencies(project); + dependencyManager.handleDependencies(project, serviceManager); releaseLock(project); extension.setRefreshDeps(previousRefreshDeps); @@ -178,7 +181,7 @@ public final class CompileConfiguration { } // This is not thread safe across projects synchronize it here just to be sure, might be possible to move this further down, but for now this will do. - private static synchronized void setupMinecraft(Project project) throws Exception { + private static synchronized void setupMinecraft(Project project, SharedServiceManager serviceManager) throws Exception { final LoomGradleExtension extension = LoomGradleExtension.get(project); final MinecraftJarConfiguration jarConfiguration = extension.getMinecraftJarConfiguration().get(); @@ -188,7 +191,7 @@ public final class CompileConfiguration { minecraftProvider.provide(); final DependencyInfo mappingsDep = DependencyInfo.create(project, Constants.Configurations.MAPPINGS); - final MappingsProviderImpl mappingsProvider = MappingsProviderImpl.getInstance(project, mappingsDep, minecraftProvider); + final MappingsProviderImpl mappingsProvider = MappingsProviderImpl.getInstance(serviceManager, project, mappingsDep, minecraftProvider); extension.setMappingsProvider(mappingsProvider); mappingsProvider.applyToProject(project, mappingsDep); @@ -331,4 +334,12 @@ public final class CompileConfiguration { private static void finalizedBy(Project project, String a, String b) { project.getTasks().named(a).configure(task -> task.finalizedBy(project.getTasks().named(b))); } + + private static void afterEvaluationWithService(Project project, Consumer consumer) { + GradleUtils.afterSuccessfulEvaluation(project, () -> { + try (var serviceManager = new ScopedSharedServiceManager()) { + consumer.accept(serviceManager); + } + }); + } } diff --git a/src/main/java/net/fabricmc/loom/configuration/LoomDependencyManager.java b/src/main/java/net/fabricmc/loom/configuration/LoomDependencyManager.java index 22ce5a3c..3ce043ae 100644 --- a/src/main/java/net/fabricmc/loom/configuration/LoomDependencyManager.java +++ b/src/main/java/net/fabricmc/loom/configuration/LoomDependencyManager.java @@ -44,9 +44,10 @@ import net.fabricmc.loom.configuration.mods.ModConfigurationRemapper; import net.fabricmc.loom.util.Constants; import net.fabricmc.loom.util.SourceRemapper; import net.fabricmc.loom.util.ZipUtils; +import net.fabricmc.loom.util.service.SharedServiceManager; public class LoomDependencyManager { - public void handleDependencies(Project project) { + public void handleDependencies(Project project, SharedServiceManager serviceManager) { List afterTasks = new ArrayList<>(); project.getLogger().info(":setting up loom dependencies"); @@ -78,7 +79,7 @@ public class LoomDependencyManager { SourceRemapper sourceRemapper = new SourceRemapper(project, true); String mappingsIdentifier = extension.getMappingsProvider().mappingsIdentifier(); - ModConfigurationRemapper.supplyModConfigurations(project, mappingsIdentifier, extension, sourceRemapper); + ModConfigurationRemapper.supplyModConfigurations(project, serviceManager, mappingsIdentifier, extension, sourceRemapper); sourceRemapper.remapAll(); diff --git a/src/main/java/net/fabricmc/loom/configuration/mods/ModConfigurationRemapper.java b/src/main/java/net/fabricmc/loom/configuration/mods/ModConfigurationRemapper.java index d29c4c66..e25f7c79 100644 --- a/src/main/java/net/fabricmc/loom/configuration/mods/ModConfigurationRemapper.java +++ b/src/main/java/net/fabricmc/loom/configuration/mods/ModConfigurationRemapper.java @@ -58,6 +58,7 @@ import net.fabricmc.loom.util.Constants; import net.fabricmc.loom.util.OperatingSystem; import net.fabricmc.loom.util.SourceRemapper; import net.fabricmc.loom.util.fmj.FabricModJsonFactory; +import net.fabricmc.loom.util.service.SharedServiceManager; @SuppressWarnings("UnstableApiUsage") public class ModConfigurationRemapper { @@ -65,7 +66,7 @@ public class ModConfigurationRemapper { // 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) { + public static void supplyModConfigurations(Project project, SharedServiceManager serviceManager, String mappingsSuffix, LoomGradleExtension extension, SourceRemapper sourceRemapper) { final DependencyHandler dependencies = project.getDependencies(); for (RemapConfigurationSettings entry : extension.getRemapConfigurations()) { @@ -110,7 +111,7 @@ public class ModConfigurationRemapper { if (!toRemap.isEmpty()) { try { - new ModProcessor(project, sourceConfig).processMods(toRemap); + new ModProcessor(project, sourceConfig, serviceManager).processMods(toRemap); } catch (IOException e) { throw new UncheckedIOException("Failed to remap mods", e); } diff --git a/src/main/java/net/fabricmc/loom/configuration/mods/ModProcessor.java b/src/main/java/net/fabricmc/loom/configuration/mods/ModProcessor.java index a5998ff8..f79d8553 100644 --- a/src/main/java/net/fabricmc/loom/configuration/mods/ModProcessor.java +++ b/src/main/java/net/fabricmc/loom/configuration/mods/ModProcessor.java @@ -53,6 +53,7 @@ import net.fabricmc.loom.util.TinyRemapperHelper; import net.fabricmc.loom.util.ZipUtils; import net.fabricmc.loom.util.kotlin.KotlinClasspathService; import net.fabricmc.loom.util.kotlin.KotlinRemapperClassloader; +import net.fabricmc.loom.util.service.SharedServiceManager; import net.fabricmc.tinyremapper.InputTag; import net.fabricmc.tinyremapper.NonClassCopyMode; import net.fabricmc.tinyremapper.OutputConsumerPath; @@ -64,10 +65,12 @@ public class ModProcessor { private final Project project; private final Configuration sourceConfiguration; + private final SharedServiceManager serviceManager; - public ModProcessor(Project project, Configuration sourceConfiguration) { + public ModProcessor(Project project, Configuration sourceConfiguration, SharedServiceManager serviceManager) { this.project = project; this.sourceConfiguration = sourceConfiguration; + this.serviceManager = serviceManager; } public void processMods(List remapList) throws IOException { @@ -101,7 +104,7 @@ public class ModProcessor { .withMappings(TinyRemapperHelper.create(mappingsProvider.getMappings(), fromM, toM, false)) .renameInvalidLocals(false); - final KotlinClasspathService kotlinClasspathService = KotlinClasspathService.getOrCreateIfRequired(project); + final KotlinClasspathService kotlinClasspathService = KotlinClasspathService.getOrCreateIfRequired(serviceManager, project); KotlinRemapperClassloader kotlinRemapperClassloader = null; if (kotlinClasspathService != null) { diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/GradleMappingContext.java b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/GradleMappingContext.java index fdbd27d0..88ede35c 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/GradleMappingContext.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/GradleMappingContext.java @@ -38,6 +38,7 @@ import net.fabricmc.loom.LoomGradleExtension; import net.fabricmc.loom.api.mappings.layered.MappingContext; import net.fabricmc.loom.configuration.providers.minecraft.MinecraftProvider; import net.fabricmc.loom.util.download.DownloadBuilder; +import net.fabricmc.loom.util.service.ScopedSharedServiceManager; import net.fabricmc.mappingio.tree.MemoryMappingTree; public class GradleMappingContext implements MappingContext { @@ -66,7 +67,11 @@ public class GradleMappingContext implements MappingContext { @Override public Supplier intermediaryTree() { - return () -> IntermediateMappingsService.getInstance(project, minecraftProvider()).getMemoryMappingTree(); + return () -> { + try (var serviceManager = new ScopedSharedServiceManager()) { + return IntermediateMappingsService.getInstance(serviceManager, project, minecraftProvider()).getMemoryMappingTree(); + } + }; } @Override diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/IntermediateMappingsService.java b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/IntermediateMappingsService.java index 13b1427c..d605ea27 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/IntermediateMappingsService.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/IntermediateMappingsService.java @@ -56,12 +56,12 @@ public final class IntermediateMappingsService implements SharedService { this.intermediaryTiny = intermediaryTiny; } - public static synchronized IntermediateMappingsService getInstance(Project project, MinecraftProvider minecraftProvider) { + public static synchronized IntermediateMappingsService getInstance(SharedServiceManager sharedServiceManager, Project project, MinecraftProvider minecraftProvider) { final LoomGradleExtension extension = LoomGradleExtension.get(project); final IntermediateMappingsProvider intermediateProvider = extension.getIntermediateMappingsProvider(); final String id = "IntermediateMappingsService:%s:%s".formatted(intermediateProvider.getName(), intermediateProvider.getMinecraftVersion().get()); - return SharedServiceManager.get(project).getOrCreateService(id, () -> create(intermediateProvider, minecraftProvider)); + return sharedServiceManager.getOrCreateService(id, () -> create(intermediateProvider, minecraftProvider)); } @VisibleForTesting diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingsProviderImpl.java b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingsProviderImpl.java index c780a8cc..11966c23 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingsProviderImpl.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingsProviderImpl.java @@ -98,9 +98,9 @@ public class MappingsProviderImpl implements MappingsProvider, SharedService { this.intermediaryService = intermediaryService; } - public static synchronized MappingsProviderImpl getInstance(Project project, DependencyInfo dependency, MinecraftProvider minecraftProvider) { - return SharedServiceManager.get(project).getOrCreateService("MappingsProvider:%s:%s".formatted(dependency.getDepString(), minecraftProvider.minecraftVersion()), () -> { - Supplier intermediaryService = Suppliers.memoize(() -> IntermediateMappingsService.getInstance(project, minecraftProvider)); + public static synchronized MappingsProviderImpl getInstance(SharedServiceManager sharedServiceManager, Project project, DependencyInfo dependency, MinecraftProvider minecraftProvider) { + return sharedServiceManager.getOrCreateService("MappingsProvider:%s:%s".formatted(dependency.getDepString(), minecraftProvider.minecraftVersion()), () -> { + Supplier intermediaryService = Suppliers.memoize(() -> IntermediateMappingsService.getInstance(sharedServiceManager, project, minecraftProvider)); return create(dependency, minecraftProvider, intermediaryService); }); } diff --git a/src/main/java/net/fabricmc/loom/task/AbstractRemapJarTask.java b/src/main/java/net/fabricmc/loom/task/AbstractRemapJarTask.java index 053d8ec5..57f7dcdc 100644 --- a/src/main/java/net/fabricmc/loom/task/AbstractRemapJarTask.java +++ b/src/main/java/net/fabricmc/loom/task/AbstractRemapJarTask.java @@ -45,10 +45,12 @@ import org.gradle.api.file.RegularFileProperty; import org.gradle.api.provider.ListProperty; import org.gradle.api.provider.MapProperty; import org.gradle.api.provider.Property; +import org.gradle.api.provider.Provider; import org.gradle.api.tasks.Input; import org.gradle.api.tasks.InputFile; import org.gradle.api.tasks.InputFiles; import org.gradle.api.tasks.Internal; +import org.gradle.build.event.BuildEventsListenerRegistry; import org.gradle.jvm.tasks.Jar; import org.gradle.workers.WorkAction; import org.gradle.workers.WorkParameters; @@ -89,15 +91,23 @@ public abstract class AbstractRemapJarTask extends Jar { @Inject protected abstract WorkerExecutor getWorkerExecutor(); + @Inject + protected abstract BuildEventsListenerRegistry getBuildEventsListenerRegistry(); + @Input public abstract Property getIncludesClientOnlyClasses(); + private final Provider jarManifestServiceProvider; + @Inject public AbstractRemapJarTask() { getSourceNamespace().convention(MappingsNamespace.NAMED.toString()).finalizeValueOnRead(); getTargetNamespace().convention(MappingsNamespace.INTERMEDIARY.toString()).finalizeValueOnRead(); getRemapperIsolation().convention(false).finalizeValueOnRead(); getIncludesClientOnlyClasses().convention(false).finalizeValueOnRead(); + + jarManifestServiceProvider = JarManifestService.get(getProject()); + usesService(jarManifestServiceProvider); } public final

void submitWork(Class> workAction, Action

action) { @@ -113,7 +123,7 @@ public abstract class AbstractRemapJarTask extends Jar { params.getArchivePreserveFileTimestamps().set(isPreserveFileTimestamps()); params.getArchiveReproducibleFileOrder().set(isReproducibleFileOrder()); - params.getJarManifestService().set(JarManifestService.get(getProject())); + params.getJarManifestService().set(jarManifestServiceProvider); if (getIncludesClientOnlyClasses().get()) { final List clientOnlyEntries = getClientOnlyEntries(); diff --git a/src/main/java/net/fabricmc/loom/task/PrepareJarRemapTask.java b/src/main/java/net/fabricmc/loom/task/PrepareJarRemapTask.java index f5761d0a..360f88ef 100644 --- a/src/main/java/net/fabricmc/loom/task/PrepareJarRemapTask.java +++ b/src/main/java/net/fabricmc/loom/task/PrepareJarRemapTask.java @@ -78,7 +78,7 @@ public abstract class PrepareJarRemapTask extends AbstractLoomTask { final WorkQueue workQueue = getWorkerExecutor().noIsolation(); workQueue.submit(ReadInputsAction.class, params -> { - params.getTinyRemapperBuildServiceUuid().set(UnsafeWorkQueueHelper.create(getProject(), remapJarTask.getTinyRemapperService())); + params.getTinyRemapperBuildServiceUuid().set(UnsafeWorkQueueHelper.create(remapJarTask.getTinyRemapperService())); params.getInputFile().set(getInputFile()); }); } diff --git a/src/main/java/net/fabricmc/loom/task/RemapJarTask.java b/src/main/java/net/fabricmc/loom/task/RemapJarTask.java index 8938f832..ada1462a 100644 --- a/src/main/java/net/fabricmc/loom/task/RemapJarTask.java +++ b/src/main/java/net/fabricmc/loom/task/RemapJarTask.java @@ -46,11 +46,13 @@ import org.gradle.api.file.FileCollection; import org.gradle.api.plugins.JavaPlugin; import org.gradle.api.provider.ListProperty; import org.gradle.api.provider.Property; +import org.gradle.api.provider.Provider; import org.gradle.api.tasks.Input; import org.gradle.api.tasks.InputFiles; import org.gradle.api.tasks.Internal; import org.gradle.api.tasks.SourceSet; import org.gradle.api.tasks.TaskAction; +import org.jetbrains.annotations.ApiStatus; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -71,6 +73,7 @@ import net.fabricmc.loom.util.SidedClassVisitor; import net.fabricmc.loom.util.ZipUtils; import net.fabricmc.loom.util.fmj.FabricModJson; import net.fabricmc.loom.util.fmj.FabricModJsonFactory; +import net.fabricmc.loom.util.service.BuildSharedServiceManager; import net.fabricmc.loom.util.service.UnsafeWorkQueueHelper; import net.fabricmc.tinyremapper.OutputConsumerPath; import net.fabricmc.tinyremapper.TinyRemapper; @@ -82,11 +85,18 @@ public abstract class RemapJarTask extends AbstractRemapJarTask { @Input public abstract Property getAddNestedDependencies(); - private Supplier tinyRemapperService = Suppliers.memoize(() -> TinyRemapperService.getOrCreate(this)); + @Input + @ApiStatus.Internal + 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(); @@ -94,6 +104,8 @@ public abstract class RemapJarTask extends AbstractRemapJarTask { Configuration includeConfiguration = getProject().getConfigurations().getByName(Constants.Configurations.INCLUDE); getNestedJars().from(new IncludedJarFactory(getProject()).getNestedJars(includeConfiguration)); + getUseMixinAP().set(LoomGradleExtension.get(getProject()).getMixin().getUseLegacyMixinAp()); + setupPreparationTask(); } @@ -115,20 +127,18 @@ public abstract class RemapJarTask extends AbstractRemapJarTask { @TaskAction public void run() { - final LoomGradleExtension extension = LoomGradleExtension.get(getProject()); - submitWork(RemapAction.class, params -> { if (getAddNestedDependencies().get()) { params.getNestedJars().from(getNestedJars()); } - params.getTinyRemapperBuildServiceUuid().set(UnsafeWorkQueueHelper.create(getProject(), tinyRemapperService.get())); + params.getTinyRemapperBuildServiceUuid().set(UnsafeWorkQueueHelper.create(tinyRemapperService.get())); params.getRemapClasspath().from(getClasspath()); - final boolean legacyMixin = extension.getMixin().getUseLegacyMixinAp().get(); - params.getUseMixinExtension().set(!legacyMixin); + final boolean mixinAp = getUseMixinAP().get(); + params.getUseMixinExtension().set(!mixinAp); - if (legacyMixin) { + if (mixinAp) { setupLegacyMixinRefmapRemapping(params); } }); diff --git a/src/main/java/net/fabricmc/loom/task/RemapSourcesJarTask.java b/src/main/java/net/fabricmc/loom/task/RemapSourcesJarTask.java index c65b1c54..67319696 100644 --- a/src/main/java/net/fabricmc/loom/task/RemapSourcesJarTask.java +++ b/src/main/java/net/fabricmc/loom/task/RemapSourcesJarTask.java @@ -32,6 +32,7 @@ import javax.inject.Inject; import org.gradle.api.plugins.JavaPlugin; import org.gradle.api.provider.Property; +import org.gradle.api.provider.Provider; import org.gradle.api.tasks.SourceSet; import org.gradle.api.tasks.TaskAction; import org.slf4j.Logger; @@ -39,12 +40,16 @@ import org.slf4j.LoggerFactory; import net.fabricmc.loom.configuration.providers.minecraft.MinecraftSourceSets; import net.fabricmc.loom.task.service.SourceRemapperService; +import net.fabricmc.loom.util.service.BuildSharedServiceManager; import net.fabricmc.loom.util.service.UnsafeWorkQueueHelper; public abstract class RemapSourcesJarTask extends AbstractRemapJarTask { + private final Provider serviceManagerProvider; + @Inject public RemapSourcesJarTask() { super(); + serviceManagerProvider = BuildSharedServiceManager.createForTask(this, getBuildEventsListenerRegistry()); getClasspath().from(getProject().getConfigurations().getByName(JavaPlugin.COMPILE_CLASSPATH_CONFIGURATION_NAME)); } @@ -52,7 +57,7 @@ public abstract class RemapSourcesJarTask extends AbstractRemapJarTask { @TaskAction public void run() { submitWork(RemapSourcesAction.class, params -> { - params.getSourcesRemapperServiceUuid().set(UnsafeWorkQueueHelper.create(getProject(), SourceRemapperService.create(this))); + params.getSourcesRemapperServiceUuid().set(UnsafeWorkQueueHelper.create(SourceRemapperService.create(serviceManagerProvider.get().get(), this))); }); } diff --git a/src/main/java/net/fabricmc/loom/task/service/JarManifestService.java b/src/main/java/net/fabricmc/loom/task/service/JarManifestService.java index 117207fa..f1c3d9b2 100644 --- a/src/main/java/net/fabricmc/loom/task/service/JarManifestService.java +++ b/src/main/java/net/fabricmc/loom/task/service/JarManifestService.java @@ -40,6 +40,7 @@ import org.gradle.util.GradleVersion; import net.fabricmc.loom.LoomGradleExtension; import net.fabricmc.loom.LoomGradlePlugin; +import net.fabricmc.loom.configuration.InstallerData; import net.fabricmc.loom.util.Constants; import net.fabricmc.tinyremapper.TinyRemapper; @@ -63,10 +64,10 @@ public abstract class JarManifestService implements BuildService extension.getMinecraftProvider().minecraftVersion())); params.getTinyRemapperVersion().set(tinyRemapperVersion.orElse("unknown")); - params.getFabricLoaderVersion().set(getLoaderVersion(project).orElse("unknown")); - params.getMixinVersion().set(getMixinVersion(project).orElse(new MixinVersion("unknown", "unknown"))); + params.getFabricLoaderVersion().set(project.provider(() -> Optional.ofNullable(extension.getInstallerData()).map(InstallerData::version).orElse("unknown"))); + params.getMixinVersion().set(getMixinVersion(project)); }); }); } @@ -98,31 +99,23 @@ public abstract class JarManifestService implements BuildService getLoaderVersion(Project project) { - LoomGradleExtension extension = LoomGradleExtension.get(project); - - if (extension.getInstallerData() == null) { - project.getLogger().warn("Could not determine fabric loader version for jar manifest"); - return Optional.empty(); - } - - return Optional.of(extension.getInstallerData().version()); - } - private record MixinVersion(String group, String version) implements Serializable { } - private static Optional getMixinVersion(Project project) { - // Not super ideal that this uses the mod compile classpath, should prob look into making this not a thing at somepoint - Optional dependency = project.getConfigurations().getByName(Constants.Configurations.LOADER_DEPENDENCIES) - .getDependencies() - .stream() - .filter(dep -> "sponge-mixin".equals(dep.getName())) - .findFirst(); + private static Provider getMixinVersion(Project project) { + return project.getConfigurations().named(Constants.Configurations.LOADER_DEPENDENCIES).map(configuration -> { + // Not super ideal that this uses the mod compile classpath, should prob look into making this not a thing at somepoint + Optional dependency = configuration + .getDependencies() + .stream() + .filter(dep -> "sponge-mixin".equals(dep.getName())) + .findFirst(); - if (dependency.isEmpty()) { - project.getLogger().warn("Could not determine Mixin version for jar manifest"); - } + if (dependency.isEmpty()) { + project.getLogger().warn("Could not determine Mixin version for jar manifest"); + } - return dependency.map(d -> new MixinVersion(d.getGroup(), d.getVersion())); + return dependency.map(d -> new MixinVersion(d.getGroup(), d.getVersion())) + .orElse(new MixinVersion("unknown", "unknown")); + }); } } diff --git a/src/main/java/net/fabricmc/loom/task/service/MappingsService.java b/src/main/java/net/fabricmc/loom/task/service/MappingsService.java index 53e9bec4..16a436bc 100644 --- a/src/main/java/net/fabricmc/loom/task/service/MappingsService.java +++ b/src/main/java/net/fabricmc/loom/task/service/MappingsService.java @@ -42,21 +42,17 @@ import net.fabricmc.tinyremapper.IMappingProvider; public final class MappingsService implements SharedService { private record Options(Path mappingsFile, String from, String to, boolean remapLocals) { } - public static MappingsService create(Project project, String name, Path mappingsFile, String from, String to, boolean remapLocals) { - return create(SharedServiceManager.get(project), name, mappingsFile, from, to, remapLocals); - } - public static synchronized MappingsService create(SharedServiceManager sharedServiceManager, String name, Path mappingsFile, String from, String to, boolean remapLocals) { final Options options = new Options(mappingsFile, from, to, remapLocals); final String id = name + options.hashCode(); return sharedServiceManager.getOrCreateService(id, () -> new MappingsService(options)); } - public static MappingsService createDefault(Project project, String from, String to) { + public static MappingsService createDefault(Project project, SharedServiceManager serviceManager, String from, String to) { final MappingsProviderImpl mappingsProvider = LoomGradleExtension.get(project).getMappingsProvider(); final String name = mappingsProvider.getBuildServiceName("mappingsProvider", from, to); - return MappingsService.create(project, name, mappingsProvider.tinyMappings, from, to, false); + return MappingsService.create(serviceManager, name, mappingsProvider.tinyMappings, from, to, false); } private final Options options; diff --git a/src/main/java/net/fabricmc/loom/task/service/MixinMappingsService.java b/src/main/java/net/fabricmc/loom/task/service/MixinMappingsService.java deleted file mode 100644 index a1a7336f..00000000 --- a/src/main/java/net/fabricmc/loom/task/service/MixinMappingsService.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * 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.task.service; - -import java.io.File; -import java.util.HashSet; - -import org.gradle.api.Project; -import org.gradle.api.tasks.SourceSet; - -import net.fabricmc.loom.LoomGradleExtension; -import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl; -import net.fabricmc.loom.util.service.SharedService; -import net.fabricmc.loom.util.service.SharedServiceManager; -import net.fabricmc.tinyremapper.IMappingProvider; - -public final class MixinMappingsService implements SharedService { - private final SharedServiceManager sharedServiceManager; - private final HashSet mixinMappings = new HashSet<>(); - - private MixinMappingsService(SharedServiceManager sharedServiceManager) { - this.sharedServiceManager = sharedServiceManager; - } - - public static File getMixinMappingFile(Project project, SourceSet sourceSet) { - final LoomGradleExtension extension = LoomGradleExtension.get(project); - File mixinMapping = new File(extension.getFiles().getProjectBuildCache(), "mixin-map-" + extension.getMappingsProvider().mappingsIdentifier() + "." + sourceSet.getName() + ".tiny"); - - getService(SharedServiceManager.get(project), extension.getMappingsProvider()).mixinMappings.add(mixinMapping); - - return mixinMapping; - } - - static synchronized MixinMappingsService getService(SharedServiceManager sharedServiceManager, MappingsProviderImpl mappingsProvider) { - return sharedServiceManager.getOrCreateService("MixinMappings-" + mappingsProvider.mappingsIdentifier(), () -> new MixinMappingsService(sharedServiceManager)); - } - - IMappingProvider getMappingProvider(String from, String to) { - return out -> { - for (File mixinMapping : mixinMappings) { - if (!mixinMapping.exists()) continue; - - MappingsService service = MappingsService.create(sharedServiceManager, mixinMapping.getAbsolutePath(), mixinMapping.toPath(), from, to, false); - service.getMappingsProvider().load(out); - } - }; - } -} diff --git a/src/main/java/net/fabricmc/loom/task/service/SourceRemapperService.java b/src/main/java/net/fabricmc/loom/task/service/SourceRemapperService.java index 30b1ea0f..f33a089a 100644 --- a/src/main/java/net/fabricmc/loom/task/service/SourceRemapperService.java +++ b/src/main/java/net/fabricmc/loom/task/service/SourceRemapperService.java @@ -52,16 +52,15 @@ import net.fabricmc.loom.util.service.SharedServiceManager; import net.fabricmc.lorenztiny.TinyMappingsReader; public final class SourceRemapperService implements SharedService { - public static synchronized SourceRemapperService create(RemapSourcesJarTask task) { + public static synchronized SourceRemapperService create(SharedServiceManager serviceManager, RemapSourcesJarTask task) { final Project project = task.getProject(); final String to = task.getTargetNamespace().get(); final String from = task.getSourceNamespace().get(); final LoomGradleExtension extension = LoomGradleExtension.get(project); - final SharedServiceManager sharedServiceManager = SharedServiceManager.get(project); final String id = extension.getMappingsProvider().getBuildServiceName("sourceremapper", from, to); - return sharedServiceManager.getOrCreateService(id, () -> - new SourceRemapperService(MappingsService.createDefault(project, from, to), task.getClasspath() + return serviceManager.getOrCreateService(id, () -> + new SourceRemapperService(MappingsService.createDefault(project, serviceManager, from, to), task.getClasspath() )); } 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 cd780ee7..6d29b9d9 100644 --- a/src/main/java/net/fabricmc/loom/task/service/TinyRemapperService.java +++ b/src/main/java/net/fabricmc/loom/task/service/TinyRemapperService.java @@ -37,10 +37,15 @@ import java.util.Objects; import java.util.StringJoiner; import org.gradle.api.Project; +import org.gradle.api.invocation.Gradle; +import org.gradle.api.tasks.SourceSet; import org.jetbrains.annotations.Nullable; import net.fabricmc.loom.LoomGradleExtension; +import net.fabricmc.loom.build.mixin.AnnotationProcessorInvoker; import net.fabricmc.loom.task.AbstractRemapJarTask; +import net.fabricmc.loom.util.gradle.GradleUtils; +import net.fabricmc.loom.util.gradle.SourceSetHelper; import net.fabricmc.loom.util.kotlin.KotlinClasspath; import net.fabricmc.loom.util.kotlin.KotlinClasspathService; import net.fabricmc.loom.util.kotlin.KotlinRemapperClassloader; @@ -51,14 +56,13 @@ import net.fabricmc.tinyremapper.InputTag; import net.fabricmc.tinyremapper.TinyRemapper; public class TinyRemapperService implements SharedService { - public static synchronized TinyRemapperService getOrCreate(AbstractRemapJarTask remapJarTask) { + public static synchronized TinyRemapperService getOrCreate(SharedServiceManager serviceManager, AbstractRemapJarTask remapJarTask) { final Project project = remapJarTask.getProject(); final String to = remapJarTask.getTargetNamespace().get(); final String from = remapJarTask.getSourceNamespace().get(); final LoomGradleExtension extension = LoomGradleExtension.get(project); - final SharedServiceManager sharedServiceManager = SharedServiceManager.get(project); final boolean legacyMixin = extension.getMixin().getUseLegacyMixinAp().get(); - final @Nullable KotlinClasspathService kotlinClasspathService = KotlinClasspathService.getOrCreateIfRequired(project); + final @Nullable KotlinClasspathService kotlinClasspathService = KotlinClasspathService.getOrCreateIfRequired(serviceManager, project); // Generates an id that is used to share the remapper across projects. This tasks in the remap jar task name to handle custom remap jar tasks separately. final var joiner = new StringJoiner(":"); @@ -75,12 +79,12 @@ public class TinyRemapperService implements SharedService { final String id = joiner.toString(); - TinyRemapperService service = sharedServiceManager.getOrCreateService(id, () -> { + TinyRemapperService service = serviceManager.getOrCreateService(id, () -> { List mappings = new ArrayList<>(); - mappings.add(MappingsService.createDefault(project, from, to).getMappingsProvider()); + mappings.add(MappingsService.createDefault(project, serviceManager, from, to).getMappingsProvider()); if (legacyMixin) { - mappings.add(MixinMappingsService.getService(SharedServiceManager.get(project), extension.getMappingsProvider()).getMappingProvider(from, to)); + mappings.add(gradleMixinMappingProvider(serviceManager, project.getGradle(), from, to)); } return new TinyRemapperService(mappings, !legacyMixin, kotlinClasspathService); @@ -91,6 +95,22 @@ public class TinyRemapperService implements SharedService { return service; } + // Add all of the mixin mappings from all loom projects. + private static IMappingProvider gradleMixinMappingProvider(SharedServiceManager serviceManager, Gradle gradle, String from, String to) { + return out -> GradleUtils.allLoomProjects(gradle, project -> { + for (SourceSet sourceSet : SourceSetHelper.getSourceSets(project)) { + final File mixinMappings = AnnotationProcessorInvoker.getMixinMappingsForSourceSet(project, sourceSet); + + if (!mixinMappings.exists()) { + continue; + } + + MappingsService service = MappingsService.create(serviceManager, mixinMappings.getAbsolutePath(), mixinMappings.toPath(), from, to, false); + service.getMappingsProvider().load(out); + } + }); + } + private TinyRemapper tinyRemapper; @Nullable private KotlinRemapperClassloader kotlinRemapperClassloader; diff --git a/src/main/java/net/fabricmc/loom/util/DeprecationHelper.java b/src/main/java/net/fabricmc/loom/util/DeprecationHelper.java index cce8773d..9ddbfb69 100644 --- a/src/main/java/net/fabricmc/loom/util/DeprecationHelper.java +++ b/src/main/java/net/fabricmc/loom/util/DeprecationHelper.java @@ -49,13 +49,6 @@ public interface DeprecationHelper { public ProjectBased(Project project) { this.project = project; - - project.getGradle().buildFinished(buildResult -> { - if (usingDeprecatedApi.get()) { - project.getLogger().lifecycle("Deprecated Loom APIs were used in this build, making it incompatible with future versions of Loom. " - + "Use Gradle warning modes to control the verbosity of the warnings."); - } - }); } @Override diff --git a/src/main/java/net/fabricmc/loom/util/gradle/GradleUtils.java b/src/main/java/net/fabricmc/loom/util/gradle/GradleUtils.java index 56162a2e..88accb25 100644 --- a/src/main/java/net/fabricmc/loom/util/gradle/GradleUtils.java +++ b/src/main/java/net/fabricmc/loom/util/gradle/GradleUtils.java @@ -24,7 +24,10 @@ package net.fabricmc.loom.util.gradle; +import java.util.function.Consumer; + import org.gradle.api.Project; +import org.gradle.api.invocation.Gradle; public final class GradleUtils { private GradleUtils() { @@ -41,4 +44,12 @@ public final class GradleUtils { afterEvaluate.run(); }); } + + public static void allLoomProjects(Gradle gradle, Consumer consumer) { + gradle.allprojects(project -> { + if (project.getPluginManager().hasPlugin("fabric-loom")) { + consumer.accept(project); + } + }); + } } diff --git a/src/main/java/net/fabricmc/loom/util/gradle/SourceSetHelper.java b/src/main/java/net/fabricmc/loom/util/gradle/SourceSetHelper.java index 832c4f86..4b493875 100644 --- a/src/main/java/net/fabricmc/loom/util/gradle/SourceSetHelper.java +++ b/src/main/java/net/fabricmc/loom/util/gradle/SourceSetHelper.java @@ -45,6 +45,7 @@ import org.gradle.api.internal.tasks.DefaultSourceSetOutput; import org.gradle.api.internal.tasks.DefaultTaskDependency; import org.gradle.api.plugins.JavaPluginExtension; import org.gradle.api.tasks.SourceSet; +import org.gradle.api.tasks.SourceSetContainer; import org.gradle.api.tasks.SourceSetOutput; import org.gradle.api.tasks.TaskProvider; import org.intellij.lang.annotations.Language; @@ -63,20 +64,23 @@ public final class SourceSetHelper { private SourceSetHelper() { } + public static SourceSetContainer getSourceSets(Project project) { + final JavaPluginExtension javaExtension = project.getExtensions().getByType(JavaPluginExtension.class); + return javaExtension.getSourceSets(); + } + /** * Returns true when the provided project contains the {@link SourceSet}. */ public static boolean isSourceSetOfProject(SourceSet sourceSet, Project project) { if (System.getProperty("fabric-loom.unit.testing") != null) return true; - final JavaPluginExtension javaExtension = project.getExtensions().getByType(JavaPluginExtension.class); - return javaExtension.getSourceSets().stream() + return getSourceSets(project).stream() .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); + return getSourceSets(project).getByName(name); } public static SourceSet getMainSourceSet(Project project) { @@ -84,8 +88,7 @@ public final class SourceSetHelper { } public static SourceSet createSourceSet(String name, Project project) { - final JavaPluginExtension javaExtension = project.getExtensions().getByType(JavaPluginExtension.class); - return javaExtension.getSourceSets().create(name); + return getSourceSets(project).create(name); } /** diff --git a/src/main/java/net/fabricmc/loom/util/kotlin/KotlinClasspathService.java b/src/main/java/net/fabricmc/loom/util/kotlin/KotlinClasspathService.java index 05b9cada..9657413b 100644 --- a/src/main/java/net/fabricmc/loom/util/kotlin/KotlinClasspathService.java +++ b/src/main/java/net/fabricmc/loom/util/kotlin/KotlinClasspathService.java @@ -39,17 +39,16 @@ import net.fabricmc.loom.util.service.SharedServiceManager; public record KotlinClasspathService(Set classpath, String version) implements KotlinClasspath, SharedService { @Nullable - public static KotlinClasspathService getOrCreateIfRequired(Project project) { + public static KotlinClasspathService getOrCreateIfRequired(SharedServiceManager sharedServiceManager, Project project) { if (!KotlinPluginUtils.hasKotlinPlugin(project)) { return null; } - return getOrCreate(project, KotlinPluginUtils.getKotlinPluginVersion(project), KotlinPluginUtils.getKotlinMetadataVersion()); + return getOrCreate(sharedServiceManager, project, KotlinPluginUtils.getKotlinPluginVersion(project), KotlinPluginUtils.getKotlinMetadataVersion()); } - public static synchronized KotlinClasspathService getOrCreate(Project project, String kotlinVersion, String kotlinMetadataVersion) { + public static synchronized KotlinClasspathService getOrCreate(SharedServiceManager sharedServiceManager, Project project, String kotlinVersion, String kotlinMetadataVersion) { final String id = "kotlinclasspath:%s:%s".formatted(kotlinVersion, kotlinMetadataVersion); - final SharedServiceManager sharedServiceManager = SharedServiceManager.get(project); return sharedServiceManager.getOrCreateService(id, () -> create(project, kotlinVersion, kotlinMetadataVersion)); } diff --git a/src/main/java/net/fabricmc/loom/util/service/BuildSharedServiceManager.java b/src/main/java/net/fabricmc/loom/util/service/BuildSharedServiceManager.java new file mode 100644 index 00000000..bde78bc3 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/util/service/BuildSharedServiceManager.java @@ -0,0 +1,90 @@ +/* + * 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.util.service; + +import java.util.Objects; +import java.util.concurrent.atomic.AtomicInteger; + +import org.gradle.api.Task; +import org.gradle.api.provider.Provider; +import org.gradle.api.services.BuildService; +import org.gradle.api.services.BuildServiceParameters; +import org.gradle.build.event.BuildEventsListenerRegistry; +import org.gradle.tooling.events.OperationCompletionListener; +import org.gradle.tooling.events.task.TaskOperationDescriptor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public abstract class BuildSharedServiceManager implements BuildService { + private static final Logger LOGGER = LoggerFactory.getLogger(BuildSharedServiceManager.class); + private static final String NAME = "loom:sharedServiceManager"; + + private SharedServiceManager sharedServiceManager = new BuildSharedServiceManagerImpl(); + private final AtomicInteger refCount = new AtomicInteger(0); + + public static Provider createForTask(Task task, BuildEventsListenerRegistry buildEventsListenerRegistry) { + Provider provider = task.getProject().getGradle().getSharedServices().registerIfAbsent(NAME, BuildSharedServiceManager.class, spec -> { + }); + task.usesService(provider); + + final BuildSharedServiceManager serviceManager = provider.get(); + buildEventsListenerRegistry.onTaskCompletion(registerTaskCompletion(task, serviceManager::onFinish)); + int count = serviceManager.refCount.incrementAndGet(); + LOGGER.debug("Creating shared service manager provider for task: {} count: {}", task.getName(), count); + + return provider; + } + + public SharedServiceManager get() { + LOGGER.debug("Shared build service get"); + return Objects.requireNonNull(sharedServiceManager); + } + + private void onFinish() { + int count = refCount.decrementAndGet(); + + LOGGER.debug("Build service finish. count: {}", count); + + if (count == 0) { + sharedServiceManager.onFinish(); + sharedServiceManager = null; + } else if (count < 0) { + throw new IllegalStateException(); + } + } + + private static Provider registerTaskCompletion(Task task, Runnable runnable) { + return task.getProject().provider(() -> event -> { + if (event.getDescriptor() instanceof TaskOperationDescriptor taskDescriptor) { + if (taskDescriptor.getTaskPath().equals(task.getPath())) { + runnable.run(); + } + } + }); + } + + private static final class BuildSharedServiceManagerImpl extends SharedServiceManager { + } +} diff --git a/src/main/java/net/fabricmc/loom/util/service/ScopedSharedServiceManager.java b/src/main/java/net/fabricmc/loom/util/service/ScopedSharedServiceManager.java new file mode 100644 index 00000000..8431ac3a --- /dev/null +++ b/src/main/java/net/fabricmc/loom/util/service/ScopedSharedServiceManager.java @@ -0,0 +1,35 @@ +/* + * 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.util.service; + +public final class ScopedSharedServiceManager extends SharedServiceManager implements AutoCloseable { + public ScopedSharedServiceManager() { + } + + @Override + public void close() { + onFinish(); + } +} diff --git a/src/main/java/net/fabricmc/loom/util/service/SharedServiceManager.java b/src/main/java/net/fabricmc/loom/util/service/SharedServiceManager.java index 62f1e922..0aa7922a 100644 --- a/src/main/java/net/fabricmc/loom/util/service/SharedServiceManager.java +++ b/src/main/java/net/fabricmc/loom/util/service/SharedServiceManager.java @@ -31,33 +31,21 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.function.Supplier; -import org.gradle.BuildResult; -import org.gradle.api.Project; -import org.gradle.api.invocation.Gradle; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * A simple manager for {@link SharedService} to be used across gradle (sub) projects. * This is a basic replacement for gradle's build service api. */ -public final class SharedServiceManager { - private static final Map SERVICE_FACTORY_MAP = new ConcurrentHashMap<>(); - private final Gradle gradle; - +public abstract class SharedServiceManager { + private static final Logger LOGGER = LoggerFactory.getLogger(BuildSharedServiceManager.class); private final Map sharedServiceMap = new ConcurrentHashMap<>(); private boolean shutdown = false; - private SharedServiceManager(Gradle gradle) { - this.gradle = gradle; - this.gradle.buildFinished(this::onFinish); - } - - public static SharedServiceManager get(Project project) { - return get(project.getGradle()); - } - - public static SharedServiceManager get(Gradle gradle) { - return SERVICE_FACTORY_MAP.computeIfAbsent(gradle, SharedServiceManager::new); + SharedServiceManager() { + LOGGER.info("Creating new SharedServiceManager({})", hashCode()); } public S getOrCreateService(String id, Supplier function) { @@ -78,12 +66,12 @@ public final class SharedServiceManager { } } - private void onFinish(BuildResult buildResult) { + protected void onFinish() { synchronized (sharedServiceMap) { shutdown = true; } - SERVICE_FACTORY_MAP.remove(gradle); + LOGGER.info("Closing SharedServiceManager({})", hashCode()); final List exceptionList = new ArrayList<>(); diff --git a/src/main/java/net/fabricmc/loom/util/service/UnsafeWorkQueueHelper.java b/src/main/java/net/fabricmc/loom/util/service/UnsafeWorkQueueHelper.java index 62faa290..13ab18bb 100644 --- a/src/main/java/net/fabricmc/loom/util/service/UnsafeWorkQueueHelper.java +++ b/src/main/java/net/fabricmc/loom/util/service/UnsafeWorkQueueHelper.java @@ -28,7 +28,6 @@ import java.util.Map; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; -import org.gradle.api.Project; import org.gradle.api.provider.Property; // Massive hack to work around WorkerExecutor.noIsolation() doing isolation checks. @@ -38,12 +37,10 @@ public final class UnsafeWorkQueueHelper { private UnsafeWorkQueueHelper() { } - public static String create(Project project, SharedService service) { + public static String create(SharedService service) { final String uuid = UUID.randomUUID().toString(); SERVICE_MAP.put(uuid, service); - // Ensure we don't make a mess if things go wrong. - project.getGradle().buildFinished(buildResult -> SERVICE_MAP.remove(uuid)); return uuid; }