kitgit

tirbofish/dropbear · diff

8640886 · tk

fix up magna-carta crate and magna-carta-plugin gradle plugin. it works pretty nicely now :)

Unverified

diff --git a/README.md b/README.md
index b605152..c316b05 100644
--- a/README.md
+++ b/README.md
@@ -75,6 +75,10 @@ The dropbear engine uses Kotlin Multiplatform, which allows the cooked up produc
 KMP can support, which includes mobile, WASM and desktop. Because the editor is only available on desktop, the JVM is 
 used to evaluate the scripts as it allows for hot-reloading (not made yet).
 
+The dropbear engine does not support any Java code (for class scripting) as it won't be read by the magna-carta parser. 
+Java libraries are still fine, and java classes work, but cannot be annotated by the parser, and only works
+on the JVM target. You can customise the build.gradle.kts file in your project to your own likings. 
+
 ## Documentation
 
 API documentation and articles are available at (todo)
diff --git a/magna-carta-plugin/src/main/kotlin/com/dropbear/magna_carta/DownloadMagnaCartaToolTask.kt b/magna-carta-plugin/src/main/kotlin/com/dropbear/magna_carta/DownloadMagnaCartaToolTask.kt
index 6e29c46..10fe799 100644
--- a/magna-carta-plugin/src/main/kotlin/com/dropbear/magna_carta/DownloadMagnaCartaToolTask.kt
+++ b/magna-carta-plugin/src/main/kotlin/com/dropbear/magna_carta/DownloadMagnaCartaToolTask.kt
@@ -8,8 +8,6 @@ import org.gradle.api.provider.Property
 import org.gradle.api.provider.Provider
 import org.gradle.api.tasks.*
 import org.gradle.internal.os.OperatingSystem
