aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/net/fabricmc/loom/build/mixin
diff options
context:
space:
mode:
authorshedaniel <daniel@shedaniel.me>2021-01-14 17:51:34 +0800
committershedaniel <daniel@shedaniel.me>2021-01-18 09:07:03 +0800
commit3a49510c0189b787b82b4829a217e99053bfec39 (patch)
treece82c1a8a6c4e5c25351cef5612c24ab9a2fe591 /src/main/java/net/fabricmc/loom/build/mixin
parent6f10845562dd1fdb87e8cd842e75c649a127ce3b (diff)
parent9de836b2c45dc3cac7469f5f9ac6b1ddfec9ac79 (diff)
downloadarchitectury-loom-3a49510c0189b787b82b4829a217e99053bfec39.tar.gz
architectury-loom-3a49510c0189b787b82b4829a217e99053bfec39.tar.bz2
architectury-loom-3a49510c0189b787b82b4829a217e99053bfec39.zip
Merge remote-tracking branch 'FabricMC/dev/0.6' into dev/0.6-forge
Diffstat (limited to 'src/main/java/net/fabricmc/loom/build/mixin')
-rw-r--r--src/main/java/net/fabricmc/loom/build/mixin/AnnotationProcessorInvoker.java119
-rw-r--r--src/main/java/net/fabricmc/loom/build/mixin/JavaApInvoker.java63
-rw-r--r--src/main/java/net/fabricmc/loom/build/mixin/KaptApInvoker.java122
-rw-r--r--src/main/java/net/fabricmc/loom/build/mixin/ScalaApInvoker.java50
4 files changed, 354 insertions, 0 deletions
diff --git a/src/main/java/net/fabricmc/loom/build/mixin/AnnotationProcessorInvoker.java b/src/main/java/net/fabricmc/loom/build/mixin/AnnotationProcessorInvoker.java
new file mode 100644
index 00000000..02714ab2
--- /dev/null
+++ b/src/main/java/net/fabricmc/loom/build/mixin/AnnotationProcessorInvoker.java
@@ -0,0 +1,119 @@
+/*
+ * This file is part of fabric-loom, licensed under the MIT License (MIT).
+ *
+ * Copyright (c) 2016, 2017, 2018 FabricMC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package net.fabricmc.loom.build.mixin;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.stream.Stream;
+
+import org.gradle.api.Project;
+import org.gradle.api.Task;
+import org.gradle.api.artifacts.Configuration;
+import org.gradle.api.artifacts.ConfigurationContainer;
+import org.gradle.api.plugins.JavaPluginConvention;
+import org.gradle.api.tasks.SourceSet;
+import org.gradle.api.tasks.TaskCollection;
+
+import net.fabricmc.loom.LoomGradleExtension;
+import net.fabricmc.loom.util.Constants;
+
+/**
+ * Normally javac invokes annotation processors, but when the scala or kapt plugin are installed they will want to invoke
+ * the annotation processor themselves.
+ * See Java and Kapt implementations for a more deep understanding of the things passed by the children.
+ */
+public abstract class AnnotationProcessorInvoker<T extends Task> {
+ protected final Project project;
+ private final Collection<Configuration> annotationProcessorConfigurations;
+ protected final TaskCollection<T> invokerTasks;
+
+ protected AnnotationProcessorInvoker(Project project,
+ Collection<Configuration> annotationProcessorConfigurations,
+ TaskCollection<T> invokerTasks) {
+ this.project = project;
+ this.annotationProcessorConfigurations = annotationProcessorConfigurations;
+ this.invokerTasks = invokerTasks;
+ }
+
+ protected abstract void passArgument(T compileTask, String key, String value);
+
+ protected abstract File getDestinationDir(T task);
+
+ protected final String getRefmapDestination(T task, LoomGradleExtension extension) throws IOException {
+ return new File(getDestinationDir(task), extension.getRefmapName()).getCanonicalPath();
+ }
+
+ private void passMixinArguments(T task) {
+ try {
+ LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
+ File inMapFile = extension.isForge() ? extension.getMappingsProvider().mixinTinyMappingsWithSrg : extension.getMappingsProvider().tinyMappings;
+ Map<String, String> args = new HashMap<String, String>() {{
+ put(Constants.MixinArguments.IN_MAP_FILE_NAMED_INTERMEDIARY, inMapFile.getCanonicalPath());
+ put(Constants.MixinArguments.OUT_MAP_FILE_NAMED_INTERMEDIARY, extension.getNextMixinMappings().getCanonicalPath());
+ put(Constants.MixinArguments.OUT_REFMAP_FILE, getRefmapDestination(task, extension));
+ put(Constants.MixinArguments.DEFAULT_OBFUSCATION_ENV, "named:intermediary");
+ }};
+
+ project.getLogger().debug("Outputting refmap to dir: " + getDestinationDir(task) + " for compile task: " + task);
+ args.forEach((k, v) -> passArgument(task, k, v));
+ } catch (IOException e) {
+ project.getLogger().error("Could not configure mixin annotation processors", e);
+ }
+ }
+
+ public void configureMixin() {
+ ConfigurationContainer configs = project.getConfigurations();
+ LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
+
+ if (!extension.ideSync()) {
+ for (Configuration processorConfig : annotationProcessorConfigurations) {
+ project.getLogger().info("Adding mixin to classpath of AP config: " + processorConfig.getName());
+ // Pass named MC classpath to mixin AP classpath
+ processorConfig.extendsFrom(
+ configs.getByName(Constants.Configurations.MINECRAFT_NAMED),
+ configs.getByName(Constants.Configurations.MOD_COMPILE_CLASSPATH_MAPPED),
+ configs.getByName(Constants.Configurations.MAPPINGS_FINAL)
+ );
+
+ // Add Mixin and mixin extensions (fabric-mixin-compile-extensions pulls mixin itself too)
+ project.getDependencies().add(processorConfig.getName(),
+ Constants.Dependencies.MIXIN_COMPILE_EXTENSIONS + Constants.Dependencies.Versions.MIXIN_COMPILE_EXTENSIONS);
+ }
+ }
+
+ for (T task : invokerTasks) {
+ passMixinArguments(task);
+ }
+ }
+
+ static Stream<SourceSet> getNonTestSourceSets(Project project) {
+ return project.getConvention().getPlugin(JavaPluginConvention.class).getSourceSets()
+ .stream()
+ .filter(sourceSet -> !sourceSet.getName().equals("test"));
+ }
+}
diff --git a/src/main/java/net/fabricmc/loom/build/mixin/JavaApInvoker.java b/src/main/java/net/fabricmc/loom/build/mixin/JavaApInvoker.java
new file mode 100644
index 00000000..2e52d0d7
--- /dev/null
+++ b/src/main/java/net/fabricmc/loom/build/mixin/JavaApInvoker.java
@@ -0,0 +1,63 @@
+/*
+ * This file is part of fabric-loom, licensed under the MIT License (MIT).
+ *
+ * Copyright (c) 2016, 2017, 2018 FabricMC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package net.fabricmc.loom.build.mixin;
+
+import java.io.File;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import org.gradle.api.Project;
+import org.gradle.api.artifacts.Configuration;
+import org.gradle.api.plugins.JavaPlugin;
+import org.gradle.api.tasks.compile.JavaCompile;
+
+public class JavaApInvoker extends AnnotationProcessorInvoker<JavaCompile> {
+ public JavaApInvoker(Project project) {
+ super(project, getConfigurations(project), project.getTasks().withType(JavaCompile.class));
+ }
+
+ @Override
+ protected void passArgument(JavaCompile compileTask, String key, String value) {
+ compileTask.getOptions().getCompilerArgs().add("-A" + key + "=" + value);
+ }
+
+ @Override
+ protected File getDestinationDir(JavaCompile task) {
+ return task.getDestinationDir();
+ }
+
+ private static List<Configuration> getConfigurations(Project project) {
+ // java plugin generates an AP configuration for every source set based off of the getAptConfigurationName method.
+ return AnnotationProcessorInvoker.getNonTestSourceSets(project)
+ .map(sourceSet -> project.getConfigurations()
+ .getByName(getAptConfigurationName(sourceSet.getName()))
+ ).collect(Collectors.toList());
+ }
+
+ private static String getAptConfigurationName(String sourceSet) {
+ // This is documented by the gradle 4.6 release notes https://docs.gradle.org/4.6/release-notes.html#potential-breaking-changes
+ return sourceSet.equals("main") ? JavaPlugin.ANNOTATION_PROCESSOR_CONFIGURATION_NAME : sourceSet + "AnnotationProcessor";
+ }
+}
diff --git a/src/main/java/net/fabricmc/loom/build/mixin/KaptApInvoker.java b/src/main/java/net/fabricmc/loom/build/mixin/KaptApInvoker.java
new file mode 100644
index 00000000..41d6d0ba
--- /dev/null
+++ b/src/main/java/net/fabricmc/loom/build/mixin/KaptApInvoker.java
@@ -0,0 +1,122 @@
+/*
+ * This file is part of fabric-loom, licensed under the MIT License (MIT).
+ *
+ * Copyright (c) 2016, 2017, 2018 FabricMC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package net.fabricmc.loom.build.mixin;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import kotlin.Unit;
+import org.gradle.api.Project;
+import org.gradle.api.artifacts.Configuration;
+import org.gradle.api.tasks.SourceSet;
+import org.gradle.api.tasks.compile.JavaCompile;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.kotlin.gradle.plugin.KaptExtension;
+
+import net.fabricmc.loom.LoomGradleExtension;
+
+public class KaptApInvoker extends AnnotationProcessorInvoker<JavaCompile> {
+ private final KaptExtension kaptExtension = project.getExtensions().getByType(KaptExtension.class);
+ // Refmap will be written to here with mixin, then moved after JavaCompile to the correct place
+ private final File dummyRefmapDirectory;
+
+ public KaptApInvoker(Project project) {
+ super(project, getConfigurations(project), project.getTasks().withType(JavaCompile.class));
+
+ try {
+ dummyRefmapDirectory = Files.createTempDirectory("temp_refmap").toFile();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+
+ dummyRefmapDirectory.deleteOnExit();
+
+ // Needed for mixin AP to run
+ kaptExtension.setIncludeCompileClasspath(false);
+ }
+
+ @Override
+ public void configureMixin() {
+ super.configureMixin();
+
+ for (JavaCompile task : invokerTasks) {
+ // Kapt only allows specifying javac args to all annotation processors at once. So we need to specify some dummy
+ // target location for the refmap and then move it to the correct place for each sourceset
+ task.doLast(t -> {
+ try {
+ LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
+ Path src = Paths.get(getRefmapDestination(task, extension));
+ Path dest = Paths.get(task.getDestinationDir().toString(), extension.getRefmapName());
+
+ // Possible that no mixin annotations exist
+ if (Files.exists(src)) {
+ project.getLogger().info("Copying refmap from " + src + " to " + dest);
+ Files.move(src, dest);
+ }
+ } catch (IOException e) {
+ project.getLogger().warn("Could not move refmap generated by kapt for task " + task, e);
+ }
+ });
+ }
+ }
+
+ @NotNull
+ private static List<Configuration> getConfigurations(Project project) {
+ // Kapt generates an AP configuration for every source set based off of the getKaptConfigurationName method.
+ return AnnotationProcessorInvoker.getNonTestSourceSets(project)
+ .map(sourceSet -> project.getConfigurations()
+ .getByName(getKaptConfigurationName(sourceSet.getName()))
+ ).collect(Collectors.toList());
+ }
+
+ // Pulled out from the internal class: https://github.com/JetBrains/kotlin/blob/33a0ec9b4f40f3d6f1f96b2db504ade4c2fafe03/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/Kapt3KotlinGradleSubplugin.kt#L92
+ private static String getKaptConfigurationName(String sourceSetName) {
+ if (!sourceSetName.equals(SourceSet.MAIN_SOURCE_SET_NAME)) {
+ return "kapt" + (sourceSetName.substring(0, 1).toUpperCase() + sourceSetName.substring(1));
+ }
+
+ return "kapt";
+ }
+
+ @Override
+ protected void passArgument(JavaCompile compileTask, String key, String value) {
+ // Note: this MUST be run early on, before kapt uses this data, and there is only a point to setting the value once since
+ // kapt shares the options with all java compilers
+ kaptExtension.arguments(args -> {
+ args.arg(key, value);
+ return Unit.INSTANCE;
+ });
+ }
+
+ @Override
+ protected File getDestinationDir(JavaCompile task) {
+ return dummyRefmapDirectory;
+ }
+}
diff --git a/src/main/java/net/fabricmc/loom/build/mixin/ScalaApInvoker.java b/src/main/java/net/fabricmc/loom/build/mixin/ScalaApInvoker.java
new file mode 100644
index 00000000..7fed5610
--- /dev/null
+++ b/src/main/java/net/fabricmc/loom/build/mixin/ScalaApInvoker.java
@@ -0,0 +1,50 @@
+/*
+ * This file is part of fabric-loom, licensed under the MIT License (MIT).
+ *
+ * Copyright (c) 2016, 2017, 2018 FabricMC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package net.fabricmc.loom.build.mixin;
+
+import java.io.File;
+
+import com.google.common.collect.ImmutableList;
+import org.gradle.api.Project;
+import org.gradle.api.tasks.scala.ScalaCompile;
+
+public class ScalaApInvoker extends AnnotationProcessorInvoker<ScalaCompile> {
+ public ScalaApInvoker(Project project) {
+ super(project,
+ // Scala just uses the java AP configuration afaik. This of course assumes the java AP also gets configured.
+ ImmutableList.of(),
+ project.getTasks().withType(ScalaCompile.class));
+ }
+
+ @Override
+ protected void passArgument(ScalaCompile compileTask, String key, String value) {
+ compileTask.getOptions().getCompilerArgs().add("-A" + key + "=" + value);
+ }
+
+ @Override
+ protected File getDestinationDir(ScalaCompile task) {
+ return task.getDestinationDir();
+ }
+}