This document is a step-by-step recipe to get your Mac client app to build with Breakpad.
You can either check in a binary build of the Breakpad framework & tools or build it as a dependency of your project. The former is recommended, and detailed here, since building dependencies through other projects is problematic(matching up configuration names), and the Breakpad code doesn‘t change nearly often enough as your application’s will.
All directories are relative to the src
directory of the Breakpad checkout.
client/mac/Breakpad.xcodeproj
in Release mode.cp -R client/mac/build/Release/Breakpad.framework <location in your source tree>
tools/mac/dump_syms
directory, build dump_syms.xcodeproj, and copy tools/mac/dump_syms/build/Release/dump_syms to a safe location where it can be run during the build process.Inside your application‘s framework, add the Breakpad.Framework to your project’s framework settings. When you select it from the file chooser, it will let you pick a target to add it to; go ahead and check the one that's relevant to your application.
Copy Breakpad into your Application Package, so it will be around at run time.
Go to the Targets section of your Xcode Project window. Hit the disclosure triangle to reveal the build phases of your application. Add a new Copy Files phase using the Contextual menu (Control Click). On the General panel of the new ‘Get Info’ of this new phase, set the destination to ‘Frameworks’ Close the ‘Info’ panel. Use the Contextual Menu to Rename your new phase ‘Copy Frameworks’ Now drag Breakpad again into this Copy Frameworks phase. Drag it from whereever it appears in the project file tree.
Near the end of the build phases, add a new Run Script build phase. This will be run before Xcode calls /usr/bin/strip on your project. This is where you'll be calling dump_sym to output the symbols for each architecture of your build. In my case, the relevant lines read:
#!/bin/sh $TOOL_DIR=<location of dump_syms from step 3 above> "$TOOL_DIR/dump_syms" -a ppc "$PROD" > "$TARGET_NAME ppc.breakpad" "$TOOL_DIR/dump_syms" -a i386 "$PROD" > "$TARGET_NAME i386.breakpad"
You‘ll need to have an object that acts as the delegate for NSApplication. Inside this object’s header, you'll need to add
*
sender) message.#import <Breakpad/Breakpad.h> @interface BreakpadTest : NSObject { . . . BreakpadRef breakpad; . . . } . . - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender; . . @end
Inside your object's implementation file,
static BreakpadRef InitBreakpad(void) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; BreakpadRef breakpad = 0; NSDictionary *plist = [[NSBundle mainBundle] infoDictionary]; if (plist) { // Note: version 1.0.0.4 of the framework changed the type of the argument // from CFDictionaryRef to NSDictionary * on the next line: breakpad = BreakpadCreate(plist); } [pool release]; return breakpad; } - (void)awakeFromNib { breakpad = InitBreakpad(); } - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender { BreakpadRelease(breakpad); return NSTerminateNow; }
Configure Breakpad for your application.
Example from the Notifier Info.plist: <key>BreakpadProduct</key><string>Google_Notifier_Mac</string> <key>BreakpadProductDisplay</key><string>${PRODUCT_NAME}</string>
Almost done!
Double-check:
Your app should have in its package contents: myApp.app/Contents/Frameworks/Breakpad.framework.
The symbol files have reasonable contents (you can look at them with a text editor.)
Look again at the Copy Frameworks phase of your project. Are you leaking .h files? Select them and delete them. (If you drag a bunch of files into your project, Xcode often wants to copy your .h files into the build, revealing Google secrets. Be vigilant!)
You'll need to configure your build process to store symbols in a location that is accessible by the minidump processor. There is a tool in tools/mac/symupload that can be used to send the symbol file via HTTP post.
Configure breakpad to send reports to a URL by adding to your app's Info.plist:
<key>BreakpadURL</key> <string>upload URL</string> <key>BreakpadReportInterval</key> <string>30</string>
Breakpad checks whether it is being run under a debugger, and if so, normally does nothing. But, you can force Breakpad to function under a debugger by setting the Unix shell variable BREAKPAD_IGNORE_DEBUGGER to a non-zero value. You can bracket the source code in the above Write The Code step with #if DEBUG to completely eliminate it from Debug builds. See //depot/googlemac/GoogleNotifier/main.m for an example. FYI, when your process forks(), exception handlers are reset to the default for child processes. So they must reinitialize Breakpad, otherwise exceptions will be handled by Apple's Crash Reporter.