dSYM using xcodebuild

I am building my macOS app for distribution outside the Mac App store using a shell script as shown below. When a user reports a crash, all I get is offsets and I can’t tell what is going on, where:

Thread 3 Crashed:
0   Meteorologist                 	       0x1026da778 0x10268c000 + 321400
1   Meteorologist                 	       0x1026d6354 0x10268c000 + 303956
2   Meteorologist                 	       0x1026d0a8c 0x10268c000 + 281228
3   Meteorologist                 	       0x1026e8ae4 0x10268c000 + 379620
4   Meteorologist                 	       0x1026f7501 0x10268c000 + 439553
5   Meteorologist                 	       0x1026f6621 0x10268c000 + 435745
6   Meteorologist                 	       0x1026f74f9 0x10268c000 + 439545
7   Meteorologist                 	       0x1026f7509 0x10268c000 + 439561

If I understand correctly, I need to include a dSYM file in my executable. I have DWARF with dSYM File in my Build Options, Release value.

I can see the dSYM in my .xcarchive file. How do I get it into my .app executable? I do include uploadSymbols=TRUE in my exportOptionsPlist file.

If I manually copy the dSYM file, prior to the notarytool step, notarytool throws an error. If I insert the dSYM file after I notarize then it gets flagged when I open the app because it doesn't match what was notarized.

#!/bin/bash
#set -e
#set -x

TEMPLATE_DMG=dist/template.dmg

# "working copy" names for the intermediate dmgs
WC_DMG=wc.dmg
WC_DIR=/Volumes/Meteorologist
VERSION=`cat ../website/VERSION2`
SOURCE_FILES="./Build/Release/Meteorologist.app ./dist/Readme.rtf"
MASTER_DMG="./Build/Meteorologist-${VERSION}.dmg"

# .altoolid = abc@icloud.com aka Developer Email
# .altoolpw = abcd-efgh-ijkl-mnop aka App-specific password
# .altooltm = ABCD123456 aka Team ID
dev_account=$(cat ~/.altoolid)
dev_passwd=$(cat ~/.altoolpw)
dev_teamid=$(cat ~/.altooltm)

mkdir ./Build
rm -rf ./Build/*

echo
echo ........................
echo "------------------------ Storing Credentials -----------------------"
echo xcrun notarytool store-credentials --apple-id \"$dev_account\" --team-id \"$dev_teamid\" --password \"$dev_passwd\" notary-scriptingosx
     xcrun notarytool store-credentials --apple-id "$dev_account" --team-id="$dev_teamid" --password "$dev_passwd" notary-scriptingosx > xcodebuild.log
     exit_status=$?
     if [ "${exit_status}" != "0" ]
     then
        cat xcodebuild.log
        exit 1
     fi
     rm xcodebuild.log

echo
echo ........................
echo "------------------------ Building Project as an Archive -----------------------"
echo xcodebuild -project Meteorologist.xcodeproj -scheme Meteorologist -configuration Release -derivedDataPath ./Build -allowProvisioningUpdates --options=runtime clean archive -archivePath ./Build/Meteorologist.xcarchive
	 xcodebuild -project Meteorologist.xcodeproj -scheme Meteorologist -configuration Release -derivedDataPath ./Build -allowProvisioningUpdates --options=runtime clean archive -archivePath ./Build/Meteorologist.xcarchive > xcodebuild.log
     exit_status=$?
     if [ "${exit_status}" != "0" ]
     then
        cat xcodebuild.log
        exit 1
     fi
     rm xcodebuild.log

echo
echo ........................
echo "------------------------ Creating exportOptions.plist -----------------------"
echo \<?xml version=\"1.0\" encoding=\"UTF-8\"?\> > exportOptions.plist
echo \<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\"\> >> exportOptions.plist
echo \<plist version=\"1.0\"\> >> exportOptions.plist
echo \<dict\> >> exportOptions.plist
echo         \<key\>destination\</key\> >> exportOptions.plist
echo         \<string\>export\</string\> >> exportOptions.plist
echo         \<key\>signingStyle\</key\> >> exportOptions.plist
echo         \<string\>automatic\</string\> >> exportOptions.plist
echo         \<key\>method\</key\> >> exportOptions.plist
echo         \<string\>developer-id\</string\> >> exportOptions.plist
echo         \<key\>uploadSymbols\</key\> >> exportOptions.plist
echo         \<true/\> >> exportOptions.plist
echo \</dict\> >> exportOptions.plist
echo \</plist\> >> exportOptions.plist

echo
echo ........................
echo "------------------------ Exporting the Archive -----------------------"
echo xcodebuild -exportArchive -archivePath ./Build/Meteorologist.xcarchive  -exportOptionsPlist exportOptions.plist -exportPath ./Build/Release
     xcodebuild -exportArchive -archivePath ./Build/Meteorologist.xcarchive  -exportOptionsPlist exportOptions.plist -exportPath ./Build/Release > xcodebuild.log
     exit_status=$?
     if [ "${exit_status}" != "0" ]
     then
        cat xcodebuild.log
        exit 1
     fi
     rm xcodebuild.log

echo
echo ........................
echo "------------------------ Compressing the app -----------------------"
echo /usr/bin/ditto -c -k --keepParent ./Build/Release/Meteorologist.app ./Build/Release/Meteorologist.zip
     /usr/bin/ditto -c -k --keepParent ./Build/Release/Meteorologist.app ./Build/Release/Meteorologist.zip
     if [ "${exit_status}" != "0" ]
     then
        echo "Compress (ditto) failed"
        exit 1
     fi
     
echo
echo ........................
echo "------------------------ Notarizing the app -----------------------"
echo xcrun notarytool submit ./Build/Release/Meteorologist.zip --keychain-profile=notary-scriptingosx --wait
     xcrun notarytool submit ./Build/Release/Meteorologist.zip --keychain-profile=notary-scriptingosx --wait
     if [ "${exit_status}" != "0" ]
     then
        echo "xcrun notarytool failed"
        exit 1
     fi

echo
echo ........................
echo "------------------------ Stapling the app -----------------------"
echo xcrun stapler staple "./Build/Release/Meteorologist.app"
     xcrun stapler staple "./Build/Release/Meteorologist.app"
     if [ "${exit_status}" != "0" ]
     then
        echo "xcrun stapler failed"
        exit 1
     fi
echo
rm ./Build/Release/Meteorologist.zip

Replies

A .app bundle is not an executable, it is a folder with a specific structure. The executable code is in the bundle's Contents/MacOS directory. You don't want to add anything to that.

You could put the symbol file into the bundle you distribute to users, but there is really no reason to do so. It is just dead weight to users, it is only useful to you. If you really want to put it into the bundle, you could copy it to some location in the bundle before signing and notarization. You'd do this by adding a post-build script to the Build Phases of your target in Xcode.

A more reasonable approach is to simply archive the .dSYM files for every release you make, and use the appropriate dSYM when you receive a crash log. You can symbolicate the crash logs by hand or using Xcode. See https://developer.apple.com/documentation/xcode/adding-identifiable-symbol-names-to-a-crash-report

Thanks ssmith_c. I understand .app is a bundle. I thought the .dSYM file was supposed to live in Contents/Resources/DWARF/. I tried to put it in there before notarization but then notarization rejected the app.

Ed