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:
21
src/core.zig
21
src/core.zig
@@ -244,6 +244,12 @@ pub const Compilation = struct {
|
||||
try registry.put(entry.key_ptr.*, entry.value_ptr.*.foreign_path);
|
||||
}
|
||||
|
||||
// Derive the `System.loadLibrary` argument from the `-o` basename
|
||||
// (e.g. `/tmp/libsxchess.so` → `sxchess`). When `-o` is unset the
|
||||
// emitter omits the static init block; the user must then arrange
|
||||
// .so loading via another class.
|
||||
const lib_name = libNameFromOutputPath(self.target_config.output_path);
|
||||
|
||||
var it = lowering.foreign_class_map.iterator();
|
||||
while (it.next()) |entry| {
|
||||
const fcd = entry.value_ptr.*;
|
||||
@@ -253,7 +259,10 @@ pub const Compilation = struct {
|
||||
if (seen.contains(fcd.foreign_path)) continue;
|
||||
try seen.put(fcd.foreign_path, {});
|
||||
|
||||
const java_source = try ir.jni_java_emit.emitJavaSource(self.allocator, fcd, .{ .classes = ®istry });
|
||||
const java_source = try ir.jni_java_emit.emitJavaSource(self.allocator, fcd, .{
|
||||
.classes = ®istry,
|
||||
.lib_name = lib_name,
|
||||
});
|
||||
try self.lowering_jni_main_decls.append(self.allocator, .{
|
||||
.foreign_path = try self.allocator.dupe(u8, fcd.foreign_path),
|
||||
.java_source = java_source,
|
||||
@@ -261,6 +270,16 @@ pub const Compilation = struct {
|
||||
}
|
||||
}
|
||||
|
||||
/// `/path/to/libfoo.so` → `foo`. Anything else → null (caller skips
|
||||
/// emitting the `System.loadLibrary` init block).
|
||||
fn libNameFromOutputPath(output_path: ?[]const u8) ?[]const u8 {
|
||||
const path = output_path orelse return null;
|
||||
const basename = std.fs.path.basename(path);
|
||||
if (!std.mem.startsWith(u8, basename, "lib")) return null;
|
||||
if (!std.mem.endsWith(u8, basename, ".so")) return null;
|
||||
return basename[3 .. basename.len - 3];
|
||||
}
|
||||
|
||||
/// Java sources rendered from `#jni_main #jni_class("...")` decls during
|
||||
/// lowering. Empty unless `lowerToIR` has run.
|
||||
pub fn getJniMainEmissions(self: *const Compilation) []const JniMainEmission {
|
||||
|
||||
Reference in New Issue
Block a user