mirror of
https://github.com/yuzu-emu/breakpad
synced 2024-11-25 12:29:21 +00:00
185 lines
5.9 KiB
Markdown
185 lines
5.9 KiB
Markdown
|
# 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.
|