From 7ccfe6aac71bca30375297fd128947eeab72ee98 Mon Sep 17 00:00:00 2001 From: Gwynne Raskind Date: Wed, 10 Jun 2015 11:32:03 -0500 Subject: [PATCH 1/8] Port C++ exception handling support over from PLCrashReporter's non-merged implementation. Includes changes to auto-link C++ with client apps where possible. Correctly handles cases where client apps use libstdc++. --- Classes/BITCrashCXXExceptionHandler.h | 48 +++++++ Classes/BITCrashCXXExceptionHandler.mm | 150 ++++++++++++++++++++ Classes/BITCrashManager.m | 45 ++++++ Classes/HockeySDK.h | 5 - Support/HockeySDK.xcodeproj/project.pbxproj | 46 ++++-- Support/module.modulemap | 2 + 6 files changed, 278 insertions(+), 18 deletions(-) create mode 100644 Classes/BITCrashCXXExceptionHandler.h create mode 100644 Classes/BITCrashCXXExceptionHandler.mm diff --git a/Classes/BITCrashCXXExceptionHandler.h b/Classes/BITCrashCXXExceptionHandler.h new file mode 100644 index 0000000000..f73fe275b4 --- /dev/null +++ b/Classes/BITCrashCXXExceptionHandler.h @@ -0,0 +1,48 @@ +/* + * Author: Gwynne Raskind + * + * Copyright (c) 2015 HockeyApp, Bit Stadium GmbH. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#import + +typedef struct { + const void * __nullable exception; + const char * __nullable exception_type_name; + const char * __nullable exception_message; + uint32_t exception_frames_count; + const uintptr_t * __nonnull exception_frames; +} BITCrashUncaughtCXXExceptionInfo; + +typedef void (*BITCrashUncaughtCXXExceptionHandler)( + const BITCrashUncaughtCXXExceptionInfo * __nonnull info +); + +@interface BITCrashUncaughtCXXExceptionHandlerManager : NSObject + ++ (void)addCXXExceptionHandler:(nonnull BITCrashUncaughtCXXExceptionHandler)handler; ++ (void)removeCXXExceptionHandler:(nonnull BITCrashUncaughtCXXExceptionHandler)handler; + +@end diff --git a/Classes/BITCrashCXXExceptionHandler.mm b/Classes/BITCrashCXXExceptionHandler.mm new file mode 100644 index 0000000000..a71826212e --- /dev/null +++ b/Classes/BITCrashCXXExceptionHandler.mm @@ -0,0 +1,150 @@ +/* + * Author: Gwynne Raskind + * + * Copyright (c) 2015 HockeyApp, Bit Stadium GmbH. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#import "BITCrashCXXExceptionHandler.h" +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import + +typedef std::vector BITCrashUncaughtCXXExceptionHandlerList; + +static bool _BITCrashIsOurTerminateHandlerInstalled = false; +static std::terminate_handler _BITCrashOriginalTerminateHandler = nullptr; +static BITCrashUncaughtCXXExceptionHandlerList _BITCrashUncaughtExceptionHandlerList; +static OSSpinLock _BITCrashCXXExceptionHandlingLock = OS_SPINLOCK_INIT; + +@implementation BITCrashUncaughtCXXExceptionHandlerManager + +__attribute__((always_inline)) +static inline void BITCrashIterateExceptionHandlers_unlocked(const BITCrashUncaughtCXXExceptionInfo &info) +{ + for (const auto &handler : _BITCrashUncaughtExceptionHandlerList) { + handler(&info); + } +} + +static void BITCrashUncaughtCXXTerminateHandler(void) +{ + BITCrashUncaughtCXXExceptionInfo info = { + .exception = nullptr, + .exception_type_name = nullptr, + .exception_message = nullptr, + .exception_frames_count = 0, + .exception_frames = nullptr, + }; + auto p = std::current_exception(); + + OSSpinLockLock(&_BITCrashCXXExceptionHandlingLock); { + if (p) { // explicit operator bool + info.exception = reinterpret_cast(&p); + info.exception_type_name = __cxxabiv1::__cxa_current_exception_type()->name(); + + void *frames[128] = { nullptr }; + + info.exception_frames_count = backtrace(&frames[0], sizeof(frames) / sizeof(frames[0])) - 1; + info.exception_frames = reinterpret_cast(&frames[1]); + + try { + std::rethrow_exception(p); + } catch (const std::exception &e) { // C++ exception. + info.exception_message = e.what(); + BITCrashIterateExceptionHandlers_unlocked(info); + } catch (const std::exception *e) { // C++ exception by pointer. + info.exception_message = e->what(); + BITCrashIterateExceptionHandlers_unlocked(info); + } catch (const std::string &e) { // C++ string as exception. + info.exception_message = e.c_str(); + BITCrashIterateExceptionHandlers_unlocked(info); + } catch (const std::string *e) { // C++ string pointer as exception. + info.exception_message = e->c_str(); + BITCrashIterateExceptionHandlers_unlocked(info); + } catch (const char *e) { // Plain string as exception. + info.exception_message = e; + BITCrashIterateExceptionHandlers_unlocked(info); + } catch (id e) { // Objective-C exception. Pass it on to Foundation. + OSSpinLockUnlock(&_BITCrashCXXExceptionHandlingLock); + if (_BITCrashOriginalTerminateHandler != nullptr) { + _BITCrashOriginalTerminateHandler(); + } + return; + } catch (...) { // Any other kind of exception. No message. + BITCrashIterateExceptionHandlers_unlocked(info); + } + } + } OSSpinLockUnlock(&_BITCrashCXXExceptionHandlingLock); // In case terminate is called reentrantly by pasing it on + + if (_BITCrashOriginalTerminateHandler != nullptr) { + _BITCrashOriginalTerminateHandler(); + } else { + abort(); + } +} + ++ (void)addCXXExceptionHandler:(BITCrashUncaughtCXXExceptionHandler)handler +{ + OSSpinLockLock(&_BITCrashCXXExceptionHandlingLock); { + if (!_BITCrashIsOurTerminateHandlerInstalled) { + _BITCrashOriginalTerminateHandler = std::set_terminate(BITCrashUncaughtCXXTerminateHandler); + _BITCrashIsOurTerminateHandlerInstalled = true; + } + _BITCrashUncaughtExceptionHandlerList.push_back(handler); + } OSSpinLockUnlock(&_BITCrashCXXExceptionHandlingLock); +} + ++ (void)removeCXXExceptionHandler:(BITCrashUncaughtCXXExceptionHandler)handler +{ + OSSpinLockLock(&_BITCrashCXXExceptionHandlingLock); { + auto i = std::find(_BITCrashUncaughtExceptionHandlerList.begin(), _BITCrashUncaughtExceptionHandlerList.end(), handler); + + if (i != _BITCrashUncaughtExceptionHandlerList.end()) { + _BITCrashUncaughtExceptionHandlerList.erase(i); + } + + if (_BITCrashIsOurTerminateHandlerInstalled) { + if (_BITCrashUncaughtExceptionHandlerList.empty()) { + std::terminate_handler previous_handler = std::set_terminate(_BITCrashOriginalTerminateHandler); + + if (previous_handler != BITCrashUncaughtCXXTerminateHandler) { + std::set_terminate(previous_handler); + } else { + _BITCrashIsOurTerminateHandlerInstalled = false; + _BITCrashOriginalTerminateHandler = nullptr; + } + } + } + } OSSpinLockUnlock(&_BITCrashCXXExceptionHandlingLock); +} + +@end diff --git a/Classes/BITCrashManager.m b/Classes/BITCrashManager.m index fd637359a9..c445d59e31 100644 --- a/Classes/BITCrashManager.m +++ b/Classes/BITCrashManager.m @@ -44,6 +44,7 @@ #import "BITCrashManagerPrivate.h" #import "BITCrashReportTextFormatter.h" #import "BITCrashDetailsPrivate.h" +#import "BITCrashCXXExceptionHandler.h" #include @@ -97,6 +98,47 @@ static PLCrashReporterCallbacks plCrashCallbacks = { }; +// Temporary routine until PLCR catches up +// We trick PLCR with an Objective-C exception. It's ugly but it works. +@interface BITCrashCXXExceptionWrapperException : NSException +- (instancetype)initWithCXXExceptionInfo:(const BITCrashUncaughtCXXExceptionInfo *)info; +@end +@implementation BITCrashCXXExceptionWrapperException +{ + const BITCrashUncaughtCXXExceptionInfo *_info; +} +- (instancetype)initWithCXXExceptionInfo:(const BITCrashUncaughtCXXExceptionInfo *)info +{ + extern char* __cxa_demangle(const char* mangled_name, char* output_buffer, size_t* length, int* status); + char *demangled_name = __cxa_demangle ? __cxa_demangle(info->exception_type_name ?: "", NULL, NULL, NULL) : NULL; + + if ((self = [super + initWithName:[NSString stringWithUTF8String:demangled_name ?: info->exception_type_name ?: ""] + reason:[NSString stringWithUTF8String:info->exception_message ?: ""] + userInfo:nil])) { + _info = info; + } + return self; +} + +- (NSArray *)callStackReturnAddresses +{ + NSMutableArray *cxxFrames = [NSMutableArray arrayWithCapacity:_info->exception_frames_count]; + + for (uint32_t i = 0; i < _info->exception_frames_count; ++i) { + [cxxFrames addObject:[NSNumber numberWithUnsignedLongLong:_info->exception_frames[i]]]; + } + return cxxFrames; +} + +@end +static void uncaught_cxx_exception_handler(const BITCrashUncaughtCXXExceptionInfo *info) +{ + // This relies on a LOT of sneaky internal knowledge of how PLCR works and should not be considered a long-term solution. + NSGetUncaughtExceptionHandler()([[BITCrashCXXExceptionWrapperException alloc] initWithCXXExceptionInfo:info]); + abort(); +} + @implementation BITCrashManager { NSMutableDictionary *_approvedCrashReports; @@ -1091,6 +1133,9 @@ static PLCrashReporterCallbacks plCrashCallbacks = { // this should never happen, theoretically only if NSSetUncaugtExceptionHandler() has some internal issues NSLog(@"[HockeySDK] ERROR: Exception handler could not be set. Make sure there is no other exception handler set up!"); } + + // Add the C++ uncaught exception handler, which is currently not handled by PLCrashReporter internally + [BITCrashUncaughtCXXExceptionHandlerManager addCXXExceptionHandler:uncaught_cxx_exception_handler]; } _isSetup = YES; }); diff --git a/Classes/HockeySDK.h b/Classes/HockeySDK.h index 0d04c43832..52de84d72f 100644 --- a/Classes/HockeySDK.h +++ b/Classes/HockeySDK.h @@ -27,9 +27,6 @@ * OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef HockeySDK_h -#define HockeySDK_h - #import "HockeySDKFeatureConfig.h" #import "BITHockeyManager.h" @@ -208,5 +205,3 @@ typedef NS_ENUM(NSInteger, BITHockeyErrorReason) { }; extern NSString *const __attribute__((unused)) kBITHockeyErrorDomain; - -#endif diff --git a/Support/HockeySDK.xcodeproj/project.pbxproj b/Support/HockeySDK.xcodeproj/project.pbxproj index 9cb5657ff5..f1bd2bc7b9 100644 --- a/Support/HockeySDK.xcodeproj/project.pbxproj +++ b/Support/HockeySDK.xcodeproj/project.pbxproj @@ -14,7 +14,7 @@ 1E4F61ED1621ADE70033EFC5 /* Build universal embedded framework */, ); dependencies = ( - 1E754E431621F6290070AB92 /* PBXTargetDependency */, + 846A906B1B20D4BB0076BB80 /* PBXTargetDependency */, ); name = "HockeySDK Distribution"; productName = "HockeySDK Framework"; @@ -272,6 +272,10 @@ 1EF95CA7162CB037000AE3AD /* BITFeedbackActivity.m in Sources */ = {isa = PBXBuildFile; fileRef = 1EF95CA5162CB036000AE3AD /* BITFeedbackActivity.m */; }; 1EF95CAA162CB314000AE3AD /* BITFeedbackComposeViewControllerDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 1EF95CA9162CB313000AE3AD /* BITFeedbackComposeViewControllerDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; }; 1EFF03E517F2485500A5F13C /* BITCrashManagerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 1EFF03E417F2485500A5F13C /* BITCrashManagerTests.m */; }; + 846A901F1B20B0EB0076BB80 /* BITCrashCXXExceptionHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 846A901D1B20B0EB0076BB80 /* BITCrashCXXExceptionHandler.h */; }; + 846A90201B20B0EB0076BB80 /* BITCrashCXXExceptionHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 846A901D1B20B0EB0076BB80 /* BITCrashCXXExceptionHandler.h */; }; + 846A90211B20B0EB0076BB80 /* BITCrashCXXExceptionHandler.mm in Sources */ = {isa = PBXBuildFile; fileRef = 846A901E1B20B0EB0076BB80 /* BITCrashCXXExceptionHandler.mm */; }; + 846A90221B20B0EB0076BB80 /* BITCrashCXXExceptionHandler.mm in Sources */ = {isa = PBXBuildFile; fileRef = 846A901E1B20B0EB0076BB80 /* BITCrashCXXExceptionHandler.mm */; }; 973EC8B418BCA7BC00DBFFBB /* BITImageAnnotationViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 97F0FA0018AE375E00EF50AA /* BITImageAnnotationViewController.m */; }; 973EC8B718BCA8A200DBFFBB /* BITRectangleImageAnnotation.h in Headers */ = {isa = PBXBuildFile; fileRef = 973EC8B518BCA8A200DBFFBB /* BITRectangleImageAnnotation.h */; }; 973EC8B818BCA8A200DBFFBB /* BITRectangleImageAnnotation.m in Sources */ = {isa = PBXBuildFile; fileRef = 973EC8B618BCA8A200DBFFBB /* BITRectangleImageAnnotation.m */; }; @@ -323,13 +327,6 @@ remoteGlobalIDString = 1E59550915B6F45800A03429; remoteInfo = HockeySDKResources; }; - 1E754E421621F6290070AB92 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = E4005611148D79B500EB22B9 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 1E8E66AD15BC3D7700632A2E; - remoteInfo = "HockeySDK Documentation"; - }; 1EA116FE16F4D302001C015C /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = E4005611148D79B500EB22B9 /* Project object */; @@ -358,6 +355,13 @@ remoteGlobalIDString = 1E59550915B6F45800A03429; remoteInfo = HockeySDKResources; }; + 846A906A1B20D4BB0076BB80 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = E4005611148D79B500EB22B9 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 1E8E66AD15BC3D7700632A2E; + remoteInfo = "HockeySDK Documentation"; + }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ @@ -500,6 +504,8 @@ 1EF95CA9162CB313000AE3AD /* BITFeedbackComposeViewControllerDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BITFeedbackComposeViewControllerDelegate.h; sourceTree = ""; }; 1EFF03D717F20F8300A5F13C /* BITCrashManagerPrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BITCrashManagerPrivate.h; sourceTree = ""; }; 1EFF03E417F2485500A5F13C /* BITCrashManagerTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BITCrashManagerTests.m; sourceTree = ""; }; + 846A901D1B20B0EB0076BB80 /* BITCrashCXXExceptionHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BITCrashCXXExceptionHandler.h; sourceTree = ""; }; + 846A901E1B20B0EB0076BB80 /* BITCrashCXXExceptionHandler.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = BITCrashCXXExceptionHandler.mm; sourceTree = ""; }; 973EC8B518BCA8A200DBFFBB /* BITRectangleImageAnnotation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BITRectangleImageAnnotation.h; sourceTree = ""; }; 973EC8B618BCA8A200DBFFBB /* BITRectangleImageAnnotation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BITRectangleImageAnnotation.m; sourceTree = ""; }; 973EC8B918BDE29800DBFFBB /* BITArrowImageAnnotation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BITArrowImageAnnotation.h; sourceTree = ""; }; @@ -790,6 +796,8 @@ 1ED570C618BF878C00AB3350 /* BITCrashAttachment.m */, 1E754E5A1621FBB70070AB92 /* BITCrashReportTextFormatter.h */, 1E754E5B1621FBB70070AB92 /* BITCrashReportTextFormatter.m */, + 846A901D1B20B0EB0076BB80 /* BITCrashCXXExceptionHandler.h */, + 846A901E1B20B0EB0076BB80 /* BITCrashCXXExceptionHandler.mm */, ); name = CrashReports; sourceTree = ""; @@ -1011,6 +1019,7 @@ 1E90FD7318EDB86400CF0417 /* BITCrashDetails.h in Headers */, 1E49A4731612226D00463151 /* BITUpdateManager.h in Headers */, 1E49A4791612226D00463151 /* BITUpdateManagerDelegate.h in Headers */, + 846A901F1B20B0EB0076BB80 /* BITCrashCXXExceptionHandler.h in Headers */, 1E49A44E1612223B00463151 /* BITFeedbackManager.h in Headers */, E405266217A2AD300096359C /* BITFeedbackManagerDelegate.h in Headers */, 973EC8BF18BE2B5B00DBFFBB /* BITBlurImageAnnotation.h in Headers */, @@ -1069,6 +1078,7 @@ 1EB617991B0A31650035A986 /* BITFeedbackComposeViewController.h in Headers */, 1EB617651B0A30B30035A986 /* BITKeychainUtils.h in Headers */, 1EB617821B0A31310035A986 /* BITImageAnnotation.h in Headers */, + 846A90201B20B0EB0076BB80 /* BITCrashCXXExceptionHandler.h in Headers */, 1EB617961B0A31550035A986 /* BITArrowImageAnnotation.h in Headers */, 1EB617801B0A31260035A986 /* BITCrashReportTextFormatter.h in Headers */, 1EB6179C1B0A31730035A986 /* BITFeedbackListViewCell.h in Headers */, @@ -1431,6 +1441,7 @@ 1E754E5D1621FBB70070AB92 /* BITCrashManager.m in Sources */, 1E754E611621FBB70070AB92 /* BITCrashReportTextFormatter.m in Sources */, 1EF95CA7162CB037000AE3AD /* BITFeedbackActivity.m in Sources */, + 846A90211B20B0EB0076BB80 /* BITCrashCXXExceptionHandler.mm in Sources */, 1EACC97C162F041E007578C5 /* BITAttributedLabel.m in Sources */, 973EC8BC18BDE29800DBFFBB /* BITArrowImageAnnotation.m in Sources */, 973EC8B418BCA7BC00DBFFBB /* BITImageAnnotationViewController.m in Sources */, @@ -1499,6 +1510,7 @@ 1EB617831B0A31350035A986 /* BITImageAnnotation.m in Sources */, 1EB617681B0A30BD0035A986 /* BITAttributedLabel.m in Sources */, 1EB617621B0A30AA0035A986 /* BITHockeyBaseViewController.m in Sources */, + 846A90221B20B0EB0076BB80 /* BITCrashCXXExceptionHandler.mm in Sources */, 1EB6178A1B0A31510035A986 /* BITFeedbackComposeViewController.m in Sources */, 1EB617701B0A30D70035A986 /* BITHockeyAttachment.m in Sources */, 1EB617881B0A31510035A986 /* BITFeedbackMessage.m in Sources */, @@ -1531,11 +1543,6 @@ target = 1E59550915B6F45800A03429 /* HockeySDKResources */; targetProxy = 1E59557D15B6F97100A03429 /* PBXContainerItemProxy */; }; - 1E754E431621F6290070AB92 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 1E8E66AD15BC3D7700632A2E /* HockeySDK Documentation */; - targetProxy = 1E754E421621F6290070AB92 /* PBXContainerItemProxy */; - }; 1EA116FF16F4D302001C015C /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 1E5954CB15B6F24A00A03429 /* HockeySDK */; @@ -1556,6 +1563,11 @@ target = 1E59550915B6F45800A03429 /* HockeySDKResources */; targetProxy = 1EB618191B0A3C380035A986 /* PBXContainerItemProxy */; }; + 846A906B1B20D4BB0076BB80 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 1E8E66AD15BC3D7700632A2E /* HockeySDK Documentation */; + targetProxy = 846A906A1B20D4BB0076BB80 /* PBXContainerItemProxy */; + }; /* End PBXTargetDependency section */ /* Begin PBXVariantGroup section */ @@ -1608,6 +1620,8 @@ isa = XCBuildConfiguration; buildSettings = { "ARCHS[sdk=iphonesimulator*]" = "$(BIT_SIM_ARCHS)"; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; DSTROOT = /tmp/HockeySDK.dst; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -1625,6 +1639,8 @@ isa = XCBuildConfiguration; buildSettings = { "ARCHS[sdk=iphonesimulator*]" = "$(BIT_SIM_ARCHS)"; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; DSTROOT = /tmp/HockeySDK.dst; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -1781,6 +1797,8 @@ isa = XCBuildConfiguration; buildSettings = { "ARCHS[sdk=iphonesimulator*]" = "$(BIT_SIM_ARCHS)"; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; DSTROOT = /tmp/HockeySDK.dst; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -1900,6 +1918,8 @@ isa = XCBuildConfiguration; buildSettings = { "ARCHS[sdk=iphonesimulator*]" = "$(BIT_SIM_ARCHS)"; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; DSTROOT = /tmp/HockeySDK.dst; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", diff --git a/Support/module.modulemap b/Support/module.modulemap index 73fba6726e..0d9ba04aae 100644 --- a/Support/module.modulemap +++ b/Support/module.modulemap @@ -3,4 +3,6 @@ framework module HockeySDK { export * module * { export * } + + link "c++" } From 0bb78d7201df1c3673f6eb53d810d83b4b95890d Mon Sep 17 00:00:00 2001 From: Andreas Linde Date: Thu, 11 Jun 2015 17:09:29 +0200 Subject: [PATCH 2/8] Update documentation - Remove Advanced setup guide - Added `libc++` dependency - Updated modulemap files to automatically link all required libraries and frameworks - Updated setup doc to use module import style - Update CrashOnly build modulemap file - Code style fixes --- Classes/BITCrashManager.m | 22 +- HockeySDK.podspec | 1 + README.md | 1 - Support/HockeySDK.xcconfig | 2 +- Support/HockeySDK.xcodeproj/project.pbxproj | 2 +- Support/module.modulemap | 12 +- Support/module_crashonly.modulemap | 12 + ...de-Installation-Setup-Advanced-template.md | 209 ------------------ docs/Guide-Installation-Setup-template.md | 52 ++++- 9 files changed, 84 insertions(+), 229 deletions(-) create mode 100644 Support/module_crashonly.modulemap delete mode 100644 docs/Guide-Installation-Setup-Advanced-template.md diff --git a/Classes/BITCrashManager.m b/Classes/BITCrashManager.m index c445d59e31..4ab481f98d 100644 --- a/Classes/BITCrashManager.m +++ b/Classes/BITCrashManager.m @@ -98,17 +98,17 @@ static PLCrashReporterCallbacks plCrashCallbacks = { }; -// Temporary routine until PLCR catches up -// We trick PLCR with an Objective-C exception. It's ugly but it works. +// Temporary class until PLCR catches up +// We trick PLCR with an Objective-C exception. @interface BITCrashCXXExceptionWrapperException : NSException - (instancetype)initWithCXXExceptionInfo:(const BITCrashUncaughtCXXExceptionInfo *)info; @end -@implementation BITCrashCXXExceptionWrapperException -{ + +@implementation BITCrashCXXExceptionWrapperException { const BITCrashUncaughtCXXExceptionInfo *_info; } -- (instancetype)initWithCXXExceptionInfo:(const BITCrashUncaughtCXXExceptionInfo *)info -{ + +- (instancetype)initWithCXXExceptionInfo:(const BITCrashUncaughtCXXExceptionInfo *)info { extern char* __cxa_demangle(const char* mangled_name, char* output_buffer, size_t* length, int* status); char *demangled_name = __cxa_demangle ? __cxa_demangle(info->exception_type_name ?: "", NULL, NULL, NULL) : NULL; @@ -121,8 +121,7 @@ static PLCrashReporterCallbacks plCrashCallbacks = { return self; } -- (NSArray *)callStackReturnAddresses -{ +- (NSArray *)callStackReturnAddresses { NSMutableArray *cxxFrames = [NSMutableArray arrayWithCapacity:_info->exception_frames_count]; for (uint32_t i = 0; i < _info->exception_frames_count; ++i) { @@ -132,13 +131,16 @@ static PLCrashReporterCallbacks plCrashCallbacks = { } @end -static void uncaught_cxx_exception_handler(const BITCrashUncaughtCXXExceptionInfo *info) -{ + + +// C++ Exception Handler +static void uncaught_cxx_exception_handler(const BITCrashUncaughtCXXExceptionInfo *info) { // This relies on a LOT of sneaky internal knowledge of how PLCR works and should not be considered a long-term solution. NSGetUncaughtExceptionHandler()([[BITCrashCXXExceptionWrapperException alloc] initWithCXXExceptionInfo:info]); abort(); } + @implementation BITCrashManager { NSMutableDictionary *_approvedCrashReports; diff --git a/HockeySDK.podspec b/HockeySDK.podspec index 123627e72c..ef956e0f2f 100644 --- a/HockeySDK.podspec +++ b/HockeySDK.podspec @@ -23,6 +23,7 @@ Pod::Spec.new do |s| s.requires_arc = true s.frameworks = 'AssetsLibrary', 'CoreText', 'CoreGraphics', 'MobileCoreServices', 'QuartzCore', 'QuickLook', 'Security', 'SystemConfiguration', 'UIKit' + s.libraries = 'c++' s.ios.vendored_frameworks = 'Vendor/CrashReporter.framework' s.xcconfig = {'GCC_PREPROCESSOR_DEFINITIONS' => %{$(inherited) BITHOCKEY_VERSION="@\\"#{s.version}\\"" BITHOCKEY_C_VERSION="\\"#{s.version}\\"" BITHOCKEY_BUILD="@\\"38\\"" BITHOCKEY_C_BUILD="\\"38\\""} } s.resource_bundle = { 'HockeySDKResources' => ['Resources/*.png', 'Resources/*.lproj'] } diff --git a/README.md b/README.md index 537cc8cac3..3e7b797cb4 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,6 @@ The main SDK class is `BITHockeyManager`. It initializes all modules and provide ## Installation & Setup - [Installation & Setup](http://www.hockeyapp.net/help/sdk/ios/3.6.4/docs/docs/Guide-Installation-Setup.html) (Recommended) -- [Installation & Setup Advanced](http://www.hockeyapp.net/help/sdk/ios/3.6.4/docs/docs/Guide-Installation-Setup-Advanced.html) (Using Git submodule and Xcode sub-project) - [Identify and authenticate users of Ad-Hoc or Enterprise builds](http://www.hockeyapp.net/help/sdk/ios/3.6.4/docs/docs/HowTo-Authenticating-Users-on-iOS.html) - [Migration from previous SDK Versions](http://www.hockeyapp.net/help/sdk/ios/3.6.2/docs/docs/Guide-Migration-Kits.html) diff --git a/Support/HockeySDK.xcconfig b/Support/HockeySDK.xcconfig index b0b89b3da2..2b0a43933c 100644 --- a/Support/HockeySDK.xcconfig +++ b/Support/HockeySDK.xcconfig @@ -1,3 +1,3 @@ -OTHER_LDFLAGS=$(inherited) -framework CoreText -framework CoreGraphics -framework Foundation -framework QuartzCore -framework SystemConfiguration -framework UIKit -framework Security -framework AssetsLibrary -framework MobileCoreServices -framework QuickLook +OTHER_LDFLAGS=$(inherited) -framework CoreText -framework CoreGraphics -framework Foundation -framework QuartzCore -framework SystemConfiguration -framework UIKit -framework Security -framework AssetsLibrary -framework MobileCoreServices -framework QuickLook -lc++ HOCKEYSDK_DOCSET_NAME=HockeySDK-iOS GCC_PREPROCESSOR_DEFINITIONS=$(inherited) CONFIGURATION_$(CONFIGURATION) diff --git a/Support/HockeySDK.xcodeproj/project.pbxproj b/Support/HockeySDK.xcodeproj/project.pbxproj index f1bd2bc7b9..e14c771064 100644 --- a/Support/HockeySDK.xcodeproj/project.pbxproj +++ b/Support/HockeySDK.xcodeproj/project.pbxproj @@ -1373,7 +1373,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "# Sets the target folders and the final framework product.\nFMK_NAME=HockeySDK\nFMK_VERSION=A\nFMK_RESOURCE_BUNDLE=HockeySDKResources\nFMK_iOS8_NAME=\"HockeySDK Framework\"\n\n# Documentation\nHOCKEYSDK_DOCSET_VERSION_NAME=\"de.bitstadium.${HOCKEYSDK_DOCSET_NAME}-${VERSION_STRING}\"\n\n# Install dir will be the final output to the framework.\n# The following line create it in the root folder of the current project.\nPRODUCTS_DIR=${SRCROOT}/../Products\nZIP_FOLDER=HockeySDK-iOS\nTEMP_DIR=${PRODUCTS_DIR}/${ZIP_FOLDER}\nINSTALL_DIR=${TEMP_DIR}/${FMK_NAME}.framework\n\n# Working dir will be deleted after the framework creation.\nWRK_DIR=build\nDEVICE_DIR=${WRK_DIR}/Release-iphoneos\nSIMULATOR_DIR=${WRK_DIR}/Release-iphonesimulator\nDEVICE_CRASH_ONLY_DIR=${WRK_DIR}/ReleaseCrashOnly-iphoneos\nSIMULATOR_CRASH_ONLY_DIR=${WRK_DIR}/ReleaseCrashOnly-iphonesimulator\n\n# Building the full featured SDK\n\n# Building both architectures.\nxcodebuild -project \"HockeySDK.xcodeproj\" -configuration \"Release\" -target \"${FMK_NAME}\" -sdk iphoneos\nxcodebuild -project \"HockeySDK.xcodeproj\" -configuration \"Release\" -target \"${FMK_NAME}\" -sdk iphonesimulator\n\n# Cleaning the oldest.\nif [ -d \"${TEMP_DIR}\" ]\nthen\nrm -rf \"${TEMP_DIR}\"\nfi\n\n# Creates and renews the final product folder.\nmkdir -p \"${INSTALL_DIR}\"\nmkdir -p \"${INSTALL_DIR}/Modules\"\nmkdir -p \"${INSTALL_DIR}/Versions\"\nmkdir -p \"${INSTALL_DIR}/Versions/${FMK_VERSION}\"\nmkdir -p \"${INSTALL_DIR}/Versions/${FMK_VERSION}/Resources\"\nmkdir -p \"${INSTALL_DIR}/Versions/${FMK_VERSION}/Headers\"\n\n# Creates the internal links.\n# It MUST uses relative path, otherwise will not work when the folder is copied/moved.\nln -s \"${FMK_VERSION}\" \"${INSTALL_DIR}/Versions/Current\"\nln -s \"Versions/Current/Headers\" \"${INSTALL_DIR}/Headers\"\nln -s \"Versions/Current/Resources\" \"${INSTALL_DIR}/Resources\"\nln -s \"Versions/Current/${FMK_NAME}\" \"${INSTALL_DIR}/${FMK_NAME}\"\n\n# Copy the swift import file\ncp -f \"${SRCROOT}/module.modulemap\" \"${INSTALL_DIR}/Modules/\"\n\n# Copies the headers and resources files to the final product folder.\ncp -R \"${SRCROOT}/build/Release-iphoneos/include/HockeySDK/\" \"${INSTALL_DIR}/Versions/${FMK_VERSION}/Headers/\"\ncp -R \"${DEVICE_DIR}/${FMK_RESOURCE_BUNDLE}.bundle\" \"${INSTALL_DIR}/Versions/${FMK_VERSION}/Resources/\"\ncp -f \"${SRCROOT}/${FMK_NAME}.xcconfig\" \"${INSTALL_DIR}/Versions/${FMK_VERSION}/Resources/\"\n\n# Uses the Lipo Tool to merge both binary files (i386 + armv6/armv7) into one Universal final product.\nlipo -create \"${DEVICE_DIR}/lib${FMK_NAME}.a\" \"${SIMULATOR_DIR}/lib${FMK_NAME}.a\" -output \"${INSTALL_DIR}/Versions/${FMK_VERSION}/${FMK_NAME}\"\n\n# Combine the CrashReporter static library into a new Hockey static library file if they are not already present and copy the public headers too\nif [ -z $(otool -L \"${INSTALL_DIR}/Versions/${FMK_VERSION}/${FMK_NAME}\" | grep 'libCrashReporter') ]\nthen\nlibtool -static -o \"${INSTALL_DIR}/Versions/${FMK_VERSION}/${FMK_NAME}\" \"${INSTALL_DIR}/Versions/${FMK_VERSION}/${FMK_NAME}\" \"${SRCROOT}/../Vendor/CrashReporter.framework/Versions/A/CrashReporter\"\nfi\n\nrm -r \"${WRK_DIR}\"\n\n# build embeddedframework folder and move framework into it\nmkdir \"${INSTALL_DIR}/../${FMK_NAME}.embeddedframework\"\nmv \"${INSTALL_DIR}\" \"${INSTALL_DIR}/../${FMK_NAME}.embeddedframework/${FMK_NAME}.framework\"\n\n# link Resources\nNEW_INSTALL_DIR=${TEMP_DIR}/${FMK_NAME}.embeddedframework\nmkdir \"${NEW_INSTALL_DIR}/Resources\"\nln -s \"../${FMK_NAME}.framework/Resources/${FMK_RESOURCE_BUNDLE}.bundle\" \"${NEW_INSTALL_DIR}/Resources/${FMK_RESOURCE_BUNDLE}.bundle\"\nln -s \"../${FMK_NAME}.framework/Resources/${FMK_NAME}.xcconfig\" \"${NEW_INSTALL_DIR}/Resources/${FMK_NAME}.xcconfig\"\n\n\n# Building the crash only SDK without resources\n\n# Building both architectures.\nxcodebuild -project \"HockeySDK.xcodeproj\" -configuration \"ReleaseCrashOnly\" -target \"${FMK_NAME}\" -sdk iphoneos\nxcodebuild -project \"HockeySDK.xcodeproj\" -configuration \"ReleaseCrashOnly\" -target \"${FMK_NAME}\" -sdk iphonesimulator\n\n# Creates and renews the final product folder.\nmkdir -p \"${INSTALL_DIR}\"\nmkdir -p \"${INSTALL_DIR}/Modules\"\nmkdir -p \"${INSTALL_DIR}/Versions\"\nmkdir -p \"${INSTALL_DIR}/Versions/${FMK_VERSION}\"\nmkdir -p \"${INSTALL_DIR}/Versions/${FMK_VERSION}/Resources\"\nmkdir -p \"${INSTALL_DIR}/Versions/${FMK_VERSION}/Headers\"\n\n# Creates the internal links.\n# It MUST uses relative path, otherwise will not work when the folder is copied/moved.\nln -s \"${FMK_VERSION}\" \"${INSTALL_DIR}/Versions/Current\"\nln -s \"Versions/Current/Headers\" \"${INSTALL_DIR}/Headers\"\nln -s \"Versions/Current/Resources\" \"${INSTALL_DIR}/Resources\"\nln -s \"Versions/Current/${FMK_NAME}\" \"${INSTALL_DIR}/${FMK_NAME}\"\n\n# Copy the swift import file\ncp -f \"${SRCROOT}/module.modulemap\" \"${INSTALL_DIR}/Modules/\"\n\n# Copies the headers and resources files to the final product folder.\ncp -R \"${SRCROOT}\"/build/ReleaseCrashOnly-iphoneos/include/HockeySDK/BITCrash*.h \"${INSTALL_DIR}/Versions/${FMK_VERSION}/Headers/\"\ncp -R \"${SRCROOT}/\"build/ReleaseCrashOnly-iphoneos/include/HockeySDK/BITHockeyAttachment.h \"${INSTALL_DIR}/Versions/${FMK_VERSION}/Headers/\"\ncp -R \"${SRCROOT}/\"build/ReleaseCrashOnly-iphoneos/include/HockeySDK/BITHockeyBaseManager.h \"${INSTALL_DIR}/Versions/${FMK_VERSION}/Headers/\"\ncp -R \"${SRCROOT}/\"build/ReleaseCrashOnly-iphoneos/include/HockeySDK/BITHockeyManager.h \"${INSTALL_DIR}/Versions/${FMK_VERSION}/Headers/\"\ncp -R \"${SRCROOT}/\"build/ReleaseCrashOnly-iphoneos/include/HockeySDK/BITHockeyManagerDelegate.h \"${INSTALL_DIR}/Versions/${FMK_VERSION}/Headers/\"\ncp -R \"${SRCROOT}/build/ReleaseCrashOnly-iphoneos/include/HockeySDK/HockeySDK.h\" \"${INSTALL_DIR}/Versions/${FMK_VERSION}/Headers/\"\ncp -f \"${SRCROOT}/${FMK_NAME}.xcconfig\" \"${INSTALL_DIR}/Versions/${FMK_VERSION}/Resources/\"\n\n# Copy the patched feature header\ncp -f \"${SRCROOT}/HockeySDKCrashOnlyConfig.h\" \"${INSTALL_DIR}/Versions/${FMK_VERSION}/Headers/HockeySDKFeatureConfig.h\"\n\n# Uses the Lipo Tool to merge both binary files (i386/x86_64 + armv7/armv7s/arm64) into one Universal final product.\nlipo -create \"${DEVICE_CRASH_ONLY_DIR}/lib${FMK_NAME}.a\" \"${SIMULATOR_CRASH_ONLY_DIR}/lib${FMK_NAME}.a\" -output \"${INSTALL_DIR}/Versions/${FMK_VERSION}/${FMK_NAME}\"\n\n# Combine the CrashReporter static library into a new Hockey static library file if they are not already present and copy the public headers too\nif [ -z $(otool -L \"${INSTALL_DIR}/Versions/${FMK_VERSION}/${FMK_NAME}\" | grep 'libCrashReporter') ]\nthen\nlibtool -static -o \"${INSTALL_DIR}/Versions/${FMK_VERSION}/${FMK_NAME}\" \"${INSTALL_DIR}/Versions/${FMK_VERSION}/${FMK_NAME}\" \"${SRCROOT}/../Vendor/CrashReporter.framework/Versions/A/CrashReporter\"\nfi\n\n# Move the crash reporting only framework into a new folder\nmkdir \"${INSTALL_DIR}/../${FMK_NAME}CrashOnly\"\nmv \"${INSTALL_DIR}\" \"${INSTALL_DIR}/../${FMK_NAME}CrashOnly/${FMK_NAME}.framework\"\n\nrm -r \"${WRK_DIR}\"\n\n\n# Building the iOS 8 and later compatible dynamic framework\n\n# Using the iOS 8 framework binary distribution is not yet recommended, as it contains all architectures (i386, x86_64, armv7, armv7s, arm64)\n# and would be part of the app as is, which currently is about 5.2 MB in size. A proper usage would require the binary to be stripped from non-needed architectures at app build time before\n# This is why the following section is currently commented and not included in any release build\n\n## Building both architectures.\n#xcodebuild -project \"HockeySDK.xcodeproj\" -configuration \"Release\" -target \"${FMK_iOS8_NAME}\" -sdk iphonesimulator clean build\n#xcodebuild -project \"HockeySDK.xcodeproj\" -configuration \"Release\" -target \"${FMK_iOS8_NAME}\" -sdk iphoneos clean build\n#\n## Copy the framework structure to the destination folder\n#cp -R \"${DEVICE_DIR}/${FMK_NAME}.framework\" \"${TEMP_DIR}/\"\n#\n## Use the Lipo Tool to merge both binary files (i386/x86_64 + armv7/armv7s/arm64) into one Universal final product.\n#lipo -create \"${DEVICE_DIR}/${FMK_NAME}.framework/${FMK_NAME}\" \"${SIMULATOR_DIR}/${FMK_NAME}.framework/${FMK_NAME}\" -output \"${TEMP_DIR}/${FMK_NAME}.framework/${FMK_NAME}\"\n#\n## Move the crash reporting only framework into a new folder\n#mkdir \"${INSTALL_DIR}/../${FMK_NAME}-iOS8\"\n#mv \"${INSTALL_DIR}\" \"${INSTALL_DIR}/../${FMK_NAME}-iOS8/${FMK_NAME}.framework\"\n#\n#rm -r \"${WRK_DIR}\"\n\n\n# copy license, changelog, documentation, integration json\ncp -f \"${SRCROOT}/../Docs/Changelog-template.md\" \"${TEMP_DIR}/CHANGELOG\"\ncp -f \"${SRCROOT}/../Docs/Guide-Installation-Setup-template.md\" \"${TEMP_DIR}/README.md\"\ncp -f \"${SRCROOT}/../LICENSE\" \"${TEMP_DIR}\"\nmkdir \"${TEMP_DIR}/${HOCKEYSDK_DOCSET_VERSION_NAME}.docset\"\ncp -R \"${SRCROOT}/../documentation/docset/Contents\" \"${TEMP_DIR}/${HOCKEYSDK_DOCSET_VERSION_NAME}.docset\"\n\n# build zip\ncd \"${PRODUCTS_DIR}\"\nrm -f \"${FMK_NAME}-iOS-${VERSION_STRING}.zip\"\nzip -yr \"${FMK_NAME}-iOS-${VERSION_STRING}.zip\" \"${ZIP_FOLDER}\" -x \\*/.*\n"; + shellScript = "# Sets the target folders and the final framework product.\nFMK_NAME=HockeySDK\nFMK_VERSION=A\nFMK_RESOURCE_BUNDLE=HockeySDKResources\nFMK_iOS8_NAME=\"HockeySDK Framework\"\n\n# Documentation\nHOCKEYSDK_DOCSET_VERSION_NAME=\"de.bitstadium.${HOCKEYSDK_DOCSET_NAME}-${VERSION_STRING}\"\n\n# Install dir will be the final output to the framework.\n# The following line create it in the root folder of the current project.\nPRODUCTS_DIR=${SRCROOT}/../Products\nZIP_FOLDER=HockeySDK-iOS\nTEMP_DIR=${PRODUCTS_DIR}/${ZIP_FOLDER}\nINSTALL_DIR=${TEMP_DIR}/${FMK_NAME}.framework\n\n# Working dir will be deleted after the framework creation.\nWRK_DIR=build\nDEVICE_DIR=${WRK_DIR}/Release-iphoneos\nSIMULATOR_DIR=${WRK_DIR}/Release-iphonesimulator\nDEVICE_CRASH_ONLY_DIR=${WRK_DIR}/ReleaseCrashOnly-iphoneos\nSIMULATOR_CRASH_ONLY_DIR=${WRK_DIR}/ReleaseCrashOnly-iphonesimulator\n\n# Building the full featured SDK\n\n# Building both architectures.\nxcodebuild -project \"HockeySDK.xcodeproj\" -configuration \"Release\" -target \"${FMK_NAME}\" -sdk iphoneos\nxcodebuild -project \"HockeySDK.xcodeproj\" -configuration \"Release\" -target \"${FMK_NAME}\" -sdk iphonesimulator\n\n# Cleaning the oldest.\nif [ -d \"${TEMP_DIR}\" ]\nthen\nrm -rf \"${TEMP_DIR}\"\nfi\n\n# Creates and renews the final product folder.\nmkdir -p \"${INSTALL_DIR}\"\nmkdir -p \"${INSTALL_DIR}/Modules\"\nmkdir -p \"${INSTALL_DIR}/Versions\"\nmkdir -p \"${INSTALL_DIR}/Versions/${FMK_VERSION}\"\nmkdir -p \"${INSTALL_DIR}/Versions/${FMK_VERSION}/Resources\"\nmkdir -p \"${INSTALL_DIR}/Versions/${FMK_VERSION}/Headers\"\n\n# Creates the internal links.\n# It MUST uses relative path, otherwise will not work when the folder is copied/moved.\nln -s \"${FMK_VERSION}\" \"${INSTALL_DIR}/Versions/Current\"\nln -s \"Versions/Current/Headers\" \"${INSTALL_DIR}/Headers\"\nln -s \"Versions/Current/Resources\" \"${INSTALL_DIR}/Resources\"\nln -s \"Versions/Current/${FMK_NAME}\" \"${INSTALL_DIR}/${FMK_NAME}\"\n\n# Copy the swift import file\ncp -f \"${SRCROOT}/module.modulemap\" \"${INSTALL_DIR}/Modules/\"\n\n# Copies the headers and resources files to the final product folder.\ncp -R \"${SRCROOT}/build/Release-iphoneos/include/HockeySDK/\" \"${INSTALL_DIR}/Versions/${FMK_VERSION}/Headers/\"\ncp -R \"${DEVICE_DIR}/${FMK_RESOURCE_BUNDLE}.bundle\" \"${INSTALL_DIR}/Versions/${FMK_VERSION}/Resources/\"\ncp -f \"${SRCROOT}/${FMK_NAME}.xcconfig\" \"${INSTALL_DIR}/Versions/${FMK_VERSION}/Resources/\"\n\n# Uses the Lipo Tool to merge both binary files (i386 + armv6/armv7) into one Universal final product.\nlipo -create \"${DEVICE_DIR}/lib${FMK_NAME}.a\" \"${SIMULATOR_DIR}/lib${FMK_NAME}.a\" -output \"${INSTALL_DIR}/Versions/${FMK_VERSION}/${FMK_NAME}\"\n\n# Combine the CrashReporter static library into a new Hockey static library file if they are not already present and copy the public headers too\nif [ -z $(otool -L \"${INSTALL_DIR}/Versions/${FMK_VERSION}/${FMK_NAME}\" | grep 'libCrashReporter') ]\nthen\nlibtool -static -o \"${INSTALL_DIR}/Versions/${FMK_VERSION}/${FMK_NAME}\" \"${INSTALL_DIR}/Versions/${FMK_VERSION}/${FMK_NAME}\" \"${SRCROOT}/../Vendor/CrashReporter.framework/Versions/A/CrashReporter\"\nfi\n\nrm -r \"${WRK_DIR}\"\n\n# build embeddedframework folder and move framework into it\nmkdir \"${INSTALL_DIR}/../${FMK_NAME}.embeddedframework\"\nmv \"${INSTALL_DIR}\" \"${INSTALL_DIR}/../${FMK_NAME}.embeddedframework/${FMK_NAME}.framework\"\n\n# link Resources\nNEW_INSTALL_DIR=${TEMP_DIR}/${FMK_NAME}.embeddedframework\nmkdir \"${NEW_INSTALL_DIR}/Resources\"\nln -s \"../${FMK_NAME}.framework/Resources/${FMK_RESOURCE_BUNDLE}.bundle\" \"${NEW_INSTALL_DIR}/Resources/${FMK_RESOURCE_BUNDLE}.bundle\"\nln -s \"../${FMK_NAME}.framework/Resources/${FMK_NAME}.xcconfig\" \"${NEW_INSTALL_DIR}/Resources/${FMK_NAME}.xcconfig\"\n\n\n# Building the crash only SDK without resources\n\n# Building both architectures.\nxcodebuild -project \"HockeySDK.xcodeproj\" -configuration \"ReleaseCrashOnly\" -target \"${FMK_NAME}\" -sdk iphoneos\nxcodebuild -project \"HockeySDK.xcodeproj\" -configuration \"ReleaseCrashOnly\" -target \"${FMK_NAME}\" -sdk iphonesimulator\n\n# Creates and renews the final product folder.\nmkdir -p \"${INSTALL_DIR}\"\nmkdir -p \"${INSTALL_DIR}/Modules\"\nmkdir -p \"${INSTALL_DIR}/Versions\"\nmkdir -p \"${INSTALL_DIR}/Versions/${FMK_VERSION}\"\nmkdir -p \"${INSTALL_DIR}/Versions/${FMK_VERSION}/Resources\"\nmkdir -p \"${INSTALL_DIR}/Versions/${FMK_VERSION}/Headers\"\n\n# Creates the internal links.\n# It MUST uses relative path, otherwise will not work when the folder is copied/moved.\nln -s \"${FMK_VERSION}\" \"${INSTALL_DIR}/Versions/Current\"\nln -s \"Versions/Current/Headers\" \"${INSTALL_DIR}/Headers\"\nln -s \"Versions/Current/Resources\" \"${INSTALL_DIR}/Resources\"\nln -s \"Versions/Current/${FMK_NAME}\" \"${INSTALL_DIR}/${FMK_NAME}\"\n\n# Copy the swift import file\ncp -f \"${SRCROOT}/module_crashonly.modulemap\" \"${INSTALL_DIR}/Modules/module.modulemap\"\n\n# Copies the headers and resources files to the final product folder.\ncp -R \"${SRCROOT}\"/build/ReleaseCrashOnly-iphoneos/include/HockeySDK/BITCrash*.h \"${INSTALL_DIR}/Versions/${FMK_VERSION}/Headers/\"\ncp -R \"${SRCROOT}/\"build/ReleaseCrashOnly-iphoneos/include/HockeySDK/BITHockeyAttachment.h \"${INSTALL_DIR}/Versions/${FMK_VERSION}/Headers/\"\ncp -R \"${SRCROOT}/\"build/ReleaseCrashOnly-iphoneos/include/HockeySDK/BITHockeyBaseManager.h \"${INSTALL_DIR}/Versions/${FMK_VERSION}/Headers/\"\ncp -R \"${SRCROOT}/\"build/ReleaseCrashOnly-iphoneos/include/HockeySDK/BITHockeyManager.h \"${INSTALL_DIR}/Versions/${FMK_VERSION}/Headers/\"\ncp -R \"${SRCROOT}/\"build/ReleaseCrashOnly-iphoneos/include/HockeySDK/BITHockeyManagerDelegate.h \"${INSTALL_DIR}/Versions/${FMK_VERSION}/Headers/\"\ncp -R \"${SRCROOT}/build/ReleaseCrashOnly-iphoneos/include/HockeySDK/HockeySDK.h\" \"${INSTALL_DIR}/Versions/${FMK_VERSION}/Headers/\"\ncp -f \"${SRCROOT}/${FMK_NAME}.xcconfig\" \"${INSTALL_DIR}/Versions/${FMK_VERSION}/Resources/\"\n\n# Copy the patched feature header\ncp -f \"${SRCROOT}/HockeySDKCrashOnlyConfig.h\" \"${INSTALL_DIR}/Versions/${FMK_VERSION}/Headers/HockeySDKFeatureConfig.h\"\n\n# Uses the Lipo Tool to merge both binary files (i386/x86_64 + armv7/armv7s/arm64) into one Universal final product.\nlipo -create \"${DEVICE_CRASH_ONLY_DIR}/lib${FMK_NAME}.a\" \"${SIMULATOR_CRASH_ONLY_DIR}/lib${FMK_NAME}.a\" -output \"${INSTALL_DIR}/Versions/${FMK_VERSION}/${FMK_NAME}\"\n\n# Combine the CrashReporter static library into a new Hockey static library file if they are not already present and copy the public headers too\nif [ -z $(otool -L \"${INSTALL_DIR}/Versions/${FMK_VERSION}/${FMK_NAME}\" | grep 'libCrashReporter') ]\nthen\nlibtool -static -o \"${INSTALL_DIR}/Versions/${FMK_VERSION}/${FMK_NAME}\" \"${INSTALL_DIR}/Versions/${FMK_VERSION}/${FMK_NAME}\" \"${SRCROOT}/../Vendor/CrashReporter.framework/Versions/A/CrashReporter\"\nfi\n\n# Move the crash reporting only framework into a new folder\nmkdir \"${INSTALL_DIR}/../${FMK_NAME}CrashOnly\"\nmv \"${INSTALL_DIR}\" \"${INSTALL_DIR}/../${FMK_NAME}CrashOnly/${FMK_NAME}.framework\"\n\nrm -r \"${WRK_DIR}\"\n\n\n# Building the iOS 8 and later compatible dynamic framework\n\n# Using the iOS 8 framework binary distribution is not yet recommended, as it contains all architectures (i386, x86_64, armv7, armv7s, arm64)\n# and would be part of the app as is, which currently is about 5.2 MB in size. A proper usage would require the binary to be stripped from non-needed architectures at app build time before\n# This is why the following section is currently commented and not included in any release build\n\n## Building both architectures.\n#xcodebuild -project \"HockeySDK.xcodeproj\" -configuration \"Release\" -target \"${FMK_iOS8_NAME}\" -sdk iphonesimulator clean build\n#xcodebuild -project \"HockeySDK.xcodeproj\" -configuration \"Release\" -target \"${FMK_iOS8_NAME}\" -sdk iphoneos clean build\n#\n## Copy the framework structure to the destination folder\n#cp -R \"${DEVICE_DIR}/${FMK_NAME}.framework\" \"${TEMP_DIR}/\"\n#\n## Use the Lipo Tool to merge both binary files (i386/x86_64 + armv7/armv7s/arm64) into one Universal final product.\n#lipo -create \"${DEVICE_DIR}/${FMK_NAME}.framework/${FMK_NAME}\" \"${SIMULATOR_DIR}/${FMK_NAME}.framework/${FMK_NAME}\" -output \"${TEMP_DIR}/${FMK_NAME}.framework/${FMK_NAME}\"\n#\n## Move the crash reporting only framework into a new folder\n#mkdir \"${INSTALL_DIR}/../${FMK_NAME}-iOS8\"\n#mv \"${INSTALL_DIR}\" \"${INSTALL_DIR}/../${FMK_NAME}-iOS8/${FMK_NAME}.framework\"\n#\n#rm -r \"${WRK_DIR}\"\n\n\n# copy license, changelog, documentation, integration json\ncp -f \"${SRCROOT}/../Docs/Changelog-template.md\" \"${TEMP_DIR}/CHANGELOG\"\ncp -f \"${SRCROOT}/../Docs/Guide-Installation-Setup-template.md\" \"${TEMP_DIR}/README.md\"\ncp -f \"${SRCROOT}/../LICENSE\" \"${TEMP_DIR}\"\nmkdir \"${TEMP_DIR}/${HOCKEYSDK_DOCSET_VERSION_NAME}.docset\"\ncp -R \"${SRCROOT}/../documentation/docset/Contents\" \"${TEMP_DIR}/${HOCKEYSDK_DOCSET_VERSION_NAME}.docset\"\n\n# build zip\ncd \"${PRODUCTS_DIR}\"\nrm -f \"${FMK_NAME}-iOS-${VERSION_STRING}.zip\"\nzip -yr \"${FMK_NAME}-iOS-${VERSION_STRING}.zip\" \"${ZIP_FOLDER}\" -x \\*/.*\n"; }; 1E8E66B215BC3D8200632A2E /* ShellScript */ = { isa = PBXShellScriptBuildPhase; diff --git a/Support/module.modulemap b/Support/module.modulemap index 0d9ba04aae..5d2fcb61d2 100644 --- a/Support/module.modulemap +++ b/Support/module.modulemap @@ -3,6 +3,16 @@ framework module HockeySDK { export * module * { export * } - + + link framework "AssetsLibrary" + link framework "CoreText" + link framework "CoreGraphics" + link framework "Foundation" + link framework "MobileCoreServices" + link framework "QuartzCore" + link framework "QuickLook" + link framework "Security" + link framework "SystemConfiguration" + link framework "UIKit" link "c++" } diff --git a/Support/module_crashonly.modulemap b/Support/module_crashonly.modulemap new file mode 100644 index 0000000000..0c4bf94e0b --- /dev/null +++ b/Support/module_crashonly.modulemap @@ -0,0 +1,12 @@ +framework module HockeySDK { + umbrella header "HockeySDK.h" + + export * + module * { export * } + + link framework "Foundation" + link framework "Security" + link framework "SystemConfiguration" + link framework "UIKit" + link "c++" +} diff --git a/docs/Guide-Installation-Setup-Advanced-template.md b/docs/Guide-Installation-Setup-Advanced-template.md deleted file mode 100644 index d81c833f29..0000000000 --- a/docs/Guide-Installation-Setup-Advanced-template.md +++ /dev/null @@ -1,209 +0,0 @@ -## Version 3.6.4 - -- [Changelog](http://www.hockeyapp.net/help/sdk/ios/3.6.4/docs/docs/Changelog.html) - -## Introduction - -This article describes how to integrate HockeyApp into your iOS apps using a Git submodule and Xcode sub-projects. The SDK allows testers to update your app to another beta version right from within the application. It will notify the tester if a new update is available. The SDK also allows to send crash reports. If a crash has happened, it will ask the tester on the next start whether he wants to send information about the crash to the server. - -This document contains the following sections: - -- [Requirements](#requirements) -- [Set up Git submodule](#download) -- [Set up Xcode](#xcode) -- [Modify Code](#modify) -- [iOS 8 Extensions](#extension) -- [Additional Options](#options) - - -## Requirements - -The SDK runs on devices with iOS 6.0 or higher. - - -## Set up Git submodule - -1. Open a Terminal window - -2. Change to your projects directory `cd /path/to/MyProject' - -3. If this is a new project, initialize Git: `git init` - -4. Add the submodule: `git submodule add git://github.com/bitstadium/HockeySDK-iOS.git Vendor/HockeySDK`. This would add the submodule into the `Vendor/HockeySDK` subfolder. Change this to the folder you prefer. - -5. Releases are always in the `master` branch while the `develop` branch provides the latest in development source code (Using the git flow branching concept). We recommend using the `master` branch! - - -## Set up Xcode - -1. Find the `HockeySDK.xcodeproj` file inside of the cloned HockeySDK-iOS project directory. - -2. Drag & Drop it into the `Project Navigator` (⌘+1). - -3. Select your project in the `Project Navigator` (⌘+1). - -4. Select your app target. - -5. Select the tab `Build Phases`. - -6. Expand `Link Binary With Libraries`. - -7. Add `libHockeySDK.a` - - - -8. Select `Add Other...`. - -9. Select `CrashReporter.framework` from the `Vendor/HockeySDK/Vendor` folder - - - -10. Add the following system frameworks, if they are missing: - - `AssetsLibrary` - - `CoreText` - - `CoreGraphics` - - `Foundation` - - `MobileCoreServices` - - `QuartzCore` - - `QuickLook` - - `Security` - - `SystemConfiguration` - - `UIKit` - -11. Expand `Copy Bundle Resource`. - -12. Drag `HockeySDKResources.bundle` from the `HockeySDK` sub-projects `Products` folder and drop into the `Copy Bundle Resource` section - -13. Select `Build Settings` - -14. Add the following `Header Search Path` - - `$(SRCROOT)/Vendor/HockeySDK/Classes` - - -## Modify Code - -### Objective-C - -1. Open your `AppDelegate.m` file. - -2. Add the following line at the top of the file below your own #import statements: - - #import - -3. Search for the method `application:didFinishLaunchingWithOptions:` - -4. Add the following lines: - - [[BITHockeyManager sharedHockeyManager] configureWithIdentifier:@"APP_IDENTIFIER"]; - [[BITHockeyManager sharedHockeyManager] startManager]; - [[BITHockeyManager sharedHockeyManager].authenticator authenticateInstallation]; - -5. Continue with [General subsection](#generalcode) - -### Swift - -1. Add the following line to your [Objective-C bridging header](https://developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/MixandMatch.html) file: - - #import - -2. Open your `AppDelegate.swift` file. - -3. Search for the method `application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool` - -4. Add the following lines: - - BITHockeyManager.sharedHockeyManager().configureWithIdentifier("APP_IDENTIFIER"); - BITHockeyManager.sharedHockeyManager().startManager(); - BITHockeyManager.sharedHockeyManager().authenticator.authenticateInstallation(); - -5. Continue with [General subsection](#generalcode) - - -### General - -1. Replace `APP_IDENTIFIER` with the app identifier of your beta app. If you don't know what the app identifier is or how to find it, please read [this how-to](http://support.hockeyapp.net/kb/how-tos/how-to-find-the-app-identifier). - -2. If you want to see beta analytics, use the beta distribution feature with in-app updates, restrict versions to specific users, or want to know who is actually testing your app, you need to follow the instructions on our guide [Identify and authenticate users of Ad-Hoc or Enterprise builds](HowTo-Authenticating-Users-on-iOS) - -*Note:* The SDK is optimized to defer everything possible to a later time while making sure e.g. crashes on startup can also be caught and each module executes other code with a delay some seconds. This ensures that applicationDidFinishLaunching will process as fast as possible and the SDK will not block the startup sequence resulting in a possible kill by the watchdog process. - - -## iOS 8 Extensions - -The following points need to be considered to use HockeySDK with iOS 8 Extensions: - -1. Each extension is required to use the same values for version (`CFBundleShortVersionString`) and build number (`CFBundleVersion`) as the main app uses. (This is required only if you are using the same APP_IDENTIFIER for your app and extensions). -2. You need to make sure the SDK setup code is only invoked once. Since there is no `applicationDidFinishLaunching:` equivalent and `viewDidLoad` can run multiple times, you need to use a setup like the following example: - - @interface TodayViewController () - - @property (nonatomic, assign) BOOL didSetupHockeySDK; - - @end - - @implementation TodayViewController - - - (void)viewDidLoad { - [super viewDidLoad]; - if (!self.didSetupHockeySDK) { - [[BITHockeyManager sharedHockeyManager] configureWithIdentifier:@"APP_IDENTIFIER"]; - [[BITHockeyManager sharedHockeyManager] startManager]; - self.didSetupHockeySDK = YES; - } - } - - -## Additional Options - -### Xcode Documentation - -This documentation provides integrated help in Xcode for all public APIs and a set of additional tutorials and how-tos. - -1. Download the [HockeySDK-iOS documentation](http://hockeyapp.net/releases/). - -2. Unzip the file. A new folder `HockeySDK-iOS-documentation` is created. - -3. Copy the content into ~`/Library/Developer/Shared/Documentation/DocSets` - -The documentation is also available via the following URL: [http://hockeyapp.net/help/sdk/ios/3.6.4/](http://hockeyapp.net/help/sdk/ios/3.6.4/) - -### Set up with xcconfig - -Instead of manually adding the missing frameworks, you can also use our bundled xcconfig file. - -1. Create a new `Project.xcconfig` file, if you don't already have one (You can give it any name) - - **Note:** You can also add the required frameworks manually to your targets `Build Phases` an continue with step `4.` instead. - - a. Select your project in the `Project Navigator` (⌘+1). - - b. Select the tab `Info`. - - c. Expand `Configurations`. - - d. Select `Project.xcconfig` for all your configurations - - - -2. Open `Project.xcconfig` in the editor - -3. Add the following line: - - `#include "../Vendor/HockeySDK/Support/HockeySDK.xcconfig"` - - (Adjust the path depending where the `Project.xcconfig` file is located related to the Xcode project package) - - **Important note:** Check if you overwrite any of the build settings and add a missing `$(inherited)` entry on the projects build settings level, so the `HockeySDK.xcconfig` settings will be passed through successfully. - -4. If you are getting build warnings, then the `.xcconfig` setting wasn't included successfully or its settings in `Other Linker Flags` get ignored because `$(inherited)` is missing on project or target level. Either add `$(inherited)` or link the following frameworks manually in `Link Binary With Libraries` under `Build Phases`: - - `AssetsLibrary` - - `CoreText` - - `CoreGraphics` - - `Foundation` - - `MobileCoreServices` - - `QuartzCore` - - `QuickLook` - - `Security` - - `SystemConfiguration` - - `UIKit` diff --git a/docs/Guide-Installation-Setup-template.md b/docs/Guide-Installation-Setup-template.md index dc83562844..9817ef4ef8 100644 --- a/docs/Guide-Installation-Setup-template.md +++ b/docs/Guide-Installation-Setup-template.md @@ -32,6 +32,8 @@ The SDK runs on devices with iOS 6.0 or higher. ## Set up Xcode +### Full featured SDK + 1. Drag & drop `HockeySDK.embeddedframework` from your project directory to your Xcode project. 2. Similar to above, our projects have a group `Vendor`, so we drop it there. @@ -42,13 +44,15 @@ The SDK runs on devices with iOS 6.0 or higher. 4. Select your project in the `Project Navigator` (⌘+1). -5. Select your app target. +5. If your app target is enabled to use Modules (which is default since Xcode 5 for new projects), you can continue with the section "Modify Code", otherwise continue with step 6. -6. Select the tab `Build Phases`. +6. Select your app target. -7. Expand `Link Binary With Libraries`. +7. Select the tab `Build Phases`. -8. Add the following system frameworks, if they are missing: +8. Expand `Link Binary With Libraries`. + +9. Add the following system frameworks, if they are missing: - `AssetsLibrary` - `CoreText` - `CoreGraphics` @@ -59,6 +63,35 @@ The SDK runs on devices with iOS 6.0 or higher. - `Security` - `SystemConfiguration` - `UIKit` + - `libc++` + +### Crash reporting only SDK + +1. Drag & drop `HockeySDK.framework` from your project directory to your Xcode project. + +2. If you don't want to auto-send crash reports, also copy the following resource bundle from `HockeySDK.embeddedframework/HockeySDK.framework/Versions/A/Resources/HockeySDKResources.bundle` into the same folder and Drag & drop it into your Xcode project + +2. Similar to above, our projects have a group `Vendor`, so we drop it there. + +3. Select `Create groups for any added folders` and set the checkmark for your target. Then click `Finish`. + + + +4. Select your project in the `Project Navigator` (⌘+1). + +5. If your app target is enabled to use Modules (which is default since Xcode 5 for new projects), you can continue with the section "Modify Code", otherwise continue with step 6. + +6. Select your app target. + +7. Select the tab `Build Phases`. + +8. Expand `Link Binary With Libraries`. + +9. Add the following system frameworks, if they are missing (if you are using the full featured SDK): + - `Foundation` + - `Security` + - `SystemConfiguration` + - `UIKit` ## Modify Code @@ -69,6 +102,12 @@ The SDK runs on devices with iOS 6.0 or higher. 2. Add the following line at the top of the file below your own #import statements: + If your app target is enabled to use Modules (which is default since Xcode 5 for new projects) use: + + @import HockeySDK + + Otherwise use: + #import 3. Search for the method `application:didFinishLaunchingWithOptions:` @@ -77,7 +116,7 @@ The SDK runs on devices with iOS 6.0 or higher. [[BITHockeyManager sharedHockeyManager] configureWithIdentifier:@"APP_IDENTIFIER"]; [[BITHockeyManager sharedHockeyManager] startManager]; - [[BITHockeyManager sharedHockeyManager].authenticator authenticateInstallation]; + [[BITHockeyManager sharedHockeyManager].authenticator authenticateInstallation]; // This line is obsolete in the crash only build 5. Continue with [General subsection](#generalcode) @@ -95,7 +134,7 @@ The SDK runs on devices with iOS 6.0 or higher. BITHockeyManager.sharedHockeyManager().configureWithIdentifier("APP_IDENTIFIER"); BITHockeyManager.sharedHockeyManager().startManager(); - BITHockeyManager.sharedHockeyManager().authenticator.authenticateInstallation(); + BITHockeyManager.sharedHockeyManager().authenticator.authenticateInstallation(); // This line is obsolete in the crash only build 5. Continue with [General subsection](#generalcode) @@ -183,3 +222,4 @@ Instead of manually adding the missing frameworks, you can also use our bundled - `Security` - `SystemConfiguration` - `UIKit` + - `libc++` From fdb7057403a5680df9cd982a3e4bc047a4301066 Mon Sep 17 00:00:00 2001 From: Andreas Linde Date: Fri, 12 Jun 2015 14:56:09 +0200 Subject: [PATCH 3/8] Document C++ exception drawbacks --- Classes/BITCrashManager.m | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Classes/BITCrashManager.m b/Classes/BITCrashManager.m index 4ab481f98d..bae8973cbd 100644 --- a/Classes/BITCrashManager.m +++ b/Classes/BITCrashManager.m @@ -100,6 +100,20 @@ static PLCrashReporterCallbacks plCrashCallbacks = { // Temporary class until PLCR catches up // We trick PLCR with an Objective-C exception. +// +// This code provides us access to the C++ exception message, but we won't get a correct stack trace. +// The cause for this is that the iOS runtime catches every C++ exception internally and rethrows it. +// Since the exception object doesn't have the backtrace attached, we have no chance of accessing it. +// +// As a workaround we could hook into __cxx_throw and attaching the backtrace every time this is called. +// This has a few sides effects which is why we are not doing this right now: +// - CoreAdudio (and possibly other frameworks) use C++ exceptions heavily for control flow. +// Calling `backtrace()` is not cheap, so this could affect performance +// - It is not clear if such a hook is ABI compatible with all C++ runtimes +// - It is not clear if there could be any other side effects +// +// We'll evaluate this further to see if there is a safe solution. +// @interface BITCrashCXXExceptionWrapperException : NSException - (instancetype)initWithCXXExceptionInfo:(const BITCrashUncaughtCXXExceptionInfo *)info; @end From 9e1674f2232ea410771b088e195a0c751e7b80c9 Mon Sep 17 00:00:00 2001 From: Andreas Linde Date: Fri, 12 Jun 2015 15:02:17 +0200 Subject: [PATCH 4/8] Add support for __nullable on older Xcode versions --- Classes/HockeySDK.h | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/Classes/HockeySDK.h b/Classes/HockeySDK.h index 52de84d72f..c590817a5f 100644 --- a/Classes/HockeySDK.h +++ b/Classes/HockeySDK.h @@ -27,6 +27,28 @@ * OTHER DEALINGS IN THE SOFTWARE. */ +// Define nullability fallback for backwards compatibility +#if !__has_feature(nullability) +#define NS_ASSUME_NONNULL_BEGIN +#define NS_ASSUME_NONNULL_END +#define nullable +#define nonnull +#define null_unspecified +#define null_resettable +#define __nullable +#define __nonnull +#define __null_unspecified +#endif + +// Fallback for convenience syntax which might not be available in older SDKs +#ifndef NS_ASSUME_NONNULL_BEGIN +#define NS_ASSUME_NONNULL_BEGIN _Pragma("clang assume_nonnull begin") +#endif +#ifndef NS_ASSUME_NONNULL_END +#define NS_ASSUME_NONNULL_END _Pragma("clang assume_nonnull end") +#endif + + #import "HockeySDKFeatureConfig.h" #import "BITHockeyManager.h" From 747000e7e0a37264d63eee4c1346af0119078120 Mon Sep 17 00:00:00 2001 From: Andreas Linde Date: Fri, 12 Jun 2015 15:37:14 +0200 Subject: [PATCH 5/8] Add missing header include --- Classes/BITCrashCXXExceptionHandler.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Classes/BITCrashCXXExceptionHandler.h b/Classes/BITCrashCXXExceptionHandler.h index f73fe275b4..b9758f4396 100644 --- a/Classes/BITCrashCXXExceptionHandler.h +++ b/Classes/BITCrashCXXExceptionHandler.h @@ -27,6 +27,7 @@ */ #import +#import "HockeySDK.h" typedef struct { const void * __nullable exception; From 74c0a55f082bbcf8cbf5d3cde4359260f9509b67 Mon Sep 17 00:00:00 2001 From: Andreas Linde Date: Fri, 12 Jun 2015 16:18:16 +0200 Subject: [PATCH 6/8] Move nullability support into separate header --- Classes/BITCrashCXXExceptionHandler.h | 2 +- Classes/HockeyNullability.h | 33 +++++++++++++++++++++ Classes/HockeySDK.h | 21 ------------- Support/HockeySDK.xcodeproj/project.pbxproj | 2 ++ 4 files changed, 36 insertions(+), 22 deletions(-) create mode 100644 Classes/HockeyNullability.h diff --git a/Classes/BITCrashCXXExceptionHandler.h b/Classes/BITCrashCXXExceptionHandler.h index b9758f4396..937354695e 100644 --- a/Classes/BITCrashCXXExceptionHandler.h +++ b/Classes/BITCrashCXXExceptionHandler.h @@ -27,7 +27,7 @@ */ #import -#import "HockeySDK.h" +#import "HockeyNullability.h" typedef struct { const void * __nullable exception; diff --git a/Classes/HockeyNullability.h b/Classes/HockeyNullability.h new file mode 100644 index 0000000000..5a2be266d0 --- /dev/null +++ b/Classes/HockeyNullability.h @@ -0,0 +1,33 @@ +// +// HockeyNullability.h +// HockeySDK +// +// Created by Andreas Linde on 12/06/15. +// +// + +#ifndef HockeySDK_HockeyNullability_h +#define HockeySDK_HockeyNullability_h + +// Define nullability fallback for backwards compatibility +#if !__has_feature(nullability) +#define NS_ASSUME_NONNULL_BEGIN +#define NS_ASSUME_NONNULL_END +#define nullable +#define nonnull +#define null_unspecified +#define null_resettable +#define __nullable +#define __nonnull +#define __null_unspecified +#endif + +// Fallback for convenience syntax which might not be available in older SDKs +#ifndef NS_ASSUME_NONNULL_BEGIN +#define NS_ASSUME_NONNULL_BEGIN _Pragma("clang assume_nonnull begin") +#endif +#ifndef NS_ASSUME_NONNULL_END +#define NS_ASSUME_NONNULL_END _Pragma("clang assume_nonnull end") +#endif + +#endif diff --git a/Classes/HockeySDK.h b/Classes/HockeySDK.h index c590817a5f..6375b86078 100644 --- a/Classes/HockeySDK.h +++ b/Classes/HockeySDK.h @@ -27,27 +27,6 @@ * OTHER DEALINGS IN THE SOFTWARE. */ -// Define nullability fallback for backwards compatibility -#if !__has_feature(nullability) -#define NS_ASSUME_NONNULL_BEGIN -#define NS_ASSUME_NONNULL_END -#define nullable -#define nonnull -#define null_unspecified -#define null_resettable -#define __nullable -#define __nonnull -#define __null_unspecified -#endif - -// Fallback for convenience syntax which might not be available in older SDKs -#ifndef NS_ASSUME_NONNULL_BEGIN -#define NS_ASSUME_NONNULL_BEGIN _Pragma("clang assume_nonnull begin") -#endif -#ifndef NS_ASSUME_NONNULL_END -#define NS_ASSUME_NONNULL_END _Pragma("clang assume_nonnull end") -#endif - #import "HockeySDKFeatureConfig.h" diff --git a/Support/HockeySDK.xcodeproj/project.pbxproj b/Support/HockeySDK.xcodeproj/project.pbxproj index e14c771064..1953c904fb 100644 --- a/Support/HockeySDK.xcodeproj/project.pbxproj +++ b/Support/HockeySDK.xcodeproj/project.pbxproj @@ -378,6 +378,7 @@ 1E1127C316580C87007067A2 /* buttonRoundedRegularHighlighted@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "buttonRoundedRegularHighlighted@2x.png"; sourceTree = ""; }; 1E20A57F181E9D4600D5B770 /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/HockeySDK.strings; sourceTree = ""; }; 1E36D8B816667611000B134C /* hr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hr; path = hr.lproj/HockeySDK.strings; sourceTree = ""; }; + 1E3A260E1B2B207900D59683 /* HockeyNullability.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HockeyNullability.h; sourceTree = ""; }; 1E494AEA19491943001EFF74 /* AppIcon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = AppIcon.png; sourceTree = ""; }; 1E494AEB19491943001EFF74 /* AppIcon@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "AppIcon@2x.png"; sourceTree = ""; }; 1E49A42D1612223B00463151 /* BITFeedbackComposeViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BITFeedbackComposeViewController.h; sourceTree = ""; }; @@ -731,6 +732,7 @@ 1E49A4AC161222B900463151 /* BITWebTableViewCell.m */, 1EB92E711955C38C0093C8B6 /* BITHockeyAttachment.h */, 1EB92E721955C38C0093C8B6 /* BITHockeyAttachment.m */, + 1E3A260E1B2B207900D59683 /* HockeyNullability.h */, ); name = Helper; sourceTree = ""; From 43d83a0ae6abdfca7a3f63c40f6c6faa57d445d6 Mon Sep 17 00:00:00 2001 From: Andreas Linde Date: Fri, 12 Jun 2015 16:39:47 +0200 Subject: [PATCH 7/8] Make sure to test with clean build on travis --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 41e031fb73..d4d2ecae06 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,9 +5,9 @@ script: - set -o pipefail - cd Support - xcodebuild -project HockeySDK.xcodeproj -scheme "HockeySDK" -sdk iphonesimulator - -configuration Debug -destination "platform=iOS Simulator,name=iPhone 6" test | + -configuration Debug -destination "platform=iOS Simulator,name=iPhone 6" clean test | xcpretty -c - xcodebuild -project HockeySDK.xcodeproj -scheme "HockeySDK Framework" -sdk iphonesimulator - -configuration Debug -destination "platform=iOS Simulator,name=iPhone 6" test | + -configuration Debug -destination "platform=iOS Simulator,name=iPhone 6" clean test | xcpretty -c - cd .. From 74d31b1a654704c8a31204cb405fa5f0f86cdbac Mon Sep 17 00:00:00 2001 From: Andreas Linde Date: Fri, 12 Jun 2015 16:47:19 +0200 Subject: [PATCH 8/8] Fix failing tests on travis This is because of Xcodes stupid caching madness buginess crazyness. If we build &test the dynamic framework first and then the static lib target, everything works just fine. Thank you. --- .travis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index d4d2ecae06..105a3c2142 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,10 +4,10 @@ before_install: script: - set -o pipefail - cd Support -- xcodebuild -project HockeySDK.xcodeproj -scheme "HockeySDK" -sdk iphonesimulator - -configuration Debug -destination "platform=iOS Simulator,name=iPhone 6" clean test | - xcpretty -c - xcodebuild -project HockeySDK.xcodeproj -scheme "HockeySDK Framework" -sdk iphonesimulator -configuration Debug -destination "platform=iOS Simulator,name=iPhone 6" clean test | xcpretty -c +- xcodebuild -project HockeySDK.xcodeproj -scheme "HockeySDK" -sdk iphonesimulator + -configuration Debug -destination "platform=iOS Simulator,name=iPhone 6" clean test | + xcpretty -c - cd ..