// 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), ) }