Undefined C++ symbols in pure Objective-C library target

I'm using the 5.3 snapshot from June 2nd to add support for SPM to my pure Objective-C framework with resources: https://github.com/Kentzo/ShortcutRecorder/blob/spm/Package.swift

To test it I generated an executable package with swift package init --type executable and then added a dependency as following:

.package(url: "git@github.com:Kentzo/ShortcutRecorder.git", .revision("..."))

However, when I'm trying to build it via swift build I get:

Undefined symbols for architecture x86_64:
"___cxa_guard_acquire", referenced from:
_SRBundle in SRCommon.m.o
+[SRKeyBindingTransformer sharedTransformer] in SRKeyBindingTransformer.m.o
-[SRKeyBindingTransformer transformedValue:] in SRKeyBindingTransformer.m.o
+[_SRKeyCodeTranslator shared] in SRKeyCodeTransformer.m.o
+[_SRKeyCodeASCIITranslator shared] in SRKeyCodeTransformer.m.o
+[SRKeyCodeTransformer knownKeyCodes] in SRKeyCodeTransformer.m.o
+[SRKeyCodeTransformer specialKeyCodeToSymbolMapping] in SRKeyCodeTransformer.m.o
...
"___cxa_guard_release", referenced from:
_SRBundle in SRCommon.m.o
+[SRKeyBindingTransformer sharedTransformer] in SRKeyBindingTransformer.m.o
-[SRKeyBindingTransformer transformedValue:] in SRKeyBindingTransformer.m.o
+[_SRKeyCodeTranslator shared] in SRKeyCodeTransformer.m.o
+[_SRKeyCodeASCIITranslator shared] in SRKeyCodeTransformer.m.o
+[SRKeyCodeTransformer knownKeyCodes] in SRKeyCodeTransformer.m.o
+[SRKeyCodeTransformer specialKeyCodeToSymbolMapping] in SRKeyCodeTransformer.m.o
...

I'm surprised to see these symbols as there are no C++ or Objective-C++ files in my project. When I build the framework using Xcode from ShortcutRecorder.xcodeproj the compiler does not insert these calls.

Here is the output of compiling SRCommon.m.o as part of the executable via `swift build`:

/Library/Developer/Toolchains/swift-5.3-DEVELOPMENT-SNAPSHOT-2020-06-02-a.xctoolchain/usr/bin/clang
-fobjc-arc
-target x86_64-apple-macosx10.11
-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk
-F /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Frameworks
-g
-O0
-DSWIFT_PACKAGE=1
-DDEBUG=1
-fblocks
-index-store-path /private/tmp/example/.build/x86_64-apple-macosx/debug/index/store
-fmodules
-fmodule-name=ShortcutRecorder
-I /private/tmp/example/.build/checkouts/ShortcutRecorder/Sources/ShortcutRecorder/include/ShortcutRecorder
-fmodules-cache-path=/private/tmp/example/.build/x86_64-apple-macosx/debug/ModuleCache
-I/private/tmp/example/.build/checkouts/ShortcutRecorder/Sources/ShortcutRecorder/include
-include /private/tmp/example/.build/x86_64-apple-macosx/debug/ShortcutRecorder.build/DerivedSources/resource_bundle_accessor.h
-MD
-MT dependencies
-MF /private/tmp/example/.build/x86_64-apple-macosx/debug/ShortcutRecorder.build/SRCommon.m.d
-c /private/tmp/example/.build/checkouts/ShortcutRecorder/Sources/ShortcutRecorder/SRCommon.m
-o /private/tmp/example/.build/x86_64-apple-macosx/debug/ShortcutRecorder.build/SRCommon.m.o

Same file via Xcode and ShortcutRecorder.xcodeproj:

