How to run upload symbols to upload dSYMs as a part of Xcode build process?

27,629

Solution 1

Try the following steps:

Step 1: Select your application's Xcode project, then your application target, then select "Build Phases".

Step 2: In Xcode menu, select "Editor", then select "Add Build Phase", and then click on "Add Run Script Build Phase".

Step 3: You should now see a Run Script section in your Build Phase options.

Step 4: Paste in the script inside the body of the Run Script Build Phase.

Keep in mind to set the right file-path(s) in your script(s).

Solution 2

TL;DR: dSYMS generated at build time has little value in the "bitcode enabled" era, you need to download dSYMs from Apple and upload them to your 3rd party crash reporter service as a post-build step after Apple has processed your upload.

Background

Symptom

Missing dSYMs / failed symbolication in 3rd party crash reporting console. I thought despite following Crashlytics install instructions the script was failing.

Bitcode - the fundamental issue

Turns out the 3rd party crash-reporting systems (like Crashlytics, or New Relic) have a fundamental problem with the current best practice for app distribution, which is bitcode-enabled apps. Historically these 3rd party crash report systems relied on build-time steps to upload build-time generated dSYMs. But since bitcode-enabling means the app store recompiles your apps, your build-time generated dSYMs, that you are trying to upload, are effectively useless.

As background, bitcode-enabled apps are "thinned" and thus re-compiled by Apple such that each device only gets the download bits it needs. You want to enable bitcode. It is a good thing. But, bitcode-enabled distribution messes up symbolication. No matter what dSYMs you generate at build time, the dSYMs won't actually correlate to crashes from App Store or TestFlight installed builds, as your crashes will be from App-store recompiled versions of your apps with new corresponding dSYMs.

So don't worry about the upload script working or not at build time. In fact, that step could be removed from your build process as it is just wasting your time and bandwidth.

The only case it might be useful is if you want to symbolicate crashes from locally-installed release versions instead of debugging them directly in Xcode.

Solutions

