Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Firebase Xcode linker command error using Firebase Unity SDK

Firebase Unity SDK 1.1.1. Unity 5.5.0p4 XCode 8.2.1

When using Authentication and Database from Firebase I get the following error when building the project in XCode :

Undefined symbols for architecture arm64:
"_OBJC_CLASS_$_FIRGoogleAuthProvider", referenced from: objc-class-ref in libAuth.a(credential_ios_ef8c3cf45c3329a5e5902f99026c639a.o)
"_OBJC_CLASS_$_FIRGitHubAuthProvider", referenced from: objc-class-ref in libAuth.a(credential_ios_ef8c3cf45c3329a5e5902f99026c639a.o)
"_OBJC_CLASS_$_FIREmailPasswordAuthProvider", referenced from: objc-class-ref in libAuth.a(credential_ios_ef8c3cf45c3329a5e5902f99026c639a.o)
"_OBJC_CLASS_$_FIRFacebookAuthProvider", referenced from: objc-class-ref in libAuth.a(credential_ios_ef8c3cf45c3329a5e5902f99026c639a.o)
"_OBJC_CLASS_$_FIRApp", referenced from: objc-class-ref in libApp.a(app_ios_c76c7d869e568a9b561ea55e25a7dcc0.o)
"_OBJC_CLASS_$_FIRAuth", referenced from: objc-class-ref in libAuth.a(auth_ios_3c64a79cf1eb3f06f9309f4d8e91ee94.o)
"_OBJC_CLASS_$_FIRTwitterAuthProvider", referenced from: objc-class-ref in libAuth.a(credential_ios_ef8c3cf45c3329a5e5902f99026c639a.o)
"_OBJC_CLASS_$_FIROptions", referenced from: objc-class-ref in libApp.a(app_ios_c76c7d869e568a9b561ea55e25a7dcc0.o) ld: symbol(s) not found for architecture arm64 clang: error: linker command failed with exit code 1 (use -v to see invocation)

Do I miss something in XCode? Or have something to check in Unity?

Thanks!

like image 874
Tim Koppers Avatar asked Jan 27 '17 14:01

Tim Koppers


2 Answers

First, thanks to all for sharing your (hard) work !

A lot has been said on the subject, but it took me a lot of time and a lot of trial and error to gather all the pieces on both SO & Unity forums, so I will just post the solution that I finally worked out, which finally solved all issues for me, using unity cloud build/Unity 5.6.0f3/Xcode 8.0, the project using only firebase analytics package

SOLUTION FOR UNITY CLOUD BUILD

  • completely disable cocoapods from Unity > Assets > Play Services Resolver > iOS Resolver > Settings (uncheck "Podfile Generation" and "Auto Install Cocoapod Tools in Editor", choose "None - do not integrate Cocoapods") p
  • put GoogleServices-Info.plist in the Unity "Assets" folder
  • PostBuildProcessor method:

private static void ProcessPostBuild (BuildTarget buildTarget, string path)
{
    // Only perform these steps for iOS builds
    #if UNITY_IOS

    Debug.Log ("[UNITY_IOS] ProcessPostBuild - Adding Google Analytics frameworks.");

    // Go get pbxproj file
    string projPath = path + "/Unity-iPhone.xcodeproj/project.pbxproj";

    // PBXProject class represents a project build settings file,
    // here is how to read that in.
    PBXProject proj = new PBXProject ();
    proj.ReadFromFile (projPath);
    // This is the Xcode target in the generated project
    string target = proj.TargetGuidByName("Unity-iPhone");

    proj.AddBuildProperty(target, "OTHER_LDFLAGS", "-ObjC");
    proj.AddBuildProperty(target, "OTHER_LDFLAGS", "-v");
    proj.SetBuildProperty(target, "ENABLE_BITCODE", "NO");

    if (!File.Exists(path + "/GoogleService-Info.plist"))
    {
        FileUtil.CopyFileOrDirectory("Assets/GoogleService-Info.plist", path + "/GoogleService-Info.plist");
    }
    string guid = proj.AddFile("GoogleService-Info.plist", "GoogleService-Info.plist");
    proj.AddFileToBuild(target, guid);

    // List of frameworks that will be added to project
    List<string> frameworks = new List<string>() {
        "AddressBook.framework",
        "AdSupport.framework",
        "CoreData.framework",
        "SystemConfiguration.framework",
    };

    // Add each by name
    frameworks.ForEach((framework) => {
        proj.AddFrameworkToProject(target, framework, false);
    });

    // List of frameworks that will be added to project
    List<string> usrLibFrameworks = new List<string>() {
        "libsqlite3.tbd",
        "libz.tbd",
        "libicucore.tbd",
    };

    // Add each by name
    usrLibFrameworks.ForEach((framework) => {
        proj.AddFileToBuild(target, proj.AddFile("usr/lib/"+ framework, "Frameworks/" + framework, PBXSourceTree.Sdk));
    });


    // Write PBXProject object back to the file
    proj.WriteToFile (projPath);

    #endif
}