/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang
-x objective-c
-target x86_64-apple-macos10.11
-fmessage-length=0
-fdiagnostics-show-note-include-stack
-fmacro-backtrace-limit=0
-fobjc-arc
-fmodules
-gmodules
-fmodules-cache-path=.../DerivedData/ModuleCache.noindex
-fmodules-prune-interval=86400
-fmodules-prune-after=345600
-fbuild-session-file=.../DerivedData/ModuleCache.noindex/Session.modulevalidation
-fmodules-validate-once-per-build-session
-Wnon-modular-include-in-framework-module
-Werror=non-modular-include-in-framework-module
-fmodule-name=ShortcutRecorder
-Wno-trigraphs
-fpascal-strings
-O0
-fno-common
-DDEBUG
-DOBJC_OLD_DISPATCH_PROTOTYPES=0
-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk
-fasm-blocks
-fstrict-aliasing
-Wprotocol
-Wdeprecated-declarations
-g
-mssse3
-Wno-sign-conversion
-Winfinite-recursion
-Wcomma
-Wblock-capture-autoreleasing
-Wstrict-prototypes
-Wno-semicolon-before-method-body
-fprofile-instr-generate
-fcoverage-mapping
-index-store-path .../DerivedData/ShortcutRecorder/Index/DataStore
-iquote .../DerivedData/ShortcutRecorder/Build/Intermediates.noindex/ShortcutRecorder.build/Debug/ShortcutRecorder.framework.build/ShortcutRecorder-generated-files.hmap
-I.../DerivedData/ShortcutRecorder/Build/Intermediates.noindex/ShortcutRecorder.build/Debug/ShortcutRecorder.framework.build/ShortcutRecorder-own-target-headers.hmap
-I.../DerivedData/ShortcutRecorder/Build/Intermediates.noindex/ShortcutRecorder.build/Debug/ShortcutRecorder.framework.build/ShortcutRecorder-all-non-framework-target-headers.hmap
-ivfsoverlay .../DerivedData/ShortcutRecorder/Build/Intermediates.noindex/ShortcutRecorder.build/Debug/ShortcutRecorder.framework.build/all-product-headers.yaml
-iquote .../DerivedData/ShortcutRecorder/Build/Intermediates.noindex/ShortcutRecorder.build/Debug/ShortcutRecorder.framework.build/ShortcutRecorder-project-headers.hmap
-I.../DerivedData/ShortcutRecorder/Build/Products/Debug/include
-I.../DerivedData/ShortcutRecorder/Build/Intermediates.noindex/ShortcutRecorder.build/Debug/ShortcutRecorder.framework.build/DerivedSources-normal/x86_64
-I.../DerivedData/ShortcutRecorder/Build/Intermediates.noindex/ShortcutRecorder.build/Debug/ShortcutRecorder.framework.build/DerivedSources/x86_64
-I.../DerivedData/ShortcutRecorder/Build/Intermediates.noindex/ShortcutRecorder.build/Debug/ShortcutRecorder.framework.build/DerivedSources
-Wall
-F.../DerivedData/ShortcutRecorder/Build/Products/Debug
-fstack-protector
-MMD
-MT dependencies
-MF .../DerivedData/ShortcutRecorder/Build/Intermediates.noindex/ShortcutRecorder.build/Debug/ShortcutRecorder.framework.build/Objects-normal/x86_64/SRCommon.d
--serialize-diagnostics .../DerivedData/ShortcutRecorder/Build/Intermediates.noindex/ShortcutRecorder.build/Debug/ShortcutRecorder.framework.build/Objects-normal/x86_64/SRCommon.dia
-c .../ShortcutRecorder/Sources/ShortcutRecorder/SRCommon.m
-o .../DerivedData/ShortcutRecorder/Build/Intermediates.noindex/ShortcutRecorder.build/Debug/ShortcutRecorder.framework.build/Objects-normal/x86_64/SRCommon.o

Is there particular reason why my project was recognized as C++ and can I opt-out?

I've been able to circumvent the error by adding linkerSettings: [ .linkedLibrary("c++abi") ] to the library target. Yet I do not understand why my code was treated as C++ at all. I do not want to rely on a possible undefined behavior due do that.

1 Like

Still happens with July 27th snapshot, regardless whether the product is declared as a .static or .dynamic library.

Just tried the very same package with Xcode 12b3: when compiling it adds the -x objective-c flags and when linking it adds the -nostdlib -fobjc-link-runtime flags.

you just saved my day