Xcode: Undefined symbols for architecture arm64
1. SDK Version: 5.0.1
2. Development Environment: Unity-iOS
3. Tracker/Scanner: Image tracker
4. License Type: Free
5. Target Device: iPhone
I was unable to build in Xcode after upgrading from 2019.2.17f1 to 2019.3.0f6. I received the following error:
Undefined symbols for architecture arm64: "_vImageConvolve_Planar8", referenced from: +[vImage_function vImage_gaussian_3x3:Stride:Height:Source:Dest:] in libMaxstAR.a(vImage_function.o) ld: symbol(s) not found for architecture arm64 clang: error: linker command failed with exit code 1 (use -v to see invocation)
In an attempt to fix the issue, I first upgraded to Unity 2019.3.1f1, then upgraded MAXST SDK to 5.0.1, and finally upgraded to Unity 2019.3.3f1, without any success. I found this forum post describing the same sort of issue, and found out that in the Frameworks and Libraries section in my Xcode project, both Accelerate.framework and ARKit.framework were missing, as shown in the screenshot below.
After adding both of these to the project, building was succesful. The problem here is that we're using Jenkins to build my Android and iOS packages, and each time Jenkins generates the Xcode project, it's generated with the missing frameworks and I have to manually add them before manually building and uploading the iOS package. Is there any other solution to fixing the issue than downgrading to the previous working configuration?
By selecting the libMaxstAR.a file in Unity, you can add the basic framework as a dependency.
If you add a framework (ARKit.framework, Accelerate.framework) before building, you can get a project file with the framework added.
Keane
MAXST Support Team
After digging around, I figured out the issue. The problem was that in the IPlistEditor.cs file imported with MAXST SDK, the build ran into an exception when the function ChangeXcodePlist
was called:
Exception: Calling TargetGuidByName with name='Unity-iPhone' is deprecated. There are two targets now, call GetUnityMainTargetGuid() - for app or GetUnityFrameworkTargetGuid() - for source/plugins to get Guid instead.
at UnityEditor.iOS.Xcode.PBXProject.TargetGuidByName (System.String name) [0x00010] in /Users/builduser/buildslave/unity/build/External/XcodeAPI/Xcode/PBXProject.cs:168
at IPlistEditor.ChangeXcodePlist (UnityEditor.BuildTarget buildTarget, System.String pathToBuiltProject) [0x0006c] in /Users/developer/.jenkins/workspace/vikke-test/Assets/Editor/IPlistEditor.cs:41
This was due to the TargetGuidByName
function being removed in Unity 2019.3. After changing TargetGuidByName
to GetUnityMainTargetGuid
, the frameworks were added, but incorrectly to the main app instead of UnityFramework. Changinng GetUnityMainTargetGuid
to GetUnityFrameworkTargetGuid
solved this.
However, the Info.plist file doesn't have a key called "ITSAppUsesNonExemptEncryption" that the ChangeXcodePlist
function is supposed to add to the file, so there is still a bit of manual labour involved when uploading a new build to App Store. I haven't figured why the key is missing, but would love to find out if someone else has.
string plistPath = pathToBuiltProject + "/Info.plist";
PlistDocument plist = new PlistDocument();
plist.ReadFromString(File.ReadAllText(plistPath));
PlistElementDict rootDict = plist.root;
var iTSAppUsesNonExemptEncryptionKey = "ITSAppUsesNonExemptEncryption";
rootDict.SetString(iTSAppUsesNonExemptEncryptionKey, "false");
File.WriteAllText(plistPath, plist.WriteToString());
// Xcode Project File Setting.
string projPath = PBXProject.GetPBXProjectPath(pathToBuiltProject);
PBXProject proj = new PBXProject();
proj.ReadFromString(File.ReadAllText(projPath));
string target = proj.GetUnityFrameworkTargetGuid();
proj.AddFrameworkToProject(target, "Accelerate.framework", false);
proj.AddFrameworkToProject(target, "ARKit.framework", false);
File.WriteAllText(projPath, proj.WriteToString());
I wish this code helps you.
Keane
MAXST Support Team
What was missing was File.WriteAllText(plistPath, plist.WriteToString());
after rootDict.SetString(iTSAppUsesNonExemptEncryptionKey, "false");
, after adding that line the key was written to the Info.plist file. Thanks for the quick responses!