|
10 | 10 | namespace Backtrace.Unity.Editor.iOS |
11 | 11 | { |
12 | 12 | /// <summary> |
13 | | - /// Links Backtrace.xcframework + CrashReporter.xcframework on UnityFramework, |
14 | | - /// embeds and signs Backtrace (dynamic) in the app target, and sets Swift/iOS settings. |
| 13 | + /// Links Backtrace.xcframework and CrashReporter.xcframework |
| 14 | + /// embeds, signs Backtrace and sets Swift/iOS settings. |
15 | 15 | /// </summary> |
16 | 16 | public static class BacktraceXcodePostBuild |
17 | 17 | { |
18 | | - [PostProcessBuild(999)] |
19 | | - public static void OnPostProcessBuild(BuildTarget target, string buildPath) |
| 18 | + // Runs late after post-processors |
| 19 | + private const int PostBuildOrder = 500; |
| 20 | + |
| 21 | + [PostProcessBuild(PostBuildOrder)] |
| 22 | + public static void OnPostProcessBuild(BuildTarget buildTarget, string buildPath) |
20 | 23 | { |
21 | | - if (target != BuildTarget.iOS) return; |
| 24 | + if (buildTarget != BuildTarget.iOS) { |
| 25 | + return; |
| 26 | + } |
22 | 27 |
|
23 | | - var projPath = PBXProject.GetPBXProjectPath(buildPath); |
24 | | - var proj = new PBXProject(); |
25 | | - proj.ReadFromFile(projPath); |
| 28 | + var projectPath = PBXProject.GetPBXProjectPath(buildPath); |
| 29 | + var project = new PBXProject(); |
| 30 | + project.ReadFromFile(projectPath); |
26 | 31 |
|
27 | 32 | #if UNITY_2019_3_OR_NEWER |
28 | | - string appTargetGuid = proj.GetUnityMainTargetGuid(); |
29 | | - string ufTargetGuid = proj.GetUnityFrameworkTargetGuid(); |
| 33 | + string appTargetGuid = project.GetUnityMainTargetGuid(); |
| 34 | + string unityFrameworkTargetGuid = project.GetUnityFrameworkTargetGuid(); |
30 | 35 | #else |
31 | | - string appTargetGuid = proj.TargetGuidByName("Unity-iPhone"); |
32 | | - string ufTargetGuid = appTargetGuid; |
| 36 | + string appTargetGuid = project.TargetGuidByName("Unity-iPhone"); |
| 37 | + string unityFrameworkTargetGuid = appTargetGuid; |
33 | 38 | #endif |
34 | | - // Find the xcframeworks that Unity copied into the export (regardless of folder) |
35 | | - string FindXCFramework(string name) |
| 39 | + if (string.IsNullOrEmpty(appTargetGuid) || string.IsNullOrEmpty(unityFrameworkTargetGuid)) |
36 | 40 | { |
37 | | - var dirs = Directory.GetDirectories(buildPath, name, SearchOption.AllDirectories); |
38 | | - return dirs.FirstOrDefault(); |
| 41 | + Debug.LogError("[Backtrace] iOS post-build: could not resolve Xcode targets."); |
| 42 | + return; |
39 | 43 | } |
40 | 44 |
|
41 | | - var backtraceXC = FindXCFramework("Backtrace.xcframework"); |
42 | | - var crashXC = FindXCFramework("CrashReporter.xcframework"); |
| 45 | + // Locate exported xcframeworks |
| 46 | + string FindXCFramework(string folderName) |
| 47 | + { |
| 48 | + var matches = Directory.GetDirectories(buildPath, folderName, SearchOption.AllDirectories); |
| 49 | + return matches.FirstOrDefault(); |
| 50 | + } |
43 | 51 |
|
44 | | - if (string.IsNullOrEmpty(backtraceXC)) |
| 52 | + var backtraceXCPath = FindXCFramework("Backtrace.xcframework"); |
| 53 | + var crashReporterXCPath = FindXCFramework("CrashReporter.xcframework"); |
| 54 | + |
| 55 | + if (string.IsNullOrEmpty(backtraceXCPath)) |
45 | 56 | { |
46 | | - Debug.LogError("[Backtrace] Could not locate Backtrace.xcframework in the exported Xcode project."); |
| 57 | + Debug.LogError($"[Backtrace] Could not locate Backtrace.xcframework under: {buildPath}"); |
47 | 58 | return; |
48 | 59 | } |
49 | | - if (string.IsNullOrEmpty(crashXC)) |
| 60 | + if (string.IsNullOrEmpty(crashReporterXCPath)) |
50 | 61 | { |
51 | | - Debug.LogError("[Backtrace] Could not locate CrashReporter.xcframework in the exported Xcode project."); |
| 62 | + Debug.LogError($"[Backtrace] Could not locate CrashReporter.xcframework under: {buildPath}"); |
52 | 63 | return; |
53 | 64 | } |
54 | 65 |
|
55 | | - // Add files to project with paths relative to project |
56 | | - string relBacktrace = backtraceXC.Replace(buildPath + "/", ""); |
57 | | - string relCrash = crashXC.Replace(buildPath + "/", ""); |
| 66 | + // Project-relative paths |
| 67 | + string relBacktraceXC = ToProjectRelative(buildPath, backtraceXCPath); |
| 68 | + string relCrashReporterXC = ToProjectRelative(buildPath, crashReporterXCPath); |
| 69 | + |
| 70 | + // Add file references |
| 71 | + string backtraceFileGuid = project.FindFileGuidByProjectPath(relBacktraceXC); |
| 72 | + if (string.IsNullOrEmpty(backtraceFileGuid)) { |
| 73 | + backtraceFileGuid = project.AddFile(relBacktraceXC, relBacktraceXC, PBXSourceTree.Source); |
| 74 | + } |
| 75 | + |
| 76 | + string crashReporterFileGuid = project.FindFileGuidByProjectPath(relCrashReporterXC); |
| 77 | + if (string.IsNullOrEmpty(crashReporterFileGuid)) { |
| 78 | + crashReporterFileGuid = project.AddFile(relCrashReporterXC, relCrashReporterXC, PBXSourceTree.Source); |
| 79 | + } |
58 | 80 |
|
59 | | - string btGuid = proj.AddFile(relBacktrace, relBacktrace, PBXSourceTree.Source); |
60 | | - string crGuid = proj.AddFile(relCrash, relCrash, PBXSourceTree.Source); |
| 81 | + // Linking |
| 82 | + project.AddFileToBuild(unityFrameworkTargetGuid, backtraceFileGuid); |
| 83 | + project.AddFileToBuild(unityFrameworkTargetGuid, crashReporterFileGuid); |
61 | 84 |
|
62 | | - // Link both on UnityFramework |
63 | | - proj.AddFileToBuild(ufTargetGuid, btGuid); |
64 | | - proj.AddFileToBuild(ufTargetGuid, crGuid); |
| 85 | + // Embedding |
| 86 | + PBXProjectExtensions.AddFileToEmbedFrameworks(project, appTargetGuid, backtraceFileGuid); |
| 87 | + AddBuildPropertyUnique(project, appTargetGuid, "LD_RUNPATH_SEARCH_PATHS", "$(inherited)"); |
| 88 | + AddBuildPropertyUnique(project, appTargetGuid, "LD_RUNPATH_SEARCH_PATHS", "@executable_path/Frameworks"); |
65 | 89 |
|
66 | | - // Embed Backtrace (dynamic) on the app target |
67 | | - PBXProjectExtensions.AddFileToEmbedFrameworks(proj, appTargetGuid, btGuid); |
68 | | - proj.AddBuildProperty(appTargetGuid, "LD_RUNPATH_SEARCH_PATHS", "$(inherited) @executable_path/Frameworks"); |
| 90 | + // iOS settings |
| 91 | + project.SetBuildProperty(appTargetGuid, "ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES", "YES"); |
| 92 | + project.SetBuildProperty(appTargetGuid, "IPHONEOS_DEPLOYMENT_TARGET", "13.0"); |
| 93 | + project.SetBuildProperty(unityFrameworkTargetGuid, "IPHONEOS_DEPLOYMENT_TARGET", "13.0"); |
69 | 94 |
|
70 | | - // Swift / platform settings (SDK requires iOS 13+) |
71 | | - proj.SetBuildProperty(appTargetGuid, "ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES", "YES"); |
72 | | - proj.SetBuildProperty(appTargetGuid, "IPHONEOS_DEPLOYMENT_TARGET", "13.0"); |
73 | | - proj.SetBuildProperty(ufTargetGuid, "IPHONEOS_DEPLOYMENT_TARGET", "13.0"); |
| 95 | + // Obj-C Linker Flag |
| 96 | + AddBuildPropertyUnique(project, unityFrameworkTargetGuid, "OTHER_LDFLAGS", "-ObjC"); |
74 | 97 |
|
75 | | - // Recommended & safe for Obj-C categories |
76 | | - proj.AddBuildProperty(ufTargetGuid, "OTHER_LDFLAGS", "-ObjC"); |
| 98 | + project.WriteToFile(projectPath); |
| 99 | + Debug.Log("[Backtrace] iOS post-build: frameworks linked/embedded. Swift stdlib enabled."); |
| 100 | + } |
| 101 | + |
| 102 | + private static string ToProjectRelative(string buildPath, string absolutePath) |
| 103 | + { |
| 104 | + var rel = absolutePath.Replace('\\', '/'); |
| 105 | + var root = (buildPath + "/").Replace('\\', '/'); |
| 106 | + return rel.StartsWith(root) ? rel.Substring(root.Length) : rel; |
| 107 | + } |
77 | 108 |
|
78 | | - proj.WriteToFile(projPath); |
79 | | - Debug.Log("[Backtrace] iOS post-build: frameworks linked/embedded; Swift stdlib enabled; iOS 13.0 set."); |
| 109 | + private static void AddBuildPropertyUnique(PBXProject proj, string targetGuid, string key, string value) |
| 110 | + { |
| 111 | + var current = proj.GetBuildPropertyForAnyConfig(targetGuid, key); |
| 112 | + if (current == null || !current.Split(' ').Contains(value)) |
| 113 | + { |
| 114 | + proj.AddBuildProperty(targetGuid, key, value); |
| 115 | + } |
80 | 116 | } |
81 | 117 | } |
82 | 118 | } |
|
0 commit comments