Files

73 lines
1.7 KiB
Odin
Raw Permalink Normal View History

2026-09-03 10:44:30 +02:00
// jnigen -- generates JNI binding boilerplate from an annotated Odin spec.
//
// odin run jnigen -- [spec.odin] [out.odin] [package]
//
// The spec is never compiled (it carries `#+build ignore`), so it needs no
// -custom-attribute flags and cannot collide with the generated procs.
package jnigen
import "core:fmt"
import "core:odin/ast"
import "core:odin/parser"
import "core:os"
main :: proc() {
spec_path := "jni_spec.odin"
out_path := "jni_generated.odin"
package_name := "main"
args := os.args[1:]
if len(args) > 0 {
spec_path = args[0]
}
if len(args) > 1 {
out_path = args[1]
}
if len(args) > 2 {
package_name = args[2]
}
src, read_err := os.read_entire_file(spec_path, context.allocator)
if read_err != nil {
fmt.eprintfln("jnigen: cannot read %s: %v", spec_path, read_err)
os.exit(1)
}
p := parser.default_parser()
f := ast.File{
src = string(src),
fullpath = spec_path,
}
if !parser.parse_file(&p, &f) {
fmt.eprintfln("jnigen: failed to parse %s", spec_path)
os.exit(1)
}
g: Gen
g.classes = make(map[string]string)
collect_classes(&g, &f)
collect_bindings(&g, &f)
if len(g.errors) > 0 {
for e in g.errors {
fmt.eprintfln("jnigen: %s", e)
}
os.exit(1)
}
out := emit_file(&g, package_name)
if werr := os.write_entire_file(out_path, transmute([]byte)out); werr != nil {
fmt.eprintfln("jnigen: cannot write %s: %v", out_path, werr)
os.exit(1)
}
fmt.printfln(
"jnigen: %s -> %s (%d classes, %d bindings)",
spec_path,
out_path,
len(g.class_decls),
len(g.bindings),
)
}