Search Unity

iOS: Swift plugins in project on UCB

Discussion in 'Unity Build Automation' started by Wanderer13, Dec 27, 2017.

  1. Wanderer13

    Wanderer13

    Joined:
    Feb 11, 2016
    Posts:
    19
    Hi there.
    I have recently added swift framework to my project. There is also Objective-C wrapper plugin for calling this framework's functionality. Seems that UCB doesn't support swift plugins, because once app built and runned on device, there is an error:

    dyld: Library not loaded: @rpath/libswiftCore.dylib
    Referenced from: /private/var/mobile/Containers/Bundle/Application/...<used swift framework>
    Reason: no suitable image found

    While, if I compile this project on Mac OS and run on device it's going well. If before compiling project in XCode set ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES to NO, same issue appears as in UCB build.

    Added iOS post processing settings:
    ENABLE_BITCODE = NO
    OTHER_LDFLAGS = -ObjC -v
    CLANG_ENABLE_MODULES = YES
    LD_RUNPATH_SEARCH_PATHS = $(inherited) $(SDKROOT) @loader_path/Frameworks @executable_path/Frameworks
    SWIFT_VERSION = 3.0
    ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
    EMBEDDED_CONTENT_CONTAINS_SWIFT = YES
    Also, this swift framework added as additional copy files build phase to 'Frameworks' location.

    Apps/OS versions: MacOS Sierra 10.12.6, Unity 2017.1.1f1, XCode 8.3, swift 3
    Tested devices: iPhone 5 (iOS 10.2), iPhone 6+ (iOS 10.3)

    Does anyone successfully built app on UCB with swift plugins or encounter with such error?
     
  2. Wanderer13

    Wanderer13

    Joined:
    Feb 11, 2016
    Posts:
    19
    Btw found solution. Since UCB can't add standard swift libraries to build, it can be done in post processing script. Download libswiftCore.dylib, libswiftCoreGraphics.dylib, etc to unity project, and in post processing script add them to generated xcode project. Also need to add these libraries to copy files build phase, at 'Frameworks' location.
     
  3. Fattie

    Fattie

    Joined:
    Jul 5, 2012
    Posts:
    476
    What is UCB ??
     
  4. Wanderer13

    Wanderer13

    Joined:
    Feb 11, 2016
    Posts:
    19
    Unity cloud build.
     
  5. cmersereau

    cmersereau

    Joined:
    Nov 6, 2020
    Posts:
    52
    I am trying to do something similar. Some of my dependencies require the SwiftSupport libraries, but those libraries are normally added to an iOS build via Xcode. Someone from Unity reached out to me to inform me that they do not support the addition of the SwiftSupport folder. Due to this, I am trying to manually add the SwiftSupport folder myself, but running into the same problem you did because Unity ignores .dylib files.

    Two questions.

    1. When you added the .dylib files to your xcode project, where did you put them? Mine ultimately need to be in a "SwiftSupport/iphoneos" nested folder, but I am not sure if there is somewhere specific I need to put the SwiftSupport folder.

    2. What do you mean by needing "to add these libraries to copy files build phase, at 'Frameworks' location.'? Can you explain exactly what I'm supposed to do for that?

    If you have a code sample of your processing method that would be great, although I know I'm asking this quite a long time after the original post.
     
  6. angusmf

    angusmf

    Joined:
    Jan 19, 2015
    Posts:
    261
    Make a folder in the same folder as Assets, called "libs" or something. Put your support libs in there, then in a [PostProcessBuild] or Post Export method, you can File.Copy them to the same folder in your exported xcode project as the framework that needs them. That is my interpretation of what they wrote. Hope you're not still figuring this out, though!
    How are you are using swift frameworks at all, though? I'd be so happy to get mine working even locally, but I haven't been able to get the ojbc code to "see" the framework. If anyone has tips or steps, I'd be very grateful!
     
  7. Wanderer13

    Wanderer13

    Joined:
    Feb 11, 2016
    Posts:
    19
    Sorry for late response, i haven't checked this code since time of original post, but here it is:

    Code (CSharp):
    1.  
    2. using System.IO;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5. using UnityEditor;
    6. using UnityEditor.Callbacks;
    7. using UnityEditor.iOS.Xcode;
    8.  
    9. namespace Assets
    10. {
    11.     public static class BuildPostprocessor
    12.     {
    13.         [PostProcessBuild(999)]
    14.         public static void OnPostProcessBuild(BuildTarget buildTarget, string path)
    15.         {
    16.             PostProcessBuild(buildTarget, path);
    17.         }
    18.  
    19.         private static void PostProcessBuild(BuildTarget buildTarget, string path)
    20.         {
    21.             if (buildTarget == BuildTarget.iOS)
    22.             {
    23.                 var projectPath = path + "/Unity-iPhone.xcodeproj/project.pbxproj";
    24.                 var pbxProject = new PBXProject();
    25.                 pbxProject.ReadFromFile(projectPath);
    26.  
    27.                 var target = pbxProject.TargetGuidByName("Unity-iPhone");
    28.                 pbxProject.SetBuildProperty(target, "ENABLE_BITCODE", "NO");
    29.                 pbxProject.AddBuildProperty(target, "OTHER_LDFLAGS", "-ObjC");
    30.                 pbxProject.AddBuildProperty(target, "OTHER_LDFLAGS", "-v");
    31.                 pbxProject.AddBuildProperty(target, "CLANG_ENABLE_MODULES", "YES");
    32.  
    33.                 pbxProject.AddBuildProperty(target, "LD_RUNPATH_SEARCH_PATHS", "@executable_path/Frameworks");
    34.                 pbxProject.AddBuildProperty(target, "ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES", "NO");
    35.                 pbxProject.AddBuildProperty(target, "EMBEDDED_CONTENT_CONTAINS_SWIFT", "NO");
    36.  
    37.                 var pathToFrameworkFromAssets = "Plugins/iOS";
    38.                 var frameworkName = "BackgroundDownloadingManagerFramework";
    39.                 var embeddingPhase = pbxProject.AddCopyFilesBuildPhase(target, "Embed Frameworks", "", "10");
    40.                 var frameworkGuid = pbxProject.FindFileGuidByProjectPath(
    41.                     "Frameworks/" + pathToFrameworkFromAssets + "/" + frameworkName + ".framework");
    42.                 pbxProject.AddFileToBuildSection(target, embeddingPhase, frameworkGuid);
    43.  
    44.                 var swiftSupportLibs = new List<string> {
    45.                     "Core",
    46.                     "CoreFoundation",
    47.                     "CoreGraphics",
    48.                     "CoreImage",
    49.                     "Darwin",
    50.                     "Dispatch",
    51.                     "Foundation",
    52.                     "Metal",
    53.                     "ObjectiveC",
    54.                     "os",
    55.                     "QuartzCore",
    56.                     "SwiftOnoneSupport",
    57.                     "UIKit"
    58.                 };
    59.                 foreach (var swiftSupportLib in swiftSupportLibs)
    60.                 {
    61.                     var swiftLibFileName = "libswift" + swiftSupportLib + ".dylib";
    62.                     var swiftLibSourcePath = Application.dataPath + "/" + pathToFrameworkFromAssets + "/SwiftSupport/" + swiftLibFileName;
    63.                     var swiftPathInBuild = "Libraries/" + swiftLibFileName;
    64.                     var swiftLibDestPath = Path.Combine(path, swiftPathInBuild);
    65.                     File.Copy(swiftLibSourcePath, swiftLibDestPath);
    66.                     Debug.Log("swiftlib path: " + swiftLibSourcePath + "; " + swiftLibDestPath);
    67.                     var fileGuid = pbxProject.AddFile(swiftPathInBuild, swiftPathInBuild, PBXSourceTree.Source);
    68.                     pbxProject.AddFileToBuildSection(target, embeddingPhase, fileGuid);
    69.                 }
    70.  
    71.                 pbxProject.WriteToFile(projectPath);
    72.             }
    73.         }
    74.     }
    75. }
    76.  
     
  8. Wanderer13

    Wanderer13

    Joined:
    Feb 11, 2016
    Posts:
    19
    I can't remember exact project organization, but there is lib .a that compiles from swift framework and .m file. File .m that starts like

    Code (CSharp):
    1. #import <Foundation/Foundation.h>
    2. #import "string.h"
    3. @import BackgroundDownloadingManagerFramework;
    4.  
    5. extern void UnitySendMessage(const char* gameObjectName, const char* method, const char* param);
    Both .a and swift framework compiled folder should go into /Plugins unity folder
     
  9. cmersereau

    cmersereau

    Joined:
    Nov 6, 2020
    Posts:
    52
    Sorry for such a late response. My team has been busy and I haven't been able to come back to this issue for a while. I actually am not trying to implement my own swift frameworks at all. It appears that one of the pods that I am installing using CocoaPods requires swift support, which is why I need to find a way to get it in my project.
     
  10. cmersereau

    cmersereau

    Joined:
    Nov 6, 2020
    Posts:
    52
    I've tried implementing this code, and a few variations of it, but it does not solve the full issue. It appears that the code is able to work when importing the files this way. However, when I upload to the Apple app store, I still get an email from Apple with the error "ITMS-90426: Invalid Swift Support: The SwiftSupport folder is missing."

    The specific issues we are having are a bit different, so perhaps there is no solution for my issue following this trail.