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