-import java.io.File
-import java.security.MessageDigest
 
 abstract class DownloadMagnaCartaToolTask: Download() {
     @get:Input
@@ -26,37 +24,32 @@ abstract class DownloadMagnaCartaToolTask: Download() {
         val os = OperatingSystem.current()
         val arch = System.getProperty("os.arch")
 
-        val (fileName, url, expectedSha256) = when {
-            os.isLinux && arch == "amd64" -> Triple(
+        val (fileName, url) = when {
+            os.isLinux && arch == "amd64" -> arrayOf(
                 "magna-carta-linux-x64",
                 "https://github.com/4tkbytes/dropbear/releases/download/${toolVersion.get()}/magna-carta-linux-x64",
-                "88b3497ab7e787260aeb7f4d91fe46fa9f78ccfb32f841a27a693b824da4bc32"
             )
-            os.isMacOsX && arch == "aarch64" -> Triple(
+            os.isMacOsX && arch == "aarch64" -> arrayOf(
                 "magna-carta-macos-arm64",
                 "https://github.com/4tkbytes/dropbear/releases/download/${toolVersion.get()}/magna-carta-macos-arm64",
-                "73ba95d193ab7ac5925324e4c3006c60e88bf0cb89b7a08786b75f2bfc038c10"
             )
-            os.isMacOsX && (arch == "x86_64" || arch == "amd64") -> Triple(
+            os.isMacOsX && (arch == "x86_64" || arch == "amd64") -> arrayOf(
                 "magna-carta-macos-x64",
                 "https://github.com/4tkbytes/dropbear/releases/download/${toolVersion.get()}/magna-carta-macos-x64",
-                "012202ee74db0d9638033c8947b7f94d4b20be95b00f2ea181d892af20e226e2"
             )
-            os.isWindows && arch == "aarch64" -> Triple(
+            os.isWindows && arch == "aarch64" -> arrayOf(
                 "magna-carta-windows-arm64.exe",
                 "https://github.com/4tkbytes/dropbear/releases/download/${toolVersion.get()}/magna-carta-windows-arm64.exe",
-                "639ab60a2693d82b548be1497ef25117a13b6e0c69fc45a19450fd10e2610d13"
             )
-            os.isWindows && (arch == "x86_64" || arch == "amd64") -> Triple(
+            os.isWindows && (arch == "x86_64" || arch == "amd64") -> arrayOf(
                 "magna-carta-windows-x64.exe",
                 "https://github.com/4tkbytes/dropbear/releases/download/${toolVersion.get()}/magna-carta-windows-x64.exe",
-                "983880be951c9bda800a616739c4245f97e5ddb2818017d0d9c29ae62c0b9016"
             )
             else -> throw GradleException("Unsupported OS/arch: $os / $arch")
         }
 
         val outputFile = outputDir.get().file(fileName).asFile
-        if (outputFile.exists() && verifyChecksum(outputFile, expectedSha256)) {
+        if (outputFile.exists()) {
             println("Using cached magna-carta tool: $outputFile")
             return
         }
@@ -68,29 +61,11 @@ abstract class DownloadMagnaCartaToolTask: Download() {
 
         super.download()
 
-        if (!verifyChecksum(outputFile, expectedSha256)) {
-            outputFile.delete()
-            throw GradleException("Checksum verification failed for $fileName")
-        }
-
         if (!os.isWindows) {
             outputFile.setExecutable(true)
         }
     }
 
-    private fun verifyChecksum(file: File, expectedSha256: String): Boolean {
-        val digest = MessageDigest.getInstance("SHA-256")
-        file.inputStream().use { input ->
-            val buffer = ByteArray(8192)
-            var bytesRead: Int
-            while (input.read(buffer).also { bytesRead = it } > 0) {
-                digest.update(buffer, 0, bytesRead)
-            }
-        }
-        val actualSha256 = digest.digest().joinToString("") { "%02x".format(it) }
-        return actualSha256 == expectedSha256
-    }
-
     private fun getToolFileName(): String {
         val os = OperatingSystem.current()
         val arch = System.getProperty("os.arch")
diff --git a/magna-carta-plugin/src/main/kotlin/com/dropbear/magna_carta/MagnaCartaPlugin.kt b/magna-carta-plugin/src/main/kotlin/com/dropbear/magna_carta/MagnaCartaPlugin.kt
index c50d31b..fe8ef07 100644
--- a/magna-carta-plugin/src/main/kotlin/com/dropbear/magna_carta/MagnaCartaPlugin.kt
+++ b/magna-carta-plugin/src/main/kotlin/com/dropbear/magna_carta/MagnaCartaPlugin.kt
@@ -10,7 +10,7 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
 
 class MagnaCartaPlugin : Plugin<Project> {
     override fun apply(project: Project) {
-        val extension = project.extensions.create("magna-carta", MagnaCartaExtension::class)
+        project.extensions.create("magna-carta", MagnaCartaExtension::class)
 
         val downloadToolTask = project.tasks.register("downloadMagnaCartaTool", DownloadMagnaCartaToolTask::class) {
             toolVersion.set("magna-carta-v0.0.1")
@@ -22,7 +22,7 @@ class MagnaCartaPlugin : Plugin<Project> {
             toolExecutable.set(downloadToolTask.flatMap { it.outputFile })
             target.set("jvm")
             inputDir.set(project.projectDir.resolve("src"))
-            outputDir.set(project.layout.buildDirectory.dir("generated/magna-carta/jvm"))
+            outputDir.set(project.layout.buildDirectory.dir("magna-carta/jvmMain"))
         }
 
         val generateNativeTask = project.tasks.register("generateMagnaCartaNative", GenerateMagnaCartaTask::class) {
@@ -30,7 +30,7 @@ class MagnaCartaPlugin : Plugin<Project> {
             toolExecutable.set(downloadToolTask.flatMap { it.outputFile })
             target.set("native")
             inputDir.set(project.projectDir.resolve("src"))
-            outputDir.set(project.layout.buildDirectory.dir("generated/magna-carta/native"))
+            outputDir.set(project.layout.buildDirectory.dir("magna-carta/nativeLibMain"))
         }
 
         project.pluginManager.withPlugin("org.jetbrains.kotlin.multiplatform") {
@@ -42,11 +42,11 @@ class MagnaCartaPlugin : Plugin<Project> {
                     jvmMain.kotlin.srcDir(generateJvmTask.map { it.outputDir })
                 }
 
-                val nativeMain = findByName("nativeMain") ?: create("nativeMain")
-                nativeMain.kotlin.srcDir(generateNativeTask.map { it.outputDir })
+                val nativeLibMain = findByName("nativeLibMain") ?: create("nativeLibMain")
+                nativeLibMain.kotlin.srcDir(generateNativeTask.map { it.outputDir })
 
                 kotlin.targets.withType(KotlinNativeTarget::class.java) {
-                    compilations.getByName("main").defaultSourceSet.dependsOn(nativeMain)
+                    compilations.getByName("main").defaultSourceSet.dependsOn(nativeLibMain)
                 }
             }
 
@@ -54,7 +54,17 @@ class MagnaCartaPlugin : Plugin<Project> {
             kotlin.targets.all {
                 this.compilations.all {
                     this.compileTaskProvider.configure {
-                        this.dependsOn(generateJvmTask, generateNativeTask)
+                        when (this.name) {
+                            "compileKotlinNative" -> {
+                                this.dependsOn(generateNativeTask)
+                            }
+                            "compileKotlinJvm" -> {
+                                this.dependsOn(generateJvmTask)
+                            }
+                            else -> {
+                                println("Unknown compilation task: ${this.name}")
+                            }
+                        }
                     }
                 }
             }
diff --git a/magna-carta/src/generator/jvm.rs b/magna-carta/src/generator/jvm.rs
index de4b1d2..74b1c89 100644
--- a/magna-carta/src/generator/jvm.rs
+++ b/magna-carta/src/generator/jvm.rs
@@ -14,11 +14,14 @@ impl Generator for KotlinJVMGenerator {
 
         writeln!(
             output,
-            "// Auto-generated by dropbear-engine with the magna-carta parser on {}",
+            "// Auto-generated by dropbear-engine with the magna-carta parser on {} UTC",
             local_time.format("%Y-%m-%d %H:%M:%S")
         )?;
         writeln!(output)?;
 
+        writeln!(output, "package com.dropbear.decl")?;
+
+        writeln!(output)?;
         let mut imported_packages = std::collections::HashSet::new();
         for item in manifest.items() {
             if let Some(last_dot) = item.fqcn().rfind('.') {
diff --git a/magna-carta/src/generator/mod.rs b/magna-carta/src/generator/mod.rs
index b7ad01a..b3dc739 100644
--- a/magna-carta/src/generator/mod.rs
+++ b/magna-carta/src/generator/mod.rs
@@ -4,10 +4,15 @@ use std::path::Path;
 pub mod jvm;
 pub mod native;
 
-#[allow(dead_code)]
+/// A trait that can generate code from a manifest.
 pub trait Generator {
+    /// Generate code from a manifest.
+    ///
+    /// # Returns
+    /// [`anyhow::Result<String>`] - The code from the manifest into that specific language.
     fn generate(&self, manifest: &ScriptManifest) -> anyhow::Result<String>;
 
+    /// Writes to a file using the std library.
     fn write_to_file(
         &self,
         manifest: &ScriptManifest,
diff --git a/magna-carta/src/generator/native.rs b/magna-carta/src/generator/native.rs
index f63a355..c659467 100644
--- a/magna-carta/src/generator/native.rs
+++ b/magna-carta/src/generator/native.rs
@@ -12,7 +12,7 @@ impl Generator for KotlinNativeGenerator {
         let local_time = Utc::now();
         writeln!(
             output,
-            "// Auto-generated by dropbear-engine with the magna-carta parser on {}",
+            "// Auto-generated by dropbear-engine with the magna-carta parser on {} UTC",
             local_time.format("%Y-%m-%d %H:%M:%S")
         )?;
         writeln!(
@@ -21,12 +21,17 @@ impl Generator for KotlinNativeGenerator {
         )?;
         writeln!(output)?;
 
+        writeln!(output, "package com.dropbear.decl")?;
+        writeln!(output)?;
+
         writeln!(output, "import com.dropbear.DropbearEngine")?;
         writeln!(output, "import com.dropbear.EntityId")?;
         writeln!(output, "import com.dropbear.EntityRef")?;
+        writeln!(output, "import com.dropbear.System")?;
         writeln!(output, "import com.dropbear.ffi.NativeEngine")?;
         writeln!(output, "import kotlinx.cinterop.COpaquePointer")?;
         writeln!(output, "import kotlinx.cinterop.ExperimentalForeignApi")?;
+        writeln!(output, "import kotlin.experimental.ExperimentalNativeApi")?;
         writeln!(output, "import kotlin.native.CName")?;
         writeln!(output)?;
 
diff --git a/magna-carta/src/main.rs b/magna-carta/src/main.rs
index e60e425..b561306 100644
--- a/magna-carta/src/main.rs
+++ b/magna-carta/src/main.rs
@@ -11,14 +11,20 @@ struct Cli {
     #[arg(short, long, help = "Input directory containing Kotlin source files")]
     input: PathBuf,
 
-    #[arg(short, long, help = "Output directory for generated files")]
-    output: PathBuf,
+    #[arg(short, long, help = "Output directory for generated files (ignored if --stdout is used)")]
+    output: Option<PathBuf>,
 
     #[arg(short, long, help = "Target platform")]
     target: Target,
+
+    #[arg(long, help = "Print generated manifest to stdout instead of writing to file")]
+    stdout: bool,
+
+    #[arg(long, help = "Print manifest raw")]
+    raw: bool,
 }
 
-#[derive(ValueEnum, Clone)]
+#[derive(ValueEnum, Clone, Debug)]
 enum Target {
     Jvm,
     Native,
@@ -27,6 +33,10 @@ enum Target {
 fn main() -> anyhow::Result<()> {
     let cli = Cli::parse();
 
+    if !cli.stdout && cli.output.is_none() {
+        return Err(anyhow::anyhow!("--output is required unless --stdout is used"));
+    }
+
     let mut processor = KotlinProcessor::new()?;
     let mut manifest = ScriptManifest::new();
 
@@ -36,21 +46,34 @@ fn main() -> anyhow::Result<()> {
 
     visit_kotlin_files(&cli.input, &mut processor, &mut manifest)?;
 
-    fs::create_dir_all(&cli.output)?;
-
-    match cli.target {
+    let generated_content = match cli.target {
         Target::Jvm => {
             let generator = KotlinJVMGenerator;
-            let output_path = cli.output.join("RunnableRegistry.kt");
-            generator.write_to_file(&manifest, &output_path)?;
-            println!("Generated JVM manifest at: {}", output_path.display());
+            generator.generate(&manifest)?
         }
         Target::Native => {
             let generator = KotlinNativeGenerator;
-            let output_path = cli.output.join("ScriptManifest.kt");
-            generator.write_to_file(&manifest, &output_path)?;
-            println!("Generated Native manifest at: {}", output_path.display());
+            generator.generate(&manifest)?
         }
+    };
+
+    if cli.raw {
+        println!("{:#?}", manifest);
+    }
+
+    if cli.stdout {
+        print!("{}", generated_content);
+    } else {
+        let output_dir = cli.output.unwrap();
+        fs::create_dir_all(&output_dir)?;
+
+        let filename = match cli.target {
+            Target::Jvm => "RunnableRegistry.kt",
+            Target::Native => "ScriptManifest.kt",
+        };
+        let output_path = output_dir.join(filename);
+        fs::write(&output_path, generated_content)?;
+        println!("Generated {:?} manifest at: {}", cli.target, output_path.display());
     }
 
     println!("Found {} script classes", manifest.items().len());
@@ -66,18 +89,18 @@ fn visit_kotlin_files(
         for entry in fs::read_dir(dir)? {
             let entry = entry?;
             let path = entry.path();
-            
+
             if path.is_dir() {
                 visit_kotlin_files(&path, processor, manifest)?;
             } else if path.extension() == Some(std::ffi::OsStr::new("kt")) {
                 let source_code = fs::read_to_string(&path)?;
-                
+
                 if let Some(item) = processor.process_file(&source_code, path.clone())? {
                     manifest.add_item(item);
                 }
             }
         }
     }
-    
+
     Ok(())
 }
\ No newline at end of file