buildscript{ ext{ arcHash = property("archash") localArc = !project.hasProperty("release") && new File(rootDir.parent, 'Arc').exists() && !project.hasProperty("noLocalArc") arcModule = { String name -> //skip to last submodule name = name.substring(name.lastIndexOf(':') + 1) return "com.github.Anuken${localArc ? "" : ".Arc"}:$name:$arcHash" } } repositories{ mavenLocal() mavenCentral() google() maven{ url "https://oss.sonatype.org/content/repositories/snapshots/" } maven{ url 'https://jitpack.io' } } dependencies{ classpath arcModule(":extensions:packer") classpath arcModule(":arc-core") } } plugins{ id "org.jetbrains.kotlin.jvm" version "1.6.0" id "org.jetbrains.kotlin.kapt" version "1.6.0" } allprojects{ apply plugin: 'maven-publish' version = project.hasProperty("packageVersion") ? project.getProperty("packageVersion") : 'release' group = 'com.github.Anuken' ext{ versionNumber = '7' if(!project.hasProperty("versionModifier")) versionModifier = 'release' if(!project.hasProperty("versionType")) versionType = 'official' appName = 'Mindustry' steamworksVersion = '0b86023401880bb5e586bc404bedbaae9b1f1c94' rhinoVersion = '73a812444ac388ac2d94013b5cadc8f70b7ea027' loadVersionProps = { return new Properties().with{p -> p.load(file('../core/assets/version.properties').newReader()); return p } } debugged = { return new File(projectDir.parent, '../Mindustry-Debug').exists() && !project.hasProperty("release") && project.hasProperty("args") } generateDeployName = { String platform -> if(platform == "windows"){ platform += "64" } platform = platform.capitalize() if(platform.endsWith("64") || platform.endsWith("32")){ platform = "${platform.substring(0, platform.length() - 2)}-${platform.substring(platform.length() - 2)}bit" } return "[${platform}]${getModifierString()}[${getNeatVersionString()}]${appName}" } getVersionString = { String buildVersion = getBuildVersion() return "$versionNumber-$versionModifier-$buildVersion" } getNeatVersionString = { String buildVersion = getBuildVersion() return "v$buildVersion" } hasSprites = { return new File(rootDir, "core/assets/sprites/sprites.aatls").exists() } getModifierString = { if(versionModifier != "release") return "[${versionModifier.toUpperCase()}]" return "" } getBuildVersion = { if(!project.hasProperty("buildversion")) return "custom build" return project.getProperties()["buildversion"] } getPackage = { return project.ext.mainClassName.substring(0, project.ext.mainClassName.indexOf("desktop") - 1) } findSdkDir = { //null because IntelliJ doesn't get env variables def v = System.getenv("ANDROID_HOME") if(v != null) return v //rootDir is null here, amazing. brilliant. def file = new File(rootDir, "local.properties") def props = new Properties().with{p -> p.load(file.newReader()); return p } return props.get("sdk.dir") } generateLocales = { def output = 'en\n' def bundles = new File(project(':core').projectDir, 'assets/bundles/') bundles.list().sort().each{ name -> if(name == "bundle.properties") return output += name.substring("bundle".length() + 1, name.lastIndexOf('.')) + "\n" } new File(project(':core').projectDir, 'assets/locales').text = output new File(project(':core').projectDir, 'assets/basepartnames').text = new File(project(':core').projectDir, 'assets/baseparts/').list().sort().join("\n") } writeVersion = { def pfile = new File(project(':core').projectDir, 'assets/version.properties') def props = new Properties() try{ pfile.createNewFile() }catch(Exception ignored){ } if(pfile.exists()){ props.load(new FileInputStream(pfile)) String buildid = getBuildVersion() println("Compiling with build: '$buildid'") props["type"] = versionType props["number"] = versionNumber props["modifier"] = versionModifier props["build"] = buildid props.store(pfile.newWriter(), "Autogenerated file. Do not modify.") } } writeProcessors = { new File(rootDir, "annotations/src/main/resources/META-INF/services/").mkdirs() def processorFile = new File(rootDir, "annotations/src/main/resources/META-INF/services/javax.annotation.processing.Processor") def text = new StringBuilder() def files = new File(rootDir, "annotations/src/main/java") files.eachFileRecurse(groovy.io.FileType.FILES){ file -> if(file.name.endsWith(".java") && (file.text.contains(" extends BaseProcessor") || (file.text.contains(" extends AbstractProcessor") && !file.text.contains("abstract class")))){ text.append(file.path.substring(files.path.length() + 1)).append("\n") } } processorFile.text = text.toString().replace(".java", "").replace("/", ".").replace("\\", ".") } writePlugins = { new File(rootDir, "annotations/src/main/resources/META-INF/services/").mkdirs() def processorFile = new File(rootDir, "annotations/src/main/resources/META-INF/services/com.sun.source.util.Plugin") def text = new StringBuilder() def files = new File(rootDir, "annotations/src/main/java") files.eachFileRecurse(groovy.io.FileType.FILES){ file -> if(file.name.endsWith(".java") && (file.text.contains(" implements Plugin"))){ text.append(file.path.substring(files.path.length() + 1)).append("\n") } } processorFile.text = text.toString().replace(".java", "").replace("/", ".").replace("\\", ".") } } repositories{ mavenLocal() mavenCentral() maven{ url "https://oss.sonatype.org/content/repositories/snapshots/" } maven{ url "https://oss.sonatype.org/content/repositories/releases/" } maven{ url 'https://jitpack.io' } } task clearCache{ doFirst{ delete{ delete "$rootDir/core/assets/cache" } } } tasks.withType(JavaCompile){ targetCompatibility = 8 sourceCompatibility = JavaVersion.VERSION_17 options.encoding = "UTF-8" options.compilerArgs += ["-Xlint:deprecation"] dependsOn clearCache options.forkOptions.jvmArgs += [ '--add-opens=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED', '--add-opens=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED', '--add-opens=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED', '--add-opens=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED', '--add-opens=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED', '--add-opens=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED', '--add-opens=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED', '--add-opens=java.base/sun.reflect.annotation=ALL-UNNAMED' ] } } configure(project(":annotations")){ tasks.withType(JavaCompile){ targetCompatibility = 8 sourceCompatibility = 8 options.fork = true } } //compile with java 8 compatibility for everything except the annotation project configure(subprojects - project(":annotations")){ tasks.withType(JavaCompile){ options.compilerArgs.addAll(['--release', '8']) } tasks.withType(Javadoc){ options{ addStringOption('Xdoclint:none', '-quiet') addStringOption('-release', '16') encoding('UTF-8') } } } project(":desktop"){ apply plugin: "java" compileJava.options.fork = true dependencies{ implementation project(":core") implementation arcModule("extensions:discord") implementation arcModule("natives:natives-filedialogs") implementation arcModule("natives:natives-desktop") implementation arcModule("natives:natives-freetype-desktop") if(debugged()) implementation project(":debug") implementation "com.github.Anuken:steamworks4j:$steamworksVersion" implementation arcModule("backends:backend-sdl") } } project(":core"){ apply plugin: "java-library" apply plugin: "kotlin" apply plugin: "kotlin-kapt" kapt{ javacOptions{ option("-source", "16") option("-target", "1.8") } } compileJava.options.fork = true task preGen{ outputs.upToDateWhen{ false } generateLocales() writeVersion() writeProcessors() writePlugins() } task copyChangelog{ doLast{ def props = loadVersionProps() def androidVersion = props['androidBuildCode'].toInteger() - 2 def loglines = file("../changelog").text.split("\n") def notice = "[This is a truncated changelog, see Github for full notes]" def maxLength = 460 def androidLogList = [notice] + loglines.findAll{ line -> !line.endsWith("]") || line.endsWith("[Mobile]") || line.endsWith("[Android]")} def result = "" androidLogList.forEach{line -> if(result.length() + line.length() + 1 < maxLength){ result += line + "\n" } } def changelogs = file("../fastlane/metadata/android/en-US/changelogs/") changelogs.mkdirs() try{ new File(changelogs, androidVersion + ".txt").text = (result) }catch(Exception ignored){ } } } task sourcesJar(type: Jar, dependsOn: classes){ archiveClassifier = 'sources' from sourceSets.main.allSource } task assetsJar(type: Jar, dependsOn: ":tools:pack"){ archiveClassifier = 'assets' from files("assets"){ exclude "config", "cache", "music", "sounds" } } task musicJar(type: Jar){ archiveClassifier = 'music' from files("assets"){ include "music/*", "sounds/*" } } dependencies{ compileJava.dependsOn(preGen) api "org.lz4:lz4-java:1.8.0" api arcModule("arc-core") api arcModule("extensions:flabel") api arcModule("extensions:freetype") api arcModule("extensions:g3d") api arcModule("extensions:fx") api arcModule("extensions:arcnet") implementation arcModule("extensions:filedialogs") api "com.github.Anuken:rhino:$rhinoVersion" if(localArc && debugged()) api arcModule("extensions:recorder") if(localArc) api arcModule(":extensions:packer") annotationProcessor 'com.github.Anuken:jabel:0.9.0' compileOnly project(":annotations") if(!project.hasProperty("noKapt")) kapt project(":annotations") } afterEvaluate{ task mergedJavadoc(type: Javadoc){ def blacklist = [project(":ios"), project(":desktop"), project(":server"), project(":annotations")] if(findProject(":android") != null){ blacklist += project(":android") } source rootProject.subprojects.collect{ project -> if(!blacklist.contains(project) && project.hasProperty("sourceSets")){ return project.sourceSets.main.allJava } } classpath = files(rootProject.subprojects.collect { project -> if(!blacklist.contains(project) && project.hasProperty("sourceSets")){ return project.sourceSets.main.compileClasspath } }) destinationDir = new File(buildDir, 'javadoc') } } gradle.taskGraph.whenReady{ //these are completely unnecessary tasks.kaptGenerateStubsKotlin.onlyIf{ false } tasks.compileKotlin.onlyIf{ false } tasks.inspectClassesForKotlinIC.onlyIf{ false } } //comp** classes are only used for code generation jar{ exclude("mindustry/entities/comp/**") } } project(":server"){ apply plugin: "java" dependencies{ implementation project(":core") implementation arcModule("backends:backend-headless") } } project(":tests"){ apply plugin: "java" dependencies{ testImplementation project(":core") testImplementation "org.junit.jupiter:junit-jupiter-params:5.7.1" testImplementation "org.junit.jupiter:junit-jupiter-api:5.7.1" testImplementation arcModule("backends:backend-headless") testImplementation "org.json:json:20230618" testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:5.7.1" } test{ //fork every test so mods don't interact with each other forkEvery = 1 useJUnitPlatform() workingDir = new File("../core/assets") testLogging{ exceptionFormat = 'full' showStandardStreams = true } } } project(":tools"){ apply plugin: "java" dependencies{ implementation project(":core") implementation arcModule("natives:natives-desktop") implementation arcModule("natives:natives-freetype-desktop") implementation arcModule("backends:backend-headless") } } project(":annotations"){ apply plugin: "java-library" dependencies{ implementation 'com.squareup:javapoet:1.12.1' implementation arcModule("arc-core") } } configure([":core", ":server"].collect{project(it)}){ java{ withJavadocJar() withSourcesJar() } publishing{ publications{ maven(MavenPublication){ from components.java if(project.name == "core"){ artifact(tasks.named("assetsJar")) } } } } } task deployAll{ task cleanDeployOutput{ doFirst{ if(getBuildVersion() == "custom build" || getBuildVersion() == "") throw new IllegalArgumentException("----\n\nSET A BUILD NUMBER FIRST!\n\n----") if(!project.hasProperty("release")) throw new IllegalArgumentException("----\n\nSET THE RELEASE PROJECT PROPERTY FIRST!\n\n----") delete{ delete "deploy/" } } } dependsOn cleanDeployOutput dependsOn "desktop:packrLinux64" dependsOn "desktop:packrWindows64" dependsOn "desktop:packrWindows32" dependsOn "desktop:packrMacOS" if(versionModifier != "steam"){ dependsOn "server:deploy" dependsOn "android:deploy" } } task resolveDependencies{ doLast{ rootProject.allprojects{ project -> Set configurations = project.buildscript.configurations + project.configurations configurations.findAll{c -> c.canBeResolved}.forEach{c -> c.resolve()} } } }