Allow applying kapt and using mixins in other source sets (#211)
* Fix kapt and source sets * cleanup * cleanup 2
This commit is contained in:
		
							parent
							
								
									5d468efc48
								
							
						
					
					
						commit
						cf13e4aa02
					
				
					 7 changed files with 373 additions and 64 deletions
				
			
		|  | @ -62,6 +62,9 @@ dependencies { | ||||||
| 	// source code remapping | 	// source code remapping | ||||||
| 	implementation ('org.cadixdev:mercury:0.1.0.fabric-SNAPSHOT') | 	implementation ('org.cadixdev:mercury:0.1.0.fabric-SNAPSHOT') | ||||||
| 
 | 
 | ||||||
|  | 	// Kapt integration | ||||||
|  | 	compileOnly("org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.72") | ||||||
|  | 
 | ||||||
| 	// Testing | 	// Testing | ||||||
| 	testImplementation(gradleTestKit()) | 	testImplementation(gradleTestKit()) | ||||||
| 	testImplementation("org.spockframework:spock-core:1.3-groovy-2.4") | 	testImplementation("org.spockframework:spock-core:1.3-groovy-2.4") | ||||||
|  |  | ||||||
|  | @ -24,8 +24,6 @@ | ||||||
| 
 | 
 | ||||||
| package net.fabricmc.loom; | package net.fabricmc.loom; | ||||||
| 
 | 
 | ||||||
| import java.io.File; |  | ||||||
| import java.io.IOException; |  | ||||||
| import java.util.HashSet; | import java.util.HashSet; | ||||||
| import java.util.Map; | import java.util.Map; | ||||||
| import java.util.Optional; | import java.util.Optional; | ||||||
|  | @ -47,9 +45,7 @@ import org.gradle.api.publish.PublishingExtension; | ||||||
| import org.gradle.api.publish.maven.MavenPublication; | import org.gradle.api.publish.maven.MavenPublication; | ||||||
| import org.gradle.api.tasks.SourceSet; | import org.gradle.api.tasks.SourceSet; | ||||||
| import org.gradle.api.tasks.bundling.AbstractArchiveTask; | import org.gradle.api.tasks.bundling.AbstractArchiveTask; | ||||||
| import org.gradle.api.tasks.compile.JavaCompile; |  | ||||||
| import org.gradle.api.tasks.javadoc.Javadoc; | import org.gradle.api.tasks.javadoc.Javadoc; | ||||||
| import org.gradle.api.tasks.scala.ScalaCompile; |  | ||||||
| import org.gradle.plugins.ide.idea.model.IdeaModel; | import org.gradle.plugins.ide.idea.model.IdeaModel; | ||||||
| 
 | 
 | ||||||
| import net.fabricmc.loom.providers.LaunchProvider; | import net.fabricmc.loom.providers.LaunchProvider; | ||||||
|  | @ -63,6 +59,9 @@ import net.fabricmc.loom.util.LoomDependencyManager; | ||||||
| import net.fabricmc.loom.util.NestedJars; | import net.fabricmc.loom.util.NestedJars; | ||||||
| import net.fabricmc.loom.util.RemappedConfigurationEntry; | import net.fabricmc.loom.util.RemappedConfigurationEntry; | ||||||
| import net.fabricmc.loom.util.SetupIntelijRunConfigs; | import net.fabricmc.loom.util.SetupIntelijRunConfigs; | ||||||
|  | import net.fabricmc.loom.util.mixin.JavaApInvoker; | ||||||
|  | import net.fabricmc.loom.util.mixin.KaptApInvoker; | ||||||
|  | import net.fabricmc.loom.util.mixin.ScalaApInvoker; | ||||||
| 
 | 
 | ||||||
| public class AbstractPlugin implements Plugin<Project> { | public class AbstractPlugin implements Plugin<Project> { | ||||||
| 	protected Project project; | 	protected Project project; | ||||||
|  | @ -88,7 +87,6 @@ public class AbstractPlugin implements Plugin<Project> { | ||||||
| 
 | 
 | ||||||
| 		project.getExtensions().create("minecraft", LoomGradleExtension.class, project); | 		project.getExtensions().create("minecraft", LoomGradleExtension.class, project); | ||||||
| 
 | 
 | ||||||
| 		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); |  | ||||||
| 		// Force add Mojang repository | 		// Force add Mojang repository | ||||||
| 		addMavenRepo(target, "Mojang", "https://libraries.minecraft.net/"); | 		addMavenRepo(target, "Mojang", "https://libraries.minecraft.net/"); | ||||||
| 
 | 
 | ||||||
|  | @ -127,74 +125,43 @@ public class AbstractPlugin implements Plugin<Project> { | ||||||
| 		extendsFrom("compileClasspath", Constants.MINECRAFT_NAMED); | 		extendsFrom("compileClasspath", Constants.MINECRAFT_NAMED); | ||||||
| 		extendsFrom("runtimeClasspath", Constants.MINECRAFT_NAMED); | 		extendsFrom("runtimeClasspath", Constants.MINECRAFT_NAMED); | ||||||
| 
 | 
 | ||||||
| 		if (!extension.ideSync()) { |  | ||||||
| 			extendsFrom("annotationProcessor", Constants.MINECRAFT_NAMED); |  | ||||||
| 			extendsFrom("annotationProcessor", Constants.MOD_COMPILE_CLASSPATH_MAPPED); |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		extendsFrom(Constants.MINECRAFT_NAMED, Constants.MINECRAFT_DEPENDENCIES); | 		extendsFrom(Constants.MINECRAFT_NAMED, Constants.MINECRAFT_DEPENDENCIES); | ||||||
| 
 | 
 | ||||||
| 		extendsFrom("compile", Constants.MAPPINGS_FINAL); | 		extendsFrom("compile", Constants.MAPPINGS_FINAL); | ||||||
| 
 | 
 | ||||||
| 		if (!extension.ideSync()) { |  | ||||||
| 			extendsFrom("annotationProcessor", Constants.MAPPINGS_FINAL); |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		configureIDEs(); | 		configureIDEs(); | ||||||
| 		configureCompile(); | 		configureCompile(); | ||||||
| 		configureScala(); | 		configureMixin(); | ||||||
|  | 		configureMaven(); | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 		Map<Project, Set<Task>> taskMap = project.getAllTasks(true); | 	private void configureMixin() { | ||||||
| 
 | 		if (project.getPluginManager().hasPlugin("org.jetbrains.kotlin.kapt")) { | ||||||
| 		for (Map.Entry<Project, Set<Task>> entry : taskMap.entrySet()) { | 			// If loom is applied after kapt, then kapt will use the AP arguments too early for loom to pass the arguments we need for mixin. | ||||||
| 			Project project = entry.getKey(); | 			throw new IllegalArgumentException("fabric-loom must be applied BEFORE kapt in the plugins { } block."); | ||||||
| 			Set<Task> taskSet = entry.getValue(); |  | ||||||
| 
 |  | ||||||
| 			for (Task task : taskSet) { |  | ||||||
| 				if (task instanceof JavaCompile && !(task.getName().contains("Test")) && !(task.getName().contains("test"))) { |  | ||||||
| 					JavaCompile javaCompileTask = (JavaCompile) task; |  | ||||||
| 					javaCompileTask.doFirst(task1 -> { |  | ||||||
| 						project.getLogger().lifecycle(":setting java compiler args"); |  | ||||||
| 
 |  | ||||||
| 						try { |  | ||||||
| 							javaCompileTask.getOptions().getCompilerArgs().add("-AinMapFileNamedIntermediary=" + extension.getMappingsProvider().tinyMappings.getCanonicalPath()); |  | ||||||
| 							javaCompileTask.getOptions().getCompilerArgs().add("-AoutMapFileNamedIntermediary=" + extension.getMappingsProvider().mappingsMixinExport.getCanonicalPath()); |  | ||||||
| 							javaCompileTask.getOptions().getCompilerArgs().add("-AoutRefMapFile=" + new File(javaCompileTask.getDestinationDir(), extension.getRefmapName()).getCanonicalPath()); |  | ||||||
| 							javaCompileTask.getOptions().getCompilerArgs().add("-AdefaultObfuscationEnv=named:intermediary"); |  | ||||||
| 						} catch (IOException e) { |  | ||||||
| 							e.printStackTrace(); |  | ||||||
| 						} |  | ||||||
| 					}); |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		configureMaven(); | 		// Full plugin and mappings information is only available after evaluation | ||||||
|  | 		project.afterEvaluate((project) -> { | ||||||
|  | 			project.getLogger().lifecycle("Configuring mixins for Java plugin"); | ||||||
|  | 			new JavaApInvoker(project).configureMixin(); | ||||||
|  | 
 | ||||||
|  | 			if (project.getPluginManager().hasPlugin("scala")) { | ||||||
|  | 				project.getLogger().lifecycle("Configuring mixins for Scala plugin"); | ||||||
|  | 				new ScalaApInvoker(project).configureMixin(); | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			if (project.getPluginManager().hasPlugin("org.jetbrains.kotlin.kapt")) { | ||||||
|  | 				project.getLogger().lifecycle("Configuring mixins for Kapt plugin"); | ||||||
|  | 				new KaptApInvoker(project).configureMixin(); | ||||||
|  | 			} | ||||||
|  | 		}); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public Project getProject() { | 	public Project getProject() { | ||||||
| 		return project; | 		return project; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	protected void configureScala() { |  | ||||||
| 		project.afterEvaluate(proj -> { |  | ||||||
| 			if (project.getPluginManager().hasPlugin("scala")) { |  | ||||||
| 				ScalaCompile task = (ScalaCompile) project.getTasks().getByName("compileScala"); |  | ||||||
| 				LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); |  | ||||||
| 				project.getLogger().warn(":configuring scala compilation processing"); |  | ||||||
| 
 |  | ||||||
| 				try { |  | ||||||
| 					task.getOptions().getCompilerArgs().add("-AinMapFileNamedIntermediary=" + extension.getMappingsProvider().tinyMappings.getCanonicalPath()); |  | ||||||
| 					task.getOptions().getCompilerArgs().add("-AoutMapFileNamedIntermediary=" + extension.getMappingsProvider().mappingsMixinExport.getCanonicalPath()); |  | ||||||
| 					task.getOptions().getCompilerArgs().add("-AoutRefMapFile=" + new File(task.getDestinationDir(), extension.getRefmapName()).getCanonicalPath()); |  | ||||||
| 					task.getOptions().getCompilerArgs().add("-AdefaultObfuscationEnv=named:intermediary"); |  | ||||||
| 				} catch (IOException e) { |  | ||||||
| 					e.printStackTrace(); |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 		}); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	/** | 	/** | ||||||
| 	 * Permit to add a Maven repository to a target project. | 	 * Permit to add a Maven repository to a target project. | ||||||
| 	 * | 	 * | ||||||
|  | @ -234,11 +201,6 @@ public class AbstractPlugin implements Plugin<Project> { | ||||||
| 		Javadoc javadoc = (Javadoc) project.getTasks().getByName(JavaPlugin.JAVADOC_TASK_NAME); | 		Javadoc javadoc = (Javadoc) project.getTasks().getByName(JavaPlugin.JAVADOC_TASK_NAME); | ||||||
| 		javadoc.setClasspath(main.getOutput().plus(main.getCompileClasspath())); | 		javadoc.setClasspath(main.getOutput().plus(main.getCompileClasspath())); | ||||||
| 
 | 
 | ||||||
| 		if (!project.getExtensions().getByType(LoomGradleExtension.class).ideSync()) { |  | ||||||
| 			// Add Mixin dependencies |  | ||||||
| 			project.getDependencies().add(JavaPlugin.ANNOTATION_PROCESSOR_CONFIGURATION_NAME, "net.fabricmc:fabric-mixin-compile-extensions:" + Constants.MIXIN_COMPILE_EXTENSIONS_VERSION); |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		project.afterEvaluate(project1 -> { | 		project.afterEvaluate(project1 -> { | ||||||
| 			LoomGradleExtension extension = project1.getExtensions().getByType(LoomGradleExtension.class); | 			LoomGradleExtension extension = project1.getExtensions().getByType(LoomGradleExtension.class); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -311,7 +311,7 @@ public class LoomGradleExtension { | ||||||
| 	public String getRefmapName() { | 	public String getRefmapName() { | ||||||
| 		if (refmapName == null || refmapName.isEmpty()) { | 		if (refmapName == null || refmapName.isEmpty()) { | ||||||
| 			String defaultRefmapName = project.getConvention().getPlugin(BasePluginConvention.class).getArchivesBaseName() + "-refmap.json"; | 			String defaultRefmapName = project.getConvention().getPlugin(BasePluginConvention.class).getArchivesBaseName() + "-refmap.json"; | ||||||
| 			project.getLogger().warn("Could not find refmap definition, will be using default name: " + defaultRefmapName); | 			project.getLogger().info("Could not find refmap definition, will be using default name: " + defaultRefmapName); | ||||||
| 			refmapName = defaultRefmapName; | 			refmapName = defaultRefmapName; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -0,0 +1,118 @@ | ||||||
|  | /* | ||||||
|  |  * 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.util.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); | ||||||
|  | 			Map<String, String> args = new HashMap<String, String>() {{ | ||||||
|  | 					put("inMapFileNamedIntermediary", extension.getMappingsProvider().tinyMappings.getCanonicalPath()); | ||||||
|  | 					put("outMapFileNamedIntermediary", extension.getMappingsProvider().mappingsMixinExport.getCanonicalPath()); | ||||||
|  | 					put("outRefMapFile", getRefmapDestination(task, extension)); | ||||||
|  | 					put("defaultObfuscationEnv", "named:intermediary"); | ||||||
|  | 				}}; | ||||||
|  | 
 | ||||||
|  | 			project.getLogger().info("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.MINECRAFT_NAMED), | ||||||
|  | 								configs.getByName(Constants.MOD_COMPILE_CLASSPATH_MAPPED), | ||||||
|  | 								configs.getByName(Constants.MAPPINGS_FINAL) | ||||||
|  | 				); | ||||||
|  | 
 | ||||||
|  | 				// Add Mixin and mixin extensions (fabric-mixin-compile-extensions pulls mixin itself too) | ||||||
|  | 				project.getDependencies().add(processorConfig.getName(), | ||||||
|  | 								"net.fabricmc:fabric-mixin-compile-extensions:" + Constants.MIXIN_COMPILE_EXTENSIONS_VERSION); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		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")); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -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.util.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"; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										113
									
								
								src/main/java/net/fabricmc/loom/util/mixin/KaptApInvoker.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										113
									
								
								src/main/java/net/fabricmc/loom/util/mixin/KaptApInvoker.java
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,113 @@ | ||||||
|  | /* | ||||||
|  |  * 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.util.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.compile.JavaCompile; | ||||||
|  | import org.jetbrains.annotations.NotNull; | ||||||
|  | import org.jetbrains.kotlin.gradle.internal.Kapt3KotlinGradleSubplugin; | ||||||
|  | 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(Kapt3KotlinGradleSubplugin.Companion.getKaptConfigurationName(sourceSet.getName())) | ||||||
|  | 						).collect(Collectors.toList()); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@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; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -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.util.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(); | ||||||
|  | 	} | ||||||
|  | } | ||||||
		Loading…
	
		Reference in a new issue