Linking Swift frameworks to an Unreal Engine project
It’s very rare to find an app without the usage of third-party SDKs. Whether you are working on a casual puzzle or an open-world adventure, there’s a point in the project development cycle when you have to rely on some other peoples’ code doing things for you: collecting and sending crash log data, collecting in-game metrics, helping with monetization, and so on.
Third-party SDKs on iOS are usually distributed in the form of a framework. A framework is either a static or a dynamic library, corresponding headers, module descriptions, and an optional resource bundle.
When integrating iOS framework with an Unreal Engine project, two most common issues happen, and both of them are related to linking the libraries. In this post I will describe the issues and give a solution to them.
Crash on startup “DYLD Library not loaded” or “DYLD Library missing”
If your app crashes on startup with the reason “DYLD Library missing” or “DYLD Library not loaded”, it means that
dyld couldn’t find some libraries in
@rpath. You can tell this kind of issue by the crash log. It will look something like this:
Exception Type: EXC_CRASH (SIGABRT) Exception Codes: 0x0000000000000000, 0x0000000000000000 Exception Note: EXC_CORPSE_NOTIFY Termination Reason: DYLD 1 Library missing Library not loaded: '@rpath/swift_framework_dynamic.framework/swift_framework_dynamic' Referenced from: '/Volumes/VOLUME/*/MyApp.app/MyApp' Reason: tried: '' (no such file) Triggered by Thread: 0 Thread 0 Crashed: 0 dyld 0x11cf4cb14 __abort_with_payload + 8 1 dyld 0x11cf526cc abort_with_payload_wrapper_internal + 104 2 dyld 0x11cf52700 abort_with_payload + 16 3 dyld 0x11cf22a00 dyld4::halt(char const*) + 580 4 dyld 0x11cf1fa20 dyld4::prepare(dyld4::APIs&, dyld3::MachOAnalyzer const*) + 3560 5 dyld 0x11cf1dd84 start + 488
This crash log says: while executing
MyApp binary from bundle
dyld couldn’t load
swift_framework_dynamic binary from
Dyld tried to load the library from
dyld and @rpath
The dynamic linker (
dyld) is the entry point of the app. Before the app is launched,
dyld loads necessary libraries into memory. It knows where to look for libraries from a special attribute of the app binary called
@rpath stands for Runtime Search Path. Its value is set during build, either using Xcode
LD_RUNPATH_SEARCH_PATH setting or
-rpath parameter of
ld linker command tool. It can be set to several values, one of which usually is
@executable_path/Frameworks, a Frameworks subdirectory in the app bundle.
To get Runpaths of binary, you can use
otool -l MyApp.app/MyApp and look at the
LC_RPATH in the output:
Load command 92 cmd LC_RPATH cmdsize 40 path @executable_path/Frameworks (offset 12)
You can manipulate Runpaths using
Fixing the crash
To fix the crash, you should put the library into the
Frameworks directory in the bundle. Do this by adding
copyDir node to UPL file:
<copyDir src="$S(EngineDir)/Intermediate/UnzippedFrameworks/swift_framework_dynamic/swift_framework_dynamic.embeddedframework/swift_framework_dynamic.framework" dst="$S(BuildDir)/Frameworks/swift_framework_dynamic.framework" />
Linker error “Could not find or use auto-linked library” when using Swift static library
When you add a static framework containing Swift classes to an Unreal Engine project, you have to tell the linker where it should look for Swift libraries. In Xcode this is “Library Search Paths” setting in the Build Settings of a target.
If you get errors similar to these:
ld: warning: Could not find or use auto-linked library 'swiftFoundation' ld: warning: Could not find or use auto-linked library 'swiftsimd' ld: warning: Could not find or use auto-linked library 'swiftMetal' ld: warning: Could not find or use auto-linked library 'swiftDarwin' ld: warning: Could not find or use auto-linked library 'swiftCoreFoundation' ld: warning: Could not find or use auto-linked library 'swiftObjectiveC' ld: warning: Could not find or use auto-linked library 'swiftCore' ld: warning: Could not find or use auto-linked library 'swiftAVFoundation' ld: warning: Could not find or use auto-linked library 'swiftCoreMedia' ld: warning: Could not find or use auto-linked library 'swiftCoreGraphics' ld: warning: Could not find or use auto-linked library 'swiftCoreImage' ld: warning: Could not find or use auto-linked library 'swiftCoreAudio'
that’s because the library you added to the project requires Swift libraries to link. By default Unreal Engine does not have paths to Swift libraries added to Library Search paths, so you have to point UBT to it. Swift libraries are located in Xcode toolchain. Add this to your plugin
string SDKROOT = Utils.RunLocalProcessAndReturnStdOut("/usr/bin/xcrun", "--sdk iphoneos --show-sdk-path"); PublicSystemLibraryPaths.Add(SDKROOT + "/usr/lib/swift"); PublicSystemLibraryPaths.Add(SDKROOT + "../../../../../../Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/iphoneos"); PublicSystemLibraryPaths.Add(SDKROOT + "../../../../../../Toolchains/XcodeDefault.xctoolchain/usr/lib/swift-5.0/iphoneos"); PublicSystemLibraryPaths.Add(SDKROOT + "../../../../../../Toolchains/XcodeDefault.xctoolchain/usr/lib/swift-5.5/iphoneos");
and you are ready to go!