diff --git a/examples/ffi-objc-call-10-os-gate.sx b/examples/ffi-objc-call-10-os-gate.sx new file mode 100644 index 0000000..1ce16dc --- /dev/null +++ b/examples/ffi-objc-call-10-os-gate.sx @@ -0,0 +1,43 @@ +// 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(); + } +} diff --git a/tests/cross_compile.sh b/tests/cross_compile.sh index 4cd6a4b..559a07f 100755 --- a/tests/cross_compile.sh +++ b/tests/cross_compile.sh @@ -22,9 +22,12 @@ TMP_DIR="${TMPDIR:-/tmp}/sx-cross-compile" mkdir -p "$TMP_DIR" # Tuple format: "|" -# Add entries as cross-only examples land. Empty for now — Phase 0 only -# lays down the runner; baselines live in tests/run_examples.sh territory. -TUPLES=() +# Add entries as cross-only examples land. Verifies the example +# compiles cleanly for the target's NDK / SDK without needing the +# host to actually run it. +TUPLES=( + "android|examples/ffi-objc-call-10-os-gate.sx" +) PASS=0 FAIL=0 diff --git a/tests/expected/ffi-objc-call-10-os-gate.exit b/tests/expected/ffi-objc-call-10-os-gate.exit new file mode 100644 index 0000000..573541a --- /dev/null +++ b/tests/expected/ffi-objc-call-10-os-gate.exit @@ -0,0 +1 @@ +0 diff --git a/tests/expected/ffi-objc-call-10-os-gate.txt b/tests/expected/ffi-objc-call-10-os-gate.txt new file mode 100644 index 0000000..c17ab89 --- /dev/null +++ b/tests/expected/ffi-objc-call-10-os-gate.txt @@ -0,0 +1 @@ +host stripped both