diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 0c9716767..6c37d9e49 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -26,15 +26,15 @@ gradlePlugin { } create("jarSetPlugin") { id = "flywheel.jar-sets" - implementationClass = "com.jozufozu.gradle.JarSetPlugin" + implementationClass = "com.jozufozu.gradle.jarset.JarSetPlugin" } create("packageInfosPlugin") { id = "flywheel.package-infos" - implementationClass = "com.jozufozu.gradle.PackageInfosPlugin" + implementationClass = "com.jozufozu.gradle.nullability.PackageInfosPlugin" } create("transitiveSourceSetsPlugin") { id = "flywheel.transitive-source-sets" - implementationClass = "com.jozufozu.gradle.TransitiveSourceSetsPlugin" + implementationClass = "com.jozufozu.gradle.transitive.TransitiveSourceSetsPlugin" } } } diff --git a/buildSrc/src/main/groovy/com/jozufozu/gradle/GeneratePackageInfosTask.groovy b/buildSrc/src/main/groovy/com/jozufozu/gradle/GeneratePackageInfosTask.groovy deleted file mode 100644 index e3e34cf15..000000000 --- a/buildSrc/src/main/groovy/com/jozufozu/gradle/GeneratePackageInfosTask.groovy +++ /dev/null @@ -1,53 +0,0 @@ -package com.jozufozu.gradle - -import org.gradle.api.DefaultTask -import org.gradle.api.file.DirectoryProperty -import org.gradle.api.tasks.InputDirectory -import org.gradle.api.tasks.OutputDirectory -import org.gradle.api.tasks.SkipWhenEmpty -import org.gradle.api.tasks.TaskAction - -import java.nio.file.Files - -// Adapted from https://github.com/FabricMC/fabric/blob/31787236d242247e0b6c4ae806b1cfaa7042a62c/gradle/package-info.gradle, which is licensed under Apache 2.0. -class GeneratePackageInfosTask extends DefaultTask { - @SkipWhenEmpty - @InputDirectory - final DirectoryProperty sourceRoot = project.objects.directoryProperty() - - @OutputDirectory - final DirectoryProperty outputDir = project.objects.directoryProperty() - - @TaskAction - def run() { - def output = outputDir.get().asFile.toPath() - output.deleteDir() - def root = sourceRoot.get().asFile.toPath() - - root.eachDirRecurse { - def containsJava = Files.list(it).any { - Files.isRegularFile(it) && it.fileName.toString().endsWith('.java') - } - - if (containsJava && Files.notExists(it.resolve('package-info.java'))) { - def relativePath = root.relativize(it) - def target = output.resolve(relativePath) - Files.createDirectories(target) - - target.resolve('package-info.java').withWriter { - def packageName = relativePath.toString().replace(File.separator, '.') - it.write("""@ParametersAreNonnullByDefault - |@FieldsAreNonnullByDefault - |@MethodsReturnNonnullByDefault - |package $packageName; - | - |import javax.annotation.ParametersAreNonnullByDefault; - | - |import net.minecraft.FieldsAreNonnullByDefault; - |import net.minecraft.MethodsReturnNonnullByDefault; - |""".stripMargin()) - } - } - } - } -} diff --git a/buildSrc/src/main/groovy/com/jozufozu/gradle/JarSetExtension.groovy b/buildSrc/src/main/groovy/com/jozufozu/gradle/JarSetExtension.groovy deleted file mode 100644 index 733761a64..000000000 --- a/buildSrc/src/main/groovy/com/jozufozu/gradle/JarSetExtension.groovy +++ /dev/null @@ -1,23 +0,0 @@ -package com.jozufozu.gradle - -import groovy.transform.CompileStatic -import org.gradle.api.Project -import org.gradle.api.tasks.SourceSet -import org.gradle.api.tasks.SourceSetContainer - -@CompileStatic -class JarSetExtension { - private final Project project - - JarSetExtension(Project project) { - this.project = project - } - - JarTaskSet createJars(String name) { - return createJars(name, project.getExtensions().getByType(SourceSetContainer).named(name).get()) - } - - JarTaskSet createJars(String name, SourceSet... sourceSetSet) { - return JarTaskSet.create(project, name, sourceSetSet) - } -} diff --git a/buildSrc/src/main/groovy/com/jozufozu/gradle/JarSetPlugin.groovy b/buildSrc/src/main/groovy/com/jozufozu/gradle/JarSetPlugin.groovy deleted file mode 100644 index 50b572565..000000000 --- a/buildSrc/src/main/groovy/com/jozufozu/gradle/JarSetPlugin.groovy +++ /dev/null @@ -1,15 +0,0 @@ -package com.jozufozu.gradle - - -import groovy.transform.CompileStatic -import org.gradle.api.Plugin -import org.gradle.api.Project - -@CompileStatic -class JarSetPlugin implements Plugin { - @Override - void apply(Project project) { - project.extensions.create('jarSets', JarSetExtension, project) - } -} - diff --git a/buildSrc/src/main/groovy/com/jozufozu/gradle/JarTaskSet.groovy b/buildSrc/src/main/groovy/com/jozufozu/gradle/JarTaskSet.groovy deleted file mode 100644 index f75c93b0b..000000000 --- a/buildSrc/src/main/groovy/com/jozufozu/gradle/JarTaskSet.groovy +++ /dev/null @@ -1,126 +0,0 @@ -package com.jozufozu.gradle - -import groovy.transform.CompileStatic -import net.fabricmc.loom.task.RemapJarTask -import net.fabricmc.loom.task.RemapSourcesJarTask -import org.gradle.api.Action -import org.gradle.api.Project -import org.gradle.api.tasks.SourceSet -import org.gradle.api.tasks.TaskProvider -import org.gradle.api.tasks.bundling.Jar -import org.gradle.api.tasks.javadoc.Javadoc - -@CompileStatic -class JarTaskSet { - public static final String BUILD_GROUP = 'build' - public static final String LOOM_GROUP = 'loom' - public static final String JAVADOC_CLASSIFIER = "javadoc" - public static final String SOURCES_CLASSIFIER = "sources" - - Project project - String name - TaskProvider jar - TaskProvider remapJar - TaskProvider sources - TaskProvider remapSources - TaskProvider javadocJar - - JarTaskSet(Project project, String name, TaskProvider jar, TaskProvider remapJar, TaskProvider sources, TaskProvider remapSources, TaskProvider javadocJar) { - this.project = project - this.name = name - this.jar = jar - this.remapJar = remapJar - this.sources = sources - this.remapSources = remapSources - this.javadocJar = javadocJar - } - - void createOutgoingConfiguration(String prefix) { - def config = project.configurations.register("${prefix}${name.capitalize()}") { - it.canBeConsumed = true - it.canBeResolved = false - } - - project.artifacts.add(config.name, jar) - } - - void configure(Action action) { - action.execute(this) - } - - void configureEach(Action action) { - jar.configure(action) - sources.configure(action) - javadocJar.configure(action) - - remapJar.configure(action as Action) - remapSources.configure(action as Action) - } - - static JarTaskSet create(Project project, String name, SourceSet... sourceSetSet) { - def buildDirectory = project.layout.buildDirectory - def devlibs = buildDirectory.dir("devlibs/${name}") - def libs = buildDirectory.dir("libs/${name}") - - def jarTask = project.tasks.register("${name}Jar", Jar) { - it.group = BUILD_GROUP - it.destinationDirectory.set(devlibs) - - for (SourceSet set in sourceSetSet) { - it.from set.output - } - JarTaskUtils.excludeDuplicatePackageInfos(it) - } - def remapJarTask = project.tasks.register("${name}RemapJar", RemapJarTask) { - it.dependsOn(jarTask) - it.group = LOOM_GROUP - it.destinationDirectory.set(libs) - - it.inputFile.set(jarTask.flatMap { it.archiveFile }) - } - def sourcesTask = project.tasks.register("${name}SourcesJar", Jar) { - it.group = BUILD_GROUP - it.destinationDirectory.set(devlibs) - it.archiveClassifier.set(SOURCES_CLASSIFIER) - - for (SourceSet set in sourceSetSet) { - it.from set.allSource - } - JarTaskUtils.excludeDuplicatePackageInfos(it) - } - def remapSourcesTask = project.tasks.register("${name}RemapSourcesJar", RemapSourcesJarTask) { - it.dependsOn(sourcesTask) - it.group = LOOM_GROUP - it.destinationDirectory.set(libs) - it.archiveClassifier.set(SOURCES_CLASSIFIER) - - it.inputFile.set(sourcesTask.flatMap { it.archiveFile }) - } - def javadocTask = project.tasks.register("${name}Javadoc", Javadoc) { - it.group = BUILD_GROUP - it.destinationDir = buildDirectory.dir("docs/${name}-javadoc").get().asFile - it.options.encoding = 'UTF-8' - it.options.optionFiles(project.rootProject.file('javadoc-options.txt')) - - for (SourceSet set in sourceSetSet) { - it.source set.allJava - it.classpath += set.compileClasspath - } - JarTaskUtils.excludeDuplicatePackageInfos(it) - } - def javadocJarTask = project.tasks.register("${name}JavadocJar", Jar) { - it.dependsOn(javadocTask) - it.group = BUILD_GROUP - it.destinationDirectory.set(libs) - it.archiveClassifier.set(JAVADOC_CLASSIFIER) - - it.from(javadocTask.map { it.outputs }) - } - - project.tasks.named('assemble').configure { - it.dependsOn(remapJarTask, remapSourcesTask, javadocJarTask) - } - - return new JarTaskSet(project, name, jarTask, remapJarTask, sourcesTask, remapSourcesTask, javadocJarTask) - } -} diff --git a/buildSrc/src/main/groovy/com/jozufozu/gradle/JarTaskUtils.groovy b/buildSrc/src/main/groovy/com/jozufozu/gradle/JarTaskUtils.groovy deleted file mode 100644 index 34d553872..000000000 --- a/buildSrc/src/main/groovy/com/jozufozu/gradle/JarTaskUtils.groovy +++ /dev/null @@ -1,28 +0,0 @@ -package com.jozufozu.gradle - -import groovy.transform.CompileStatic -import org.gradle.api.file.DuplicatesStrategy -import org.gradle.api.file.FileCopyDetails -import org.gradle.api.tasks.AbstractCopyTask -import org.gradle.api.tasks.SourceTask - -@CompileStatic -class JarTaskUtils { - /** - * We have duplicate packages between the common and platform dependent subprojects. - * In theory the package-info.java files should be identical, so just take the first one we find. - */ - static void excludeDuplicatePackageInfos(AbstractCopyTask copyTask) { - copyTask.filesMatching('**/package-info.java') { FileCopyDetails details -> - details.duplicatesStrategy = DuplicatesStrategy.EXCLUDE - } - } - - /** - * The compile/javadoc tasks have a different base type that isn't so smart about exclusion handling. - */ - static void excludeDuplicatePackageInfos(SourceTask sourceTask) { - sourceTask.exclude('**/package-info.java') - } - -} diff --git a/buildSrc/src/main/groovy/com/jozufozu/gradle/PackageInfosExtension.groovy b/buildSrc/src/main/groovy/com/jozufozu/gradle/PackageInfosExtension.groovy deleted file mode 100644 index cecc3f80a..000000000 --- a/buildSrc/src/main/groovy/com/jozufozu/gradle/PackageInfosExtension.groovy +++ /dev/null @@ -1,50 +0,0 @@ -package com.jozufozu.gradle - -import groovy.transform.CompileStatic -import org.gradle.api.Project -import org.gradle.api.tasks.Delete -import org.gradle.api.tasks.SourceSet - -@CompileStatic -class PackageInfosExtension { - final Project project - - PackageInfosExtension(Project project) { - this.project = project - } - - void forSourceSets(SourceSet... sourceSets) { - for (SourceSet sourceSet : sourceSets) { - _forSourceSet(sourceSet) - } - } - - private void _forSourceSet(SourceSet sourceSet) { - // We have to capture the source set name for the lazy string literals, - // otherwise it'll just be whatever the last source set is in the list. - def sourceSetName = sourceSet.name - def taskName = sourceSet.getTaskName('generate', 'PackageInfos') - def task = project.tasks.register(taskName, GeneratePackageInfosTask) { - it.group = 'flywheel' - it.description = "Generates package-info files for $sourceSetName packages." - - // Only apply to default source directory since we also add the generated - // sources to the source set. - it.sourceRoot.set(project.file("src/$sourceSetName/java")) - it.outputDir.set(project.file("src/$sourceSetName/generatedPackageInfos")) - } - sourceSet.java.srcDir(task) - - project.tasks.named('ideaSyncTask').configure { - it.finalizedBy(task) - } - - def cleanTask = project.tasks.register(sourceSet.getTaskName('clean', 'PackageInfos'), Delete) { - it.group = 'flywheel' - it.delete(project.file("src/$sourceSetName/generatedPackageInfos")) - } - project.tasks.named('clean').configure { - it.dependsOn(cleanTask) - } - } -} diff --git a/buildSrc/src/main/groovy/com/jozufozu/gradle/PackageInfosPlugin.groovy b/buildSrc/src/main/groovy/com/jozufozu/gradle/PackageInfosPlugin.groovy deleted file mode 100644 index 8e6435d8f..000000000 --- a/buildSrc/src/main/groovy/com/jozufozu/gradle/PackageInfosPlugin.groovy +++ /dev/null @@ -1,14 +0,0 @@ -package com.jozufozu.gradle - -import groovy.transform.CompileStatic -import org.gradle.api.Plugin -import org.gradle.api.Project - -@CompileStatic -class PackageInfosPlugin implements Plugin { - @Override - void apply(Project target) { - target.extensions.create('defaultPackageInfos', PackageInfosExtension, target) - } -} - diff --git a/buildSrc/src/main/groovy/com/jozufozu/gradle/PlatformPlugin.groovy b/buildSrc/src/main/groovy/com/jozufozu/gradle/PlatformPlugin.groovy deleted file mode 100644 index 280df3024..000000000 --- a/buildSrc/src/main/groovy/com/jozufozu/gradle/PlatformPlugin.groovy +++ /dev/null @@ -1,134 +0,0 @@ -package com.jozufozu.gradle - -import groovy.transform.CompileStatic -import net.fabricmc.loom.api.LoomGradleExtensionAPI -import net.fabricmc.loom.task.RemapJarTask -import net.fabricmc.loom.task.RemapSourcesJarTask -import org.gradle.api.NamedDomainObjectProvider -import org.gradle.api.Plugin -import org.gradle.api.Project -import org.gradle.api.artifacts.Configuration -import org.gradle.api.file.FileCollection -import org.gradle.api.publish.PublishingExtension -import org.gradle.api.publish.maven.MavenPublication -import org.gradle.api.tasks.SourceSet -import org.gradle.api.tasks.SourceSetContainer -import org.gradle.api.tasks.bundling.Jar -import org.gradle.api.tasks.compile.JavaCompile -import org.gradle.api.tasks.javadoc.Javadoc -import org.gradle.language.jvm.tasks.ProcessResources - -// Couldn't get imports for loom to work in the simple .gradle file, so upgraded this to a real plugin. -@CompileStatic -class PlatformPlugin implements Plugin { - @Override - void apply(Project project) { - def commonProject = project.project(':common') - def commonSourceSets = commonProject.getExtensions().getByType(SourceSetContainer) - - def sourceSets = project.getExtensions().getByType(SourceSetContainer) - def loom = project.getExtensions().getByType(LoomGradleExtensionAPI) - def publishing = project.getExtensions().getByType(PublishingExtension) - - SourceSet platformImpl = sourceSets.named('main').get() - SourceSet platformApi = sourceSets.create('api') - SourceSet platformLib = sourceSets.create('lib') - SourceSet platformBackend = sourceSets.create('backend') - - // This is needed for both platforms. - def mainMod = loom.mods.maybeCreate('main') - mainMod.sourceSet(platformApi) - mainMod.sourceSet(platformLib) - mainMod.sourceSet(platformBackend) - mainMod.sourceSet(platformImpl) - - SourceSet commonApi = commonSourceSets.named('api').get() - SourceSet commonLib = commonSourceSets.named('lib').get() - SourceSet commonBackend = commonSourceSets.named('backend').get() - SourceSet commonImpl = commonSourceSets.named('main').get() - - def commonSources = [commonApi, commonLib, commonBackend, commonImpl] - - // Directly compile the platform sources with the common sources - includeFromCommon(project, platformApi, commonApi) - includeFromCommon(project, platformLib, commonLib) - includeFromCommon(project, platformBackend, commonBackend) - includeFromCommon(project, platformImpl, commonImpl) - - def tasks = project.tasks - - tasks.withType(JavaCompile).configureEach { JavaCompile compileJava -> - JarTaskUtils.excludeDuplicatePackageInfos(compileJava) - } - - tasks.named('jar', Jar).configure { Jar jar -> - jar.from platformApi.output, platformLib.output, platformBackend.output - - JarTaskUtils.excludeDuplicatePackageInfos(jar) - } - - tasks.named('javadoc', Javadoc).configure { Javadoc javadoc -> - commonSources.forEach { javadoc.source it.allJava } - - javadoc.source platformApi.allJava, platformLib.allJava, platformBackend.allJava - - JarTaskUtils.excludeDuplicatePackageInfos(javadoc) - } - - tasks.named('sourcesJar', Jar).configure { Jar jar -> - commonSources.forEach { jar.from it.allJava } - - jar.from platformApi.allJava, platformLib.allJava, platformBackend.allJava - - JarTaskUtils.excludeDuplicatePackageInfos(jar) - } - - def remapJar = tasks.named('remapJar', RemapJarTask) - def remapSourcesJar = tasks.named('remapSourcesJar', RemapSourcesJarTask) - def javadocJar = tasks.named('javadocJar', Jar) - - JarTaskSet apiSet = JarTaskSet.create(project, 'api', platformApi, platformLib) - - def mcVersion = project.property('artifact_minecraft_version') - - publishing.publications { - // we should be using remapped on both Fabric and Forge because Forge needs to put things in srg - it.register('mavenApi', MavenPublication) { MavenPublication pub -> - pub.artifact(apiSet.remapJar) - pub.artifact(apiSet.remapSources) - pub.artifact(apiSet.javadocJar) - - pub.artifactId = "flywheel-${project.name}-api-${mcVersion}" - } - it.register('mavenImpl', MavenPublication) { MavenPublication pub -> - pub.artifact(remapJar) - pub.artifact(remapSourcesJar) - pub.artifact(javadocJar) - pub.artifactId = "flywheel-${project.name}-${mcVersion}" - } - } - } - - static NamedDomainObjectProvider newConfiguration(Project project, String name) { - return project.configurations.register(name) { Configuration it -> - it.canBeConsumed = true - it.canBeResolved = false - } - } - - static void extendsFrom(Project project, String name, Configuration... configurations) { - project.configurations.named(name).configure { - it.extendsFrom(configurations) - } - } - - static void includeFromCommon(Project project, SourceSet sourceSet, SourceSet commonSourceSet) { - project.tasks.named(sourceSet.compileJavaTaskName, JavaCompile).configure { JavaCompile compileJava -> - compileJava.source commonSourceSet.allJava - } - - project.tasks.named(sourceSet.processResourcesTaskName, ProcessResources).configure { ProcessResources processResources -> - processResources.from commonSourceSet.resources - } - } -} diff --git a/buildSrc/src/main/kotlin/com/jozufozu/gradle/PlatformPlugin.kt b/buildSrc/src/main/kotlin/com/jozufozu/gradle/PlatformPlugin.kt new file mode 100644 index 000000000..eaa51344e --- /dev/null +++ b/buildSrc/src/main/kotlin/com/jozufozu/gradle/PlatformPlugin.kt @@ -0,0 +1,115 @@ +package com.jozufozu.gradle + +import com.jozufozu.gradle.jarset.JarTaskSet +import net.fabricmc.loom.api.LoomGradleExtensionAPI +import net.fabricmc.loom.task.RemapJarTask +import net.fabricmc.loom.task.RemapSourcesJarTask +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.api.publish.PublishingExtension +import org.gradle.api.publish.maven.MavenPublication +import org.gradle.api.tasks.SourceSet +import org.gradle.api.tasks.SourceSetContainer +import org.gradle.api.tasks.compile.JavaCompile +import org.gradle.api.tasks.javadoc.Javadoc +import org.gradle.jvm.tasks.Jar +import org.gradle.kotlin.dsl.the +import org.gradle.language.jvm.tasks.ProcessResources + +class PlatformPlugin: Plugin { + override fun apply(project: Project) { + val commonProject = project.project(":common") + val commonSourceSets = commonProject.the() + + val sourceSets = project.the() + val loom = project.the() + val publishing = project.the() + + val platformImpl = sourceSets.named("main").get() + val platformApi = sourceSets.create("api") + val platformLib = sourceSets.create("lib") + val platformBackend = sourceSets.create("backend") + + // This is needed for both platforms. + val mainMod = loom.mods.maybeCreate("main") + mainMod.sourceSet(platformApi) + mainMod.sourceSet(platformLib) + mainMod.sourceSet(platformBackend) + mainMod.sourceSet(platformImpl) + + val commonApi = commonSourceSets.named("api").get() + val commonLib = commonSourceSets.named("lib").get() + val commonBackend = commonSourceSets.named("backend").get() + val commonImpl = commonSourceSets.named("main").get() + + val commonSources = listOf(commonApi, commonLib, commonBackend, commonImpl) + + // Directly compile the platform sources with the common sources + includeFromCommon(project, platformApi, commonApi) + includeFromCommon(project, platformLib, commonLib) + includeFromCommon(project, platformBackend, commonBackend) + includeFromCommon(project, platformImpl, commonImpl) + + val tasks = project.tasks + + tasks.withType(JavaCompile::class.java).configureEach { + JarTaskSet.excludeDuplicatePackageInfos(this) + } + + tasks.named("jar", Jar::class.java).configure { + from(platformApi.output, platformLib.output, platformBackend.output) + + JarTaskSet.excludeDuplicatePackageInfos(this) + } + + tasks.named("javadoc", Javadoc::class.java).configure { + commonSources.forEach { source(it.allJava) } + + source(platformApi.allJava, platformLib.allJava, platformBackend.allJava) + + JarTaskSet.excludeDuplicatePackageInfos(this) + } + + tasks.named("sourcesJar", Jar::class.java).configure { + commonSources.forEach { from(it.allJava) } + + from(platformApi.allJava, platformLib.allJava, platformBackend.allJava) + + JarTaskSet.excludeDuplicatePackageInfos(this) + } + + val remapJar = tasks.named("remapJar", RemapJarTask::class.java) + val remapSourcesJar = tasks.named("remapSourcesJar", RemapSourcesJarTask::class.java) + val javadocJar = tasks.named("javadocJar", Jar::class.java) + + val apiSet = JarTaskSet.create(project, "api", platformApi, platformLib) + + val mcVersion = project.property("artifact_minecraft_version") + + publishing.publications { + // we should be using remapped on both Fabric and Forge because Forge needs to put things in srg + register("mavenApi", MavenPublication::class.java) { + artifact(apiSet.remapJar) + artifact(apiSet.remapSources) + artifact(apiSet.javadocJar) + artifactId = "flywheel-${project.name}-api-${mcVersion}" + } + register("mavenImpl", MavenPublication::class.java) { + artifact(remapJar) + artifact(remapSourcesJar) + artifact(javadocJar) + artifactId = "flywheel-${project.name}-${mcVersion}" + } + } + } + + private fun includeFromCommon(project: Project, sourceSet: SourceSet, commonSourceSet: SourceSet) { + project.tasks.named(sourceSet.compileJavaTaskName, JavaCompile::class.java).configure { + source(commonSourceSet.allJava) + } + + project.tasks.named(sourceSet.processResourcesTaskName, ProcessResources::class.java).configure { + from(commonSourceSet.resources) + } + } +} diff --git a/buildSrc/src/main/kotlin/com/jozufozu/gradle/jarset/JarSetExtension.kt b/buildSrc/src/main/kotlin/com/jozufozu/gradle/jarset/JarSetExtension.kt new file mode 100644 index 000000000..f20fcd881 --- /dev/null +++ b/buildSrc/src/main/kotlin/com/jozufozu/gradle/jarset/JarSetExtension.kt @@ -0,0 +1,16 @@ +package com.jozufozu.gradle.jarset + +import org.gradle.api.Project +import org.gradle.api.tasks.SourceSet +import org.gradle.api.tasks.SourceSetContainer +import org.gradle.kotlin.dsl.the + +open class JarSetExtension(val project: Project) { + fun createJars(name: String): JarTaskSet { + return createJars(name, project.the().named(name).get()) + } + + fun createJars(name: String, vararg sourceSetSet: SourceSet): JarTaskSet { + return JarTaskSet.create(project, name, *sourceSetSet) + } +} diff --git a/buildSrc/src/main/kotlin/com/jozufozu/gradle/jarset/JarSetPlugin.kt b/buildSrc/src/main/kotlin/com/jozufozu/gradle/jarset/JarSetPlugin.kt new file mode 100644 index 000000000..a1895b440 --- /dev/null +++ b/buildSrc/src/main/kotlin/com/jozufozu/gradle/jarset/JarSetPlugin.kt @@ -0,0 +1,10 @@ +package com.jozufozu.gradle.jarset + +import org.gradle.api.Plugin +import org.gradle.api.Project + +class JarSetPlugin: Plugin { + override fun apply(target: Project) { + target.extensions.create("jarSets", JarSetExtension::class.java, target) + } +} diff --git a/buildSrc/src/main/kotlin/com/jozufozu/gradle/jarset/JarTaskSet.kt b/buildSrc/src/main/kotlin/com/jozufozu/gradle/jarset/JarTaskSet.kt new file mode 100644 index 000000000..c3278217d --- /dev/null +++ b/buildSrc/src/main/kotlin/com/jozufozu/gradle/jarset/JarTaskSet.kt @@ -0,0 +1,138 @@ +package com.jozufozu.gradle.jarset + +import net.fabricmc.loom.task.RemapJarTask +import net.fabricmc.loom.task.RemapSourcesJarTask +import org.gradle.api.Action +import org.gradle.api.Project +import org.gradle.api.file.DuplicatesStrategy +import org.gradle.api.tasks.AbstractCopyTask +import org.gradle.api.tasks.SourceSet +import org.gradle.api.tasks.SourceTask +import org.gradle.api.tasks.TaskProvider +import org.gradle.api.tasks.javadoc.Javadoc +import org.gradle.jvm.tasks.Jar + +class JarTaskSet( + val project: Project, + val name: String, + val jar: TaskProvider, + val remapJar: TaskProvider, + val sources: TaskProvider, + val remapSources: TaskProvider, + val javadocJar: TaskProvider +) { + + fun createOutgoingConfiguration(prefix: String) { + val config = project.configurations.register("${prefix}${name.capitalize()}") { + isCanBeConsumed = true + isCanBeResolved = false + } + + project.artifacts.add(config.name, jar) + } + + fun configure(action: Action) { + action.execute(this) + } + + fun configureEach(action: Action) { + jar.configure(action) + sources.configure(action) + javadocJar.configure(action) + + remapJar.configure(action) + remapSources.configure(action) + } + + companion object { + private const val PACKAGE_INFOS_JAVA_PATTERN = "**/package-info.java" + private const val BUILD_GROUP: String = "build" + private const val LOOM_GROUP: String = "loom" + private const val JAVADOC_CLASSIFIER: String = "javadoc" + private const val SOURCES_CLASSIFIER: String = "sources" + + /** + * We have duplicate packages between the common and platform dependent subprojects. + * In theory the package-info.java files should be identical, so just take the first one we find. + */ + fun excludeDuplicatePackageInfos(copyTask: AbstractCopyTask) { + copyTask.filesMatching(PACKAGE_INFOS_JAVA_PATTERN) { + duplicatesStrategy = DuplicatesStrategy.EXCLUDE + } + } + + /** + * The compile/javadoc tasks have a different base type that isn't so smart about exclusion handling. + */ + fun excludeDuplicatePackageInfos(sourceTask: SourceTask) { + sourceTask.exclude(PACKAGE_INFOS_JAVA_PATTERN) + } + + fun create(project: Project, name: String, vararg sourceSetSet: SourceSet): JarTaskSet { + val buildDirectory = project.layout.buildDirectory + val devlibs = buildDirectory.dir("devlibs/${name}") + val libs = buildDirectory.dir("libs/${name}") + + val jarTask = project.tasks.register("${name}Jar", Jar::class.java) { + group = BUILD_GROUP + destinationDirectory.set(devlibs) + + for (set in sourceSetSet) { + from(set.output) + } + excludeDuplicatePackageInfos(this) + } + val remapJarTask = project.tasks.register("${name}RemapJar", RemapJarTask::class.java) { + dependsOn(jarTask) + group = LOOM_GROUP + destinationDirectory.set(libs) + + inputFile.set(jarTask.flatMap { it.archiveFile }) + } + val sourcesTask = project.tasks.register("${name}SourcesJar", Jar::class.java) { + group = BUILD_GROUP + destinationDirectory.set(devlibs) + archiveClassifier.set(SOURCES_CLASSIFIER) + + for (set in sourceSetSet) { + from(set.allSource) + } + excludeDuplicatePackageInfos(this) + } + val remapSourcesTask = project.tasks.register("${name}RemapSourcesJar", RemapSourcesJarTask::class.java) { + dependsOn(sourcesTask) + group = LOOM_GROUP + destinationDirectory.set(libs) + archiveClassifier.set(SOURCES_CLASSIFIER) + + inputFile.set(sourcesTask.flatMap { it.archiveFile }) + } + val javadocTask = project.tasks.register("${name}Javadoc", Javadoc::class.java) { + group = BUILD_GROUP + setDestinationDir(buildDirectory.dir("docs/${name}-javadoc").get().asFile) + options.encoding = "UTF-8" + options.optionFiles(project.rootProject.file("javadoc-options.txt")) + + for (set in sourceSetSet) { + source(set.allJava) + classpath += set.compileClasspath + } + excludeDuplicatePackageInfos(this) + } + val javadocJarTask = project.tasks.register("${name}JavadocJar", Jar::class.java) { + dependsOn(javadocTask) + group = BUILD_GROUP + destinationDirectory.set(libs) + archiveClassifier.set(JAVADOC_CLASSIFIER) + + from(javadocTask.map { it.outputs }) + } + + project.tasks.named("assemble").configure { + dependsOn(remapJarTask, remapSourcesTask, javadocJarTask) + } + + return JarTaskSet(project, name, jarTask, remapJarTask, sourcesTask, remapSourcesTask, javadocJarTask) + } + } +} diff --git a/buildSrc/src/main/kotlin/com/jozufozu/gradle/nullability/GeneratePackageInfosTask.kt b/buildSrc/src/main/kotlin/com/jozufozu/gradle/nullability/GeneratePackageInfosTask.kt new file mode 100644 index 000000000..fbe7698cb --- /dev/null +++ b/buildSrc/src/main/kotlin/com/jozufozu/gradle/nullability/GeneratePackageInfosTask.kt @@ -0,0 +1,58 @@ +package com.jozufozu.gradle.nullability + +import org.apache.groovy.nio.extensions.NioExtensions +import org.codehaus.groovy.runtime.StringGroovyMethods +import org.gradle.api.DefaultTask +import org.gradle.api.file.DirectoryProperty +import org.gradle.api.tasks.InputDirectory +import org.gradle.api.tasks.OutputDirectory +import org.gradle.api.tasks.SkipWhenEmpty +import org.gradle.api.tasks.TaskAction +import org.gradle.kotlin.dsl.closureOf +import java.io.BufferedWriter +import java.io.File +import java.nio.file.Files +import java.nio.file.Path + +// Adapted from https://github.com/FabricMC/fabric/blob/31787236d242247e0b6c4ae806b1cfaa7042a62c/gradle/package-info.gradle, which is licensed under Apache 2.0. +open class GeneratePackageInfosTask: DefaultTask() { + @SkipWhenEmpty + @InputDirectory + val sourceRoot: DirectoryProperty = project.objects.directoryProperty() + + @OutputDirectory + val outputDir: DirectoryProperty = project.objects.directoryProperty() + + @TaskAction + fun run() { + val output = outputDir.get().asFile.toPath() + NioExtensions.deleteDir(output) + val root = sourceRoot.get().asFile.toPath() + + NioExtensions.eachDirRecurse(root, closureOf { + val containsJava = Files.list(this).anyMatch { + Files.isRegularFile(it) && it.fileName.toString().endsWith(".java") + } + + if (containsJava && Files.notExists(resolve("package-info.java"))) { + val relativePath = root.relativize(this) + val target = output.resolve(relativePath) + Files.createDirectories(target) + + NioExtensions.withWriter(target.resolve("package-info.java"), closureOf { + val packageName = relativePath.toString().replace(File.separator, ".") + write(StringGroovyMethods.stripMargin("""@ParametersAreNonnullByDefault + |@FieldsAreNonnullByDefault + |@MethodsReturnNonnullByDefault + |package $packageName; + | + |import javax.annotation.ParametersAreNonnullByDefault; + | + |import net.minecraft.FieldsAreNonnullByDefault; + |import net.minecraft.MethodsReturnNonnullByDefault; + |""")) + }) + } + }) + } +} diff --git a/buildSrc/src/main/kotlin/com/jozufozu/gradle/nullability/PackageInfosExtension.kt b/buildSrc/src/main/kotlin/com/jozufozu/gradle/nullability/PackageInfosExtension.kt new file mode 100644 index 000000000..b32783ef9 --- /dev/null +++ b/buildSrc/src/main/kotlin/com/jozufozu/gradle/nullability/PackageInfosExtension.kt @@ -0,0 +1,42 @@ +package com.jozufozu.gradle.nullability + +import org.gradle.api.Project +import org.gradle.api.tasks.Delete +import org.gradle.api.tasks.SourceSet + +open class PackageInfosExtension(private val project: Project) { + fun forSourceSets(vararg sourceSets: SourceSet) { + for (sourceSet in sourceSets) { + forSourceSet(sourceSet) + } + } + + private fun forSourceSet(sourceSet: SourceSet) { + // We have to capture the source set name for the lazy string literals, + // otherwise it'll just be whatever the last source set is in the list. + val sourceSetName = sourceSet.name + val taskName = sourceSet.getTaskName("generate", "PackageInfos") + val task = project.tasks.register(taskName, GeneratePackageInfosTask::class.java) { + group = "flywheel" + description = "Generates package-info files for $sourceSetName packages." + + // Only apply to default source directory since we also add the generated + // sources to the source set. + sourceRoot.set(project.file("src/$sourceSetName/java")) + outputDir.set(project.file("src/$sourceSetName/generatedPackageInfos")) + } + sourceSet.java.srcDir(task) + + project.tasks.named("ideaSyncTask").configure { + finalizedBy(task) + } + + val cleanTask = project.tasks.register(sourceSet.getTaskName("clean", "PackageInfos"), Delete::class.java) { + group = "flywheel" + delete(project.file("src/$sourceSetName/generatedPackageInfos")) + } + project.tasks.named("clean").configure { + dependsOn(cleanTask) + } + } +} diff --git a/buildSrc/src/main/kotlin/com/jozufozu/gradle/nullability/PackageInfosPlugin.kt b/buildSrc/src/main/kotlin/com/jozufozu/gradle/nullability/PackageInfosPlugin.kt new file mode 100644 index 000000000..8c50240f0 --- /dev/null +++ b/buildSrc/src/main/kotlin/com/jozufozu/gradle/nullability/PackageInfosPlugin.kt @@ -0,0 +1,10 @@ +package com.jozufozu.gradle.nullability + +import org.gradle.api.Plugin +import org.gradle.api.Project + +class PackageInfosPlugin: Plugin { + override fun apply(target: Project) { + target.extensions.create("defaultPackageInfos", PackageInfosExtension::class.java, target) + } +} diff --git a/buildSrc/src/main/kotlin/com/jozufozu/gradle/TransitiveSourceSetConfigurator.kt b/buildSrc/src/main/kotlin/com/jozufozu/gradle/transitive/TransitiveSourceSetConfigurator.kt similarity index 96% rename from buildSrc/src/main/kotlin/com/jozufozu/gradle/TransitiveSourceSetConfigurator.kt rename to buildSrc/src/main/kotlin/com/jozufozu/gradle/transitive/TransitiveSourceSetConfigurator.kt index f105246da..f91dc56a4 100644 --- a/buildSrc/src/main/kotlin/com/jozufozu/gradle/TransitiveSourceSetConfigurator.kt +++ b/buildSrc/src/main/kotlin/com/jozufozu/gradle/transitive/TransitiveSourceSetConfigurator.kt @@ -1,4 +1,4 @@ -package com.jozufozu.gradle +package com.jozufozu.gradle.transitive import org.gradle.api.tasks.SourceSet diff --git a/buildSrc/src/main/kotlin/com/jozufozu/gradle/TransitiveSourceSetsExtension.kt b/buildSrc/src/main/kotlin/com/jozufozu/gradle/transitive/TransitiveSourceSetsExtension.kt similarity index 98% rename from buildSrc/src/main/kotlin/com/jozufozu/gradle/TransitiveSourceSetsExtension.kt rename to buildSrc/src/main/kotlin/com/jozufozu/gradle/transitive/TransitiveSourceSetsExtension.kt index 817c9d93b..020234cc5 100644 --- a/buildSrc/src/main/kotlin/com/jozufozu/gradle/TransitiveSourceSetsExtension.kt +++ b/buildSrc/src/main/kotlin/com/jozufozu/gradle/transitive/TransitiveSourceSetsExtension.kt @@ -1,4 +1,4 @@ -package com.jozufozu.gradle +package com.jozufozu.gradle.transitive import org.gradle.api.Action import org.gradle.api.Project diff --git a/buildSrc/src/main/kotlin/com/jozufozu/gradle/TransitiveSourceSetsPlugin.kt b/buildSrc/src/main/kotlin/com/jozufozu/gradle/transitive/TransitiveSourceSetsPlugin.kt similarity index 87% rename from buildSrc/src/main/kotlin/com/jozufozu/gradle/TransitiveSourceSetsPlugin.kt rename to buildSrc/src/main/kotlin/com/jozufozu/gradle/transitive/TransitiveSourceSetsPlugin.kt index 2f00416a8..8eb33eec6 100644 --- a/buildSrc/src/main/kotlin/com/jozufozu/gradle/TransitiveSourceSetsPlugin.kt +++ b/buildSrc/src/main/kotlin/com/jozufozu/gradle/transitive/TransitiveSourceSetsPlugin.kt @@ -1,4 +1,4 @@ -package com.jozufozu.gradle +package com.jozufozu.gradle.transitive import org.gradle.api.Plugin import org.gradle.api.Project