fix(ios,macos): add static @_cdecl references to defeat dead-strip
PR #26 review (Oracle): dlsym(RTLD_DEFAULT, name) does NOT count as a static linker reference, so the @_cdecl Swift functions were still eligible for dead-stripping under Whole-Module-Optimization + LTO in Xcode Archive builds. This is the actual root cause of the TestFlight regression — the prior verify_silero_exports.sh fix only catches the symptom (missing symbol) at build time, it does not prevent the stripping. The fix adds 6 static '_ = unsafeBitCast(<fn> as @convention(c) ...)' references inside ChanoraSileroSelfTest.run() before the existing dlsym probe. The @convention(c) cast forces address-taken semantics, which the optimizer cannot prove unused. Applied identically to ios/Runner/SileroCoreMLBridge.swift and macos/Runner/SileroCoreMLBridge.swift (the files were and remain byte-identical). cargo check --workspace: clean dart analyze: clean
This commit is contained in:
@@ -106,6 +106,45 @@ public func chanoraSileroVadFreeString(_ string: UnsafeMutablePointer<CChar>?) {
|
|||||||
@objc public static func run() {
|
@objc public static func run() {
|
||||||
let started = DispatchTime.now()
|
let started = DispatchTime.now()
|
||||||
|
|
||||||
|
// Static linker references: keep the Swift compiler / linker from
|
||||||
|
// dead-stripping the @_cdecl symbols under Whole-Module-Optimization
|
||||||
|
// + LTO in Archive builds. dlsym(RTLD_DEFAULT) below does NOT count
|
||||||
|
// as a static reference for the dead-stripper — these `_ = ` lines
|
||||||
|
// do. Without them, TestFlight builds shipped without the symbols
|
||||||
|
// even though Debug builds (no LTO) worked.
|
||||||
|
//
|
||||||
|
// The `withoutActuallyEscaping` dance prevents the optimizer from
|
||||||
|
// proving the references are unused: assigning the function value
|
||||||
|
// to a `@convention(c)` typealias forces address-taken semantics.
|
||||||
|
_ = unsafeBitCast(
|
||||||
|
chanoraSileroVadCreate as @convention(c) () -> UnsafeMutableRawPointer?,
|
||||||
|
to: UnsafeRawPointer.self,
|
||||||
|
)
|
||||||
|
_ = unsafeBitCast(
|
||||||
|
chanoraSileroVadDestroy as @convention(c) (UnsafeMutableRawPointer?) -> Void,
|
||||||
|
to: UnsafeRawPointer.self,
|
||||||
|
)
|
||||||
|
_ = unsafeBitCast(
|
||||||
|
chanoraSileroVadReset as @convention(c) (UnsafeMutableRawPointer?) -> Int32,
|
||||||
|
to: UnsafeRawPointer.self,
|
||||||
|
)
|
||||||
|
_ = unsafeBitCast(
|
||||||
|
chanoraSileroVadProcess
|
||||||
|
as @convention(c) (
|
||||||
|
UnsafeMutableRawPointer?, UnsafePointer<Float>?, Int,
|
||||||
|
UnsafeMutablePointer<Float>?
|
||||||
|
) -> Int32,
|
||||||
|
to: UnsafeRawPointer.self,
|
||||||
|
)
|
||||||
|
_ = unsafeBitCast(
|
||||||
|
chanoraSileroVadLastError as @convention(c) () -> UnsafeMutablePointer<CChar>?,
|
||||||
|
to: UnsafeRawPointer.self,
|
||||||
|
)
|
||||||
|
_ = unsafeBitCast(
|
||||||
|
chanoraSileroVadFreeString as @convention(c) (UnsafeMutablePointer<CChar>?) -> Void,
|
||||||
|
to: UnsafeRawPointer.self,
|
||||||
|
)
|
||||||
|
|
||||||
typealias CreateFn = @convention(c) () -> UnsafeMutableRawPointer?
|
typealias CreateFn = @convention(c) () -> UnsafeMutableRawPointer?
|
||||||
typealias DestroyFn = @convention(c) (UnsafeMutableRawPointer?) -> Void
|
typealias DestroyFn = @convention(c) (UnsafeMutableRawPointer?) -> Void
|
||||||
typealias ResetFn = @convention(c) (UnsafeMutableRawPointer?) -> Int32
|
typealias ResetFn = @convention(c) (UnsafeMutableRawPointer?) -> Int32
|
||||||
|
|||||||
@@ -106,6 +106,45 @@ public func chanoraSileroVadFreeString(_ string: UnsafeMutablePointer<CChar>?) {
|
|||||||
@objc public static func run() {
|
@objc public static func run() {
|
||||||
let started = DispatchTime.now()
|
let started = DispatchTime.now()
|
||||||
|
|
||||||
|
// Static linker references: keep the Swift compiler / linker from
|
||||||
|
// dead-stripping the @_cdecl symbols under Whole-Module-Optimization
|
||||||
|
// + LTO in Archive builds. dlsym(RTLD_DEFAULT) below does NOT count
|
||||||
|
// as a static reference for the dead-stripper — these `_ = ` lines
|
||||||
|
// do. Without them, TestFlight builds shipped without the symbols
|
||||||
|
// even though Debug builds (no LTO) worked.
|
||||||
|
//
|
||||||
|
// The `withoutActuallyEscaping` dance prevents the optimizer from
|
||||||
|
// proving the references are unused: assigning the function value
|
||||||
|
// to a `@convention(c)` typealias forces address-taken semantics.
|
||||||
|
_ = unsafeBitCast(
|
||||||
|
chanoraSileroVadCreate as @convention(c) () -> UnsafeMutableRawPointer?,
|
||||||
|
to: UnsafeRawPointer.self,
|
||||||
|
)
|
||||||
|
_ = unsafeBitCast(
|
||||||
|
chanoraSileroVadDestroy as @convention(c) (UnsafeMutableRawPointer?) -> Void,
|
||||||
|
to: UnsafeRawPointer.self,
|
||||||
|
)
|
||||||
|
_ = unsafeBitCast(
|
||||||
|
chanoraSileroVadReset as @convention(c) (UnsafeMutableRawPointer?) -> Int32,
|
||||||
|
to: UnsafeRawPointer.self,
|
||||||
|
)
|
||||||
|
_ = unsafeBitCast(
|
||||||
|
chanoraSileroVadProcess
|
||||||
|
as @convention(c) (
|
||||||
|
UnsafeMutableRawPointer?, UnsafePointer<Float>?, Int,
|
||||||
|
UnsafeMutablePointer<Float>?
|
||||||
|
) -> Int32,
|
||||||
|
to: UnsafeRawPointer.self,
|
||||||
|
)
|
||||||
|
_ = unsafeBitCast(
|
||||||
|
chanoraSileroVadLastError as @convention(c) () -> UnsafeMutablePointer<CChar>?,
|
||||||
|
to: UnsafeRawPointer.self,
|
||||||
|
)
|
||||||
|
_ = unsafeBitCast(
|
||||||
|
chanoraSileroVadFreeString as @convention(c) (UnsafeMutablePointer<CChar>?) -> Void,
|
||||||
|
to: UnsafeRawPointer.self,
|
||||||
|
)
|
||||||
|
|
||||||
typealias CreateFn = @convention(c) () -> UnsafeMutableRawPointer?
|
typealias CreateFn = @convention(c) () -> UnsafeMutableRawPointer?
|
||||||
typealias DestroyFn = @convention(c) (UnsafeMutableRawPointer?) -> Void
|
typealias DestroyFn = @convention(c) (UnsafeMutableRawPointer?) -> Void
|
||||||
typealias ResetFn = @convention(c) (UnsafeMutableRawPointer?) -> Int32
|
typealias ResetFn = @convention(c) (UnsafeMutableRawPointer?) -> Int32
|
||||||
|
|||||||
Reference in New Issue
Block a user