• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# How To Add Breakpad To Your Mac Client Application
2
3This document is a step-by-step recipe to get your Mac client app to build with
4Breakpad.
5
6## Preparing a binary build of Breakpad for use in your tree
7
8You can either check in a binary build of the Breakpad framework & tools or
9build it as a dependency of your project. The former is recommended, and
10detailed here, since building dependencies through other projects is
11problematic(matching up configuration names), and the Breakpad code doesn't
12change nearly often enough as your application's will.
13
14## Building the requisite targets
15
16All 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
27Inside your application's framework, add the Breakpad.Framework to your
28project's framework settings. When you select it from the file chooser, it will
29let you pick a target to add it to; go ahead and check the one that's relevant
30to your application.
31
32## Copy Breakpad into your Application Package
33
34Copy Breakpad into your Application Package, so it will be around at run time.
35
36Go to the Targets section of your Xcode Project window. Hit the disclosure
37triangle to reveal the build phases of your application. Add a new Copy Files
38phase 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'
41Now drag Breakpad again into this Copy Frameworks phase. Drag it from whereever
42it appears in the project file tree.
43
44## Add a New Run Script build phase
45
46Near the end of the build phases, add a new Run Script build phase. This will be
47run before Xcode calls /usr/bin/strip on your project. This is where you'll be
48calling dump\_sym to output the symbols for each architecture of your build. In
49my 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
67You'll need to have an object that acts as the delegate for NSApplication.
68Inside this object's header, you'll need to add
69
701.  add an ivar for Breakpad and
712.  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 *)sender;
89.
90.
91@end
92```
93
94Inside your object's implementation file,
95
961.  add the following method InitBreakpad
972.  modify your awakeFromNib method to look like the one below,
983.  modify/add your application's delegate method to look like the one below
99
100```
101static 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 *)sender {
119  BreakpadRelease(breakpad);
120  return NSTerminateNow;
121}
122```
123
124## Configure Breakpad
125
126Configure Breakpad for your application.
127
1281.  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().
1302.  Add/Edit the Breakpad specific entries in the dictionary passed to
131    BreakpadCreate() -- typically your application's info plist.
132
133Example 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
140Almost done!
141
142## Verify
143
144Double-check:
145
146Your app should have in its package contents:
147myApp.app/Contents/Frameworks/Breakpad.framework.
148
149The symbol files have reasonable contents (you can look at them with a text
150editor.)
151
152Look again at the Copy Frameworks phase of your project. Are you leaking .h
153files? Select them and delete them. (If you drag a bunch of files into your
154project, Xcode often wants to copy your .h files into the build, revealing
155Google secrets. Be vigilant!)
156
157## Upload the symbol file
158
159You'll need to configure your build process to store symbols in a location that
160is accessible by the minidump processor. There is a tool in tools/mac/symupload
161that can be used to send the symbol file via HTTP post.
162
1631.  Test
164
165Configure 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
176Breakpad checks whether it is being run under a debugger, and if so, normally
177does nothing. But, you can force Breakpad to function under a debugger by
178setting the Unix shell variable BREAKPAD\_IGNORE\_DEBUGGER to a non-zero value.
179You can bracket the source code in the above Write The Code step with #if DEBUG
180to completely eliminate it from Debug builds. See
181//depot/googlemac/GoogleNotifier/main.m for an example. FYI, when your process
182forks(), exception handlers are reset to the default for child processes. So
183they must reinitialize Breakpad, otherwise exceptions will be handled by Apple's
184Crash Reporter.
185