Refactor buildscript
authorLanius Trolling <lanius@laniustrolling.dev>
Sat, 6 Apr 2024 14:26:03 +0000 (10:26 -0400)
committerLanius Trolling <lanius@laniustrolling.dev>
Sat, 6 Apr 2024 14:26:03 +0000 (10:26 -0400)
build.gradle.kts

index d579236d56178163afa253348d85c5b41e6ede05..5a5bf0ed10bae03123e7d28fb059ef481ce5fd56 100644 (file)
@@ -4,7 +4,6 @@ import com.nixxcode.jvmbrotli.enc.BrotliOutputStream
 import com.nixxcode.jvmbrotli.enc.Encoder
 import groovy.json.JsonSlurper
 import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
-import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinJsBrowserDsl
 import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpack
 import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpackConfig
 import org.jetbrains.kotlin.gradle.targets.js.webpack.WebpackDevtool
@@ -37,44 +36,63 @@ plugins {
 
 group = "info.mechyrdia"
 
-val configFile = (JsonSlurper().parse(File(rootDir, "config.json")) as Map<*, *>).mapKeys { (k, _) -> k.toString() }
+val configFile by project.extra {
+       (JsonSlurper().parse(File(rootDir, "config.json")) as Map<*, *>).mapKeys { (k, _) -> k.toString() }
+}
 
-val isDevMode = (configFile["isDevMode"] as? Boolean) ?: false
+val isDevMode by project.extra {
+       (configFile["isDevMode"] as? Boolean) ?: false
+}
 
-val configureOutput: KotlinJsBrowserDsl.(name: String) -> Unit = { name ->
-       val fileName = "$name.js"
-       
-       commonWebpackConfig {
-               outputFileName = fileName
-               if (isDevMode) {
-                       mode = KotlinWebpackConfig.Mode.DEVELOPMENT
-                       devtool = WebpackDevtool.SOURCE_MAP
-                       sourceMaps = true
-               } else {
-                       mode = KotlinWebpackConfig.Mode.PRODUCTION
-                       devtool = null
-                       sourceMaps = false
-               }
-       }
-       
-       webpackTask {
-               mainOutputFileName.set(fileName)
-               if (isDevMode) {
-                       mode = KotlinWebpackConfig.Mode.DEVELOPMENT
-                       devtool = WebpackDevtool.SOURCE_MAP
-                       sourceMaps = true
-               } else {
-                       mode = KotlinWebpackConfig.Mode.PRODUCTION
-                       sourceMaps = false
-               }
-       }
+val fileDir by project.extra {
+       val fileDirPath = configFile["rootDir"]?.let { "$it" } ?: ".."
+       File(rootDir, fileDirPath)
 }
 
-val jsTarget: KotlinMultiplatformExtension.(name: String) -> Unit = { name ->
+val assetDir by project.extra {
+       configFile["assetDir"]?.let { File(rootDir, "$it") } ?: File(fileDir, "assets")
+}
+
+val browserWebpackSuffix by project.extra {
+       if (isDevMode)
+               "BrowserDevelopmentWebpack"
+       else
+               "BrowserProductionWebpack"
+}
+
+fun KotlinMultiplatformExtension.jsConfigured(name: String) {
+       val isDevMode: Boolean by project.extra
+       
        js(name) {
                browser {
-                       configureOutput(name)
+                       val fileName = "$name.js"
+                       
+                       commonWebpackConfig {
+                               outputFileName = fileName
+                               if (isDevMode) {
+                                       mode = KotlinWebpackConfig.Mode.DEVELOPMENT
+                                       devtool = WebpackDevtool.SOURCE_MAP
+                                       sourceMaps = true
+                               } else {
+                                       mode = KotlinWebpackConfig.Mode.PRODUCTION
+                                       devtool = null
+                                       sourceMaps = false
+                               }
+                       }
+                       
+                       webpackTask {
+                               mainOutputFileName.set(fileName)
+                               if (isDevMode) {
+                                       mode = KotlinWebpackConfig.Mode.DEVELOPMENT
+                                       devtool = WebpackDevtool.SOURCE_MAP
+                                       sourceMaps = true
+                               } else {
+                                       mode = KotlinWebpackConfig.Mode.PRODUCTION
+                                       sourceMaps = false
+                               }
+                       }
                }
+               
                binaries.executable()
        }
 }
@@ -84,7 +102,7 @@ repositories {
 }
 
 kotlin {
-       jsTarget("map")
+       jsConfigured("map")
        jvmToolchain(17)
        jvm("jvm") {
                withJava()
@@ -161,7 +179,7 @@ tasks.named<Copy>("jvmProcessResources") {
                
                val encoderParams = if (BrotliLoader.isBrotliAvailable()) Encoder.Parameters().setQuality(8) else null
                
-               val resourceTree = fileTree(mapOf("dir" to outputs.files.asPath + "/static/", "exclude" to listOf("*.gz", "*.br", "*.sha256")))
+               val resourceTree = fileTree(mapOf("dir" to outputs.files.asPath + "/static/", "exclude" to listOf("*.gz", "*.br")))
                val countDownLatch = CountDownLatch(resourceTree.count())
                
                for (file in resourceTree) {
@@ -189,8 +207,6 @@ tasks.named<Copy>("jvmProcessResources") {
        }
 }
 
-val browserWebpackSuffix = if (isDevMode) "BrowserDevelopmentWebpack" else "BrowserProductionWebpack"
-
 tasks.named<ShadowJar>("shadowJar") {
        mergeServiceFiles()
        exclude { it.name == "module-info.class" }
@@ -200,54 +216,63 @@ application {
        mainClass.set("info.mechyrdia.Factbooks")
 }
 
-val buildJsAsset: Task.(name: String) -> Unit = { name ->
-       val webpackTask = tasks.getByName<KotlinWebpack>("$name$browserWebpackSuffix")
-       dependsOn(webpackTask)
+fun Task.buildJsAsset(name: String) {
+       val browserWebpackSuffix: String by project.extra
+       val browserWebpackTask by tasks.named<KotlinWebpack>("$name$browserWebpackSuffix")
+       dependsOn(browserWebpackTask)
 }
 
-val copyToAssets: Task.(name: String, destSubDir: String, destFileName: String) -> Unit = { name, destSubDir, destFileName ->
-       val webpackTask = tasks.getByName<KotlinWebpack>("$name$browserWebpackSuffix")
-       
-       doFirst {
-               val assetsDirPath = configFile["assetDir"]?.let { "$it" }
-                       ?: configFile["rootDir"]?.let { "$it/assets" }
-                       ?: "../assets"
-               val assetsDir = File(rootDir, assetsDirPath)
-               
-               val destJsName = "$destFileName.js"
-               
-               val jsFile = webpackTask
-                       .mainOutputFile
-                       .get()
-                       .asFile
+fun copyToAssetsTask(from: TaskProvider<KotlinWebpack>, into: String, name: String): TaskProvider<Copy> {
+       return tasks.register("${into}DeployToAssets", Copy::class) {
+               group = "build"
                
-               val jsText = jsFile.readText()
-               val jsMapName = "${webpackTask.mainOutputFileName.get()}.map"
-               val sourceMapReplaceText = "//# sourceMappingURL=$jsMapName"
-               val sourceMapReplacement = "//# sourceMappingURL=$destJsName.map"
-               
-               val destJsFile = File(assetsDir, "$destSubDir/$destJsName")
-               val destJsMapFile = File(assetsDir, "$destSubDir/$destJsName.map")
+               val isDevMode: Boolean by project.extra
                
                if (isDevMode) {
-                       val jsMapFile = File(jsFile.parentFile, jsMapName)
-                       val jsMapText = jsMapFile.readText()
+                       val fromJs = from.flatMap { it.mainOutputFile }.map { it.asFile }
+                       val fromJsMap = fromJs.map { File(it.parentFile, "${it.name}.map") }
                        
-                       destJsFile.writeText(jsText.replace(sourceMapReplaceText, sourceMapReplacement))
-                       destJsMapFile.writeText(jsMapText)
+                       from(files(fromJs, fromJsMap)) {
+                               eachFile {
+                                       rename { if (it.endsWith(".map")) "$name.js.map" else "$name.js" }
+                                       
+                                       val sourceMapReplaceText = "//# sourceMappingURL=${fromJsMap.get().name}"
+                                       val sourceMapReplacement = "//# sourceMappingURL=$name.js.map"
+                                       filter { line ->
+                                               line.replace(sourceMapReplaceText, sourceMapReplacement)
+                                       }
+                               }
+                       }
                } else {
-                       destJsFile.writeText(jsText.replace(sourceMapReplaceText, ""))
-                       destJsMapFile.delete()
+                       val fromJs = from.flatMap { it.mainOutputFile }.map { it.asFile }
+                       
+                       from(fromJs) {
+                               eachFile {
+                                       rename { "$name.js" }
+                                       
+                                       val sourceMapTestText = "//# sourceMappingURL="
+                                       filter { line ->
+                                               if (line.contains(sourceMapTestText)) "" else line
+                                       }
+                               }
+                       }
                }
+               
+               val assetDir: File by project.extra
+               val intoDir = File(assetDir, into).apply { mkdirs() }
+               
+               into(intoDir)
        }
 }
 
+val mapDeployToAssets by copyToAssetsTask(tasks.named<KotlinWebpack>("map$browserWebpackSuffix"), "map", "main")
+
 tasks.withType<ShadowJar> {
        buildJsAsset("map")
 }
 
-tasks.getByName<JavaExec>("runShadow") {
-       copyToAssets("map", "map", "main")
+tasks.named<JavaExec>("runShadow") {
+       dependsOn(mapDeployToAssets)
 }
 
 tasks.withType<JavaExec> {