From 108677e961f0e2425083e87fd73feef3f27369f8 Mon Sep 17 00:00:00 2001 From: bitsandfoxes Date: Thu, 10 Sep 2026 16:04:28 +0200 Subject: [PATCH 01/14] fix(windows): ship the native library as `sentry-native` Native crash capture never worked on Windows with the Mono scripting backend. Mono probes the calling assembly's own folder first, so `DllImport("sentry")` from `Sentry.Unity.Native.dll` resolved to the managed `Sentry.dll` sitting beside it in `Managed/` on a case-insensitive file system. That load succeeds, the C entry point is missing, and native support dies with an `EntryPointNotFoundException` that only surfaces when the diagnostic logger is enabled. The desktop library now ships renamed. `native-sdks.targets` writes it out as `sentry-native.dll`, `libsentry-native.so` and `libsentry-native.dylib` while the SDK is built, so the package already carries the new names and the post-build step stays a plain copy. Debug sidecars keep the names their binaries record. Android cannot follow. Its `libsentry.so` comes from the sentry-android-ndk AAR and sentry-java loads it by name from Java, so it gets its own `Sentry.Unity.Native.Android.dll`, built from the same sources with a define the way the console variants already are. Closes #2818 Co-authored-by: Lou Garczynski Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01A1tV2g8KkFQGYdCGLWSay6 --- build/native-sdks.targets | 48 ++++++++---- docs/agent-guides/platform-native.md | 11 ++- .../Sentry.Unity.Native.Android.dll.meta | 78 +++++++++++++++++++ .../Runtime/Sentry.Unity.Native.dll.meta | 4 +- scripts/download-native-sdks.ps1 | 10 +-- .../Sentry.Unity.Android.csproj | 8 +- .../Native/BuildPostProcess.cs | 27 ++++--- src/Sentry.Unity.Native/CFunctions.cs | 6 +- .../Sentry.Unity.Native.csproj | 20 +++++ src/Sentry.Unity.Native/SentryNative.cs | 2 +- src/Sentry.Unity.Native/SentryNativeBridge.cs | 7 +- .../SentryNativeLibrary.cs | 24 ++++++ src/Sentry.Unity/Properties/AssemblyInfo.cs | 1 + .../package-release.zip.snapshot | 28 ++++--- 14 files changed, 213 insertions(+), 61 deletions(-) create mode 100644 package-dev/Runtime/Sentry.Unity.Native.Android.dll.meta create mode 100644 src/Sentry.Unity.Native/SentryNativeLibrary.cs diff --git a/build/native-sdks.targets b/build/native-sdks.targets index 1b6f0cc53..75aa76f75 100644 --- a/build/native-sdks.targets +++ b/build/native-sdks.targets @@ -18,6 +18,16 @@ $(SentryArtifactsDestination)Linux/SentryNative~/ $(SentryArtifactsDestination)Windows/Sentry~/ $(SentryArtifactsDestination)Windows/SentryNative~/ + + + sentry-native.dll + libsentry-native.so + libsentry-native.dylib + @@ -66,17 +77,17 @@ - + - + - + @@ -89,6 +100,7 @@ + @@ -100,16 +112,16 @@ - + - + - + @@ -130,6 +142,7 @@ + @@ -142,19 +155,19 @@ - + - + @@ -166,6 +179,7 @@ + @@ -180,7 +194,6 @@ - @@ -189,8 +202,9 @@ + - + + + @@ -220,19 +236,19 @@ - + - + - + - + + + + $(PackageRuntimePath)/Sentry.Unity.Native.Android.dll + diff --git a/src/Sentry.Unity.Editor/Native/BuildPostProcess.cs b/src/Sentry.Unity.Editor/Native/BuildPostProcess.cs index 3a3629fe2..806dd1b21 100644 --- a/src/Sentry.Unity.Editor/Native/BuildPostProcess.cs +++ b/src/Sentry.Unity.Editor/Native/BuildPostProcess.cs @@ -139,6 +139,13 @@ _ when target.IsSwitch2() => options.SwitchNativeSupportEnabled, _ => false, }; + // The names the package already ships the desktop runtime library under. `native-sdks.targets` + // renames it when the SDK is built. See `SentryNativeLibrary` in Sentry.Unity.Native for why + // binding to plain `sentry` breaks under Mono. Kept here only to clear stale artifacts. + internal const string WindowsLibraryName = "sentry-native.dll"; + internal const string LinuxLibraryName = "libsentry-native.so"; + internal const string MacOSLibraryName = "libsentry-native.dylib"; + private readonly struct NativePluginArtifact(string source, string destination, bool isExecutable = false) { public readonly string Source = source; @@ -165,7 +172,7 @@ private static IEnumerable GetNativePluginArtifact( $"Sentry Windows plugin directory not found: {windowsBackendSourcePath}\n" + $"Run 'dotnet msbuild /t:{buildTarget} src/Sentry.Unity' (or 'dotnet msbuild /t:DownloadNativeSDKs src/Sentry.Unity') to populate it."); } - // Flat copy of every non-PDB file next to the player .exe — sentry.dll and the + // Flat copy of every non-PDB file next to the player .exe. The native library and the // crash handler (crashpad_handler.exe / sentry-crash.exe) all sit at the build root. // PDBs stay in the package and are consumed at symbol-upload time only. foreach (var file in Directory.GetFiles(windowsBackendSourcePath)) @@ -210,8 +217,8 @@ private static IEnumerable GetNativePluginArtifact( $"Sentry Linux plugin directory not found: {linuxBackendSourcePath}\n" + $"Run 'dotnet msbuild /t:{buildTarget} src/Sentry.Unity' (or 'dotnet msbuild /t:DownloadNativeSDKs src/Sentry.Unity') to populate it."); } - // libsentry.so must sit in the player's native plugin dir (_Data/Plugins/x86_64) where the - // Linux player resolves DllImport("sentry"). The crash daemon (sentry-crash, native backend only) + // The native library must sit in the player's native plugin dir (_Data/Plugins/x86_64) + // where the Linux player resolves the P/Invoke. The crash daemon (sentry-crash, native backend only) // sits next to the player executable so sentry-native can spawn it on crash. // The .dbg.so / .dbg debug sidecars stay in the package and are consumed at symbol-upload time only. var linuxPluginDir = GetLinuxPluginDir(buildOutputDir); @@ -252,11 +259,9 @@ private static IEnumerable GetNativePluginArtifact( } } - // On case-insensitive APFS, leftover artifacts from a prior build with - // the *other* macOS backend break DllImport("sentry") resolution - // (Sentry.dylib gets picked over libsentry.dylib, surfacing as - // `sentry_options_new` not found at runtime). Wipe both candidates - // before copying the current backend's files in. + // Wipe both backends' leftovers before copying the current one in, so an iterative build does + // not leave two libraries sitting in PlugIns. `libsentry.dylib` is the pre-rename name and only + // turns up when building over a player made by an older SDK. private static void CleanupStaleMacOSArtifacts(IDiagnosticLogger logger, string executablePath) { var contents = Path.Combine(executablePath, "Contents"); @@ -264,6 +269,7 @@ private static void CleanupStaleMacOSArtifacts(IDiagnosticLogger logger, string { Path.Combine(contents, "PlugIns", "Sentry.dylib"), Path.Combine(contents, "PlugIns", "libsentry.dylib"), + Path.Combine(contents, "PlugIns", MacOSLibraryName), Path.Combine(contents, "MacOS", "sentry-crash"), }) { @@ -287,6 +293,8 @@ private static void CleanupStaleWindowsArtifacts(IDiagnosticLogger logger, strin Path.Combine(buildOutputDir, "crashpad_wer.dll"), Path.Combine(buildOutputDir, "sentry-crash.exe"), Path.Combine(buildOutputDir, "sentry-wer.dll"), + Path.Combine(buildOutputDir, "sentry.dll"), + Path.Combine(buildOutputDir, WindowsLibraryName), }) { if (File.Exists(stale)) @@ -321,6 +329,7 @@ private static void CleanupStaleLinuxArtifacts(IDiagnosticLogger logger, string if (dataDir is not null) { stalePaths.Add(Path.Combine(dataDir, "Plugins", "x86_64", "libsentry.so")); + stalePaths.Add(Path.Combine(dataDir, "Plugins", "x86_64", LinuxLibraryName)); } foreach (var stale in stalePaths) @@ -494,7 +503,7 @@ private static void UploadDebugSymbols(IDiagnosticLogger logger, BuildTarget tar if (options.Experimental.MacosBackend == MacosBackend.Native) { var packageMacOSDir = $"Packages/{SentryPackageInfo.GetName()}/Plugins/macOS/SentryNative~"; - AddPath(paths, Path.GetFullPath($"{packageMacOSDir}/libsentry.dylib.dSYM"), logger); + AddPath(paths, Path.GetFullPath($"{packageMacOSDir}/libsentry-native.dylib.dSYM"), logger); AddPath(paths, Path.GetFullPath($"{packageMacOSDir}/sentry-crash.dSYM"), logger); } else diff --git a/src/Sentry.Unity.Native/CFunctions.cs b/src/Sentry.Unity.Native/CFunctions.cs index e0bef2db9..ec7a27909 100644 --- a/src/Sentry.Unity.Native/CFunctions.cs +++ b/src/Sentry.Unity.Native/CFunctions.cs @@ -8,11 +8,7 @@ namespace Sentry.Unity.Native; internal static class C { -#if SENTRY_NATIVE_SWITCH - private const string SentryLib = "__Internal"; -#else - private const string SentryLib = "sentry"; -#endif + private const string SentryLib = SentryNativeLibrary.Name; internal static void SetValueIfNotNull(sentry_value_t obj, string key, string? value) { diff --git a/src/Sentry.Unity.Native/Sentry.Unity.Native.csproj b/src/Sentry.Unity.Native/Sentry.Unity.Native.csproj index ca7e5386e..d5efb6599 100644 --- a/src/Sentry.Unity.Native/Sentry.Unity.Native.csproj +++ b/src/Sentry.Unity.Native/Sentry.Unity.Native.csproj @@ -65,4 +65,24 @@ /> + + + + + + + diff --git a/src/Sentry.Unity.Native/SentryNative.cs b/src/Sentry.Unity.Native/SentryNative.cs index c255ada10..edbea2569 100644 --- a/src/Sentry.Unity.Native/SentryNative.cs +++ b/src/Sentry.Unity.Native/SentryNative.cs @@ -140,7 +140,7 @@ private static void ReinstallBackend() } catch (EntryPointNotFoundException e) { - Logger?.LogError(e, "Native dependency not found. Did you delete sentry.dll or move files around?"); + Logger?.LogError(e, "Native dependency not found. Did you delete '{0}' or move files around?", SentryNativeLibrary.Name); } } } diff --git a/src/Sentry.Unity.Native/SentryNativeBridge.cs b/src/Sentry.Unity.Native/SentryNativeBridge.cs index a01ddb6e7..216507a8e 100644 --- a/src/Sentry.Unity.Native/SentryNativeBridge.cs +++ b/src/Sentry.Unity.Native/SentryNativeBridge.cs @@ -14,11 +14,7 @@ namespace Sentry.Unity.Native; /// internal static class SentryNativeBridge { -#if SENTRY_NATIVE_SWITCH - private const string SentryLib = "__Internal"; -#else - private const string SentryLib = "sentry"; -#endif + private const string SentryLib = SentryNativeLibrary.Name; private static IDiagnosticLogger? Logger; // This is also the logger we're forwarding native messages to. private static bool UseLibC; @@ -163,7 +159,6 @@ internal static string GetDatabasePath(SentryUnityOptions options, IApplication? internal static void AppHangPause() => sentry_app_hang_pause(); - // libsentry.so [DllImport(SentryLib)] private static extern IntPtr sentry_options_new(); diff --git a/src/Sentry.Unity.Native/SentryNativeLibrary.cs b/src/Sentry.Unity.Native/SentryNativeLibrary.cs new file mode 100644 index 000000000..a848388db --- /dev/null +++ b/src/Sentry.Unity.Native/SentryNativeLibrary.cs @@ -0,0 +1,24 @@ +namespace Sentry.Unity.Native; + +/// +/// The name this build of the assembly binds its P/Invokes to. +/// +/// +/// Desktop cannot bind to plain "sentry". Mono probes the calling assembly's own directory first, +/// and on a case-insensitive file system that resolves to the managed `Sentry.dll` sitting next to +/// us in `Managed/`. It loads, the C entry point is missing, and native support dies with an +/// `EntryPointNotFoundException`. `BuildPostProcess` copies the library into the player under the +/// renamed variant instead. Android and the consoles get theirs from elsewhere - the +/// sentry-android-ndk AAR loads `libsentry.so` by name from Java, and the console plugins ship with +/// the platform SDK - so those builds keep the original name. +/// +internal static class SentryNativeLibrary +{ +#if SENTRY_NATIVE_SWITCH + internal const string Name = "__Internal"; +#elif SENTRY_NATIVE_ANDROID || SENTRY_NATIVE_PLAYSTATION || SENTRY_NATIVE_XBOX + internal const string Name = "sentry"; +#else + internal const string Name = "sentry-native"; +#endif +} diff --git a/src/Sentry.Unity/Properties/AssemblyInfo.cs b/src/Sentry.Unity/Properties/AssemblyInfo.cs index 9e8226ca7..3f9e80ca2 100644 --- a/src/Sentry.Unity/Properties/AssemblyInfo.cs +++ b/src/Sentry.Unity/Properties/AssemblyInfo.cs @@ -4,6 +4,7 @@ [assembly: InternalsVisibleTo("Sentry.Unity.Native.PlayStation")] [assembly: InternalsVisibleTo("Sentry.Unity.Native.Switch")] [assembly: InternalsVisibleTo("Sentry.Unity.Native.Xbox")] +[assembly: InternalsVisibleTo("Sentry.Unity.Native.Android")] [assembly: InternalsVisibleTo("Sentry.Unity.Tests")] [assembly: InternalsVisibleTo("Sentry.Unity.Editor")] [assembly: InternalsVisibleTo("Sentry.Unity.Editor.Tests")] diff --git a/test/Scripts.Tests/package-release.zip.snapshot b/test/Scripts.Tests/package-release.zip.snapshot index 43200dc30..e65f35846 100644 --- a/test/Scripts.Tests/package-release.zip.snapshot +++ b/test/Scripts.Tests/package-release.zip.snapshot @@ -38,9 +38,9 @@ Plugins/Switch.meta Plugins/Windows.meta Plugins/macOS/SentryNativeBridge.m Plugins/macOS/SentryNativeBridge.m.meta -Plugins/macOS/SentryNative~/libsentry.dylib.dSYM/ +Plugins/macOS/SentryNative~/libsentry-native.dylib.dSYM/ Plugins/macOS/SentryNative~/sentry-crash.dSYM/ -Plugins/macOS/SentryNative~/libsentry.dylib +Plugins/macOS/SentryNative~/libsentry-native.dylib Plugins/macOS/SentryNative~/sentry-crash Plugins/macOS/SentryNative~/sentry-crash.dSYM/Contents/Resources/ Plugins/macOS/SentryNative~/sentry-crash.dSYM/Contents/Info.plist @@ -48,12 +48,12 @@ Plugins/macOS/SentryNative~/sentry-crash.dSYM/Contents/Resources/Relocations/ Plugins/macOS/SentryNative~/sentry-crash.dSYM/Contents/Resources/Relocations/aarch64/sentry-crash.yml Plugins/macOS/SentryNative~/sentry-crash.dSYM/Contents/Resources/Relocations/x86_64/sentry-crash.yml Plugins/macOS/SentryNative~/sentry-crash.dSYM/Contents/Resources/DWARF/sentry-crash -Plugins/macOS/SentryNative~/libsentry.dylib.dSYM/Contents/Resources/ -Plugins/macOS/SentryNative~/libsentry.dylib.dSYM/Contents/Info.plist -Plugins/macOS/SentryNative~/libsentry.dylib.dSYM/Contents/Resources/Relocations/ -Plugins/macOS/SentryNative~/libsentry.dylib.dSYM/Contents/Resources/Relocations/aarch64/libsentry.dylib.yml -Plugins/macOS/SentryNative~/libsentry.dylib.dSYM/Contents/Resources/Relocations/x86_64/libsentry.dylib.yml -Plugins/macOS/SentryNative~/libsentry.dylib.dSYM/Contents/Resources/DWARF/libsentry.dylib +Plugins/macOS/SentryNative~/libsentry-native.dylib.dSYM/Contents/Resources/ +Plugins/macOS/SentryNative~/libsentry-native.dylib.dSYM/Contents/Info.plist +Plugins/macOS/SentryNative~/libsentry-native.dylib.dSYM/Contents/Resources/Relocations/ +Plugins/macOS/SentryNative~/libsentry-native.dylib.dSYM/Contents/Resources/Relocations/aarch64/libsentry-native.dylib.yml +Plugins/macOS/SentryNative~/libsentry-native.dylib.dSYM/Contents/Resources/Relocations/x86_64/libsentry-native.dylib.yml +Plugins/macOS/SentryNative~/libsentry-native.dylib.dSYM/Contents/Resources/DWARF/libsentry-native.dylib Plugins/macOS/Sentry~/Sentry.dylib Plugins/macOS/Sentry~/Sentry.dylib.dSYM Plugins/PS5/sentry_utils.c @@ -263,11 +263,11 @@ Plugins/iOS/SentryObjC.xcframework~/ios-arm64/dSYMs/SentryObjC.framework.dSYM/Co Plugins/iOS/SentryObjC.xcframework~/ios-arm64/dSYMs/SentryObjC.framework.dSYM/Contents/Resources/Relocations/aarch64/SentryObjC.yml Plugins/iOS/SentryObjC.xcframework~/ios-arm64/dSYMs/SentryObjC.framework.dSYM/Contents/Resources/DWARF/SentryObjC Plugins/Linux/SentryNative~/libsentry.dbg.so -Plugins/Linux/SentryNative~/libsentry.so +Plugins/Linux/SentryNative~/libsentry-native.so Plugins/Linux/SentryNative~/sentry-crash Plugins/Linux/SentryNative~/sentry-crash.dbg Plugins/Linux/Sentry~/libsentry.dbg.so -Plugins/Linux/Sentry~/libsentry.so +Plugins/Linux/Sentry~/libsentry-native.so Plugins/Android/proguard-sentry-unity.pro Plugins/Android/proguard-sentry-unity.pro.meta Plugins/Android/Sentry~/sentry-android-core-release.aar @@ -280,12 +280,12 @@ Plugins/Windows/SentryNative~/sentry-crash.exe Plugins/Windows/SentryNative~/sentry-crash.pdb Plugins/Windows/SentryNative~/sentry-wer.dll Plugins/Windows/SentryNative~/sentry-wer.pdb -Plugins/Windows/SentryNative~/sentry.dll +Plugins/Windows/SentryNative~/sentry-native.dll Plugins/Windows/SentryNative~/sentry.pdb Plugins/Windows/Sentry~/crashpad_handler.exe Plugins/Windows/Sentry~/crashpad_wer.dll Plugins/Windows/Sentry~/crashpad_wer.pdb -Plugins/Windows/Sentry~/sentry.dll +Plugins/Windows/Sentry~/sentry-native.dll Plugins/Windows/Sentry~/sentry.pdb Prefabs/SentryUserFeedback.prefab Prefabs/SentryUserFeedback.prefab.meta @@ -321,6 +321,10 @@ Runtime/Sentry.Unity.MacOS.dll Runtime/Sentry.Unity.MacOS.dll.meta Runtime/Sentry.Unity.MacOS.pdb Runtime/Sentry.Unity.MacOS.pdb.meta +Runtime/Sentry.Unity.Native.Android.dll +Runtime/Sentry.Unity.Native.Android.dll.meta +Runtime/Sentry.Unity.Native.Android.pdb +Runtime/Sentry.Unity.Native.Android.pdb.meta Runtime/Sentry.Unity.Native.dll Runtime/Sentry.Unity.Native.dll.meta Runtime/Sentry.Unity.Native.pdb From 9b7980867cd7222ab69532452a6dc85f4183676c Mon Sep 17 00:00:00 2001 From: bitsandfoxes Date: Fri, 11 Sep 2026 13:33:30 +0200 Subject: [PATCH 02/14] cleanup --- build/native-sdks.targets | 8 ++----- docs/agent-guides/platform-native.md | 10 ++++---- .../Sentry.Unity.Android.csproj | 4 +--- .../Native/BuildPostProcess.cs | 23 +++++++------------ .../Sentry.Unity.Native.csproj | 3 +-- .../SentryNativeLibrary.cs | 12 ++++------ 6 files changed, 21 insertions(+), 39 deletions(-) diff --git a/build/native-sdks.targets b/build/native-sdks.targets index 75aa76f75..ca6b954aa 100644 --- a/build/native-sdks.targets +++ b/build/native-sdks.targets @@ -19,12 +19,8 @@ $(SentryArtifactsDestination)Windows/Sentry~/ $(SentryArtifactsDestination)Windows/SentryNative~/ - + sentry-native.dll libsentry-native.so libsentry-native.dylib diff --git a/docs/agent-guides/platform-native.md b/docs/agent-guides/platform-native.md index 41419d206..6cfd76150 100644 --- a/docs/agent-guides/platform-native.md +++ b/docs/agent-guides/platform-native.md @@ -7,8 +7,8 @@ - `sentry_get_crashed_last_run` clears native state; SDK caches its result for the process lifetime. Do not make it repeatable. - Native backend reinstalls before first scene after Unity takes crash/signal handlers. - Native logger forwarding to C# exists only under IL2CPP. -- The desktop library is named `sentry-native`, not `sentry`, because Mono probes `Managed/` first and `sentry` resolves to the managed `Sentry.dll`. `build/native-sdks.targets` renames it while building the SDK, so the package already ships it that way. See `SentryNativeLibrary`. -- Android is the exception: its `libsentry.so` comes from the sentry-android-ndk AAR and sentry-java loads it by name, so it keeps `sentry` and gets its own `Sentry.Unity.Native.Android.dll` built from the same sources. +- Desktop library is named `sentry-native`; plain `sentry` resolves to the managed `Sentry.dll` under Mono. Renamed in `build/native-sdks.targets`, so the package already ships it that way. +- Android keeps `sentry` because sentry-java loads its AAR library by name, so it gets its own `Sentry.Unity.Native.Android.dll`. ## Backend Choices @@ -26,14 +26,14 @@ Experimental native modes raise minimum shutdown timeout to 10 seconds. - Windows: runtime files beside player `.exe`; the library lands as `sentry-native.dll`. - Linux: `libsentry-native.so` under `_Data/Plugins/x86_64`; native daemon beside executable. -- macOS: dylib in `.app/Contents/PlugIns` as `libsentry-native.dylib`; handler in `.app/Contents/MacOS`. The Cocoa backend's `Sentry.dylib` keeps its name, it is dlopened rather than P/Invoked. -- Post-build copies file names through unchanged. Stale cleanup still wipes the pre-rename names so builds over a player made by an older SDK do not leave two libraries behind. +- macOS: `libsentry-native.dylib` in `.app/Contents/PlugIns`; handler in `.app/Contents/MacOS`. Cocoa's `Sentry.dylib` keeps its name, it is dlopened not P/Invoked. +- Post-build copies names through unchanged; stale cleanup wipes pre-rename names. ## Console Plugins - PS5/Xbox libraries are user-supplied: `Assets/Plugins/Sentry/{PS5,XSX,XB1}/`. - Switch needs user-supplied static `libsentry.a` and `libzstd.a`; none uses shipped no-op stubs, partial installation is an error. -- Console assemblies, and the Android one, compile separately with platform defines from the same sources. Chained `Csc` targets in `Sentry.Unity.Native.csproj`. +- Console and Android assemblies compile separately with platform defines. Chained `Csc` targets in `Sentry.Unity.Native.csproj`. ## Tests diff --git a/src/Sentry.Unity.Android/Sentry.Unity.Android.csproj b/src/Sentry.Unity.Android/Sentry.Unity.Android.csproj index a9fff2e3f..1953ee328 100644 --- a/src/Sentry.Unity.Android/Sentry.Unity.Android.csproj +++ b/src/Sentry.Unity.Android/Sentry.Unity.Android.csproj @@ -6,9 +6,7 @@ - + $(PackageRuntimePath)/Sentry.Unity.Native.Android.dll diff --git a/src/Sentry.Unity.Editor/Native/BuildPostProcess.cs b/src/Sentry.Unity.Editor/Native/BuildPostProcess.cs index 806dd1b21..fd943e7c8 100644 --- a/src/Sentry.Unity.Editor/Native/BuildPostProcess.cs +++ b/src/Sentry.Unity.Editor/Native/BuildPostProcess.cs @@ -139,9 +139,7 @@ _ when target.IsSwitch2() => options.SwitchNativeSupportEnabled, _ => false, }; - // The names the package already ships the desktop runtime library under. `native-sdks.targets` - // renames it when the SDK is built. See `SentryNativeLibrary` in Sentry.Unity.Native for why - // binding to plain `sentry` breaks under Mono. Kept here only to clear stale artifacts. + // Only needed to clear stale artifacts; the package already ships these names. internal const string WindowsLibraryName = "sentry-native.dll"; internal const string LinuxLibraryName = "libsentry-native.so"; internal const string MacOSLibraryName = "libsentry-native.dylib"; @@ -172,9 +170,8 @@ private static IEnumerable GetNativePluginArtifact( $"Sentry Windows plugin directory not found: {windowsBackendSourcePath}\n" + $"Run 'dotnet msbuild /t:{buildTarget} src/Sentry.Unity' (or 'dotnet msbuild /t:DownloadNativeSDKs src/Sentry.Unity') to populate it."); } - // Flat copy of every non-PDB file next to the player .exe. The native library and the - // crash handler (crashpad_handler.exe / sentry-crash.exe) all sit at the build root. - // PDBs stay in the package and are consumed at symbol-upload time only. + // Windows resolves both the library and the crash handler next to the player .exe. + // PDBs stay in the package for symbol upload. foreach (var file in Directory.GetFiles(windowsBackendSourcePath)) { if (file.EndsWith(".pdb", StringComparison.OrdinalIgnoreCase)) @@ -196,8 +193,7 @@ private static IEnumerable GetNativePluginArtifact( { var name = Path.GetFileName(file); var isDylib = name.EndsWith(".dylib", StringComparison.OrdinalIgnoreCase); - // The .dylibs need to go into the `*.app/Contents/Plugins` dirctory and will be picked - // up by unity. The crash handler (sentry-native) needs to be next to the game's executable + // Unity loads dylibs from PlugIns; the crash handler has to be next to the executable. var desination = Path.Combine(contents, isDylib ? "PlugIns" : "MacOS", name); yield return new NativePluginArtifact( file, @@ -217,10 +213,8 @@ private static IEnumerable GetNativePluginArtifact( $"Sentry Linux plugin directory not found: {linuxBackendSourcePath}\n" + $"Run 'dotnet msbuild /t:{buildTarget} src/Sentry.Unity' (or 'dotnet msbuild /t:DownloadNativeSDKs src/Sentry.Unity') to populate it."); } - // The native library must sit in the player's native plugin dir (_Data/Plugins/x86_64) - // where the Linux player resolves the P/Invoke. The crash daemon (sentry-crash, native backend only) - // sits next to the player executable so sentry-native can spawn it on crash. - // The .dbg.so / .dbg debug sidecars stay in the package and are consumed at symbol-upload time only. + // The Linux player resolves the P/Invoke from the plugin dir, and sentry-native spawns + // the crash daemon from next to the executable. Debug sidecars stay in the package. var linuxPluginDir = GetLinuxPluginDir(buildOutputDir); foreach (var file in Directory.GetFiles(linuxBackendSourcePath)) { @@ -259,9 +253,8 @@ private static IEnumerable GetNativePluginArtifact( } } - // Wipe both backends' leftovers before copying the current one in, so an iterative build does - // not leave two libraries sitting in PlugIns. `libsentry.dylib` is the pre-rename name and only - // turns up when building over a player made by an older SDK. + // A prior build with the other backend, or an older SDK's pre-rename library, would otherwise + // leave a second library behind in PlugIns. private static void CleanupStaleMacOSArtifacts(IDiagnosticLogger logger, string executablePath) { var contents = Path.Combine(executablePath, "Contents"); diff --git a/src/Sentry.Unity.Native/Sentry.Unity.Native.csproj b/src/Sentry.Unity.Native/Sentry.Unity.Native.csproj index d5efb6599..de28b4ec0 100644 --- a/src/Sentry.Unity.Native/Sentry.Unity.Native.csproj +++ b/src/Sentry.Unity.Native/Sentry.Unity.Native.csproj @@ -65,8 +65,7 @@ /> - + diff --git a/src/Sentry.Unity.Native/SentryNativeLibrary.cs b/src/Sentry.Unity.Native/SentryNativeLibrary.cs index a848388db..2d37b61a1 100644 --- a/src/Sentry.Unity.Native/SentryNativeLibrary.cs +++ b/src/Sentry.Unity.Native/SentryNativeLibrary.cs @@ -1,16 +1,12 @@ namespace Sentry.Unity.Native; /// -/// The name this build of the assembly binds its P/Invokes to. +/// The library name this build binds its P/Invokes to. /// /// -/// Desktop cannot bind to plain "sentry". Mono probes the calling assembly's own directory first, -/// and on a case-insensitive file system that resolves to the managed `Sentry.dll` sitting next to -/// us in `Managed/`. It loads, the C entry point is missing, and native support dies with an -/// `EntryPointNotFoundException`. `BuildPostProcess` copies the library into the player under the -/// renamed variant instead. Android and the consoles get theirs from elsewhere - the -/// sentry-android-ndk AAR loads `libsentry.so` by name from Java, and the console plugins ship with -/// the platform SDK - so those builds keep the original name. +/// Desktop cannot use "sentry": Mono probes the calling assembly's own directory first, where it +/// resolves to the managed `Sentry.dll` on a case-insensitive file system. Android and the consoles +/// get their library from elsewhere and keep the original name. /// internal static class SentryNativeLibrary { From 5e79198952b4c2da305ef8883962079c8540fe2e Mon Sep 17 00:00:00 2001 From: bitsandfoxes Date: Fri, 11 Sep 2026 15:13:57 +0200 Subject: [PATCH 03/14] added x86 windows native build --- .github/workflows/ci.yml | 29 +++++ .github/workflows/test-run-desktop.yml | 11 +- build/native-sdks.targets | 101 ++++++++++-------- docs/agent-guides/platform-native.md | 4 +- scripts/download-native-sdks.ps1 | 10 +- .../Native/BuildPostProcess.cs | 19 ++-- .../Editor/Builder.cs | 8 ++ test/Scripts.Integration.Test/globals.ps1 | 1 + .../package-release.zip.snapshot | 35 ++++-- .../Native/BuildPostProcessTests.cs | 17 +++ 10 files changed, 165 insertions(+), 70 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 94ca1885c..683f2b565 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -427,6 +427,21 @@ jobs: with: unity-version: ${{ matrix.unity-version }} + test-build-windows-x86: + # Unity still ships a 32-bit standalone player and it needs its own sentry-native build. + # Pinned to the oldest supported Unity version, native backend only: x86 is on its way out + # and the x64 matrix already covers the version spread and the crashpad backend. + name: Build Windows x86 2021.3 Integration Test + if: ${{ !startsWith(github.ref, 'refs/heads/release/') }} + needs: [test-create] + secrets: + UNITY_LICENSE_SERVER_CONFIG: ${{ secrets.UNITY_LICENSE_SERVER_CONFIG }} + SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} + SENTRY_TEST_DSN: ${{ secrets.SENTRY_TEST_DSN }} + uses: ./.github/workflows/test-build-windows-x86.yml + with: + unity-version: "2021.3" + test-build-macos: name: Build macOS ${{ matrix.unity-version }} Integration Test if: ${{ !startsWith(github.ref, 'refs/heads/release/') }} @@ -479,6 +494,20 @@ jobs: platform: windows backend: ${{ matrix.backend }} + test-run-windows-x86: + name: Run Windows x86 native 2021.3 Integration Test + if: ${{ !startsWith(github.ref, 'refs/heads/release/') }} + needs: [test-build-windows-x86] + secrets: + SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} + SENTRY_TEST_DSN: ${{ secrets.SENTRY_TEST_DSN }} + uses: ./.github/workflows/test-run-desktop.yml + with: + unity-version: "2021.3" + platform: windows + architecture: x86 + backend: native + test-run-macos: name: Run macOS ${{ matrix.backend }} ${{ matrix.unity-version }} Integration Test if: ${{ !startsWith(github.ref, 'refs/heads/release/') }} diff --git a/.github/workflows/test-run-desktop.yml b/.github/workflows/test-run-desktop.yml index 979ee9a45..9c19d16ac 100644 --- a/.github/workflows/test-run-desktop.yml +++ b/.github/workflows/test-run-desktop.yml @@ -14,6 +14,11 @@ on: type: string default: "" description: "macOS: native or cocoa. Windows: native or crashpad. Linux: native or breakpad." + architecture: + required: false + type: string + default: "" + description: "Only set for non-default architectures, e.g. x86 for the 32-bit Windows player." secrets: SENTRY_AUTH_TOKEN: required: true @@ -26,7 +31,7 @@ defaults: jobs: run: - name: ${{ inputs.platform }}${{ inputs.backend && format(' ({0})', inputs.backend) || '' }} ${{ inputs.unity-version }} + name: ${{ inputs.platform }}${{ inputs.architecture && format(' {0}', inputs.architecture) || '' }}${{ inputs.backend && format(' ({0})', inputs.backend) || '' }} ${{ inputs.unity-version }} runs-on: ${{ inputs.platform == 'linux' && 'ubuntu-latest' || inputs.platform == 'macos' && 'macos-latest' || 'windows-latest' }} env: SENTRY_DSN: ${{ secrets.SENTRY_TEST_DSN }} @@ -43,7 +48,7 @@ jobs: - name: Download test app artifact uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: - name: testapp-desktop-compiled-${{ inputs.unity-version }}-${{ inputs.platform }}${{ inputs.backend && format('-{0}', inputs.backend) || '' }} + name: testapp-desktop-compiled-${{ inputs.unity-version }}-${{ inputs.platform }}${{ inputs.architecture && format('-{0}', inputs.architecture) || '' }}${{ inputs.backend && format('-{0}', inputs.backend) || '' }} - name: Extract test app run: tar -xvzf test-app-desktop.tar.gz @@ -90,7 +95,7 @@ jobs: if: ${{ failure() }} uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: - name: testapp-desktop-logs-${{ inputs.platform }}${{ inputs.backend && format('-{0}', inputs.backend) || '' }}-${{ inputs.unity-version }} + name: testapp-desktop-logs-${{ inputs.platform }}${{ inputs.architecture && format('-{0}', inputs.architecture) || '' }}${{ inputs.backend && format('-{0}', inputs.backend) || '' }}-${{ inputs.unity-version }} path: | test/IntegrationTest/results/ retention-days: 14 diff --git a/build/native-sdks.targets b/build/native-sdks.targets index 75aa76f75..bb91eb879 100644 --- a/build/native-sdks.targets +++ b/build/native-sdks.targets @@ -128,83 +128,94 @@ - + - - - - - - - - + + + + + + + build_$(SentryWindowsArch) + $(SentryWindowsArtifactsDestination)$(SentryWindowsArch)/ + + + + + - - - + + + - + - - - - + + + + - - + + - + - + - - - - - - - - - + + + + + + + build_native_$(SentryWindowsArch) + $(SentryWindowsNativeArtifactsDestination)$(SentryWindowsArch)/ + + + + + - - - - + + + + - + - - - - - + + + + + - - + + - +