"Undefined symbol: __swift_FORCE_LOAD_$_swiftCompatibility56" or "Symbol not found: (_objc_claimAutoreleasedReturnValue)"

I'm working on a Payment SDK integrating Storekit2 for Unity games. The workflow is as follows:

  1. build the swift project that exposes objective c interface to static libraries, then archive them into xcframework
  2. embed the xcframework into native unity plugin where we call objective-c functions from C#
  3. export the unity project to Xcode project
  4. build the game Xcode project

When deployment target of swift project is set to iOS15

No matter what iOS version target is set in the game Xcode project, I got build error:

Undefined symbol: __swift_FORCE_LOAD_$_swiftCompatibility56

When deployment target of swift project is set to iOS16

And set the deployment target of game project to iOS15 (I need to let the payment sdk to work on iOS15 as Storekit2 and swift concurrency shipped with iOS15).

I can build the game Xcode project, and it works on iOS16+ device. But when I run on iOS15 device, I got runtime error:

2024-08-26 18:17:29.289078+0900 ***[1404:95780] Error loading /var/containers/Bundle/Application/123/***/Frameworks/UnityFramework.framework/UnityFramework:  dlopen(/var/containers/Bundle/Application/123/***/Frameworks/UnityFramework.framework/UnityFramework, 0x0109): Symbol not found: (_objc_claimAutoreleasedReturnValue)
  Referenced from: '/private/var/containers/Bundle/Application/123/***/Frameworks/UnityFramework.framework/UnityFramework'
  Expected in: '/usr/lib/libobjc.A.dylib'
2024-08-26 18:17:29.418604+0900 ***[1404:95780] Error loading /var/containers/Bundle/Application/123/***/Frameworks/UnityFramework.framework/UnityFramework:  dlopen(/var/containers/Bundle/Application/123/***/Frameworks/UnityFramework.framework/UnityFramework, 0x0109): Symbol not found: (_objc_claimAutoreleasedReturnValue)
  Referenced from: '/private/var/containers/Bundle/Application/123/***/Frameworks/UnityFramework.framework/UnityFramework'
  Expected in: '/usr/lib/libobjc.A.dylib'

If I chose not to build framework into static libraries but dynamic ones, I can avoid this problem but Unity cannot handle dynamic libraries well when exporting to Xcode project so I have no choice here but to stick to static ones.

minimum reproduction

I made a minimum reproduction project to exclude the process of unity.

  1. a fresh new empty objective-c app project
  2. embed the xcframework built with target iOS15
  3. call a function in the framework in applicationDidFinishLaunch
  4. set the deployment target of main target of the app project to iOS15.
  5. build the project

I still get

Undefined symbol: __swift_FORCE_LOAD_$_swiftCompatibility56

versions

  • Xcode version 15.4
  • Test iOS device version 15.8
Answered by DTS Engineer in 803090022
Here is the GitHub repo

Ta!

With that I was able to reproduce the problem easily.

I’ll note that the error you mentioned isn’t the only error in play. If you look at the full build transcript — something I talk about more in Command [something] failed with a nonzero exit code — there are actually two warnings and an error:

ld: warning: Could not find or use auto-linked library 'swiftCompatibility56': library 'swiftCompatibility56' not found

ld: warning: Could not find or use auto-linked library 'swiftCompatibilityPacks': library 'swiftCompatibilityPacks' not found

Undefined symbols for architecture arm64:
  "__swift_FORCE_LOAD_$_swiftCompatibility56", referenced from:
      __swift_FORCE_LOAD_$_swiftCompatibility56_$_MinimumFramework in libMinimumFramework.a[3](Util.o)

Those warnings are interesting. They suggest that:

  1. The static library is trying to autolink some compatibility stuff.

  2. The linker is unable to find that, probably due to a search path issue.

The easiest way to resolve this is to add a Swift file to the app target. The Swift file can be empty, but its presence tells Xcode that Swift might be in play, and thus to adjust the way it invokes the linker.

Comparing the linker build step in the working and non-working cases I see this:

% diff -c ng.txt ok.txt 
*** ng.txt	Tue Sep 10 13:09:08 2024
--- ok.txt	Tue Sep 10 13:09:02 2024
***************
*** 30,35 ****
--- 30,41 ----
  -no_deduplicate
  -fobjc-arc
  -fobjc-link-runtime
