I'm facing a crash when using
#if DEBUG directives in a Swift Package that is linked (but not embedded) to a release build of a static library. If the static library and the Package's library target are then embedded into an App a runtime crash occurs.
If the App target is also build in release or my static library compiles in debug, the crash doesn't occur. Similarly, when I remove all
#if DEBUG directives from the public code in the Swift Package, the App runs fine (in debug, whereas the library can stay in release).
I have created a sample project on GitHub that provides a setup to reproduce this issue.
The SampleProject consists of:
- an App Target called SampleApp
- a Framework Target called SampleFramework
- a local Swift Package called SamplePackage
The Dependency Graph looks like this:
SampleApp └── embeds SampleFramework └── links to SamplePackage └── embeds SamplePackage
If we compile SampleFramework in release configuration and add the binary from the build directory to SampleApp, the following crash be witnessed:
Exception Type: EXC_BAD_ACCESS (SIGSEGV) Exception Subtype: KERN_INVALID_ADDRESS at 0xfffffffffffffff0 Exception Codes: 0x0000000000000001, 0xfffffffffffffff0 VM Region Info: 0xfffffffffffffff0 is not in any region. Bytes after previous region: 18446638520056414193 REGION TYPE START - END [ VSIZE] PRT/MAX SHRMOD REGION DETAIL MALLOC_NANO (reserved) 600018000000-600020000000 [128.0M] rw-/rwx SM=NUL ...(unallocated) ---> UNUSED SPACE AT END Termination Reason: SIGNAL 11 Segmentation fault: 11 Terminating Process: exc handler  Triggered by Thread: 0 Thread 0 Crashed:: Dispatch queue: com.apple.main-thread 0 libswiftCore.dylib 0x18bf8620c _swift_release_dealloc + 16 1 libswiftCore.dylib 0x18bf86df4 bool swift::RefCounts<swift::RefCountBitsT<(swift::RefCountInlinedness)1>>::doDecrementSlow<(swift::PerformDeinit)1>(swift::RefCountBitsT<(swift::RefCountInlinedness)1>, unsigned int) + 128 2 SampleApp 0x100c4de3c outlined destroy of SampleView + 36 3 SampleApp 0x100c4da60 closure #1 in SampleAppApp.body.getter + 108 (SampleApp.swift:15) 4 SwiftUI 0x105cd1b6c 0x1050d4000 + 12573548 5 SampleApp 0x100c4d900 SampleAppApp.body.getter + 144 (SampleApp.swift:14) 6 SampleApp 0x100c4dd98 protocol witness for App.body.getter in conformance SampleAppApp + 12
This crash raises the following questions for me and I haven't been able to find any answers?
- Should Compiler Directives like
#if DEBUGnot be distributed in the
publiccode of a Swift Package and are known to cause crashes when linked to binary frameworks?
- What kind of references to a Swift Package dependency are compiled into a static library by Xcode, when the Package is only added via Target Dependencies, but not to Frameworks, Libraries and Embedded Content?
The crash looks to me like the static library, when compiled in release configuration always assumes its dependency (in this case the Swift Package) to be compiled and linked in the same configuration. When the App integrates both, but compiles the Swift Package's code in debug the static library doesn't seem to like that. But this can't be right?