在 Mac 客户端应用程序中使用 breakpad

本文档是使用 Breakpad 构建 Mac 客户端应用程序的分步指南。

准备 Breakpad 的二进制构建以用于你的代码树

你可以通过 Breakpad 工程中的 xcode 工程文件构建 Breakpad 框架和工具的二进制文件,也可以将其构建为项目的依赖项。建议采用前者的方式,这里会对这种方式做详细介绍,因为通过其它工程构建依赖项是有问题的(匹配配置名称),并且 Breakpad 代码几乎不会像你的应用程序那样经常更改。

构建必要的目标

所有的目录都是相对于 Breakpad 源码的 src 目录的。

  • 以 Release 模式构建
    client/mac/Breakpad.xcodeproj 的 'All' 目标。通过 xcodebuild 命令可以看到这个工程的所有目标:
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

通过如下命令可以以 Release 模式构建 Breakpad 的 'All' 目标:

xcodebuild -configuration Release -target All -project src/client/mac/Breakpad.xcodeproj

也可以通过如下命令只构建 Breakpad 框架:

xcodebuild -configuration Release -target Breakpad -project src/client/mac/Breakpad.xcodeproj
  • 执行 cp -R client/mac/build/Release/Breakpad.framework <location in your source tree>
  • tools/mac/dump_syms 目录中,构建 dump_syms.xcodeproj,并把 tools/mac/dump_syms/build/Release/dump_syms 拷贝到一个在构建过程中可以运行的安全的地方。

添加 Breakpad.framework

在你的应用程序的框架中,把 Breakpad.Framework 添加进你的工程的框架设置中。当你从文件选择器中选择它时,它将让你选取一个目标来添加;请继续,并检查与你的应用程序关联的那个。

将 Breakpad 复制到你的应用程序包中

将 Breakpad 复制到你的应用程序包中,这样它就会在运行时出现。

转到 Xcode Project 窗口的 Targets 部分。点击开合三角以显示应用程序的构建阶段。使用上下文菜单(控制单击,Control Click)添加一个新的复制文件(Copy Files)阶段。在此新阶段的新 'Get Info' 的 General 面板上,将目标设置为 'Frameworks' 关闭 'Info' 面板。使用上下文菜单重命名你的新阶段 'Copy Frameworks'。现在再次将 Breakpad 拖入此 Copy Frameworks 阶段。将其从项目文件树中出现的任何位置拖动。

添加一个新的 Run Script 构建阶段

在构建阶段快结束时,添加一个新的 Run Script 构建阶段。这将在 Xcode 对你的项目调用 /usr/bin/strip 之前运行。这是你将调用 dump_sym 以输出构建的每个体系结构的符号的地方。在我的情况下,相关的代码为:

#!/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"

调整工程设置

  • 打开 Separate Strip,
  • 把 Strip Style 设置为 Non-Global Symbols。

编写代码

你需要有一个对象作为 NSApplication 的委托。 在此对象的头文件中,你需要添加

  1. 为 Breakpad 添加一个 ivar,以及
  2. 一个 applicationShouldTerminate:(NSApplication* sender) 消息的声明。
#import <Breakpad/Breakpad.h>

@interface BreakpadTest : NSObject {
   .
   .
   .
   BreakpadRef breakpad;
   .
   .
   .
}
.
.
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender;
.
.
@end

在你的对象的实现文件中,

  1. 添加如下的 InitBreakpad 方法
  2. 将你的 awakeFromNib 方法修改为如下所示,
  3. 修改/添加你的应用程序的委托方法,如下所示
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;
}

配置 Breakpad

为你的应用程序配置 Breakpad。

  1. 在 Breakpad.framework 的 Breakpad.h 文件中查看要传递给 BreakpadCreate() 的键、默认值和描述。
  2. 在传递给 BreakpadCreate() 的字典中添加/编辑特定于 Breakpad 的条目 —— 通常是应用程序的信息 plist。

Notifier Info.plist 中的示例:<key>BreakpadProduct</key><string>Google_Notifier_Mac</string> <key>BreakpadProductDisplay</key><string>${PRODUCT_NAME}</string>

构建你的应用程序

快完成了!

验证

再检查一遍:

你的应用程序应在其包内容中包含:myApp.app/Contents/Frameworks/Breakpad.framework。

符号文件中具有合理的内容(你可以使用文本编辑器查看它们。)

再次查看项目的 Copy Frameworks 阶段。 你泄露了 .h 文件吗?选择它们并删除它们。(如果你将一堆文件拖到你的项目中,Xcode 经常想将你的 .h 文件复制到构建中,这会泄露谷歌的秘密。要警惕!)

上传符号文件

你需要配置构建过程以将符号存储在 minidump 处理器可以访问的位置。tools/mac/symupload 中有一个工具,可用于通过 HTTP post 发送符号文件。

  1. 测试

过添加到应用程序的 Info.plist 中,配置 breakpad 以将报告发送到 URL:

<key>BreakpadURL</key>
<string>upload URL</string>
<key>BreakpadReportInterval</key>
<string>30</string>

最后的说明

Breakpad 会检查它是否在调试器下运行,如果是,通常什么都不做。但是,你可以通过将 Unix shell 变量 BREAKPAD_IGNORE_DEBUGGER 设置为非零值来强制 Breakpad 在调试器下运行。你可以使用 #if DEBUG 将上述编写代码步骤中的源代码括起来,以从调试版本中完全消除它。参考 //depot/googlemac/GoogleNotifier/main.m 的例子。FYI,当你的进程 forks() 是,子进程的异常处理器复位为默认值。因此它们必须重新初始化 Breakpad,否则异常将由 Apple 的 Crash Reporter 处理。

参考文档

mac下利用Breakpad的dump文件进行调试

How To Add Breakpad To Your Mac Client Application

通过Xcode命令行编译

探究 Xcode 命令行用法一:Xcode 构建必备认知

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,490评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,581评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,830评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,957评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,974评论 6 393
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,754评论 1 307
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,464评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,357评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,847评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,995评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,137评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,819评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,482评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,023评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,149评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,409评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,086评论 2 355

推荐阅读更多精彩内容