The solution is to wait "some time" (reportedly several minutes, via NewRelic documentation, in my experience a sleep of 120 seconds after fastlane upload but before I ran fastlane's download_dsyms action failed sometimes, a sleep of 300 seconds works reliably) after uploading your app (likely the duration of time the App Store says your build is "Processing"), then download the dSYMs from there and use your 3rd party crash reporters command-line upload script

Manual download / upload

The current recommended solutions from the 3rd party crash reporters (both NewRelic and Crashlytics documentation at least) is to either go to the App Store Connect page for the build and download dSYMs then upload, or using XCode's Organizer for the archive hit the "Download Debug Symbols" button, then upload them.

This does work, with manual dSYM downloads pushed out to your crash reporting vendor you will get symbolicated reports. It is a manual process though using either the Xcode GUI or the App Store Connect interface.

Fastlane automation

You may automate the process with Fastlane though, which is I believe the proper solution.

https://docs.fastlane.tools/actions/download_dsyms/#download_dsyms

https://docs.fastlane.tools/actions/upload_symbols_to_crashlytics/

Solution 3

You need to requred update in Project Target-> Build setting -> debug information (Debug and release both) -> DWARF with dSYM file

enter image description here

Share:
27,629

Related videos on Youtube

user3554626
Author by

user3554626

Updated on July 09, 2022

Comments

  • user3554626
    user3554626 almost 2 years

    Ok, so I'm trying to automatically upload dSYMs. I'm following instructions from this official documentation: https://firebase.google.com/docs/crashlytics/get-deobfuscated-reports

    I'm stuck at "Run the upload symbols script manually" section. There are 3 ways to upload dSYMs. I'm trying to follow the first one - including the following line in your build process: find ${DWARF_DSYM_FOLDER_PATH} -name "*.dSYM" | xargs -I \{\} ${PODS_ROOT}/Fabric/upload-symbols -gsp MyProjectFolder/GoogleService-Info.plist -p ios \{\}

    For now I've tried the following:

    1. I go to Project->Scheme->Edit Scheme.
    2. I click on Build->Post actions
    3. I start small - I only want to show "echo" in build process: dSYMs
    4. I run Product->Build
    5. I go to View->Navigators->Show Report Navigator
    6. There's not indication that echo was run.

    Where to put this script?

    How to find if it is being run or not?

  • user3554626
    user3554626 over 5 years
    This is on the documentation guide page I linked. It doesn't work for me and that's why I'm trying to make the next step work - upload dSYMs with a script.
  • Mike Hardy
    Mike Hardy about 5 years
    You want the fastlane actions I linked in the bottom of my answer then. They work great for me - I have it download/upload "latest" dsyms after builds, which sometimes works (it's a timing thing), I have a lane just for "latest" dsyms which I can run on demand (in case the timing issue where Apple wasn't done processing yet happens during the build), and I have a full refresh_dsyms lane - all just built with one-liners on those linked actions. Huge time-saver
  • Mike Hardy
    Mike Hardy over 4 years
    True indeed. I mentioned that in the TLDR and in the intro that it is a best practice (because it is) implying that it only applies to that. I even explained what it meant, and I thought that made it clear?
  • CyberMew
    CyberMew over 4 years
    No problem, it just read out to me as symbols not uploading due to bitcode only.
  • Eggy
    Eggy over 4 years
    question form this new command from Firebase firebase.google.com/docs/crashlytics/… do I need to change the PATH to absolute? thanks
  • Mitemmetim
    Mitemmetim about 4 years
    Thanks for this great answer! I have a question about the "wait some time" part. I am using fastlanes download_dsyms with the flag wait_for_dsym_processing and even set the wait_timout to 10 minutes but always get the errors ITC.response.error.BUILD_NOT_FOUND and Error accessing dSYM file for build. I guess this is because the build is still processing, right? So I was thinking about running the dsym refresh on a daily routine, since I don't want to let the CI wait for too long, but does this actually make sense? When is a new dsym generated? Once a new build is processed or more often?
  • Mike Hardy
    Mike Hardy about 4 years
    @Mitemmetim that's a good question and unfortunately the answer is I don't know? As mentioned I wait 300 seconds personally and it has been working for me, but that's experience, and is waiting for a system out of my control so maybe my app is different (so your experience is different) or they changed the system? A daily run of "refresh latest dsyms" (or latest NN dsyms) seems like a valid workaround. Can't hurt to try?
  • Lucky_girl
    Lucky_girl about 4 years
    Does it mean that DSYM should updated each time, when there is new build uploaded to App Store?
  • Mike Hardy
    Mike Hardy about 4 years
    Hi @Lucky_girl - every time you create a new build, you will need the corresponding dSYMs to decode crashes. It follows that if you send a new build out for release, your crash reporting services will need those matching dSYMs, so yes, every build you upload matching dSYMs. For that reason I recommend using fastlane (or similar) as part of an automated process. Doing it manually is viable only for initial setup testing in my opinion
  • Lucky_girl
    Lucky_girl about 4 years
    @MikeHardy would Firebase still show reports for old builds if new Dsym would be uploaded for new build?
  • Mike Hardy
    Mike Hardy about 4 years
    @Lucky_girl yes - I wish my app was perfect, but sadly it crashes, and of course it is always the old versions (my new versions are perfect!), and I still get decoded crash reports (using the previous uploaded dSYMs) just fine. Judging by the code (github.com/fastlane/fastlane/blob/master/fastlane/lib/fastl‌​ane/…) the dSYMs zip must contain enough information for crashlytics (or sentry, etc) to figure it out. It always works.
  • Kruupös
    Kruupös about 2 years
    Is this still possible in 2022 ? I fell that Fastlane is not showing any dSYMs files recently, not the app store. I've been stuck for a while finding a new solution.
  • Mike Hardy
    Mike Hardy about 2 years
    @Kruupös I just did a TestFlight build today, and with current version of fastlane (2.205.1) it worked just fine to sleep 300 after waiting for the build to show up, followed by downloading the dsyms then calling the crashlytics upload script. I think everything's working great
  • Kruupös
    Kruupös about 2 years
    @MikeHardy thank you for your answer. I had Enable Bitcode set to No for my recents builds (I did it for no real reasons, while updating a react-native version). After switching back to Yes everything seems to work.
  • Mike Hardy
    Mike Hardy almost 2 years
    New flash: Xcode 14 (almost released...) deprecates bitcode, disables it by default, will warn you if you try to set it to true manually, strips it prior to upload, and App Store will reject apps with bitcode. So this whole thing may change style soon, back to a state where build-time dSYM upload is best. stackoverflow.com/questions/72543728/…