This document is a step-by-step guide to building Mac client applications using Breakpad.
Prepare binary builds of Breakpad for use in your code tree
You can build breakpad framework and tool binaries through the xcode project file in the Breakpad project, or you can build them as project dependencies. The former approach is recommended and is covered in detail here, since building dependencies through other projects is problematic (matching configuration names) and the Breakpad code rarely changes as often as your application.
Build necessary goals
All directories are relative to the Breakpad source src
directory.
client/mac/Breakpad.xcodeproj
'All' target built in Release mode .xcodebuild
You can see all targets of this project through the command:
breakpad % xcodebuild -list -project src/client/mac/Breakpad.xcodeproj
Command line invocation:
/Applications/Xcode.app/Contents/Developer/usr/bin/xcodebuild -list -project src/client/mac/Breakpad.xcodeproj
User defaults from command line:
IDEPackageSupportUseBuiltinSCM = YES
Information about project "Breakpad":
Targets:
Breakpad
Inspector
breakpadUtilities
crash_report_sender
BreakpadTest
All
UnitTests
generator_test
minidump_file_writer_unittest
handler_test
gtest
crash_generation_server_test
minidump_generator_test_helper
Build Configurations:
Debug
Debug With Code Coverage
Release
If no build configuration is specified and -scheme is not passed then "Release" is used.
Schemes:
All
all_unittests
Breakpad
BreakpadTest
breakpadUtilities
byte_cursor_unittest
bytereader_unittest
crash_generation_server_test
crash_report
crash_report_sender
dump_syms
dwarf_cfi_to_module_unittest
dwarf_cu_to_module_unittest
dwarf_line_to_module_unittest
dwarf2diehandler_unittest
dwarf2reader_cfi_unittest
generator_test
gtest
gtestmockall
handler_test
Inspector
macho_dump
macho_reader_unittest
minidump_file_writer_unittest
minidump_generator_test_helper
minidump_upload
module_unittest
stabs_reader_unittest
stabs_to_module_unittest
symupload
test_assembler_unittest
UnitTests
Breakpad's 'All' target can be built in Release mode with the following command:
xcodebuild -configuration Release -target All -project src/client/mac/Breakpad.xcodeproj
You can also build only the Breakpad framework through the following command:
xcodebuild -configuration Release -target Breakpad -project src/client/mac/Breakpad.xcodeproj
- implement
cp -R client/mac/build/Release/Breakpad.framework <location in your source tree>
- In
tools/mac/dump_syms
the directory, builddump_syms.xcodeproj
, andtools/mac/dump_syms/build/Release/dump_syms
copy to a safe place where you can run it during the build process.
AddBreakpad.framework
In your application's framework, add Breakpad.Framework to your project's framework settings. When you select it from the file picker, it will let you pick a target to add; go ahead and check the one associated with your application.
Copy Breakpad into your application bundle
Copy Breakpad into your application bundle so it appears at runtime.
Go to the Targets section of the Xcode Project window. Click the triangle to display the application's build phases. Use the context menu (Control Click) to add a new Copy Files stage. In the new 'Get Info' General panel of this new stage, set the target to 'Frameworks' Close the 'Info' panel. Use the context menu to rename your new stage 'Copy Frameworks'. Now drag the Breakpad into this Copy Frameworks stage again. Drag it from wherever it appears in the project file tree.
Add a new Run Script build phase
Towards the end of the build phase, add a new Run Script build phase. This will run before Xcode calls on your project /usr/bin/strip
. This is where you will call dump_sym
to output the symbols for each architecture built. In my case the relevant code was:
#!/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 project settings
- Open Separate Strip,
- Set Strip Style to Non-Global Symbols.
Write code
You need to have an object as the delegate of NSApplication. In the header file of this object you need to add
- Add an ivar for Breakpad, and
- A declaration of applicationShouldTerminate:(NSApplication* sender) message.
#import <Breakpad/Breakpad.h>
@interface BreakpadTest : NSObject {
.
.
.
BreakpadRef breakpad;
.
.
.
}
.
.
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender;
.
.
@end
In your object's implementation file,
- Add the following InitBreakpad method
- Modify your awakeFromNib method to look like this,
- Modify/add your application's delegate method as shown 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.
- Look in the Breakpad.h file in Breakpad.framework for the keys, default values, and descriptions to be passed to BreakpadCreate().
- Add/edit Breakpad-specific entries in the dictionary passed to BreakpadCreate() - typically the application's information plist.
Example from Notifier Info.plist:<key>BreakpadProduct</key><string>Google_Notifier_Mac</string> <key>BreakpadProductDisplay</key><string>${PRODUCT_NAME}</string>
Build your application
almost finished!
verify
Check again:
Your app should include: myApp.app/Contents/Frameworks/Breakpad.framework in its bundle content.
The symbol files have reasonable contents (you can view them using a text editor.)
Look again at the Copy Frameworks phase of the project. Did you leak the .h file? Select them and delete them. (If you drag a bunch of files into your project, Xcode will often want to copy your .h files into the build, which will give away Google's secrets. Be wary!)
Upload symbol file
You need to configure the build process to store symbols in a location accessible to the minidump processor. There is a tool in tools/mac/symupload that can be used to send symbol files via HTTP post.
- test
Configure breakpad to send reports to a URL by adding to your application's Info.plist:
<key>BreakpadURL</key>
<string>upload URL</string>
<key>BreakpadReportInterval</key>
<string>30</string>
final notes
Breakpad checks to see if it's running under a debugger, and if so, usually does nothing. However, you can force Breakpad to run under a debugger by setting the Unix shell variable BREAKPAD_IGNORE_DEBUGGER to a non-zero value. You can use #if DEBUG to completely eliminate it from the debug build by surrounding the source code in the coding step above. Refer to //depot/googlemac/GoogleNotifier/main.m for examples. FYI, when your process forks(), the child process's exception handler is reset to default. Therefore they must reinitialize the Breakpad, otherwise the exception will be handled by Apple's Crash Reporter.
Reference documentation
Debugging using Breakpad’s dump file under mac
How To Add Breakpad To Your Mac Client Application
Compile via Xcode command line
Explore Xcode command line usage 1: Essential knowledge for Xcode builds