+ -L/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/iphoneos
+ -L/usr/lib/swift
+ -Xlinker
+ -add_ast_path
+ -Xlinker
+ /Users/quinn/Library/Developer/Xcode/DerivedData/MinimumApp-ckfwmiiefkdgcdbqanvnclfzdcoo/Build/Intermediates.noindex/MinimumApp.build/Debug-iphoneos/MinimumApp.build/Objects-normal/arm64/MinimumApp.swiftmodule
  -Xlinker
  -alias
  -Xlinker

The key thing seems to be that linker include path of /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/iphoneos. That’s where those libraries should be found:

% ls -lh /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/iphoneos
…
-rwxr-xr-x  1 quinn  staff    84K  9 Aug 16:47 libswiftCompatibility56.a
…

I guess you could fix this by manually adding that link path, but it might just be easier to include a dummy Swift file in the final target.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Xcode version: 15.4

I made a minimum reproduction project to exclude the process of unity.

Cool, that’d be helpful. Can you upload your test project somewhere (like GitHub) and then post the link here?

IMPORTANT Post the link in the clear, per tip 14 in Quinn’s Top Ten DevForums Tips.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Cool, that’d be helpful. Can you upload your test project somewhere (like GitHub) and then post the link here?

Here is the GitHub repo

Accepted Answer
Here is the GitHub repo

Ta!

With that I was able to reproduce the problem easily.

I’ll note that the error you mentioned isn’t the only error in play. If you look at the full build transcript — something I talk about more in Command [something] failed with a nonzero exit code — there are actually two warnings and an error:

ld: warning: Could not find or use auto-linked library 'swiftCompatibility56': library 'swiftCompatibility56' not found

ld: warning: Could not find or use auto-linked library 'swiftCompatibilityPacks': library 'swiftCompatibilityPacks' not found

Undefined symbols for architecture arm64:
  "__swift_FORCE_LOAD_$_swiftCompatibility56", referenced from:
      __swift_FORCE_LOAD_$_swiftCompatibility56_$_MinimumFramework in libMinimumFramework.a[3](Util.o)

Those warnings are interesting. They suggest that:

  1. The static library is trying to autolink some compatibility stuff.

  2. The linker is unable to find that, probably due to a search path issue.

The easiest way to resolve this is to add a Swift file to the app target. The Swift file can be empty, but its presence tells Xcode that Swift might be in play, and thus to adjust the way it invokes the linker.

Comparing the linker build step in the working and non-working cases I see this:

% diff -c ng.txt ok.txt 
*** ng.txt	Tue Sep 10 13:09:08 2024
--- ok.txt	Tue Sep 10 13:09:02 2024
***************
*** 30,35 ****
--- 30,41 ----
  -no_deduplicate
  -fobjc-arc
  -fobjc-link-runtime
+ -L/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/iphoneos
+ -L/usr/lib/swift
+ -Xlinker
+ -add_ast_path
+ -Xlinker
+ /Users/quinn/Library/Developer/Xcode/DerivedData/MinimumApp-ckfwmiiefkdgcdbqanvnclfzdcoo/Build/Intermediates.noindex/MinimumApp.build/Debug-iphoneos/MinimumApp.build/Objects-normal/arm64/MinimumApp.swiftmodule
  -Xlinker
  -alias
  -Xlinker

The key thing seems to be that linker include path of /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/iphoneos. That’s where those libraries should be found:

% ls -lh /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/iphoneos
…
-rwxr-xr-x  1 quinn  staff    84K  9 Aug 16:47 libswiftCompatibility56.a
…

I guess you could fix this by manually adding that link path, but it might just be easier to include a dummy Swift file in the final target.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

I guess you could fix this by manually adding that link path, but it might just be easier to include a dummy Swift file in the final target.

It works.

Is this the expected behavior of Xcode? Shouldn't Xcode handle this scenario automatically? Does Apple consider it an Xcode bug and fix it in the future?

Is this the expected behavior of Xcode?

Well, not by you, obviously (-:

Seriously though, I’ve found that questions like that aren’t relevant. Rather, if Xcode isn’t behaving the way that you want it to behave, the best path forward is to file a bug requesting a change.

Please post your bug number, just for the record.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Please post your bug number, just for the record.

FB15160728

"Undefined symbol: __swift_FORCE_LOAD_$_swiftCompatibility56" or "Symbol not found: (_objc_claimAutoreleasedReturnValue)"
 
 
Q