OLD | NEW |
(Empty) | |
| 1 # How To Add Breakpad To Your Mac Client Application |
| 2 |
| 3 This document is a step-by-step recipe to get your Mac client app to build with |
| 4 Breakpad. |
| 5 |
| 6 ## Preparing a binary build of Breakpad for use in your tree |
| 7 |
| 8 You can either check in a binary build of the Breakpad framework & tools or |
| 9 build it as a dependency of your project. The former is recommended, and |
| 10 detailed here, since building dependencies through other projects is |
| 11 problematic(matching up configuration names), and the Breakpad code doesn't |
| 12 change nearly often enough as your application's will. |
| 13 |
| 14 ## Building the requisite targets |
| 15 |
| 16 All directories are relative to the `src` directory of the Breakpad checkout. |
| 17 |
| 18 * Build the 'All' target of `client/mac/Breakpad.xcodeproj` in Release mode. |
| 19 * Execute `cp -R client/mac/build/Release/Breakpad.framework <location in your |
| 20 source tree>` |
| 21 * Inside `tools/mac/dump_syms` directory, build dump\_syms.xcodeproj, and copy |
| 22 tools/mac/dump\_syms/build/Release/dump\_syms to a safe location where it |
| 23 can be run during the build process. |
| 24 |
| 25 ## Adding Breakpad.framework |
| 26 |
| 27 Inside your application's framework, add the Breakpad.Framework to your |
| 28 project's framework settings. When you select it from the file chooser, it will |
| 29 let you pick a target to add it to; go ahead and check the one that's relevant |
| 30 to your application. |
| 31 |
| 32 ## Copy Breakpad into your Application Package |
| 33 |
| 34 Copy Breakpad into your Application Package, so it will be around at run time. |
| 35 |
| 36 Go to the Targets section of your Xcode Project window. Hit the disclosure |
| 37 triangle to reveal the build phases of your application. Add a new Copy Files |
| 38 phase using the Contextual menu (Control Click). On the General panel of the new |
| 39 'Get Info' of this new phase, set the destination to 'Frameworks' Close the |
| 40 'Info' panel. Use the Contextual Menu to Rename your new phase 'Copy Frameworks' |
| 41 Now drag Breakpad again into this Copy Frameworks phase. Drag it from whereever |
| 42 it appears in the project file tree. |
| 43 |
| 44 ## Add a New Run Script build phase |
| 45 |
| 46 Near the end of the build phases, add a new Run Script build phase. This will be |
| 47 run before Xcode calls /usr/bin/strip on your project. This is where you'll be |
| 48 calling dump\_sym to output the symbols for each architecture of your build. In |
| 49 my case, the relevant lines read: |
| 50 |
| 51 ``` |
| 52 #!/bin/sh |
| 53 $TOOL_DIR=<location of dump_syms from step 3 above> |
| 54 |
| 55 "$TOOL_DIR/dump_syms" -a ppc "$PROD" > "$TARGET_NAME ppc.breakpad" |
| 56 |
| 57 "$TOOL_DIR/dump_syms" -a i386 "$PROD" > "$TARGET_NAME i386.breakpad" |
| 58 ``` |
| 59 |
| 60 ## Adjust the Project Settings |
| 61 |
| 62 * Turn on Separate Strip, |
| 63 * Set the Strip Style to Non-Global Symbols. |
| 64 |
| 65 ## Write Code! |
| 66 |
| 67 You'll need to have an object that acts as the delegate for NSApplication. |
| 68 Inside this object's header, you'll need to add |
| 69 |
| 70 1. add an ivar for Breakpad and |
| 71 2. a declaration for the applicationShouldTerminate:(NSApplication`*` sender) |
| 72 message. |
| 73 |
| 74 ``` |
| 75 #import <Breakpad/Breakpad.h> |
| 76 |
| 77 @interface BreakpadTest : NSObject { |
| 78 . |
| 79 . |
| 80 . |
| 81 BreakpadRef breakpad; |
| 82 . |
| 83 . |
| 84 . |
| 85 } |
| 86 . |
| 87 . |
| 88 - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sende
r; |
| 89 . |
| 90 . |
| 91 @end |
| 92 ``` |
| 93 |
| 94 Inside your object's implementation file, |
| 95 |
| 96 1. add the following method InitBreakpad |
| 97 2. modify your awakeFromNib method to look like the one below, |
| 98 3. modify/add your application's delegate method to look like the one below |
| 99 |
| 100 ``` |
| 101 static BreakpadRef InitBreakpad(void) { |
| 102 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; |
| 103 BreakpadRef breakpad = 0; |
| 104 NSDictionary *plist = [[NSBundle mainBundle] infoDictionary]; |
| 105 if (plist) { |
| 106 // Note: version 1.0.0.4 of the framework changed the type of the argument |
| 107 // from CFDictionaryRef to NSDictionary * on the next line: |
| 108 breakpad = BreakpadCreate(plist); |
| 109 } |
| 110 [pool release]; |
| 111 return breakpad; |
| 112 } |
| 113 |
| 114 - (void)awakeFromNib { |
| 115 breakpad = InitBreakpad(); |
| 116 } |
| 117 |
| 118 - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sende
r { |
| 119 BreakpadRelease(breakpad); |
| 120 return NSTerminateNow; |
| 121 } |
| 122 ``` |
| 123 |
| 124 ## Configure Breakpad |
| 125 |
| 126 Configure Breakpad for your application. |
| 127 |
| 128 1. Take a look inside the Breakpad.framework at the Breakpad.h file for the |
| 129 keys, default values, and descriptions to be passed to BreakpadCreate(). |
| 130 2. Add/Edit the Breakpad specific entries in the dictionary passed to |
| 131 BreakpadCreate() -- typically your application's info plist. |
| 132 |
| 133 Example from the Notifier Info.plist: |
| 134 `<key>BreakpadProduct</key><string>Google_Notifier_Mac</string> |
| 135 <key>BreakpadProductDisplay</key><string>${PRODUCT_NAME}</string> |
| 136 ` |
| 137 |
| 138 ## Build Your Application |
| 139 |
| 140 Almost done! |
| 141 |
| 142 ## Verify |
| 143 |
| 144 Double-check: |
| 145 |
| 146 Your app should have in its package contents: |
| 147 myApp.app/Contents/Frameworks/Breakpad.framework. |
| 148 |
| 149 The symbol files have reasonable contents (you can look at them with a text |
| 150 editor.) |
| 151 |
| 152 Look again at the Copy Frameworks phase of your project. Are you leaking .h |
| 153 files? Select them and delete them. (If you drag a bunch of files into your |
| 154 project, Xcode often wants to copy your .h files into the build, revealing |
| 155 Google secrets. Be vigilant!) |
| 156 |
| 157 ## Upload the symbol file |
| 158 |
| 159 You'll need to configure your build process to store symbols in a location that |
| 160 is accessible by the minidump processor. There is a tool in tools/mac/symupload |
| 161 that can be used to send the symbol file via HTTP post. |
| 162 |
| 163 1. Test |
| 164 |
| 165 Configure breakpad to send reports to a URL by adding to your app's Info.plist: |
| 166 |
| 167 ``` |
| 168 <key>BreakpadURL</key> |
| 169 <string>upload URL</string> |
| 170 <key>BreakpadReportInterval</key> |
| 171 <string>30</string> |
| 172 ``` |
| 173 |
| 174 ## Final Notes |
| 175 |
| 176 Breakpad checks whether it is being run under a debugger, and if so, normally |
| 177 does nothing. But, you can force Breakpad to function under a debugger by |
| 178 setting the Unix shell variable BREAKPAD\_IGNORE\_DEBUGGER to a non-zero value. |
| 179 You can bracket the source code in the above Write The Code step with #if DEBUG |
| 180 to completely eliminate it from Debug builds. See |
| 181 //depot/googlemac/GoogleNotifier/main.m for an example. FYI, when your process |
| 182 forks(), exception handlers are reset to the default for child processes. So |
| 183 they must reinitialize Breakpad, otherwise exceptions will be handled by Apple's |
| 184 Crash Reporter. |
OLD | NEW |