Skip to content

Commit

Permalink
Load automatically korge.yaml, create build.gradle.kts as require…
Browse files Browse the repository at this point in the history
…d and initial code for Korge Kotlin Plugin (#2245)

* Initial code for Korge Kotlin Plugin required for reflective operations

* Automatically apply the korge kotlin plugin when applying the korge plugin

* Detect and configure new directory schema

* More work

* Some improvements

* Read more information from korge.yaml

* Use korlibs 6.0.0-alpha5
  • Loading branch information
soywiz authored Jun 20, 2024
1 parent c947b02 commit 6e44781
Show file tree
Hide file tree
Showing 29 changed files with 523 additions and 18 deletions.
1 change: 1 addition & 0 deletions buildSrc/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ dependencies {
implementation(libs.proguard.gradle)
implementation(libs.gson)
implementation(libs.gradle.publish.plugin)
implementation(libs.korlibs.serialization)
implementation(libs.kotlin.gradle.plugin)
implementation(libs.android.build.gradle)
testImplementation(libs.junit)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,10 @@ enum class GameCategory {
ACTION, ADVENTURE, ARCADE, BOARD, CARD,
CASINO, DICE, EDUCATIONAL, FAMILY, KIDS,
MUSIC, PUZZLE, RACING, ROLE_PLAYING, SIMULATION,
SPORTS, STRATEGY, TRIVIA, WORD
SPORTS, STRATEGY, TRIVIA, WORD;

companion object {
val VALUES: Map<String, GameCategory> = GameCategory.values().toList().associateBy { it.name.uppercase() }
operator fun get(key: String): GameCategory? = VALUES[key.uppercase().trim()]
}
}
66 changes: 66 additions & 0 deletions buildSrc/src/main/kotlin/korlibs/korge/gradle/KorgeExtension.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package korlibs.korge.gradle

import groovy.text.*
import korlibs.*
import korlibs.io.serialization.yaml.*
import korlibs.korge.gradle.processor.*
import korlibs.korge.gradle.targets.*
import korlibs.korge.gradle.targets.android.*
Expand All @@ -13,6 +14,8 @@ import korlibs.modules.*
import korlibs.root.*
import org.gradle.api.*
import org.gradle.api.artifacts.*
import org.gradle.api.logging.*
import org.gradle.internal.impldep.org.yaml.snakeyaml.Yaml
import org.jetbrains.kotlin.gradle.plugin.mpp.*
import java.io.*
import java.net.*
Expand Down Expand Up @@ -172,6 +175,69 @@ open class KorgeExtension(
}
}

fun loadYaml(file: File) {
val korgeYamlString = file.takeIfExists()?.readText() ?: return
try {
val info = korlibs.io.serialization.yaml.Yaml.read(korgeYamlString).dyn
info["id"].toStringOrNull()?.let { this.id = it }

author(
name = info["author"]["name"].str,
email = info["author"]["email"].str,
href = info["author"]["href"].str,
)

gameCategory = GameCategory[info["category"].str]

info["icon"].toStringOrNull()?.also {
icon = project.file(it)
}

info["banner"].toStringOrNull()?.also {
banner = project.file(it)
}

val targetList = info["targets"].list
if (targetList.isEmpty()) {
targetDefault()
} else {
for (target in targetList) {
when (target.str) {
"all" -> targetAll()
"default" -> targetDefault()
"jvm" -> targetJvm()
"js" -> targetJs()
"wasm", "wasmJs" -> targetWasmJs()
"android" -> targetAndroid()
"ios" -> targetIos()
else -> project.logger.log(LogLevel.WARN, "Unknown target in korge.yaml: '${target.str}'")
}
}
}

for (plugin in info["plugins"].list) {
val pluginStr = plugin.str
when (pluginStr) {
"\$kotlin.serialization" -> serialization()
"\$kotlin.serialization.json" -> serializationJson()
else -> project.logger.log(LogLevel.WARN, "Unknown plugin in korge.yaml: '${pluginStr}'")
}
}

for ((key, value) in info["config"].map) {
config(key.str, value.str)
}

for ((name, jvmMainClassName) in info["entrypoints"].map) {
entrypoint(name.str, jvmMainClassName.str)
}

// @TODO: Implement the rest of the properties including targets etc.
} catch (e: Throwable) {
e.printStackTrace()
}
}

internal fun implicitCheckVersion() {
checkVersion(check = true, report = false)
}
Expand Down
11 changes: 0 additions & 11 deletions buildSrc/src/main/kotlin/korlibs/korge/gradle/KorgeGradlePlugin.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,6 @@ import java.util.*
import java.util.concurrent.*
import kotlin.concurrent.*

abstract class KorgeGradleAbstractPlugin(val projectType: ProjectType) : Plugin<Project> {
override fun apply(project: Project) {
project.configureAutoVersions()
project.configureBuildScriptClasspathTasks()
KorgeGradleApply(project, projectType).apply(includeIndirectAndroid = true)
}
}

open class KorgeGradlePlugin : KorgeGradleAbstractPlugin(projectType = ProjectType.EXECUTABLE)
open class KorgeLibraryGradlePlugin : KorgeGradleAbstractPlugin(projectType = ProjectType.LIBRARY)

class KorgeGradleApply(val project: Project, val projectType: ProjectType) {
fun apply(includeIndirectAndroid: Boolean = true) = project {
checkMinimumJavaVersion()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,18 @@ fun Project.generateKorgeProcessedFromTask(task: ProcessResources) {
val compilation = target.compilations.findByName(compilationName)
val folders: MutableList<FileCollection> = when {
compilation != null -> compilation.allKotlinSourceSets.map { it.resources.sourceDirectories }.toMutableList()
else -> arrayListOf(project.files(file("src/commonMain/resources"), file("src/${targetNameRaw}${compilationName.capitalize()}/resources")))
else -> arrayListOf(project.files(
file("resources"),
file("src/commonMain/resources"),
file("src/${targetNameRaw}${compilationName.capitalize()}/resources")
))
}

//println("PROJECT: $project : ${this.project.allDependantProjects()}")

for (subproject in this.project.allDependantProjects()) {
val files = files(
file("resources"),
subproject.file("src/commonMain/resources"),
subproject.file("src/${targetNameRaw}${compilationName.capitalize()}/resources")
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import javax.imageio.ImageIO
val ICON_SIZES = listOf(20, 29, 40, 44, 48, 50, 55, 57, 58, 60, 72, 76, 80, 87, 88, 100, 114, 120, 144, 152, 167, 172, 180, 196, 1024)

fun tryGetResourceBytes(path: String): ByteArray? =
KorgeGradlePlugin::class.java.getResource("/" + path.trim('/'))?.readBytes()
KorgeExtension::class.java.getResource("/" + path.trim('/'))?.readBytes()

fun getResourceBytes(path: String): ByteArray = tryGetResourceBytes(path) ?: error("Can't find resource '$path'")
fun getResourceString(path: String): String = getResourceBytes(path).toString(Charsets.UTF_8)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ fun NamedDomainObjectContainer<KotlinSourceSet>.createPairSourceSet(

val newVariant = if (project?.projectDir != null) !File(project.projectDir, "src/commonMain").isDirectory else false

//println("!!!!!!!!!!! newVariant=$newVariant, project?.projectDir=${project?.projectDir} isDirectory=${project?.projectDir?.get("src/commonMain")?.isDirectory}")

if (newVariant) {
if (name == "common") {
main.kotlin.srcDirs(listOf("src"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import korlibs.korge.gradle.*
import korlibs.korge.gradle.kotlin
import korlibs.korge.gradle.targets.*
import korlibs.korge.gradle.targets.all.*
import korlibs.korge.gradle.targets.jvm.*
import korlibs.korge.gradle.util.*
import org.gradle.api.*
import org.gradle.api.tasks.*
Expand Down Expand Up @@ -43,6 +44,8 @@ fun Project.configureAndroidDirect(projectType: ProjectType, isKorge: Boolean) {
AddFreeCompilerArgs.addFreeCompilerArgs(project, this)
}

ensureSourceSetsConfigure("common", "android")

//if (isKorge) {
// project.afterEvaluate {
// //println("@TODO: Info is not generated")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package korlibs.korge.gradle.targets.ios
import korlibs.korge.gradle.*
import korlibs.korge.gradle.targets.*
import korlibs.korge.gradle.targets.desktop.*
import korlibs.korge.gradle.targets.jvm.*
import korlibs.korge.gradle.targets.native.*
import korlibs.korge.gradle.util.*
import org.gradle.api.*
Expand All @@ -16,6 +17,7 @@ import java.io.*
fun Project.configureNativeIos(projectType: ProjectType) {
configureNativeIosTvos(projectType, "ios")
configureNativeIosTvos(projectType, "tvos")
ensureSourceSetsConfigure("common", "ios", "tvos")

val exKotlinSourceSetContainer = this.project.exKotlinSourceSetContainer
this.project.kotlin.apply {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import korlibs.korge.gradle.targets.*
import korlibs.korge.gradle.targets.windows.*
import korlibs.korge.gradle.util.*
import korlibs.*
import korlibs.korge.gradle.targets.jvm.*
import org.gradle.api.*
import org.gradle.api.file.*
import org.gradle.api.tasks.*
Expand Down Expand Up @@ -90,6 +91,8 @@ fun Project.configureJavaScript(projectType: ProjectType) {
configureJavascriptRun()
}
configureWebpack()

ensureSourceSetsConfigure("common", "js")
}

fun KotlinJsTargetDsl.configureJsTargetOnce() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package korlibs.korge.gradle.targets.js
import korlibs.korge.gradle.gkotlin
import korlibs.korge.gradle.kotlin
import korlibs.korge.gradle.targets.*
import korlibs.korge.gradle.targets.jvm.*
import korlibs.korge.gradle.targets.wasm.*
import korlibs.korge.gradle.util.*
import org.gradle.api.*
Expand All @@ -12,6 +13,7 @@ import java.io.*

fun Project.configureWasm(projectType: ProjectType, binaryen: Boolean = false) {
if (gkotlin.targets.findByName("wasm") != null) return
ensureSourceSetsConfigure("common", "wasmJs")

configureWasmTarget(executable = true, binaryen = binaryen)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,13 @@ import java.io.*
val KORGE_RELOAD_AGENT_CONFIGURATION_NAME = "KorgeReloadAgent"
val httpPort = 22011

fun Project.ensureSourceSetsConfigure(vararg names: String) {
val sourceSets = project.kotlin.sourceSets
for (name in names) {
sourceSets.createPairSourceSet(name, project = project)
}
}

fun Project.configureJvm(projectType: ProjectType) {
if (gkotlin.targets.findByName("jvm") != null) return

Expand Down Expand Up @@ -51,6 +58,8 @@ fun Project.configureJvm(projectType: ProjectType) {

val jvmProcessResources = tasks.findByName("jvmProcessResources") as? Copy?
jvmProcessResources?.duplicatesStrategy = org.gradle.api.file.DuplicatesStrategy.INCLUDE

ensureSourceSetsConfigure("common", "jvm")
}

fun Project.configureJvmRunJvm(isRootKorlibs: Boolean) {
Expand Down
10 changes: 9 additions & 1 deletion buildSrc/src/main/kotlin/korlibs/root/RootKorlibsPlugin.kt
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import org.jetbrains.kotlin.gradle.targets.js.testing.mocha.*
import org.jetbrains.kotlin.gradle.tasks.*
import java.io.*
import java.nio.file.*
import kotlin.io.path.*

object RootKorlibsPlugin {
val KORGE_GROUP = "com.soywiz.korge"
Expand Down Expand Up @@ -808,6 +809,7 @@ fun Project.hasBuildGradle() = listOf("build.gradle", "build.gradle.kts").any {
val Project.isSample: Boolean get() = project.path.startsWith(":samples:") || project.path.startsWith(":korge-sandbox") || project.path.startsWith(":korge-editor") || project.path.startsWith(":korge-starter-kit")
fun Project.mustAutoconfigureKMM(): Boolean =
!project.name.startsWith("korge-gradle-plugin") &&
project.name != "korge-kotlin-plugin" &&
project.name != "korge-reload-agent" &&
project.name != "korge-ipc" &&
project.name != "korge-benchmarks" &&
Expand Down Expand Up @@ -836,7 +838,13 @@ fun Project.symlinktree(fromFolder: File, intoFolder: File) {
runCatching { intoFolder.delete() }
runCatching { intoFolder.deleteRecursively() }
intoFolder.parentFile.mkdirs()
Files.createSymbolicLink(intoFolder.toPath(), intoFolder.parentFile.toPath().relativize(fromFolder.toPath()))
val intoPath = intoFolder.toPath()
val relativeFromPath = intoFolder.parentFile.toPath().relativize(fromFolder.toPath())
//if (isWindows) {
// exec { it.commandLine("cmd", "/c", "mklink", "/d", intoPath.pathString, relativeFromPath.pathString) }
//} else {
Files.createSymbolicLink(intoPath, relativeFromPath)
//}
}
} catch (e: Throwable) {
e.printStackTrace()
Expand Down
2 changes: 1 addition & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ kotlinx-coroutines = "1.9.0-RC"
kotlinx-serialization = "1.7.0"
kotlinx-atomicfu = "0.24.0"

korlibs = "6.0.0-alpha4"
korlibs = "6.0.0-alpha5"
#korlibs = "999.0.0.999"

kotlinx-benchmark = "0.4.7"
Expand Down
6 changes: 6 additions & 0 deletions korge-gradle-plugin-common/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ plugins {
id("maven-publish")
id("com.gradle.plugin-publish")
id("org.jetbrains.kotlin.jvm")
id("com.github.gmazzo.buildconfig") version "5.3.5"
}

description = "Multiplatform Game Engine written in Kotlin"
Expand Down Expand Up @@ -72,3 +73,8 @@ afterEvaluate {
}

tasks { val jvmTest by creating { dependsOn("test") } }

buildConfig {
packageName("korlibs.korge.gradle.common")
buildConfigField("String", "KOTLIN_PLUGIN_VERSION", "\"${project.version}\"")
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import com.soywiz.kproject.model.*
import org.gradle.api.initialization.*
import java.io.*
import kotlin.collections.LinkedHashMap
import kotlin.collections.contains
import kotlin.collections.firstOrNull
import kotlin.collections.listOf
import kotlin.collections.set

/**
* Example: "git::korge-dragonbones:korlibs/korge::/korge-dragonbones::v3.2.0"
Expand Down Expand Up @@ -33,6 +38,9 @@ fun Settings.kproject(path: String) {
val sourceDirectory = (result.projectDir as LocalFileRef).file
//println(":$rname -> $sourceDirectory")
settings.include(":${rname}")
settings.project(":${rname}").projectDir = sourceDirectory.relativeTo(rootDir)
val project = settings.project(":${rname}")
val projectDir = sourceDirectory.relativeTo(rootDir)
project.projectDir = projectDir
//project.buildFileName = buildFileKts.relativeTo(projectDir).path
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package korlibs.korge.gradle.common

object KorgeGradlePluginVersion {
val VERSION: String get() = BuildConfig.KOTLIN_PLUGIN_VERSION
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.soywiz.kproject

import com.soywiz.kproject.util.*
import kproject
import org.gradle.api.*
import org.gradle.api.initialization.*
Expand All @@ -12,5 +13,19 @@ class KProjectSettingsPlugin : Plugin<Settings> {
if (File(settings.rootDir, "deps.kproject.yml").exists()) {
settings.kproject("./deps")
}

val projectDir = settings.rootProject.projectDir
val buildFileKts = File(projectDir, "build.gradle.kts")
val buildFileGroovy = File(projectDir, "build.gradle")
if (!buildFileKts.exists() && !buildFileGroovy.exists()) {
buildFileKts.writeTextIfNew("""
import korlibs.korge.gradle.*
plugins { alias(libs.plugins.korge) version korlibs.korge.gradle.common.KorgeGradlePluginVersion.VERSION }
korge { id = "org.korge.unknown.game"; loadYaml(file("korge.yaml")) }
dependencies { findProject(":deps")?.also { add("commonMainApi", it) } }
val baseFile = file("build.extra.gradle.kts").takeIf { it.exists() }?.also { apply(from = it) }
""".trimIndent())
}

}
}
Loading

0 comments on commit 6e44781

Please sign in to comment.