PS it's crazy that firebase unity sdk is requiring such hacks to work (UCB is an absolute requirement for us and I guess for most multiplatform mobile developers) and I hope all those workarounds will soon be useless, but judging that all those issues are here from the beginning of official firebase Unity support, I wouldn't count too much on it

like image 107
jauboux Avatar answered Oct 28 '22 21:10

jauboux


I spent a couple of days trying to figure out the errors from building with Unity Cloud Build vs building locally. Hopefully this can help someone else!

Building Locally

This just worked as long as you have CocoaPods installed. An error will appear in the Unity console after building for iOS if CocoaPods is not installed. Other than that, the instructions provided by Firebase worked fine with Unity 5.6 and Xcode 8.3.

Building with Unity Cloud Build

CocoaPods is not available on UCB but Firebase has a non-CocoaPods alternative: https://firebase.google.com/docs/ios/setup#frameworks

Add Frameworks Manually

The instructions are assuming a native iOS build but you can simply drag the frameworks you need into Assets/Plugins/iOS/Firebase instead of into an Xcode project. Unity will add those frameworks to the Xcode project on build.

Add Linker Flag

You will need to manually add -ObjC into Other Link Flags. For some reason it showed up in my local Xcode project but not when UCB made the build. Create a post process script much like maros mentioned: https://forum.unity3d.com/threads/problem-building-ios-app-with-cloud-build-using-google-analytics.390803/#post-2549911

You will need to add -ObjC like this:

proj.AddBuildProperty(target, "OTHER_LDFLAGS", "-ObjC");

If you do not add this part, UCB may still create a build but the game will crash immediately after trying to create FirebaseAuth as it will reference an extension/category method that was not included due to the missing -ObjC flag.

Add Other Required Frameworks and Libraries

Depending on which Firebase features you are using, you may need different additional frameworks or libs. For example I had used FirebaseDatabase and while the docs did not mention this, Xcode complained about a linker error that required me to add libicucore.tbd.

The best way I could think to solve this was uninstall CocoaPods locally and then have Unity create the Xcode project so that I could get a more accurate representation of what UCB would experience. This part may take some trial and error as well as Googling to figure out which framework or lib the linker error is referring to. Just try to build the Xcode project locally and you will get the linker errors if any.

I added:

List<string> frameworks = new List<string>() {
    "AdSupport.framework",
    "CoreData.framework",
    "SystemConfiguration.framework",
    "libz.dylib",
    "libsqlite3.dylib",
    "libicucore.tbd"
};

Manually Move GoogleServices-Info.plist

Another oddity is that UCB did not move the GoogleServices-Info.plist into the Xcode project. There must be some other script that is not running on UCB that does run locally. In the post process script where you add the linker flag and frameworks, you can also move the GoogleServices-Info.plist into the Xcode project directory and then add it to the bundle.

First move the file:

if (!File.Exists(path + "/GoogleService-Info.plist"))
{
    FileUtil.CopyFileOrDirectory ("GoogleService-Info.plist", path + "/GoogleService-Info.plist");
}

Then add it to the build:

string guid = proj.AddFile("GoogleService-Info.plist", "GoogleService-Info.plist");
proj.AddFileToBuild(target, guid);

And that should be it. I will update if I run into any other issues as I add more Firebase features. Currently I am using Auth, Database, and Analytics.

like image 6
Tommy Leung Avatar answered Oct 28 '22 20:10

Tommy Leung