Last active
May 16, 2026 01:37
-
-
Save isXander/45e8fe49c7232a9a804de669f1151ccd to your computer and use it in GitHub Desktop.
multi-loader, single-project
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| plugins { | |
| `java-library` | |
| id("net.fabricmc.fabric-loom") version "1.17.0-alpha.8" | |
| id("net.neoforged.gradle.userdev") version "7.1.27" | |
| `maven-publish` | |
| } | |
| group = "dev.isxander" | |
| version = "1.0.4" | |
| val fabric by sourceSets.registering | |
| val neoforge by sourceSets.registering | |
| java { | |
| withSourcesJar() | |
| registerFeature("fabric") { | |
| usingSourceSet(fabric.get()) | |
| withSourcesJar() | |
| } | |
| registerFeature("neoforge") { | |
| usingSourceSet(neoforge.get()) | |
| withSourcesJar() | |
| } | |
| } | |
| // These configurations are shared between all source sets | |
| // They should not be used for mod-like dependencies where different variants | |
| // would be required across sourcesets | |
| val commonCompileOnly by configurations.registering | |
| val commonRuntimeOnly by configurations.registering | |
| val commonImplementation by configurations.registering | |
| val commonApi by configurations.registering | |
| val commonCompileOnlyApi by configurations.registering | |
| val commonAnnotationProcessor by configurations.registering | |
| // Share the common source set's sources/resources with loader source sets. | |
| // Reference the source set directly — routing through resolvable configurations | |
| // in the same project yields an empty resolution because no incoming dependency exists. | |
| val commonJava = sourceSets.main.map { it.java } | |
| val commonResources = sourceSets.main.map { it.resources } | |
| configurations { | |
| compileOnly { extendsFrom(commonCompileOnly) } | |
| runtimeOnly { extendsFrom(commonRuntimeOnly) } | |
| implementation { extendsFrom(commonImplementation) } | |
| api { extendsFrom(commonApi) } | |
| compileOnlyApi { extendsFrom(commonCompileOnlyApi) } | |
| annotationProcessor { extendsFrom(commonAnnotationProcessor) } | |
| "fabricCompileOnly" { extendsFrom(commonCompileOnly) } | |
| "fabricRuntimeOnly" { extendsFrom(commonRuntimeOnly) } | |
| "fabricImplementation" { extendsFrom(commonImplementation) } | |
| "fabricApi" { extendsFrom(commonApi) } | |
| "fabricCompileOnlyApi" { extendsFrom(commonCompileOnlyApi) } | |
| "fabricAnnotationProcessor" { extendsFrom(commonAnnotationProcessor) } | |
| afterEvaluate { | |
| "fabricCompileClasspath" { extendsFrom(named("minecraftNamedCompile")) } | |
| "fabricRuntimeClasspath" { extendsFrom(named("minecraftNamedRuntime")) } | |
| } | |
| "neoforgeCompileOnly" { extendsFrom(commonCompileOnly) } | |
| "neoforgeRuntimeOnly" { extendsFrom(commonRuntimeOnly) } | |
| "neoforgeImplementation" { extendsFrom(commonImplementation) } | |
| "neoforgeApi" { extendsFrom(commonApi) } | |
| "neoforgeCompileOnlyApi" { extendsFrom(commonCompileOnlyApi) } | |
| "neoforgeAnnotationProcessor" { extendsFrom(commonAnnotationProcessor) } | |
| } | |
| dependencies { | |
| minecraft("com.mojang:minecraft:26.1.2") | |
| // need fabric loader in main sourceset to compile against Mixin. | |
| compileOnly("net.fabricmc:fabric-loader:0.19.2") | |
| // example common | |
| commonImplementation("net.fabricmc:mapping-io:0.8.0") | |
| "fabricImplementation"("net.fabricmc:fabric-loader:0.19.2") | |
| "fabricImplementation"("net.fabricmc.fabric-api:fabric-api:0.149.0+26.1.2") | |
| "fabricCompileOnly"(sourceSets.main.get().output) | |
| "neoforgeImplementation"("net.neoforged:neoforge:26.1.2.50-beta") | |
| "neoforgeCompileOnly"(sourceSets.main.get().output) | |
| } | |
| java { | |
| toolchain { | |
| languageVersion = JavaLanguageVersion.of(25) | |
| } | |
| } | |
| // include common sourceset in loader-specific compilation and resource processing | |
| // this allows for compile-time guarantees when NeoForge patches a vanilla method signature like a bitch | |
| tasks.named<JavaCompile>("compileFabricJava") { | |
| dependsOn(commonJava) | |
| source(commonJava) | |
| } | |
| tasks.named<Jar>("fabricSourcesJar") { | |
| dependsOn(commonJava) | |
| from(commonJava) | |
| } | |
| tasks.named<JavaCompile>("compileNeoforgeJava") { | |
| dependsOn(commonJava) | |
| source(commonJava) | |
| } | |
| tasks.named<Jar>("neoforgeSourcesJar") { | |
| dependsOn(commonJava) | |
| from(commonJava) | |
| } | |
| tasks.named<ProcessResources>("processFabricResources") { | |
| dependsOn(commonResources) | |
| from(commonResources) | |
| } | |
| tasks.named<ProcessResources>("processNeoforgeResources") { | |
| dependsOn(commonResources) | |
| from(commonResources) | |
| } | |
| // Create a universal jar that includes both loaders | |
| val universalJar by tasks.registering(Jar::class) { | |
| archiveClassifier = "universal" | |
| duplicatesStrategy = DuplicatesStrategy.EXCLUDE | |
| from(sourceSets.main.get().output) | |
| from(fabric.get().output) | |
| from(neoforge.get().output) | |
| } | |
| val universalSourcesJar by tasks.registering(Jar::class) { | |
| archiveClassifier = "universal-sources" | |
| duplicatesStrategy = DuplicatesStrategy.EXCLUDE | |
| from(sourceSets.main.get().allSource) | |
| from(fabric.get().allSource) | |
| from(neoforge.get().allSource) | |
| } | |
| // Ensure the jars are generated on `build` | |
| tasks.assemble { | |
| dependsOn("fabricJar", "neoforgeJar", universalJar, universalSourcesJar) | |
| } | |
| val modLoaderAttribute = Attribute.of("io.github.mcgradleconventions.loader", String::class.java) | |
| fun ConfigurationContainer.configureLoaderVariant( | |
| sourceSet: SourceSet, | |
| action: Action<in Configuration>, | |
| ) { | |
| listOf( | |
| sourceSet.apiElementsConfigurationName, | |
| sourceSet.runtimeElementsConfigurationName, | |
| sourceSet.sourcesElementsConfigurationName, | |
| //sourceSet.javadocElementsConfigurationName, | |
| ).forEach { configurationName -> | |
| named(configurationName, action) | |
| } | |
| } | |
| configurations { | |
| configureLoaderVariant(sourceSets.main.get()) { | |
| attributes { | |
| attribute(modLoaderAttribute, "common") | |
| } | |
| outgoing.capability(provider { "${project.group}:${project.name}:${project.version}" }) | |
| outgoing.capability(provider { "${project.group}:${project.name}-common:${project.version}" }) | |
| } | |
| configureLoaderVariant(fabric.get()) { | |
| attributes { | |
| attribute(modLoaderAttribute, "fabric") | |
| } | |
| // fabric capability defined by the feature | |
| outgoing.capability(provider { "${project.group}:${project.name}:${project.version}" }) | |
| } | |
| configureLoaderVariant(neoforge.get()) { | |
| attributes { | |
| attribute(modLoaderAttribute, "neoforge") | |
| } | |
| // neoforge capability defined by the feature | |
| outgoing.capability(provider { "${project.group}:${project.name}:${project.version}" }) | |
| } | |
| } | |
| publishing { | |
| repositories { | |
| mavenLocal() | |
| } | |
| publications { | |
| create<MavenPublication>("mavenJava") { | |
| from(components["java"]) | |
| } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| { | |
| "formatVersion": "1.1", | |
| "component": { | |
| "group": "dev.isxander", | |
| "module": "testmod", | |
| "version": "1.0.4", | |
| "attributes": { | |
| "org.gradle.status": "release" | |
| } | |
| }, | |
| "createdBy": { | |
| "gradle": { | |
| "version": "9.5.1" | |
| } | |
| }, | |
| "variants": [ | |
| { | |
| "name": "apiElements", | |
| "attributes": { | |
| "io.github.mcgradleconventions.loader": "common", | |
| "org.gradle.category": "library", | |
| "org.gradle.dependency.bundling": "external", | |
| "org.gradle.jvm.version": 25, | |
| "org.gradle.libraryelements": "jar", | |
| "org.gradle.usage": "java-api" | |
| }, | |
| "files": [ | |
| { | |
| "name": "testmod-1.0.4.jar", | |
| "url": "testmod-1.0.4.jar", | |
| "size": 1347, | |
| "sha512": "c8e70ea09767f4f2d93105706cb60478c848c1a48aa1b87c11089e420a1c0f170ba6959944c47582c2d409fd6b935f6553c89df4d8d4410c27671d4a63e76510", | |
| "sha256": "1efb9063d8aec0d8cfc446e4172340eab2ce8eb5f1c38823bb4c3e3e51f4b16d", | |
| "sha1": "37546da2b6f030f843b1339b9ecc12ed73302014", | |
| "md5": "10e84cbb07e4a08c21007016bc732561" | |
| } | |
| ], | |
| "capabilities": [ | |
| { | |
| "group": "dev.isxander", | |
| "name": "testmod", | |
| "version": "1.0.4" | |
| }, | |
| { | |
| "group": "dev.isxander", | |
| "name": "testmod-common", | |
| "version": "1.0.4" | |
| } | |
| ] | |
| }, | |
| { | |
| "name": "runtimeElements", | |
| "attributes": { | |
| "io.github.mcgradleconventions.loader": "common", | |
| "org.gradle.category": "library", | |
| "org.gradle.dependency.bundling": "external", | |
| "org.gradle.jvm.version": 25, | |
| "org.gradle.libraryelements": "jar", | |
| "org.gradle.usage": "java-runtime" | |
| }, | |
| "dependencies": [ | |
| { | |
| "group": "net.fabricmc", | |
| "module": "mapping-io", | |
| "version": { | |
| "requires": "0.8.0" | |
| } | |
| } | |
| ], | |
| "files": [ | |
| { | |
| "name": "testmod-1.0.4.jar", | |
| "url": "testmod-1.0.4.jar", | |
| "size": 1347, | |
| "sha512": "c8e70ea09767f4f2d93105706cb60478c848c1a48aa1b87c11089e420a1c0f170ba6959944c47582c2d409fd6b935f6553c89df4d8d4410c27671d4a63e76510", | |
| "sha256": "1efb9063d8aec0d8cfc446e4172340eab2ce8eb5f1c38823bb4c3e3e51f4b16d", | |
| "sha1": "37546da2b6f030f843b1339b9ecc12ed73302014", | |
| "md5": "10e84cbb07e4a08c21007016bc732561" | |
| } | |
| ], | |
| "capabilities": [ | |
| { | |
| "group": "dev.isxander", | |
| "name": "testmod", | |
| "version": "1.0.4" | |
| }, | |
| { | |
| "group": "dev.isxander", | |
| "name": "testmod-common", | |
| "version": "1.0.4" | |
| } | |
| ] | |
| }, | |
| { | |
| "name": "sourcesElements", | |
| "attributes": { | |
| "io.github.mcgradleconventions.loader": "common", | |
| "org.gradle.category": "documentation", | |
| "org.gradle.dependency.bundling": "external", | |
| "org.gradle.docstype": "sources", | |
| "org.gradle.usage": "java-runtime" | |
| }, | |
| "files": [ | |
| { | |
| "name": "testmod-1.0.4-sources.jar", | |
| "url": "testmod-1.0.4-sources.jar", | |
| "size": 928, | |
| "sha512": "73bdff4789d48010552d43e2e1e761f6cd8daf29cfda5f9473432ada613a598476801d8a61b79b35b68bff72ec0123cc554b1e33bcb8a711cecf9271c47b7649", | |
| "sha256": "b406d595a774280198a540dcee49610bacdbd42feb4cef31fb53fcfbbd732c48", | |
| "sha1": "004322258ac127eb53fdf5cae6947bc0e7360180", | |
| "md5": "0ca52e4ddad8778e73d2cc5d43f2a9b3" | |
| } | |
| ], | |
| "capabilities": [ | |
| { | |
| "group": "dev.isxander", | |
| "name": "testmod", | |
| "version": "1.0.4" | |
| }, | |
| { | |
| "group": "dev.isxander", | |
| "name": "testmod-common", | |
| "version": "1.0.4" | |
| } | |
| ] | |
| }, | |
| { | |
| "name": "fabricSourcesElements", | |
| "attributes": { | |
| "io.github.mcgradleconventions.loader": "fabric", | |
| "org.gradle.category": "documentation", | |
| "org.gradle.dependency.bundling": "external", | |
| "org.gradle.docstype": "sources", | |
| "org.gradle.usage": "java-runtime" | |
| }, | |
| "files": [ | |
| { | |
| "name": "testmod-1.0.4-fabric-sources.jar", | |
| "url": "testmod-1.0.4-fabric-sources.jar", | |
| "size": 1358, | |
| "sha512": "209e6551d1b55546d2c5860f74f93e1762c59110cc5916f30baad5036251b2021be66f2edc38e473d42ca794d2d834a12c330e7c9217ef7d4ac0dc5d4d60033c", | |
| "sha256": "71633775026bc8d433369a6f637b93cc69ca3be62d40808bcab8b33336fea9ce", | |
| "sha1": "356cee3fe6ed122e2ed114e715217a72f3d24865", | |
| "md5": "9c18811d1f69965db2dcd33e98a81ab1" | |
| } | |
| ], | |
| "capabilities": [ | |
| { | |
| "group": "dev.isxander", | |
| "name": "testmod", | |
| "version": "1.0.4" | |
| }, | |
| { | |
| "group": "dev.isxander", | |
| "name": "testmod-fabric", | |
| "version": "1.0.4" | |
| } | |
| ] | |
| }, | |
| { | |
| "name": "fabricApiElements", | |
| "attributes": { | |
| "io.github.mcgradleconventions.loader": "fabric", | |
| "org.gradle.category": "library", | |
| "org.gradle.dependency.bundling": "external", | |
| "org.gradle.jvm.version": 25, | |
| "org.gradle.libraryelements": "jar", | |
| "org.gradle.usage": "java-api" | |
| }, | |
| "files": [ | |
| { | |
| "name": "testmod-1.0.4-fabric.jar", | |
| "url": "testmod-1.0.4-fabric.jar", | |
| "size": 1909, | |
| "sha512": "cc54eeacbb544fb27ed85cebf4972c9eb39e71a546a457308a93f9d789caeb31c0834927980fe95b4a2e0ed5e21e708ff877098764fa64e1ce1881d52aadeba9", | |
| "sha256": "2980ab707568378786e0b97b7ecf34978fc4504eb30dcb6fde259e957835e831", | |
| "sha1": "36600ceaf906da86d2dc960289becaa892e1682d", | |
| "md5": "d2a19185a860ee2c521549991ba8dcce" | |
| } | |
| ], | |
| "capabilities": [ | |
| { | |
| "group": "dev.isxander", | |
| "name": "testmod", | |
| "version": "1.0.4" | |
| }, | |
| { | |
| "group": "dev.isxander", | |
| "name": "testmod-fabric", | |
| "version": "1.0.4" | |
| } | |
| ] | |
| }, | |
| { | |
| "name": "fabricRuntimeElements", | |
| "attributes": { | |
| "io.github.mcgradleconventions.loader": "fabric", | |
| "org.gradle.category": "library", | |
| "org.gradle.dependency.bundling": "external", | |
| "org.gradle.jvm.version": 25, | |
| "org.gradle.libraryelements": "jar", | |
| "org.gradle.usage": "java-runtime" | |
| }, | |
| "dependencies": [ | |
| { | |
| "group": "net.fabricmc", | |
| "module": "fabric-loader", | |
| "version": { | |
| "requires": "0.19.2" | |
| } | |
| }, | |
| { | |
| "group": "net.fabricmc.fabric-api", | |
| "module": "fabric-api", | |
| "version": { | |
| "requires": "0.149.0+26.1.2" | |
| } | |
| }, | |
| { | |
| "group": "net.fabricmc", | |
| "module": "mapping-io", | |
| "version": { | |
| "requires": "0.8.0" | |
| } | |
| } | |
| ], | |
| "files": [ | |
| { | |
| "name": "testmod-1.0.4-fabric.jar", | |
| "url": "testmod-1.0.4-fabric.jar", | |
| "size": 1909, | |
| "sha512": "cc54eeacbb544fb27ed85cebf4972c9eb39e71a546a457308a93f9d789caeb31c0834927980fe95b4a2e0ed5e21e708ff877098764fa64e1ce1881d52aadeba9", | |
| "sha256": "2980ab707568378786e0b97b7ecf34978fc4504eb30dcb6fde259e957835e831", | |
| "sha1": "36600ceaf906da86d2dc960289becaa892e1682d", | |
| "md5": "d2a19185a860ee2c521549991ba8dcce" | |
| } | |
| ], | |
| "capabilities": [ | |
| { | |
| "group": "dev.isxander", | |
| "name": "testmod", | |
| "version": "1.0.4" | |
| }, | |
| { | |
| "group": "dev.isxander", | |
| "name": "testmod-fabric", | |
| "version": "1.0.4" | |
| } | |
| ] | |
| }, | |
| { | |
| "name": "neoforgeSourcesElements", | |
| "attributes": { | |
| "io.github.mcgradleconventions.loader": "neoforge", | |
| "org.gradle.category": "documentation", | |
| "org.gradle.dependency.bundling": "external", | |
| "org.gradle.docstype": "sources", | |
| "org.gradle.usage": "java-runtime" | |
| }, | |
| "files": [ | |
| { | |
| "name": "testmod-1.0.4-neoforge-sources.jar", | |
| "url": "testmod-1.0.4-neoforge-sources.jar", | |
| "size": 1359, | |
| "sha512": "974a3a5425536d9682cad8729167a6e7f93dd435089591ee87e80a40a1bc934283a963b58e38251b3107e9356a46bacbc524b874ff90fab20b7e9d5224e9f6ff", | |
| "sha256": "1026ad000b9ac294aac4c7b5d9610958f8ad346c606bd23c36bcdbeb037d21e1", | |
| "sha1": "b69208741aa4ef31e2fef7696d178b9731adceed", | |
| "md5": "a47d24a062b17845a8e854d28e7a0212" | |
| } | |
| ], | |
| "capabilities": [ | |
| { | |
| "group": "dev.isxander", | |
| "name": "testmod", | |
| "version": "1.0.4" | |
| }, | |
| { | |
| "group": "dev.isxander", | |
| "name": "testmod-neoforge", | |
| "version": "1.0.4" | |
| } | |
| ] | |
| }, | |
| { | |
| "name": "neoforgeApiElements", | |
| "attributes": { | |
| "io.github.mcgradleconventions.loader": "neoforge", | |
| "org.gradle.category": "library", | |
| "org.gradle.dependency.bundling": "external", | |
| "org.gradle.jvm.version": 25, | |
| "org.gradle.libraryelements": "jar", | |
| "org.gradle.usage": "java-api" | |
| }, | |
| "files": [ | |
| { | |
| "name": "testmod-1.0.4-neoforge.jar", | |
| "url": "testmod-1.0.4-neoforge.jar", | |
| "size": 1943, | |
| "sha512": "6d99e94ea072c676054662777708eaa5c4375ae0f8c2f6e3a1e82aef59bbe72bd872aea7c6358899bd9d5838b49fa2fc0999c52bdb53b6cb54c5069819b85b20", | |
| "sha256": "da5ccbc9c63c06321402122699b5b0c8b36dd444b379f138288c1de1f3c9ca93", | |
| "sha1": "9bfe28ce28e1faecdd04dfe568d575acb2cec415", | |
| "md5": "cedf7c50fe0e207ef9d6cfc8905d1fcb" | |
| } | |
| ], | |
| "capabilities": [ | |
| { | |
| "group": "dev.isxander", | |
| "name": "testmod", | |
| "version": "1.0.4" | |
| }, | |
| { | |
| "group": "dev.isxander", | |
| "name": "testmod-neoforge", | |
| "version": "1.0.4" | |
| } | |
| ] | |
| }, | |
| { | |
| "name": "neoforgeRuntimeElements", | |
| "attributes": { | |
| "io.github.mcgradleconventions.loader": "neoforge", | |
| "org.gradle.category": "library", | |
| "org.gradle.dependency.bundling": "external", | |
| "org.gradle.jvm.version": 25, | |
| "org.gradle.libraryelements": "jar", | |
| "org.gradle.usage": "java-runtime" | |
| }, | |
| "dependencies": [ | |
| { | |
| "group": "net.fabricmc", | |
| "module": "mapping-io", | |
| "version": { | |
| "requires": "0.8.0" | |
| } | |
| } | |
| ], | |
| "files": [ | |
| { | |
| "name": "testmod-1.0.4-neoforge.jar", | |
| "url": "testmod-1.0.4-neoforge.jar", | |
| "size": 1943, | |
| "sha512": "6d99e94ea072c676054662777708eaa5c4375ae0f8c2f6e3a1e82aef59bbe72bd872aea7c6358899bd9d5838b49fa2fc0999c52bdb53b6cb54c5069819b85b20", | |
| "sha256": "da5ccbc9c63c06321402122699b5b0c8b36dd444b379f138288c1de1f3c9ca93", | |
| "sha1": "9bfe28ce28e1faecdd04dfe568d575acb2cec415", | |
| "md5": "cedf7c50fe0e207ef9d6cfc8905d1fcb" | |
| } | |
| ], | |
| "capabilities": [ | |
| { | |
| "group": "dev.isxander", | |
| "name": "testmod", | |
| "version": "1.0.4" | |
| }, | |
| { | |
| "group": "dev.isxander", | |
| "name": "testmod-neoforge", | |
| "version": "1.0.4" | |
| } | |
| ] | |
| } | |
| ] | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment