getsentry / sentry-unity

Development of Sentry SDK for Unity
https://docs.sentry.io/platforms/unity/
MIT License
207 stars 51 forks source link

Sentry Unity library not loading when building from Xcode #432

Closed galenmolk closed 2 years ago

galenmolk commented 2 years ago

Environment

How do you use Sentry?

Which SDK and version?

Steps to Reproduce

Hi, I hope you're doing well.

I am embedding a Unity project as a library inside of a native iOS project built in Swift. If you're curious, for more information on this, see the Unity docs for Integrating Unity into native iOS applications.

I've added the Sentry Unity package to my Unity project, built to iOS and integrated the build into my iOS project. I then attempt to build.

Expected Result

The expected result is a successful build with no errors. The Sentry.Unity.Editor.iOS namespace is expected to utilize the PBXProject class and perform all necessary Xcode steps inside of its OnPostProcessBuild method (called from BuildPostProcess.cs, with the majority of functionality existing in SentryXcodeProject.cs).

Actual Result

The build seems to succeed but as soon as the application launches, it freezes. The only message in the console is:

dyld: Library not loaded: @rpath/Sentry.framework/Sentry
    Referenced from: /private/var/containers/Bundle/Application/05E89D9D-57EC-49AD-B089-8997088861D2/Devasaurus.app/Frameworks/UnityFramework.framework/UnityFramework
    Reason: image not found
dyld: launch, loading dependent libraries
DYLD_LIBRARY_PATH=/usr/lib/system/introspection
DYLD_INSERT_LIBRARIES=/Developer/usr/lib/libBacktraceRecording.dylib:/Developer/usr/lib/libMainThreadChecker.dylib:/Developer/Library/PrivateFrameworks/DTDDISupport.framework/libViewDebuggerSupport.dylib
(lldb)

The Sentry framework parent folders are displayed in red in the sidebar:

Screen Shot 2021-11-23 at 2 11 37 PM

The Sentry framework is included in the Frameworks, Libraries, & Embedded Content sections of both the Unity-iPhone and UnityFramework targets.

Thank you for taking the time to read this. Please don't hesitate to reach out if I can provide more information regarding this issue.

Best, Galen

bitsandfoxes commented 2 years ago

Hey @galenmolk, sorry to see you're running into issues. Could this Xcode project have been exported with a version older than 0.6.0? When we added simulator-support for iOS we modified the way the Sentry.framework gets copied over and it should now rest flat inside the Frameworks directory. (e.g. Frameworks/Sentry.framework).

Does the exported build itself (before you embed it into your own iOS project) run successfully?

galenmolk commented 2 years ago

Hey @bitsandfoxes, thanks for the speedy response! Hope you had a good weekend.

The exported Unity build does indeed run successfully before I embed it in the iOS project. Nice catch. However, I'm not sure what you mean when you ask if the Xcode project was exported with a version older than 0.6.0. The Xcode project uses sentry-cocoa version 7.4.8 for its own error monitoring, etc. Are you saying if I upgrade my sentry-cocoa version, that might solve my problems?

bitsandfoxes commented 2 years ago

Hey @galenmolk! Yes, I've been doing great. Hope you too, despite the Sentry SDK being stubborn.

You should not have to do any upgrading of any underlying SDKs yourself. The Unity SDK is an "all in one package" and takes care of that for you. The screenshot you posted shows a folder structure that looks different from what it should look like in the Unity SDK 0.6.0 and newer. Screenshot 2021-11-30 at 10 20 12 The Sentry.framework should be directly inside the Frameworks directory. So it sounds to me like when you exported the Xcode project from Unity you were using a version older than 0.6.0. But don't change it by hand, the SDK should do that for you during exporting.

So as a first step I would export the Xcode project again (and make sure that it's Sentry Unity SDK 0.6.0 or higher). When getting prompted with appending or replacing the already existing project I would go with replacing.

galenmolk commented 2 years ago

Hi @bitsandfoxes! I exported the Xcode project again. I verified that it was Sentry Unity SDK 0.6.0. But just to be sure, I updated to the latest version. I just uninstalled 0.6.0 and installed Sentry Unity SDK 0.7.0, then exported a fresh build of the project. I unfortunately got the same error when Xcode attempts to run my app after a theoretically successful Xcode build process.

However, I did notice that since updating to 0.7.0, my Frameworks folder structure has changed to more closely resemble yours! So that seems like a step in the right direction at least:

Screen Shot 2021-11-30 at 2 21 21 PM

However, it also seems like the Sentry framework was added a second time, this time in the root folder as opposed to Frameworks folder (the blacked out words are just folder names along the path of the location I exported to):

Screen Shot 2021-11-30 at 2 21 39 PM

Any ideas about that?

Thank you for your insight!

bitsandfoxes commented 2 years ago

That's great news! So now we know

  1. The "game" itself with Sentry added runs
  2. We're on the same version and Sentry gets added correctly to the Xcode project
  3. Your screenshot made me realize that we are actually importing the Sentry.framework in a slightly wrong way. A PR to fix that is up: https://github.com/getsentry/sentry-unity/pull/442 Thanks for that! 😄

I'm not 100% sure if this will actually fix your specific issue since you are also embedding it. What might be missing is embedding the Sentry.framework in the "parent" project like this: Screenshot 2021-12-01 at 13 58 18 and Screenshot 2021-12-01 at 13 59 48 Just in your actual project.

galenmolk commented 2 years ago

@bitsandfoxes Nice work with the PR! Looking forward to checking it out in a new version.

I checked those spots you've highlighted in your screenshots and it looks identical to yours. It's unfortunately still giving me the error message from before.

Screen Shot 2021-12-02 at 9 49 58 AM Screen Shot 2021-12-02 at 9 49 19 AM

Although in mine, the framework icon is slightly transparent which is worrisome...

These screenshots are from the Unity project that is embedded within my Swift project. If I attempt to embed or add the Unity Sentry.framework to the Swift project, I get many errors like:

Class SentryAppStartMeasurement is implemented in both {PATH TO FRAMEWORK} (0x10ff0d648) and {PATH TO FRAMEWORK} (0x1021a1680). One of the two will be used. Which one is undefined.

I'm guessing this is because the Swift project uses its own Sentry package and it's experiencing conflicts. But of course I can't use the Sentry Cocoa package to do tracking in the embedded Unity framework, it can only track errors/performance in the container project, so here I am :)

bitsandfoxes commented 2 years ago

That made me realize something I had not considered at all so far. Sorry for stringing you along.

Sentry in general is not designed and supposed to be used in libraries. And that's basically what's happening now. The app you're exporting from Unity gets turned into a library. This raises a whole bunch of questions:

  1. We're manipulating main.mmto initialize the SDK and read the options from the NativeOptions. Who would be responsible for doing that when using the app as a library?
  2. How should conflicting Sentry SDKs (just like in this case, the "container" project uses its own Sentry SDK) be resolved since the Unity SDK brings its own framework with it.

You could try to resolve this by having both apps use the same framework, I guess? But the question about who initializes what when would remain. Sorry that I can't provide a more satisfying solution to this issue.

galenmolk commented 2 years ago

@bitsandfoxes No worries! Even though I'm still facing some issues, this has been super informative and helpful. I appreciate your time.

I've recently been able to get it successfully building by:

  1. Downgrading to Sentry Unity 0.6.0 (these steps don't work on the latest version for some reason)
  2. Building my Unity project and embedding it as a framework library in the iOS container app project as usual
  3. In Xcode:
    1. Selecting the embedded Unity-iPhone project
    2. Selecting the UnityFramework target
    3. In the General tab, navigating to Frameworks, Libraries, and Embedded Content
    4. In the dropdown next to Sentry.framework, selecting Embed & Sign

After performing these steps, the project builds. Unfortunately, up until now, our Xcode build steps were fully automated with a post-process editor build script akin to what the Sentry Unity SDK uses in BuildPostProcess.cs. I have been unable to automate the aforementioned manual steps. If you have any ideas on how to facilitate that, I would be very interested!

Thanks again.

bitsandfoxes commented 2 years ago

That's great news! I'm glad to hear you found a workaround that works for you.

Unfortunately, the downgrading seems to be necessary due to the SDK always copying and embedding the Sentry.framework in the Xcode project. I think this is a remnant of an earlier version where we relied on Unity to copy it over and we had to handle it there or it would lead to issues. https://github.com/getsentry/sentry-unity/blob/35757cb5f198a8b38fb5075491d5805dbfa1988b/src/Sentry.Unity.Editor.iOS/BuildPostProcess.cs#L24

@bruno-garcia Might be worth considering making embedding the framework depend on the EnableIOSNativeSupportflag? It could potentially help with debugging.

After completing step 3. the embedded Unity app and Sentry within are using the Sentry.framework that comes with the container app? Do native errors show up in your Sentry project? This is a very customized and basically unsupported use case but I'm curious if it works out!

I'm unfamiliar with your setup and but if your Xcode build steps already use a post-process editor of sorts then this sounds like the right place to start.

I'm closing this issue since it's technically a "won't fix" but feel free to reach out either here or on our discord.

bruno-garcia commented 2 years ago

@bruno-garcia Might be worth considering making embedding the framework depend on the EnableIOSNativeSupportflag? It could potentially help with debugging.

Probably a good idea. Just wondering how that affects the "programatic init" approach