ffi #jni_main: emit static { System.loadLibrary(...); } in the Java class
Required for Android to resolve the `Java_*` symbols R.3 synthesises:
without `System.loadLibrary(...)` running before the Activity calls its
first native method, JNI lookup fails with UnsatisfiedLinkError.
The lib name comes from the build's `-o` basename — `/tmp/libsxchess.so`
→ `sxchess` — derived in `Compilation.collectJniMainEmissions` and
threaded through new `jni_java_emit.Options.lib_name`. When `-o` is
unset (or doesn't match `lib*.so`), the emitter omits the static init
and the caller must arrange loading another way.
dex confirmation on the slice 2 smoke: `<clinit>` static constructor
appears alongside `<init>` and `sx_onCreate` — the bytecode invokes
`System.loadLibrary("sxjnimain")` matching `/tmp/libsxjnimain.so`.
131 host / 4 cross / zig build test all green.
This commit is contained in:
@@ -235,6 +235,40 @@ test "default-package class (no slash in foreign_path)" {
|
||||
try std.testing.expect(std.mem.indexOf(u8, out, "public class SxNoPackage") != null);
|
||||
}
|
||||
|
||||
test "lib_name renders System.loadLibrary static init block" {
|
||||
const a = std.testing.allocator;
|
||||
var arena = std.heap.ArenaAllocator.init(a);
|
||||
defer arena.deinit();
|
||||
const aa = arena.allocator();
|
||||
|
||||
const self_ty = try makePointer(aa, try makeTypeExpr(aa, "Self"));
|
||||
const body = try makeBodyMarker(aa);
|
||||
const method: ast.ForeignClassMember = .{ .method = .{
|
||||
.name = "onCreate",
|
||||
.params = &.{self_ty},
|
||||
.param_names = &.{"self"},
|
||||
.return_type = null,
|
||||
.body = body,
|
||||
} };
|
||||
|
||||
const fcd: ast.ForeignClassDecl = .{
|
||||
.name = "SxApp",
|
||||
.foreign_path = "co/example/SxApp",
|
||||
.runtime = .jni_class,
|
||||
.is_main = true,
|
||||
.members = &.{method},
|
||||
};
|
||||
|
||||
const out = try emit.emitJavaSource(a, &fcd, .{ .lib_name = "sxchess" });
|
||||
defer a.free(out);
|
||||
try std.testing.expect(std.mem.indexOf(u8, out, "static { System.loadLibrary(\"sxchess\"); }") != null);
|
||||
|
||||
// Without lib_name the static init is omitted.
|
||||
const out2 = try emit.emitJavaSource(a, &fcd, .{});
|
||||
defer a.free(out2);
|
||||
try std.testing.expect(std.mem.indexOf(u8, out2, "System.loadLibrary") == null);
|
||||
}
|
||||
|
||||
test "#implements clauses on the class header" {
|
||||
const a = std.testing.allocator;
|
||||
var arena = std.heap.ArenaAllocator.init(a);
|
||||
|
||||
Reference in New Issue
Block a user