Integration of Swift library into UE4

Recently, the problem arose of integrating code that was written only in Swift into a project on UE4. At the same time, the option "let's quickly rewrite everything in Objective C" was not considered. I could not find a ready-made solution anywhere, I had, as is often the case, to dig both in breadth and in depth. The task was successfully solved and in order to help someone else, I decided to write a tutorial.



Usually, if you need to integrate any code specific to the iOS / macOS platform, the library assembly is used as a Framework, which must be static. The code itself is written in Objective C. Further, the dependency is written in the project build script MyProject.Build.cs, for example, like this:



if (Target.Platform == UnrealTargetPlatform.IOS)
{
    string ExtraPath = Path.GetFullPath(Path.Combine(ModuleDirectory, "../ThirdParty"));
    PublicAdditionalFrameworks.Add(
        new Framework(
            "MyFramework",
            ExtraPath + "/" + "MyFramework.framework.zip"
        )
    );
}


For Swift, you can try to go the same way, but there will be a problem - dependence on some language libraries. The link warning will look like this:



ld: warning: Could not find auto-linked library 'swiftFoundation'
ld: warning: Could not find auto-linked library 'swiftDarwin'
ld: warning: Could not find auto-linked library 'swiftCoreFoundation'
ld: warning: Could not find auto-linked library 'swiftCore'
ld: warning: Could not find auto-linked library 'swiftCoreGraphics'
ld: warning: Could not find auto-linked library 'swiftObjectiveC'
ld: warning: Could not find auto-linked library 'swiftDispatch'
ld: warning: Could not find auto-linked library 'swiftSwiftOnoneSupport'


After that, standard errors will follow that some symbols were not found in object files. You can try to find where each library mentioned above is located and specify the path to it through the L key, but I decided to switch to the Framework dynamic type, which will load these libraries itself.



, iOS :



dyld: Library not loaded: @rpath/MyFramework.framework/MyFramework
  Referenced from: /private/var/mobile/Containers/Bundle/Application/.../MyApp.app/MyApp
  Reason: image not found


, UE4 Framework, . IOS Toolchain , IOSPlugin.



plist , , :



<iosPListUpdates>
    <addElements tag="dict" once="true">
        <key>NSCameraUsageDescription</key>
        <string>The camera is used for live preview.</string>
    </addElements>
</iosPListUpdates>


copyDir. , , :



<init>
    <log text="Copy MyFramwork..."/>
    <copyDir src="/.../MyFramework.framework" dst="$S(BuildDir)/Frameworks/MyFramework.framework" />
</init>


, init. .



MyProject.Build.cs :



using UnrealBuildTool;
using System.IO;

public class MyProject : ModuleRules
{
    public MyProject(ReadOnlyTargetRules Target) : base(Target)
    {
        PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;

        PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore" });

        if (Target.Platform == UnrealTargetPlatform.IOS)
        {
            string ExtraPath = Path.GetFullPath(Path.Combine(ModuleDirectory, "../ThirdParty"));
            PublicAdditionalFrameworks.Add(
                new Framework(
                    "MyFramework",
                    ExtraPath + "/" + "MyFramework.framework.zip"
                )
            );

            string PluginPath = Utils.MakePathRelativeTo(ModuleDirectory, Target.RelativeEnginePath);
            AdditionalPropertiesForReceipt.Add("IOSPlugin", Path.Combine(PluginPath, "MyProject_IOS_UPL.xml"));
        }
    }
}


And the file is MyProject_IOS_UPL.xmllike this:



<?xml version="1.0" encoding="utf-8"?>
<root>
    <init>
        <log text="Copy MyFramework..."/>
        <copyDir src="/.../MyFramework.framework" dst="$S(BuildDir)/Frameworks/MyFramework.framework" />
    </init>
</root>


This solution is kind of a workaround until there is normal dynamic Framework support in UE4, but I was completely satisfied with it.




All Articles