forked from eden-emu/eden
		
	
		
			
	
	
		
			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. |