109/109 host tests pass; tests/cross_compile.sh's first real tuple
(`android | examples/ffi-objc-call-10-os-gate.sx`) compiles
through `sx build --target android` without finding any
`@objc_msgSend` / `@sel_registerName` symbols in the output —
the `inline if OS == .ios { #objc_call(...) }` arm is stripped
at sx compile time before emit_llvm runs, so the Android
toolchain (Bionic + libGLESv3 / NDK linker) doesn't see the
Obj-C runtime references that would otherwise be undefined.
Host (macOS): the example prints "host stripped both" — the iOS
arm is stripped (we're not iOS) AND the Android arm is stripped
(we're not Android), confirming `inline if OS == { case }`
symmetric strip-and-render works around `#objc_call` sites.
The example carries a 3-line `android_main` trampoline so the
NDK linker's `-u ANativeActivity_onCreate` / entry-point
discovery is satisfied — pattern shared with chess + the other
android examples.
44 lines
1.5 KiB
Plaintext
44 lines
1.5 KiB
Plaintext
// Phase 1 step 1.14 (PLAN-FFI.md): `#objc_call` inside an
|
|
// `inline if OS == .ios { ... }` arm cross-compiles cleanly to
|
|
// Android. The comptime gate must strip the arm BEFORE the
|
|
// `objc_msg_send` lowering runs, otherwise emit_llvm would
|
|
// produce calls to `@objc_msgSend` / `@sel_registerName` that
|
|
// don't exist in Bionic + libGLESv3 / linker would fail.
|
|
//
|
|
// On macOS the iOS arm is also stripped (we're not iOS) so the
|
|
// runtime test just prints "host stripped both", proving the
|
|
// `inline if OS == { case }` form works around `#objc_call`
|
|
// sites the same way it does elsewhere.
|
|
|
|
#import "modules/std.sx";
|
|
#import "modules/compiler.sx";
|
|
|
|
main :: () -> s32 {
|
|
inline if OS == {
|
|
case .ios: {
|
|
// Stripped on macOS + Android. Compiled on iOS / ios-sim.
|
|
#objc_call(void)(null, "init");
|
|
print("ios path\n");
|
|
}
|
|
case .android: {
|
|
// Stripped on macOS + iOS. Compiled on Android.
|
|
// Nothing #objc_call-shaped here — just text — so we
|
|
// exercise the gate symmetrically across targets.
|
|
print("android path\n");
|
|
}
|
|
else: {
|
|
print("host stripped both\n");
|
|
}
|
|
}
|
|
0;
|
|
}
|
|
|
|
// Android target requires `android_main` as the NDK entry — kept as
|
|
// a 3-line trampoline so this example can pass through
|
|
// `--target android` builds in `tests/cross_compile.sh`.
|
|
android_main :: (app: *void) {
|
|
inline if OS == .android {
|
|
main();
|
|
}
|
|
}
|