Automatically inject dependencies into eclipse classpath
This commit is contained in:
1 parent
162f44ad94
commit
58717bc355
6 files changed
+203
-33
No files matched your search
@@ -7,3 +7,6 @@
|
|||||||
[submodule "libs/DiamondBank-OG"]
|
[submodule "libs/DiamondBank-OG"]
|
||||||
path = libs/DiamondBank-OG
|
path = libs/DiamondBank-OG
|
||||||
url = https://github.com/true-og/DiamondBank-OG
|
url = https://github.com/true-og/DiamondBank-OG
|
||||||
|
[submodule "libs/Chat-OG"]
|
||||||
|
path = libs/Chat-OG
|
||||||
|
url = https://github.com/true-og/Chat-OG
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
Template-OG but with Kotlin examples.
|
Template-OG but with Kotlin examples.
|
||||||
|
|
||||||
Gradle Version: 8.14.2
|
Gradle Version: 8.14.3
|
||||||
|
|
||||||
Java Version: 17
|
Java Version: 17
|
||||||
|
|
||||||
|
|||||||
+188
-19
@@ -1,16 +1,26 @@
|
|||||||
|
/* This is free and unencumbered software released into the public domain*/
|
||||||
|
|
||||||
|
import java.nio.file.Files
|
||||||
|
import javax.xml.parsers.DocumentBuilderFactory
|
||||||
|
import javax.xml.transform.OutputKeys
|
||||||
|
import javax.xml.transform.TransformerFactory
|
||||||
|
import javax.xml.transform.dom.DOMSource
|
||||||
|
import javax.xml.transform.stream.StreamResult
|
||||||
|
|
||||||
|
/* ------------------------------ Plugins ------------------------------ */
|
||||||
plugins {
|
plugins {
|
||||||
|
id("java") // Tell gradle this is a java project.
|
||||||
id("java-library") // Import helper for source-based libraries.
|
id("java-library") // Import helper for source-based libraries.
|
||||||
kotlin("jvm") version
|
kotlin("jvm") version "2.1.21" // Import kotlin jvm plugin for kotlin/java integration.
|
||||||
"2.1.21" // Import kotlin jvm plugin for kotlin/java integration (Required for DiamondBank-OG API)
|
|
||||||
id("com.diffplug.spotless") version "7.0.4" // Import auto-formatter.
|
id("com.diffplug.spotless") version "7.0.4" // Import auto-formatter.
|
||||||
id("com.gradleup.shadow") version "8.3.6" // Import shadow API.
|
id("com.gradleup.shadow") version "8.3.6" // Import shadow API.
|
||||||
eclipse // Import eclipse plugin for IDE integration.
|
eclipse // Import eclipse plugin for IDE integration.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* --------------------------- JDK / Kotlin ---------------------------- */
|
||||||
java {
|
java {
|
||||||
sourceCompatibility = JavaVersion.VERSION_17 // Compile with JDK 17 compatibility.
|
sourceCompatibility = JavaVersion.VERSION_17 // Compile with JDK 17 compatibility.
|
||||||
|
toolchain { // Select Java toolchain.
|
||||||
toolchain {
|
|
||||||
languageVersion.set(JavaLanguageVersion.of(17)) // Use JDK 17.
|
languageVersion.set(JavaLanguageVersion.of(17)) // Use JDK 17.
|
||||||
vendor.set(JvmVendorSpec.GRAAL_VM) // Use GraalVM CE.
|
vendor.set(JvmVendorSpec.GRAAL_VM) // Use GraalVM CE.
|
||||||
}
|
}
|
||||||
@@ -18,60 +28,219 @@ java {
|
|||||||
|
|
||||||
kotlin { jvmToolchain(17) }
|
kotlin { jvmToolchain(17) }
|
||||||
|
|
||||||
group = "net.trueog.kotlintemplate-og" // Declare bundle identifier.
|
/* ----------------------------- Metadata ------------------------------ */
|
||||||
|
group = "net.trueog.kotlintemplate-og"
|
||||||
|
|
||||||
version = "1.0" // Declare plugin version (will be in .jar).
|
version = "1.0"
|
||||||
|
|
||||||
val apiVersion = "1.19" // Declare minecraft server target version.
|
val apiVersion = "1.19"
|
||||||
|
|
||||||
|
eclipse { project { name = "KotlinTemplate-OG-Plugin" } }
|
||||||
|
|
||||||
|
/* -------- Kotlin subprojects -> jars on Eclipse/compile classpath ----- */
|
||||||
|
val kotlinPluginProjects = listOf(":libs:DiamondBank-OG", ":libs:Chat-OG") // <— single place
|
||||||
|
|
||||||
|
kotlinPluginProjects.forEach { evaluationDependsOn(it) } // Ensure subprojects are evaluated first.
|
||||||
|
|
||||||
|
val ideLibDir = layout.buildDirectory.dir("ide-libs")
|
||||||
|
val hashRegex = Regex("-[0-9a-fA-F]{10}(?=\\.jar$)") // Black magic.
|
||||||
|
|
||||||
|
/* --------------------------- IDE-only configuration ------------------- */
|
||||||
|
val ideLibs: Configuration by
|
||||||
|
configurations.creating {
|
||||||
|
isCanBeResolved = true
|
||||||
|
isCanBeConsumed = false
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tell Eclipse/Buildship to include the IDE jars */
|
||||||
|
eclipse { classpath { plusConfigurations += ideLibs } }
|
||||||
|
|
||||||
|
/* ----------------------------- Resources ----------------------------- */
|
||||||
tasks.named<ProcessResources>("processResources") {
|
tasks.named<ProcessResources>("processResources") {
|
||||||
val props = mapOf("version" to version, "apiVersion" to apiVersion)
|
val props = mapOf("version" to version, "apiVersion" to apiVersion)
|
||||||
inputs.properties(props) // Indicates to rerun if version changes.
|
inputs.properties(props) // Indicates to rerun if version changes.
|
||||||
filesMatching("plugin.yml") { expand(props) }
|
filesMatching("plugin.yml") { expand(props) }
|
||||||
from("LICENSE") { into("/") } // Bundle license into .jars.
|
from("LICENSE") { into("/") } // Bundle licenses into jarfiles.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ---------------------------- Repos ---------------------------------- */
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
gradlePluginPortal()
|
gradlePluginPortal()
|
||||||
maven { url = uri("https://repo.purpurmc.org/snapshots") }
|
maven { url = uri("https://repo.purpurmc.org/snapshots") }
|
||||||
|
maven { url = uri("file://${System.getProperty("user.home")}/.m2/repository") }
|
||||||
|
System.getProperty("SELF_MAVEN_LOCAL_REPO")?.let { // TrueOG Bootstrap mavenLocal().
|
||||||
|
val dir = file(it)
|
||||||
|
if (dir.isDirectory) {
|
||||||
|
println("Using SELF_MAVEN_LOCAL_REPO at: $it")
|
||||||
|
maven { url = uri("file://${dir.absolutePath}") }
|
||||||
|
} else {
|
||||||
|
logger.error("TrueOG Bootstrap not found, defaulting to ~/.m2 for mavenLocal()")
|
||||||
|
}
|
||||||
|
} ?: logger.error("TrueOG Bootstrap not found, defaulting to ~/.m2 for mavenLocal()")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ---------------------- Java project deps ---------------------------- */
|
||||||
dependencies {
|
dependencies {
|
||||||
compileOnly("org.purpurmc.purpur:purpur-api:1.19.4-R0.1-SNAPSHOT") // Declare purpur API version to be packaged.
|
compileOnly("org.purpurmc.purpur:purpur-api:1.19.4-R0.1-SNAPSHOT")
|
||||||
compileOnly("io.github.miniplaceholders:miniplaceholders-api:2.2.3") // Import MiniPlaceholders API.
|
compileOnly("io.github.miniplaceholders:miniplaceholders-api:2.2.3")
|
||||||
implementation("org.jetbrains.kotlin:kotlin-stdlib") // Import Kotlin standard library.
|
implementation("org.jetbrains.kotlin:kotlin-stdlib") // Import Kotlin standard library.
|
||||||
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.10.2") // Import Kotlin async library.
|
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.10.2") // Import Kotlin async library.
|
||||||
compileOnlyApi(project(":libs:Utilities-OG")) // Import TrueOG Network Utilities-OG API.
|
compileOnlyApi(project(":libs:Utilities-OG"))
|
||||||
compileOnlyApi(project(":libs:GxUI-OG")) // Import TrueOG Network GxUI-OG API.
|
compileOnlyApi(project(":libs:GxUI-OG"))
|
||||||
compileOnlyApi(project(":libs:DiamondBank-OG")) // Import TrueOG Network DiamondBank-OG API.
|
|
||||||
|
// Import TrueOG Network Kotlin-based APIs as jars (shadow output) so Eclipse code later can treat them as jar deps.
|
||||||
|
kotlinPluginProjects.forEach { compileOnlyApi(project(mapOf("path" to it, "configuration" to "shadow"))) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* --- copy shaded jars & make Eclipse see them as individual libs ---- */
|
||||||
|
val copyTasks = mutableListOf<TaskProvider<Copy>>()
|
||||||
|
|
||||||
|
kotlinPluginProjects.forEach { path ->
|
||||||
|
val sub = project(path)
|
||||||
|
val shadowJarProv = sub.tasks.named("shadowJar")
|
||||||
|
val copyTask =
|
||||||
|
tasks.register<Copy>("ideCopy${sub.name.replaceFirstChar(Char::titlecase)}") {
|
||||||
|
dependsOn(shadowJarProv)
|
||||||
|
from(shadowJarProv)
|
||||||
|
into(ideLibDir)
|
||||||
|
rename { it.replace(hashRegex, "") } // Remove git commit hash from jarfile.
|
||||||
|
}
|
||||||
|
copyTasks += copyTask
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ensure the jars exist before .classpath is generated */
|
||||||
|
tasks.named("eclipseClasspath").configure { dependsOn(copyTasks) }
|
||||||
|
|
||||||
|
/* Supply those jars to the ideLibs configuration (after evaluation) */
|
||||||
|
afterEvaluate { dependencies { add("ideLibs", fileTree(ideLibDir) { include("*.jar") }) } }
|
||||||
|
|
||||||
|
/* ------------------ FINAL patcher: runs AFTER :eclipse ---------------- */
|
||||||
|
val injectIdeLibs =
|
||||||
|
tasks.register("injectIdeLibs") {
|
||||||
|
dependsOn("eclipse") // run after all eclipse files are generated
|
||||||
|
doLast {
|
||||||
|
val cpFile = file(".classpath")
|
||||||
|
if (!cpFile.exists()) return@doLast
|
||||||
|
|
||||||
|
val jars = fileTree(ideLibDir.get()) { include("*.jar") }.files.sortedBy { it.name }
|
||||||
|
if (jars.isEmpty()) return@doLast
|
||||||
|
|
||||||
|
// Parse DOM
|
||||||
|
val dbf = DocumentBuilderFactory.newInstance()
|
||||||
|
val doc = dbf.newDocumentBuilder().parse(cpFile)
|
||||||
|
val root = doc.documentElement
|
||||||
|
|
||||||
|
// Helper to see if an entry already exists
|
||||||
|
fun exists(path: String): Boolean =
|
||||||
|
root.getElementsByTagName("classpathentry").let { list ->
|
||||||
|
(0 until list.length).any { i ->
|
||||||
|
val n = list.item(i)
|
||||||
|
val kind = n.attributes?.getNamedItem("kind")?.nodeValue
|
||||||
|
val p = n.attributes?.getNamedItem("path")?.nodeValue
|
||||||
|
kind == "lib" && p == path
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove any entry that points to ide-libs dir (folder or jars) to avoid dupes
|
||||||
|
val toRemove = mutableListOf<org.w3c.dom.Node>()
|
||||||
|
val list = root.getElementsByTagName("classpathentry")
|
||||||
|
val dirPath = ideLibDir.get().asFile.absolutePath
|
||||||
|
for (i in 0 until list.length) {
|
||||||
|
val n = list.item(i)
|
||||||
|
val kind = n.attributes?.getNamedItem("kind")?.nodeValue
|
||||||
|
val p = n.attributes?.getNamedItem("path")?.nodeValue ?: ""
|
||||||
|
if (kind == "lib" && (p == dirPath || p.startsWith("$dirPath/"))) {
|
||||||
|
toRemove += n
|
||||||
|
}
|
||||||
|
}
|
||||||
|
toRemove.forEach { root.removeChild(it) }
|
||||||
|
|
||||||
|
// Append our jar entries LAST
|
||||||
|
jars.forEach { f ->
|
||||||
|
val abs = f.absolutePath
|
||||||
|
if (!exists(abs)) {
|
||||||
|
val entry = doc.createElement("classpathentry")
|
||||||
|
entry.setAttribute("kind", "lib")
|
||||||
|
entry.setAttribute("path", abs)
|
||||||
|
root.appendChild(entry)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write back pretty
|
||||||
|
val tf =
|
||||||
|
TransformerFactory.newInstance().newTransformer().apply {
|
||||||
|
setOutputProperty(OutputKeys.INDENT, "yes")
|
||||||
|
setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "1")
|
||||||
|
setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no")
|
||||||
|
setOutputProperty(OutputKeys.ENCODING, "UTF-8")
|
||||||
|
}
|
||||||
|
Files.newBufferedWriter(cpFile.toPath()).use { w -> tf.transform(DOMSource(doc), StreamResult(w)) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.named("eclipse").configure { finalizedBy(injectIdeLibs) }
|
||||||
|
|
||||||
|
/* ---------------------- Reproducible jars ---------------------------- */
|
||||||
tasks.withType<AbstractArchiveTask>().configureEach { // Ensure reproducible .jars
|
tasks.withType<AbstractArchiveTask>().configureEach { // Ensure reproducible .jars
|
||||||
isPreserveFileTimestamps = false
|
isPreserveFileTimestamps = false
|
||||||
isReproducibleFileOrder = true
|
isReproducibleFileOrder = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ----------------------------- Shadow -------------------------------- */
|
||||||
tasks.shadowJar {
|
tasks.shadowJar {
|
||||||
exclude("io.github.miniplaceholders.*") // Exclude the MiniPlaceholders package from being shadowed.
|
exclude("io.github.miniplaceholders.*") // Exclude the MiniPlaceholders package from being shadowed.
|
||||||
archiveClassifier.set("") // Use empty string instead of null.
|
archiveClassifier.set("") // Use empty string instead of null.
|
||||||
minimize()
|
minimize()
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.build {
|
tasks.jar { archiveClassifier.set("part") } // Applies to root jarfile only.
|
||||||
dependsOn(tasks.spotlessApply)
|
|
||||||
dependsOn(tasks.shadowJar)
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.jar { archiveClassifier.set("part") }
|
tasks.build { dependsOn(tasks.spotlessApply, tasks.shadowJar) }
|
||||||
|
|
||||||
|
/* --------------------------- Javac opts ------------------------------- */
|
||||||
tasks.withType<JavaCompile>().configureEach {
|
tasks.withType<JavaCompile>().configureEach {
|
||||||
options.compilerArgs.add("-parameters")
|
|
||||||
options.compilerArgs.add("-Xlint:deprecation") // Triggers deprecation warning messages.
|
options.compilerArgs.add("-Xlint:deprecation") // Triggers deprecation warning messages.
|
||||||
options.encoding = "UTF-8"
|
options.encoding = "UTF-8"
|
||||||
options.isFork = true
|
options.isFork = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ----------------------- Eclipse BuildShip SHIM ----------------------- */
|
||||||
|
fun Project.addResolvableEclipseConfigs() {
|
||||||
|
val jarAttr =
|
||||||
|
objects.named(org.gradle.api.attributes.LibraryElements::class, org.gradle.api.attributes.LibraryElements.JAR)
|
||||||
|
val apiAttr = objects.named(org.gradle.api.attributes.Usage::class, org.gradle.api.attributes.Usage.JAVA_API)
|
||||||
|
|
||||||
|
val compileOnlyRes =
|
||||||
|
configurations.create("eclipseCompileOnly") {
|
||||||
|
extendsFrom(configurations.compileOnly.get())
|
||||||
|
isCanBeResolved = true
|
||||||
|
isCanBeConsumed = false
|
||||||
|
attributes.attribute(org.gradle.api.attributes.Usage.USAGE_ATTRIBUTE, apiAttr)
|
||||||
|
attributes.attribute(org.gradle.api.attributes.LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, jarAttr)
|
||||||
|
}
|
||||||
|
val compileOnlyApiRes =
|
||||||
|
configurations.create("eclipseCompileOnlyApi") {
|
||||||
|
extendsFrom(configurations.getByName("compileOnlyApi"))
|
||||||
|
isCanBeResolved = true
|
||||||
|
isCanBeConsumed = false
|
||||||
|
attributes.attribute(org.gradle.api.attributes.Usage.USAGE_ATTRIBUTE, apiAttr)
|
||||||
|
attributes.attribute(org.gradle.api.attributes.LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, jarAttr)
|
||||||
|
}
|
||||||
|
eclipse.classpath.plusConfigurations.addAll(listOf(compileOnlyRes, compileOnlyApiRes))
|
||||||
|
}
|
||||||
|
|
||||||
|
addResolvableEclipseConfigs()
|
||||||
|
|
||||||
|
subprojects {
|
||||||
|
apply(plugin = "java-library")
|
||||||
|
apply(plugin = "eclipse")
|
||||||
|
addResolvableEclipseConfigs()
|
||||||
|
eclipse.project.name = "${project.name}-${rootProject.name}"
|
||||||
|
tasks.withType<Jar>().configureEach { archiveBaseName.set("${project.name}-${rootProject.name}") }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------------- Auto Formatting ------------------------ */
|
||||||
spotless {
|
spotless {
|
||||||
kotlin { ktfmt().kotlinlangStyle().configure { it.setMaxWidth(120) } }
|
kotlin { ktfmt().kotlinlangStyle().configure { it.setMaxWidth(120) } }
|
||||||
kotlinGradle {
|
kotlinGradle {
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.2-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip
|
||||||
networkTimeout=10000
|
networkTimeout=10000
|
||||||
validateDistributionUrl=true
|
validateDistributionUrl=true
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
|||||||
Submodule
+1
Submodule libs/Chat-OG added at 6d9e452c83.
+9
-12
@@ -1,16 +1,13 @@
|
|||||||
rootProject.name = "KotlinTemplate-OG"
|
rootProject.name = "KotlinTemplate-OG"
|
||||||
|
|
||||||
// Run the bootstrap at configuration time.
|
ProcessBuilder("sh", "bootstrap.sh").directory(rootDir).inheritIO().start().let {
|
||||||
val process = ProcessBuilder("sh", "bootstrap.sh").directory(rootDir).start()
|
if (it.waitFor() != 0) throw GradleException("bootstrap.sh failed")
|
||||||
|
|
||||||
val exitValue = process.waitFor()
|
|
||||||
|
|
||||||
if (exitValue != 0) {
|
|
||||||
throw GradleException("bootstrap.sh failed with exit code $exitValue")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
include("libs:Utilities-OG")
|
file("libs")
|
||||||
|
.listFiles()
|
||||||
include("libs:GxUI-OG")
|
?.filter { it.isDirectory && !it.name.startsWith(".") }
|
||||||
|
?.forEach { dir ->
|
||||||
include("libs:DiamondBank-OG")
|
include(":libs:${dir.name}")
|
||||||
|
project(":libs:${dir.name}").projectDir = dir
|
||||||
|
}
|
||||||
Reference in new issue
Block a user