Facebook-sdk-for-unity: Error when building Unity project to Xcode (arm64 function not 4-byte aligned)

Created on 15 Dec 2020  路  18Comments  路  Source: facebook/facebook-sdk-for-unity

Checklist

Environment

Describe your dev environment here, giving as many details as possible. If you have them, make sure to include:

  • Unity Editor Version: 2020.1.0f1
  • Unity SDK Version: 8.1.1
  • Installation Platform & Version: iOS|Android version (?)

Goals

Smoothly build project from unity and building and running it from Xcode.

Code Samples & Details

I am using firebase SDK's in my project. I made the Email/Password authentication to work and the next step was to implement Facebook SignIn. Everything worked fine and it seems to be working, given that there are no errors in the console and I followed all of the documentation steps. The problem starts when building the project and trying to run it through Xcode.

I read everything regarding similar errors and nothing solved it. The error I am getting is:

Showing Recent Messages
Undefined symbol: _OBJC_CLASS_$_GKLocalPlayer

ld: warning: arm64 function not 4-byte aligned: _unwind_tester from /Users/XXX/XXX/XXX/XXX/YYYY/Build_iOS/Libraries/libiPhone-lib.a(unwind_test_arm64.o)
Undefined symbols for architecture arm64:
"_OBJC_CLASS_$_GKLocalPlayer", referenced from:
objc-class-ref in libFirebaseCppAuth.a(credential_ios_ XXX.o)
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

[EDIT]
One thing I noticed is that when I run "pod --version" within the "Build_iOS" folder, it returns 1.10.0.

bug

Most helpful comment

@snorrsi

It Worked!! I can't thank you enough!

I would never have realized that I was adding the framework in the wrong place.

For anyone also having this problem, follow the footsteps above given by @snorrsi and if it is the same thing, it should work.

This is where you need to add the Gamekit.framework:

photo_2020-12-16 22 53 42

And don't forget to edit the code within the "FIRGameCenterAuthProvider.m" file.

All 18 comments

Does anyone have information on this subject?

I'm stuck with this problem for almost a day without being able to solve it. Would appreciate some help!

Hi, yes I fixed this for our app.
You need to include GameKit.framework
If you get in more trouble search for GKLocalPlayer , there is one file in Facebook sdk, can鈥檛 remember the name. Comment out all related to GKLocalPlayer, the fallback might not work or actually more likely Firebase is directly referencing GKLocalPlayer

@snorrsi

Thanks for the reply, though I already read some topics with similar suggestions and they didn't work for me.

If it isn't much trouble for you, could you give me more detailed instructions on what worked with you?

@Nicokkam I think you should remove the bug label as this is most likely Firebase SDK bug rather than Facebook SDK bug.
Was actually writing this down when I saw your comment. Here it goes

Add GameKit.framework to your UnityFramework , build phases .. Link binary with libraries
make it Optional

Search for GKLocalPlayer
One result should be FIRGameCenterAuthProvider.m
Open that file
Go to Line 34

+ (void)getCredentialWithCompletion:(FIRGameCenterCredentialCallback)completion { /** Linking GameKit.framework without using it on macOS results in App Store rejection. Thus we don't link GameKit.framework to our SDK directly.optionalLocalPlayeris used for checking whether the APP that consuming our SDK has linked GameKit.framework. If not, a GameKitNotLinkedError` will be raised.
*/
// Add this link to line 41 .. comment out everything to line 95
if (completion) {
completion(nil, [FIRAuthErrorUtils gameKitNotLinkedError]);
}
return;
/

...
// to line 95 You need to remove double comments though, replace with / * and * /
}

@end

NS_ASSUME_NONNULL_END

*/`

@snorrsi

I am getting some errors doing what you suggested.

`/*

  • Copyright 2018 Google
    *
  • Licensed under the Apache License, Version 2.0 (the "License");
  • you may not use this file except in compliance with the License.
  • You may obtain a copy of the License at
    *
  • http://www.apache.org/licenses/LICENSE-2.0
    *
  • Unless required by applicable law or agreed to in writing, software
  • distributed under the License is distributed on an "AS IS" BASIS,
  • WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  • See the License for the specific language governing permissions and
  • limitations under the License.
    */

import "FirebaseAuth/Sources/Public/FirebaseAuth/FIRGameCenterAuthProvider.h"

import

import "FirebaseAuth/Sources/AuthProvider/GameCenter/FIRGameCenterAuthCredential.h"

import "FirebaseAuth/Sources/Utilities/FIRAuthErrorUtils.h"

import "FirebaseAuth/Sources/Utilities/FIRAuthExceptionUtils.h"

