mirror of
				https://github.com/SquidDev-CC/CC-Tweaked
				synced 2025-10-31 05:33:00 +00:00 
			
		
		
		
	Switch to our own Gradle plugin for vanilla Minecraft
I didn't make a new years resolution to stop writing build tooling, but maybe I should have. This replaces our use of VanillaGradle with a new project, VanillaExtract. This offers a couple of useful features for multi-loader dev, including Parchment and Unpick support, both of which we now use in CC:T.
This commit is contained in:
		| @@ -29,19 +29,19 @@ repositories { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     maven("https://repo.spongepowered.org/repository/maven-public/") { |  | ||||||
|         name = "Sponge" |  | ||||||
|         content { |  | ||||||
|             includeGroup("org.spongepowered") |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     maven("https://maven.fabricmc.net/") { |     maven("https://maven.fabricmc.net/") { | ||||||
|         name = "Fabric" |         name = "Fabric" | ||||||
|         content { |         content { | ||||||
|             includeGroup("net.fabricmc") |             includeGroup("net.fabricmc") | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     maven("https://squiddev.cc/maven") { | ||||||
|  |         name = "SquidDev" | ||||||
|  |         content { | ||||||
|  |             includeGroup("cc.tweaked.vanilla-extract") | ||||||
|  |         } | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| dependencies { | dependencies { | ||||||
| @@ -55,7 +55,7 @@ dependencies { | |||||||
|     implementation(libs.ideaExt) |     implementation(libs.ideaExt) | ||||||
|     implementation(libs.librarian) |     implementation(libs.librarian) | ||||||
|     implementation(libs.minotaur) |     implementation(libs.minotaur) | ||||||
|     implementation(libs.vanillaGradle) |     implementation(libs.vanillaExtract) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| gradlePlugin { | gradlePlugin { | ||||||
|   | |||||||
| @@ -10,25 +10,31 @@ import cc.tweaked.gradle.MinecraftConfigurations | |||||||
| 
 | 
 | ||||||
| plugins { | plugins { | ||||||
|     id("cc-tweaked.java-convention") |     id("cc-tweaked.java-convention") | ||||||
|     id("org.spongepowered.gradle.vanilla") |     id("cc.tweaked.vanilla-extract") | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| plugins.apply(CCTweakedPlugin::class.java) | plugins.apply(CCTweakedPlugin::class.java) | ||||||
| 
 | 
 | ||||||
| val mcVersion: String by extra | val mcVersion: String by extra | ||||||
| 
 | 
 | ||||||
|  | val libs = project.extensions.getByType<VersionCatalogsExtension>().named("libs") | ||||||
|  | 
 | ||||||
| minecraft { | minecraft { | ||||||
|     version(mcVersion) |     version(mcVersion) | ||||||
|  | 
 | ||||||
|  |     mappings { | ||||||
|  |         parchment(libs.findVersion("parchmentMc").get().toString(), libs.findVersion("parchment").get().toString()) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     unpick(libs.findLibrary("yarn").get()) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| dependencies { | dependencies { | ||||||
|     val libs = project.extensions.getByType<VersionCatalogsExtension>().named("libs") |  | ||||||
| 
 |  | ||||||
|     // Depend on error prone annotations to silence a lot of compile warnings. |     // Depend on error prone annotations to silence a lot of compile warnings. | ||||||
|     compileOnlyApi(libs.findLibrary("errorProne.annotations").get()) |     compileOnly(libs.findLibrary("errorProne.annotations").get()) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| MinecraftConfigurations.setup(project) | MinecraftConfigurations.setupBasic(project) | ||||||
| 
 | 
 | ||||||
| extensions.configure(CCTweakedExtension::class.java) { | extensions.configure(CCTweakedExtension::class.java) { | ||||||
|     linters(minecraft = true, loader = null) |     linters(minecraft = true, loader = null) | ||||||
|   | |||||||
| @@ -4,23 +4,17 @@ | |||||||
| 
 | 
 | ||||||
| package cc.tweaked.gradle | package cc.tweaked.gradle | ||||||
| 
 | 
 | ||||||
|  | import cc.tweaked.vanillaextract.configurations.Capabilities | ||||||
|  | import cc.tweaked.vanillaextract.configurations.MinecraftSetup | ||||||
| import org.gradle.api.Project | import org.gradle.api.Project | ||||||
| import org.gradle.api.artifacts.Configuration |  | ||||||
| import org.gradle.api.artifacts.ModuleDependency | import org.gradle.api.artifacts.ModuleDependency | ||||||
| import org.gradle.api.artifacts.dsl.DependencyHandler | import org.gradle.api.artifacts.dsl.DependencyHandler | ||||||
| import org.gradle.api.attributes.Bundling |  | ||||||
| import org.gradle.api.attributes.Category |  | ||||||
| import org.gradle.api.attributes.LibraryElements |  | ||||||
| import org.gradle.api.attributes.Usage |  | ||||||
| import org.gradle.api.attributes.java.TargetJvmVersion |  | ||||||
| import org.gradle.api.capabilities.Capability |  | ||||||
| import org.gradle.api.plugins.BasePlugin | import org.gradle.api.plugins.BasePlugin | ||||||
| import org.gradle.api.plugins.JavaPluginExtension | import org.gradle.api.plugins.JavaPluginExtension | ||||||
| import org.gradle.api.tasks.SourceSet | import org.gradle.api.tasks.SourceSet | ||||||
| import org.gradle.api.tasks.bundling.Jar | import org.gradle.api.tasks.bundling.Jar | ||||||
| import org.gradle.api.tasks.javadoc.Javadoc | import org.gradle.api.tasks.javadoc.Javadoc | ||||||
| import org.gradle.kotlin.dsl.get | import org.gradle.kotlin.dsl.get | ||||||
| import org.gradle.kotlin.dsl.named |  | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * This sets up a separate client-only source set, and extends that and the main/common source set with additional |  * This sets up a separate client-only source set, and extends that and the main/common source set with additional | ||||||
| @@ -59,31 +53,13 @@ class MinecraftConfigurations private constructor(private val project: Project) | |||||||
|         } |         } | ||||||
|         configurations.named(client.implementationConfigurationName) { extendsFrom(clientApi) } |         configurations.named(client.implementationConfigurationName) { extendsFrom(clientApi) } | ||||||
| 
 | 
 | ||||||
|         /* |  | ||||||
|           Now add outgoing variants for the main and common source sets that we can consume downstream. This is possibly |  | ||||||
|           the worst way to do things, but unfortunately the alternatives don't actually work very well: |  | ||||||
| 
 |  | ||||||
|            - Just using source set outputs: This means dependencies don't propagate, which means when :fabric depends |  | ||||||
|              on :fabric-api, we don't inherit the fake :common-api in IDEA. |  | ||||||
| 
 |  | ||||||
|            - Having separate common/main jars: Nice in principle, but unfortunately Forge needs a separate deobf jar |  | ||||||
|              task (as the original jar is obfuscated), and IDEA is not able to map its output back to a source set. |  | ||||||
| 
 |  | ||||||
|           This works for now, but is incredibly brittle. It's part of the reason we can't use testFixtures inside our |  | ||||||
|           MC projects, as that adds a project(self) -> test dependency, which would pull in the jar instead. |  | ||||||
| 
 |  | ||||||
|           Note we register a fake client jar here. It's not actually needed, but is there to make sure IDEA has |  | ||||||
|           a way to tell that client classes are needed at runtime. |  | ||||||
| 
 |  | ||||||
|           I'm so sorry, deeply aware how cursed this is. |  | ||||||
|         */ |  | ||||||
|         setupOutgoing(main, "CommonOnly") |  | ||||||
|         project.tasks.register(client.jarTaskName, Jar::class.java) { |         project.tasks.register(client.jarTaskName, Jar::class.java) { | ||||||
|             description = "An empty jar standing in for the client classes." |             description = "An empty jar standing in for the client classes." | ||||||
|             group = BasePlugin.BUILD_GROUP |             group = BasePlugin.BUILD_GROUP | ||||||
|             archiveClassifier.set("client") |             archiveClassifier.set("client") | ||||||
|         } |         } | ||||||
|         setupOutgoing(client) | 
 | ||||||
|  |         MinecraftSetup(project).setupOutgoingConfigurations() | ||||||
| 
 | 
 | ||||||
|         // Reset the client classpath (Loom configures it slightly differently to this) and add a main -> client |         // Reset the client classpath (Loom configures it slightly differently to this) and add a main -> client | ||||||
|         // dependency. Here we /can/ use source set outputs as we add transitive deps by patching the classpath. Nasty, |         // dependency. Here we /can/ use source set outputs as we add transitive deps by patching the classpath. Nasty, | ||||||
| @@ -106,6 +82,12 @@ class MinecraftConfigurations private constructor(private val project: Project) | |||||||
|         project.tasks.named("jar", Jar::class.java) { from(client.output) } |         project.tasks.named("jar", Jar::class.java) { from(client.output) } | ||||||
|         project.tasks.named("sourcesJar", Jar::class.java) { from(client.allSource) } |         project.tasks.named("sourcesJar", Jar::class.java) { from(client.allSource) } | ||||||
| 
 | 
 | ||||||
|  |         setupBasic() | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private fun setupBasic() { | ||||||
|  |         val client = sourceSets["client"] | ||||||
|  | 
 | ||||||
|         project.extensions.configure(CCTweakedExtension::class.java) { |         project.extensions.configure(CCTweakedExtension::class.java) { | ||||||
|             sourceDirectories.add(SourceSetReference.internal(client)) |             sourceDirectories.add(SourceSetReference.internal(client)) | ||||||
|         } |         } | ||||||
| @@ -120,83 +102,19 @@ class MinecraftConfigurations private constructor(private val project: Project) | |||||||
|         project.tasks.named("check") { dependsOn(checkDependencyConsistency) } |         project.tasks.named("check") { dependsOn(checkDependencyConsistency) } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private fun setupOutgoing(sourceSet: SourceSet, suffix: String = "") { |  | ||||||
|         setupOutgoing("${sourceSet.apiElementsConfigurationName}$suffix", sourceSet, objects.named(Usage.JAVA_API)) { |  | ||||||
|             description = "API elements for ${sourceSet.name}" |  | ||||||
|             extendsFrom(configurations[sourceSet.apiConfigurationName]) |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         setupOutgoing("${sourceSet.runtimeElementsConfigurationName}$suffix", sourceSet, objects.named(Usage.JAVA_RUNTIME)) { |  | ||||||
|             description = "Runtime elements for ${sourceSet.name}" |  | ||||||
|             extendsFrom(configurations[sourceSet.implementationConfigurationName], configurations[sourceSet.runtimeOnlyConfigurationName]) |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Set up an outgoing configuration for a specific source set. We set an additional "main" or "client" capability |  | ||||||
|      * (depending on the source set name) which allows downstream projects to consume them separately (see |  | ||||||
|      * [DependencyHandler.commonClasses] and [DependencyHandler.clientClasses]). |  | ||||||
|      */ |  | ||||||
|     private fun setupOutgoing(name: String, sourceSet: SourceSet, usage: Usage, configure: Configuration.() -> Unit) { |  | ||||||
|         configurations.register(name) { |  | ||||||
|             isVisible = false |  | ||||||
|             isCanBeConsumed = true |  | ||||||
|             isCanBeResolved = false |  | ||||||
| 
 |  | ||||||
|             configure(this) |  | ||||||
| 
 |  | ||||||
|             attributes { |  | ||||||
|                 attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category.LIBRARY)) |  | ||||||
|                 attribute(Usage.USAGE_ATTRIBUTE, usage) |  | ||||||
|                 attribute(Bundling.BUNDLING_ATTRIBUTE, objects.named(Bundling.EXTERNAL)) |  | ||||||
|                 attributeProvider( |  | ||||||
|                     TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, |  | ||||||
|                     java.toolchain.languageVersion.map { it.asInt() }, |  | ||||||
|                 ) |  | ||||||
|                 attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, objects.named(LibraryElements.JAR)) |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             outgoing { |  | ||||||
|                 capability(BasicOutgoingCapability(project, sourceSet.name)) |  | ||||||
| 
 |  | ||||||
|                 // We have two outgoing variants here: the original jar and the classes. |  | ||||||
|                 artifact(project.tasks.named(sourceSet.jarTaskName)) |  | ||||||
| 
 |  | ||||||
|                 variants.create("classes") { |  | ||||||
|                     attributes.attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, objects.named(LibraryElements.CLASSES)) |  | ||||||
|                     sourceSet.output.classesDirs.forEach { artifact(it) { builtBy(sourceSet.output) } } |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     companion object { |     companion object { | ||||||
|  |         fun setupBasic(project: Project) { | ||||||
|  |             MinecraftConfigurations(project).setupBasic() | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         fun setup(project: Project) { |         fun setup(project: Project) { | ||||||
|             MinecraftConfigurations(project).setup() |             MinecraftConfigurations(project).setup() | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| private class BasicIncomingCapability(private val module: ModuleDependency, private val name: String) : Capability { | fun DependencyHandler.clientClasses(notation: Any): ModuleDependency = | ||||||
|     override fun getGroup(): String = module.group!! |     Capabilities.clientClasses(create(notation) as ModuleDependency) | ||||||
|     override fun getName(): String = "${module.name}-$name" |  | ||||||
|     override fun getVersion(): String? = null |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| private class BasicOutgoingCapability(private val project: Project, private val name: String) : Capability { | fun DependencyHandler.commonClasses(notation: Any): ModuleDependency = | ||||||
|     override fun getGroup(): String = project.group.toString() |     Capabilities.commonClasses(create(notation) as ModuleDependency) | ||||||
|     override fun getName(): String = "${project.name}-$name" |  | ||||||
|     override fun getVersion(): String = project.version.toString() |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| fun DependencyHandler.clientClasses(notation: Any): ModuleDependency { |  | ||||||
|     val dep = create(notation) as ModuleDependency |  | ||||||
|     dep.capabilities { requireCapability(BasicIncomingCapability(dep, "client")) } |  | ||||||
|     return dep |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| fun DependencyHandler.commonClasses(notation: Any): ModuleDependency { |  | ||||||
|     val dep = create(notation) as ModuleDependency |  | ||||||
|     dep.capabilities { requireCapability(BasicIncomingCapability(dep, "main")) } |  | ||||||
|     return dep |  | ||||||
| } |  | ||||||
|   | |||||||
| @@ -14,6 +14,7 @@ forgeSpi = "7.0.1" | |||||||
| mixin = "0.8.5" | mixin = "0.8.5" | ||||||
| parchment = "2023.08.20" | parchment = "2023.08.20" | ||||||
| parchmentMc = "1.20.1" | parchmentMc = "1.20.1" | ||||||
|  | yarn = "1.20.1+build.10" | ||||||
|  |  | ||||||
| # Core dependencies (these versions are tied to the version Minecraft uses) | # Core dependencies (these versions are tied to the version Minecraft uses) | ||||||
| fastutil = "8.5.9" | fastutil = "8.5.9" | ||||||
| @@ -71,7 +72,7 @@ nullAway = "0.9.9" | |||||||
| spotless = "6.23.3" | spotless = "6.23.3" | ||||||
| taskTree = "2.1.1" | taskTree = "2.1.1" | ||||||
| teavm = "0.10.0-SQUID.2" | teavm = "0.10.0-SQUID.2" | ||||||
| vanillaGradle = "0.2.1-SNAPSHOT" | vanillaExtract = "0.1.1" | ||||||
| versionCatalogUpdate = "0.8.1" | versionCatalogUpdate = "0.8.1" | ||||||
|  |  | ||||||
| [libraries] | [libraries] | ||||||
| @@ -158,7 +159,8 @@ teavm-metaprogramming-api = { module = "org.teavm:teavm-metaprogramming-api", ve | |||||||
| teavm-metaprogramming-impl = { module = "org.teavm:teavm-metaprogramming-impl", version.ref = "teavm" } | teavm-metaprogramming-impl = { module = "org.teavm:teavm-metaprogramming-impl", version.ref = "teavm" } | ||||||
| teavm-platform = { module = "org.teavm:teavm-platform", version.ref = "teavm" } | teavm-platform = { module = "org.teavm:teavm-platform", version.ref = "teavm" } | ||||||
| teavm-tooling = { module = "org.teavm:teavm-tooling", version.ref = "teavm" } | teavm-tooling = { module = "org.teavm:teavm-tooling", version.ref = "teavm" } | ||||||
| vanillaGradle = { module = "org.spongepowered:vanillagradle", version.ref = "vanillaGradle" } | vanillaExtract = { module = "cc.tweaked.vanilla-extract:plugin", version.ref = "vanillaExtract" } | ||||||
|  | yarn = { module = "net.fabricmc:yarn", version.ref = "yarn" } | ||||||
|  |  | ||||||
| [plugins] | [plugins] | ||||||
| forgeGradle = { id = "net.minecraftforge.gradle", version.ref = "forgeGradle" } | forgeGradle = { id = "net.minecraftforge.gradle", version.ref = "forgeGradle" } | ||||||
|   | |||||||
| @@ -22,6 +22,14 @@ configurations { | |||||||
|     register("cctJavadoc") |     register("cctJavadoc") | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | repositories { | ||||||
|  |     maven("https://maven.minecraftforge.net/") { | ||||||
|  |         content { | ||||||
|  |             includeModule("org.spongepowered", "mixin") | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| dependencies { | dependencies { | ||||||
|     // Pull in our other projects. See comments in MinecraftConfigurations on this nastiness. |     // Pull in our other projects. See comments in MinecraftConfigurations on this nastiness. | ||||||
|     implementation(project(":core")) |     implementation(project(":core")) | ||||||
|   | |||||||
| @@ -27,7 +27,6 @@ pluginManagement { | |||||||
|             name = "Sponge" |             name = "Sponge" | ||||||
|             content { |             content { | ||||||
|                 includeGroup("org.spongepowered") |                 includeGroup("org.spongepowered") | ||||||
|                 includeGroup("org.spongepowered.gradle.vanilla") |  | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| @@ -38,6 +37,13 @@ pluginManagement { | |||||||
|                 includeGroup("net.fabricmc") |                 includeGroup("net.fabricmc") | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  | 
 | ||||||
|  |         maven("https://squiddev.cc/maven") { | ||||||
|  |             name = "SquidDev" | ||||||
|  |             content { | ||||||
|  |                 includeGroup("cc.tweaked.vanilla-extract") | ||||||
|  |             } | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     resolutionStrategy { |     resolutionStrategy { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Jonathan Coates
					Jonathan Coates