-
-
Notifications
You must be signed in to change notification settings - Fork 61
Expand file tree
/
Copy pathBuildPostProcess.cs
More file actions
235 lines (198 loc) · 9.14 KB
/
Copy pathBuildPostProcess.cs
File metadata and controls
235 lines (198 loc) · 9.14 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
using System;
using System.IO;
using Sentry.Extensibility;
using Sentry.Unity.Editor.ConfigurationWindow;
using UnityEngine;
using UnityEditor;
using UnityEditor.Build;
using UnityEditor.Callbacks;
namespace Sentry.Unity.Editor.iOS;
public static class BuildPostProcess
{
[PostProcessBuild(1)]
public static void OnPostProcessBuild(BuildTarget target, string pathToProject)
{
if (target != BuildTarget.iOS)
{
return;
}
var cliOptions = SentryScriptableObject.LoadCliOptions();
var options = SentryScriptableObject.LoadOptions(isBuilding: true);
var logger = options?.DiagnosticLogger ?? new UnityLogger(new SentryUnityOptions());
AddSentryToXcodeProject(options, cliOptions, logger, pathToProject);
}
internal static bool IsNativeSupportEnabled(SentryUnityOptions options, IDiagnosticLogger logger)
{
if (!options.IsValid())
{
logger.LogWarning("Sentry SDK has been disabled. There will be no iOS native support.");
return false;
}
if (!options.IosNativeSupportEnabled)
{
logger.LogInfo("The iOS native support has been disabled through the options.");
return false;
}
return true;
}
internal static void AddSentryToXcodeProject(SentryUnityOptions? options,
SentryCliOptions? cliOptions,
IDiagnosticLogger logger,
string pathToProject)
{
if (options is null)
{
logger.LogWarning("iOS native support disabled because Sentry has not been configured. " +
"You can do that through the editor: {0}", SentryWindow.EditorMenuPath);
// Even with native support disabled the P/Invoke declarations from `SentryCocoaBridgeProxy` must exist.
SetupNoOpBridge(logger, pathToProject);
return;
}
if (IsNativeSupportEnabled(options, logger))
{
SetupSentry(options, logger, pathToProject);
}
else
{
logger.LogInfo("iOS native support has been disabled through the options. " +
"Native support will not be available at runtime.");
// Even with native support disabled the P/Invoke declarations from `SentryCocoaBridgeProxy` must exist.
SetupNoOpBridge(logger, pathToProject);
}
SetupSentryCli(options, cliOptions, logger, pathToProject);
// We want to avoid users getting stuck on a cached built output.
// This can happen if the user appends builds
// - and toggles the `IosNativeSupportEnabled` from `true` to `false`
// - and toggles the `IosNativeInitializationType` from `Standalone` to `Runtime`
if (options.IosNativeInitializationType is NativeInitializationType.Runtime)
{
var mainPath = Path.Combine(pathToProject, SentryXcodeProject.MainPath);
if (File.Exists(mainPath))
{
var main = File.ReadAllText(mainPath);
if (NativeMain.ContainsSentry(main, logger))
{
throw new BuildFailedException(
"The iOS native support has been disabled but the exported project has been modified " +
"during a previous build. Select 'Replace' when exporting the project to create a clean project.");
}
}
}
}
internal static void SetupNoOpBridge(IDiagnosticLogger logger, string pathToProject)
{
try
{
logger.LogDebug("Copying the NoOp bride to the output project.");
var nativeBridgePath = Path.GetFullPath(Path.Combine("Packages", SentryPackageInfo.GetName(), "Plugins", "iOS", SentryXcodeProject.NoOpBridgeName));
CopyFile(nativeBridgePath, Path.Combine(pathToProject, "Libraries", SentryPackageInfo.GetName(), SentryXcodeProject.BridgeName), logger);
using var sentryXcodeProject = SentryXcodeProject.Open(pathToProject);
sentryXcodeProject.AddSentryNativeBridge();
}
catch (Exception e)
{
logger.LogError(e, "Failed to add the Sentry NoOp bridge to the output project.");
}
}
internal static void SetupSentry(SentryUnityOptions options, IDiagnosticLogger logger, string pathToProject)
{
logger.LogInfo("Attempting to add Sentry to the Xcode project.");
try
{
// The SentryObjC.xcframework ends in '~' to hide it from Unity. This prevents Unity from exporting it with the Xcode build.
// Ideally, we would let Unity copy this over but:
// - Detection of `.xcframework` as datatype and non-folder happened in Unity 2021
// - Without a `.meta` file we cannot opt-in embedding the framework
// - Even if Unity copies it, the framework still requires to be 'linked with binary' for it to work
var frameworkPath = Path.GetFullPath(Path.Combine("Packages", SentryPackageInfo.GetName(), "Plugins", "iOS", SentryXcodeProject.FrameworkName + "~"));
CopyFramework(frameworkPath, Path.Combine(pathToProject, "Frameworks", SentryXcodeProject.FrameworkName), logger);
var nativeBridgePath = Path.GetFullPath(Path.Combine("Packages", SentryPackageInfo.GetName(), "Plugins", "iOS", SentryXcodeProject.BridgeName));
CopyFile(nativeBridgePath, Path.Combine(pathToProject, "Libraries", SentryPackageInfo.GetName(), SentryXcodeProject.BridgeName), logger);
using var sentryXcodeProject = SentryXcodeProject.Open(pathToProject, logger);
sentryXcodeProject.AddSentryFramework();
sentryXcodeProject.AddSentryNativeBridge();
if (options.IosNativeInitializationType is NativeInitializationType.BuildTime)
{
sentryXcodeProject.AddNativeOptions(options, NativeOptions.CreateFile);
sentryXcodeProject.AddSentryToMain(options);
}
}
catch (Exception e)
{
logger.LogError(e, "Failed to add the Sentry framework to the generated Xcode project");
return;
}
logger.LogInfo("Successfully added Sentry to the Xcode project.");
}
internal static void SetupSentryCli(SentryUnityOptions options,
SentryCliOptions? cliOptions,
IDiagnosticLogger logger,
string pathToProject)
{
if (cliOptions is null)
{
logger.LogWarning("No Sentry CLI options provided. You can create them by opening the Configuration Window at Tools -> Sentry");
return;
}
logger.LogInfo("Setting up Sentry CLI.");
if (options.Il2CppLineNumberSupportEnabled && !cliOptions.IsValid(logger, EditorUserBuildSettings.development))
{
logger.LogWarning("The IL2CPP line number support requires the debug symbol upload to be enabled.");
}
SentryCli.CreateSentryProperties(pathToProject, cliOptions, options);
SentryCli.SetupSentryCli(pathToProject, RuntimePlatform.OSXEditor);
try
{
using var sentryXcodeProject = SentryXcodeProject.Open(pathToProject, logger);
sentryXcodeProject.AddBuildPhaseSymbolUpload(cliOptions);
}
catch (Exception e)
{
logger.LogError(e, "Failed to add the debug symbol upload build phase.");
}
}
internal static void CopyFramework(string sourcePath, string targetPath, IDiagnosticLogger? logger)
{
if (!Directory.Exists(sourcePath))
{
throw new DirectoryNotFoundException($"Failed to find '{sourcePath}'");
}
if (Directory.Exists(targetPath))
{
logger?.LogDebug("'{0}' has already been copied to '{1}'", Path.GetFileName(targetPath), targetPath);
return;
}
if (Directory.Exists(sourcePath))
{
logger?.LogDebug("Copying from: '{0}' to '{1}'", sourcePath, targetPath);
Directory.CreateDirectory(Path.Combine(Path.GetDirectoryName(targetPath)));
FileUtil.CopyFileOrDirectory(sourcePath, targetPath);
}
if (!Directory.Exists(targetPath))
{
throw new DirectoryNotFoundException($"Failed to copy '{sourcePath}' to '{targetPath}'");
}
}
internal static void CopyFile(string sourcePath, string targetPath, IDiagnosticLogger? logger)
{
if (!File.Exists(sourcePath))
{
throw new FileNotFoundException($"Failed to find '{sourcePath}'");
}
if (File.Exists(targetPath))
{
logger?.LogDebug("'{0}' has already been copied to '{1}'", Path.GetFileName(targetPath), targetPath);
return;
}
if (File.Exists(sourcePath))
{
logger?.LogDebug("Copying from: '{0}' to '{1}'", sourcePath, targetPath);
Directory.CreateDirectory(Path.Combine(Path.GetDirectoryName(targetPath)));
FileUtil.CopyFileOrDirectory(sourcePath, targetPath);
}
if (!File.Exists(targetPath))
{
throw new FileNotFoundException($"Failed to copy '{sourcePath}' to '{targetPath}'");
}
}
}