diff options
Diffstat (limited to 'docs/mac_breakpad_starter_guide.md')
-rw-r--r-- | docs/mac_breakpad_starter_guide.md | 184 |
1 files changed, 184 insertions, 0 deletions
diff --git a/docs/mac_breakpad_starter_guide.md b/docs/mac_breakpad_starter_guide.md new file mode 100644 index 00000000..6e0bdb0e --- /dev/null +++ b/docs/mac_breakpad_starter_guide.md @@ -0,0 +1,184 @@ +# How To Add Breakpad To Your Mac Client Application + +This document is a step-by-step recipe to get your Mac client app to build with +Breakpad. + +## Preparing a binary build of Breakpad for use in your tree + +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. + +## Building the requisite targets + +All directories are relative to the `src` directory of the Breakpad checkout. + +* Build the 'All' target of `client/mac/Breakpad.xcodeproj` in Release mode. +* Execute `cp -R client/mac/build/Release/Breakpad.framework <location in your + source tree>` +* Inside `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. + +## Adding Breakpad.framework + +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 + +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. + +## Add a New Run Script build phase + +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" +``` + +## Adjust the Project Settings + +* Turn on Separate Strip, +* Set the Strip Style to Non-Global Symbols. + +## Write Code! + +You'll need to have an object that acts as the delegate for NSApplication. +Inside this object's header, you'll need to add + +1. add an ivar for Breakpad and +2. a declaration for the applicationShouldTerminate:(NSApplication`*` sender) + message. + +``` +#import <Breakpad/Breakpad.h> + +@interface BreakpadTest : NSObject { + . + . + . + BreakpadRef breakpad; + . + . + . +} +. +. +- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender; +. +. +@end +``` + +Inside your object's implementation file, + +1. add the following method InitBreakpad +2. modify your awakeFromNib method to look like the one below, +3. modify/add your application's delegate method to look like the one below + +``` +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 + +Configure Breakpad for your application. + +1. Take a look inside the Breakpad.framework at the Breakpad.h file for the + keys, default values, and descriptions to be passed to BreakpadCreate(). +2. Add/Edit the Breakpad specific entries in the dictionary passed to + BreakpadCreate() -- typically your application's info plist. + +Example from the Notifier Info.plist: +`<key>BreakpadProduct</key><string>Google_Notifier_Mac</string> +<key>BreakpadProductDisplay</key><string>${PRODUCT_NAME}</string> +` + +## Build Your Application + +Almost done! + +## Verify + +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!) + +## Upload the symbol file + +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. + +1. Test + +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> +``` + +## Final Notes + +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. |