NS_ASSUME_NONNULL_BEGIN

@implementation FIRGameCenterAuthProvider

  • (instancetype)init {
    [FIRAuthExceptionUtils
    raiseMethodNotImplementedExceptionWithReason:@"This class is not meant to be initialized."];
    return nil;
    }

  • (void)getCredentialWithCompletion:(FIRGameCenterCredentialCallback)completion {
    /*
    Linking GameKit.framework without using it on macOS results in App Store rejection.
    Thus we don't link GameKit.framework to our SDK directly. optionalLocalPlayer is used for
    checking whether the APP that consuming our SDK has linked GameKit.framework. If not, a
    GameKitNotLinkedError will be raised.
    *
    /
    if (completion) {
    completion(nil, [FIRAuthErrorUtils gameKitNotLinkedError]);
    }
    return;
    /*

    GKLocalPlayer *_Nullable optionalLocalPlayer = [[NSClassFromString(@"GKLocalPlayer") alloc] init];

    if (!optionalLocalPlayer) {
    if (completion) {
    completion(nil, [FIRAuthErrorUtils gameKitNotLinkedError]);
    }
    return;
    }

    __weak GKLocalPlayer *localPlayer = [[optionalLocalPlayer class] localPlayer];
    if (!localPlayer.isAuthenticated) {
    if (completion) {
    completion(nil, [FIRAuthErrorUtils localPlayerNotAuthenticatedError]);
    }
    return;
    }

    [localPlayer generateIdentityVerificationSignatureWithCompletionHandler:^(
    NSURL *publicKeyURL, NSData *signature, NSData *salt, uint64_t timestamp,
    NSError *error) {
    if (error) {
    if (completion) {
    completion(nil, error);
    }
    } else {
    if (completion) {

    NSString *displayName = localPlayer.alias;
    

pragma clang diagnostic push

pragma clang diagnostic ignored "-Wdeprecated-declarations"

    FIRGameCenterAuthCredential *credential =
        [[FIRGameCenterAuthCredential alloc] initWithPlayerID:localPlayer.playerID
                                                 publicKeyURL:publicKeyURL
                                                    signature:signature
                                                         salt:salt
                                                    timestamp:timestamp
                                                  displayName:displayName];

pragma clang diagnostic pop

    completion(credential, nil);
  }
}

}];
}
**/
@end

NS_ASSUME_NONNULL_END
`

I'm not familiar with Swift, maybe thats why.

@Nicokkam you need to remove the comments .. can't have /* and / inside / .. */
Or you can simply just remove all of the the lines

From line 34, change it to this below

+ (void)getCredentialWithCompletion:(FIRGameCenterCredentialCallback)completion {
  /**
   Linking GameKit.framework without using it on macOS results in App Store rejection.
   Thus we don't link GameKit.framework to our SDK directly. `optionalLocalPlayer` is used for
   checking whether the APP that consuming our SDK has linked GameKit.framework. If not, a
   `GameKitNotLinkedError` will be raised.
   **/
    if (completion) {
        completion(nil, [FIRAuthErrorUtils gameKitNotLinkedError]);
    }
    return;
}

@end

NS_ASSUME_NONNULL_END


@snorrsi

I did those changes and it didn't solve the issue... I'm considering using another alternative to managing the sign in of my app.

But thanks for the attention. If something else comes to mind please let me know!

@Nicokkam did you add GameKit.framework also ?

Yes I did.

image

@Nicokkam you are adding the adding the GameKit.framework on wrong place.. add it to UnityFramework target, not Unity-iPhone .. that should do it

@Nicokkam I think you should remove the bug label as this is most likely Firebase SDK bug rather than Facebook SDK bug.
Was actually writing this down when I saw your comment. Here it goes

Add GameKit.framework to your UnityFramework , build phases .. Link binary with libraries
make it Optional

Search for GKLocalPlayer
One result should be FIRGameCenterAuthProvider.m
Open that file
Go to Line 34

  • (void)getCredentialWithCompletion:(FIRGameCenterCredentialCallback)completion {
    /*
    Linking GameKit.framework without using it on macOS results in App Store rejection.
    Thus we don't link GameKit.framework to our SDK directly. optionalLocalPlayer is used for
    checking whether the APP that consuming our SDK has linked GameKit.framework. If not, a
    GameKitNotLinkedError will be raised.
    *
    /
    if (completion) {
    completion(nil, [FIRAuthErrorUtils gameKitNotLinkedError]);
    }
    return;
    }

@end

NS_ASSUME_NONNULL_END

Thanks works for me! Once again thanks

@snorrsi

It Worked!! I can't thank you enough!

I would never have realized that I was adding the framework in the wrong place.

For anyone also having this problem, follow the footsteps above given by @snorrsi and if it is the same thing, it should work.

This is where you need to add the Gamekit.framework:

photo_2020-12-16 22 53 42

And don't forget to edit the code within the "FIRGameCenterAuthProvider.m" file.

Screenshot 2020-12-23 at 11 07 48 AM
Screenshot 2020-12-23 at 11 08 05 AM

I'm still having the same issue. I'm using FirebaseAuth Email/Facebook/Google, FacebookSDK, GoogleMobileAds, Firebase Storage and Firestore.
I followed what @snorrsi suggested but it is not working for me

Also I'm using unity2019.1.17 for this and I don't get any option of UnityFramework target. How do I get that?
I think I need use unity2019.3 or above

https://www.fiverr.com/s2/3fee81076a
I can help you any type xcode errors

Temporary fix:

[PostProcessBuild]
    public static void OnPostProcessBuildAddFirebaseFile(BuildTarget buildTarget, string pathToBuiltProject)
    {
        if (buildTarget == BuildTarget.iOS)
        {
            // Go get pbxproj file
            string projPath = PBXProject.GetPBXProjectPath(pathToBuiltProject);

            // PBXProject class represents a project build settings file,
            // here is how to read that in.
            PBXProject proj = new PBXProject();
            proj.ReadFromFile(projPath);

            // Copy plist from the project folder to the build folder
            proj.AddFileToBuild(proj.GetUnityMainTargetGuid(), proj.AddFile("GoogleService-Info.plist", "GoogleService-Info.plist"));

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

    const string GameKitFrameworkName = "GameKit.framework";
    [PostProcessBuild(101)]
    private static void PostProcessBuild_LinkGameKit(BuildTarget target, string buildPath)
    {
#if UNITY_EDITOR_OSX
        if (target == BuildTarget.iOS)
        {

            string projPath = PBXProject.GetPBXProjectPath(buildPath);
            PBXProject proj = new PBXProject();
            proj.ReadFromString(File.ReadAllText(projPath));

            // embed gamekit into Unity framework target because its used in the facebooksdk
            Debug.Log("Embedding gamekit frameworks into UnityFramework target...");
            string targetGuid = proj.GetUnityFrameworkTargetGuid();

            proj.AddFrameworkToProject(targetGuid, GameKitFrameworkName, true);
            proj.WriteToFile(projPath);
        }
#endif
    }

Reverting to Firebase 6.16.1 or reverting to Facebook 8.1.0 fix it according to this:
https://github.com/firebase/quickstart-unity/issues/908

Temporary fix:

[PostProcessBuild]
    public static void OnPostProcessBuildAddFirebaseFile(BuildTarget buildTarget, string pathToBuiltProject)
    {
        if (buildTarget == BuildTarget.iOS)
        {
            // Go get pbxproj file
            string projPath = PBXProject.GetPBXProjectPath(pathToBuiltProject);

            // PBXProject class represents a project build settings file,
            // here is how to read that in.
            PBXProject proj = new PBXProject();
            proj.ReadFromFile(projPath);

            // Copy plist from the project folder to the build folder
            proj.AddFileToBuild(proj.GetUnityMainTargetGuid(), proj.AddFile("GoogleService-Info.plist", "GoogleService-Info.plist"));

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

    const string GameKitFrameworkName = "GameKit.framework";
    [PostProcessBuild(101)]
    private static void PostProcessBuild_LinkGameKit(BuildTarget target, string buildPath)
    {
#if UNITY_EDITOR_OSX
        if (target == BuildTarget.iOS)
        {

            string projPath = PBXProject.GetPBXProjectPath(buildPath);
            PBXProject proj = new PBXProject();
            proj.ReadFromString(File.ReadAllText(projPath));

            // embed gamekit into Unity framework target because its used in the facebooksdk
            Debug.Log("Embedding gamekit frameworks into UnityFramework target...");
            string targetGuid = proj.GetUnityFrameworkTargetGuid();

            proj.AddFrameworkToProject(targetGuid, GameKitFrameworkName, true);
            proj.WriteToFile(projPath);
        }
#endif
    }

Thanks for this, where in my project should this be included?

Figured it out! Had to add this script into a Editor directory so its picked up by the build processes

Was this page helpful?
0 / 5 - 0 ratings

Related issues

sivu picture sivu  路  6Comments

Shaitan1805 picture Shaitan1805  路  6Comments

bblpny picture bblpny  路  4Comments

1901 picture 1901  路  6Comments

manofspirit picture manofspirit  路  6Comments