buildscript { repositories { mavenCentral() } dependencies { // used at configuration-time for version info classpath 'org.eclipse.jgit:org.eclipse.jgit:5.7.+' classpath "javax.inject:javax.inject:1" } } plugins { id 'java' id 'antlr' id 'eclipse' id 'idea' id 'jacoco' id 'maven-publish' id 'com.github.kt3k.coveralls' version '2.12.2' id 'com.gradleup.shadow' version '9.2.2' id 'de.undercouch.download' version '5.6.0' } import de.undercouch.gradle.tasks.download.Download import java.util.regex.Pattern ext.mainClassName = "de.peeeq.wurstio.Main" version = "1.9.0.0" java { toolchain { languageVersion = JavaLanguageVersion.of(25) } } def toolchainSvc = extensions.getByType(JavaToolchainService) def j25Launcher = toolchainSvc.launcherFor(java.toolchain) tasks.withType(JavaExec).configureEach { javaLauncher.set(j25Launcher) } tasks.withType(JavaCompile).configureEach { options.release = 25 } jacoco { toolVersion = "0.8.13" } tasks.named("jacocoTestReport", JacocoReport) { dependsOn(tasks.named("test")) reports { xml.required.set(true) } def excluded = ['**/ast/**', '**/jassAst/**', '**/jassIm/**', '**/luaAst/**', '**/antlr/**'] classDirectories.setFrom( files(classDirectories.files.collect { dir -> fileTree(dir: dir, exclude: excluded) }) ) } def genDir = "$projectDir/src-gen" sourceSets { main { java.srcDir(genDir) } } repositories { mavenLocal() mavenCentral() maven { url 'https://jitpack.io' } } configurations { // isolated classpath for the generator astgen } dependencies { implementation 'org.jetbrains:annotations:23.0.0' // Antlr antlr "org.antlr:antlr4:4.13.1" // abstractsyntaxgen (available to IDE via compileOnly; used at runtime via astgen) compileOnly 'com.github.peterzeller:abstractsyntaxgen:623da1c60f' astgen 'com.github.peterzeller:abstractsyntaxgen:623da1c60f' // Tests testImplementation 'org.testng:testng:7.11.0' testImplementation 'org.hamcrest:hamcrest-all:1.3' // Libs implementation 'com.google.guava:guava:32.1.3-jre' implementation 'io.vavr:vavr:0.10.7' implementation 'org.eclipse.lsp4j:org.eclipse.lsp4j:0.24.0' implementation 'org.eclipse.jdt:org.eclipse.jdt.annotation:2.1.0' implementation 'com.google.code.gson:gson:2.10.1' implementation 'org.apache.velocity:velocity:1.7' implementation 'com.github.albfernandez:juniversalchardet:2.4.0' implementation 'com.github.inwc3:jmpq3:29b55f2c32' implementation 'com.github.inwc3:wc3libs:bab65b961b' implementation 'com.github.wurstscript:wurstsetup:393cf5ea39' implementation 'org.slf4j:slf4j-api:2.0.17' implementation 'ch.qos.logback:logback-classic:1.5.20' implementation 'org.eclipse.jgit:org.eclipse.jgit:6.7.0.202309050840-r' implementation 'org.eclipse.jgit:org.eclipse.jgit.ssh.apache:6.7.0.202309050840-r' implementation 'it.unimi.dsi:fastutil:8.5.16' // Smallcheck testImplementation 'com.github.peterzeller:java-smallcheck:3f6a178ba7' } configurations.configureEach { exclude group: "org.slf4j", module: "slf4j-log4j12" exclude group: "log4j", module: "log4j" } /** -------- AST generation (abstractsyntaxgen) -------- */ def parseqFiles = fileTree(dir: 'parserspec', include: '*.parseq') def pkgPattern = Pattern.compile(/package\s+(\S+)\s*;/) // resolve once at configuration time def genDirFile = file(genDir) def astgenCp = configurations.astgen def pkgPatternLocal = pkgPattern def perFileTasks = [] parseqFiles.files.each { File f -> // determine package at configuration time (same logic you had) String contents = f.getText('UTF-8') def m = pkgPatternLocal.matcher(contents) String pkg = m.find() ? m.group(1) : "" File targetDir = new File(genDirFile, pkg.replace('.', '/')) def t = tasks.register("genAst_${f.name.replaceAll(/[^A-Za-z0-9_]/, '_')}", JavaExec) { // incremental + cache correctness for the generator inputs.file(f) inputs.files(astgenCp).withPropertyName("astgenClasspath") outputs.dir(targetDir) classpath = astgenCp mainClass.set("asg.Main") args(f.absolutePath, targetDir.absolutePath) // optional: ensure target dir exists doFirst { targetDir.mkdirs() } } perFileTasks << t } tasks.register("genAst") { inputs.files(parseqFiles) outputs.dir(genDirFile) dependsOn(perFileTasks) } /** -------- Version info file generation -------- */ tasks.register('versionInfoFile') { description "Generates a file CompileTimeInfo.java with version number etc." def repoDir = new File(rootProject.projectDir, '..') def dir = new File("$genDir/de/peeeq/wurstscript/") def out = new File(dir, 'CompileTimeInfo.java') outputs.file(out) // capture at configuration time (no Task.project usage later) def versionString = project.version.toString() // Inputs so the task reruns when metadata changes: // - project version changes inputs.property("projectVersion", versionString) // - HEAD changes (branch updates) inputs.file(new File(repoDir, ".git/HEAD")).withPropertyName("gitHeadRef") // - branch ref changes (only for branch-based HEAD; harmless if missing) inputs.files(fileTree(new File(repoDir, ".git/refs"))).withPropertyName("gitRefs") // - tags move / new tags (for git describe --tags) inputs.files(fileTree(new File(repoDir, ".git/refs/tags"))).withPropertyName("gitTags") // - working tree dirtiness affects "--dirty" inputs.file(new File(repoDir, ".git/index")).optional().withPropertyName("gitIndex") doLast { def rev8 = ["git", "rev-parse", "--short=8", "HEAD"].execute(null, repoDir).text.trim() def revLong = ["git", "rev-parse", "HEAD"].execute(null, repoDir).text.trim() def tag = ["git", "describe", "--tags", "--always"].execute(null, repoDir).text.trim() def wurstVersion = "${versionString}-${tag}" dir.mkdirs() out.text = """ package de.peeeq.wurstscript; public class CompileTimeInfo { public static final String revision="${rev8}"; public static final String revisionLong="${revLong}"; public static final String version="${wurstVersion}"; } """ } } /** -------- Aggregate generation + wiring into compile -------- */ tasks.register('gen') { description "Generates code from various input files" dependsOn 'genAst', 'versionInfoFile', 'generateGrammarSource' } tasks.named('compileJava') { it.dependsOn('gen') } /** -------- Tests -------- */ test { useTestNG() jvmArgs( '-Xmx2g', // local: give it room to finish and dump '-XX:MaxMetaspaceSize=256m', '-XX:+HeapDumpOnOutOfMemoryError', ) } /** -------- Clean generated sources -------- */ tasks.named('clean') { doFirst { delete genDir } } /** -------- Download helpers -------- */ tasks.register('downloadZipFile', Download) { src 'https://github.com/wurstscript/wurstStdlib2/archive/master.zip' dest new File(buildDir, 'stdlib2.zip') } tasks.register('downloadAndUnzipFile', Copy) { dependsOn 'downloadZipFile' from zipTree(tasks.named('downloadZipFile').get().dest) into new File(buildDir, '/deps/') } /** -------- Shadow / packaging -------- */ shadowJar { archiveBaseName.set('wurstscript') archiveClassifier.set('') archiveVersion.set('') manifest { attributes 'Main-Class': mainClassName } } def fatJar = shadowJar.archiveFile.map { it.asFile } tasks.register('make_for_userdir', Copy) { dependsOn 'shadowJar' from fatJar into "${System.properties['user.home']}/.wurst/" } tasks.register('make_for_wurstpack', Copy) { dependsOn 'shadowJar' from fatJar into '../Wurstpack/wurstscript/' } tasks.register('create_zip_wurstpack_complete', Zip) { dependsOn 'make_for_wurstpack' from '../Wurstpack' archiveFileName.set('wurstpack_complete.zip') } tasks.register('create_zip_wurstpack_compiler', Zip) { dependsOn 'make_for_wurstpack' from '../Wurstpack/wurstscript/' archiveFileName.set('wurstpack_compiler.zip') } tasks.register('create_zips') { dependsOn 'shadowJar', 'create_zip_wurstpack_complete', 'create_zip_wurstpack_compiler' doLast { ExecOperations execOps = project.services.get(ExecOperations) mkdir("../downloads/") copy { from fatJar.get() into '../downloads/' } copy { from '../Wurstpack' into '../downloads/Wurstpack/' } copy { from '../WurstSetup/build/libs/WurstSetup.jar' into '../downloads/' } mkdir("../Checksums/bin") execOps.javaexec { classpath = sourceSets.main.runtimeClasspath mainClass.set('de.peeeq.wurstio.Checksums') args("../downloads/Wurstpack/", "../downloads/wurstpack.md5") } } } /** -------- Hotdoc generation -------- */ tasks.register('generate_hotdoc') { dependsOn 'compileJava', 'downloadAndUnzipFile' doLast { ExecOperations execOps = project.services.get(ExecOperations) copy { from("src/main/resources/") // Gradle 9 output classes dir into("build/classes/java/main/") } execOps.javaexec { classpath = sourceSets.main.runtimeClasspath mainClass.set('de.peeeq.wurstio.Main') args("--hotdoc", "./build/deps/", "../downloads/hotdoc") } } } tasks.named("coveralls") { notCompatibleWithConfigurationCache("coveralls plugin task uses Project at execution time") } /** -------- Apply deployment settings -------- */ apply from: 'deploy.gradle'