KISS

Keep It Simple Stupid

GHUnitIOS with new Xcode and iOS SDK 6.0

| comments

After an update last week, I got Mac OS X 10.8.2, Xcode 4.5, and iOS SDK 6.0 on my working Mac. And the unit tests in my project stopped building…

Update on 2012-10-09: Turned out the latest version of the GTM library actually has fixes for iOS SDK 6.0, but the version of GHUnitIOS in CocoaPods at that moment (0.4.33) didn’t include them. So I had to update the spec for a newer version and it’s been merged into the main repository (https://github.com/CocoaPods/Specs/pull/561), so I only had to run pod update to fetch the updates. No more these issues!

I’d used CocoaPods to create a target, which added GHUnitIOS and OCMock libraries for testing. After the update, the target won’t compile for iPhone Simulator:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Compile GTMObjC2Runtime.m:

Direct access to objective-c's isa is deprecated in favor of object_setClass() and object_getClass()
No member named 'name' in 'struct objc_class'
No member named 'protocols' in 'struct objc_class'
Incomplete definition of type 'struct objc_protocol_list'
Incomplete definition of type 'struct objc_protocol_list'
Incomplete definition of type 'struct objc_protocol_list'
No member named 'super_class' in 'struct objc_class'
'class_nextMethodList' is unavailable
Incomplete definition of type 'struct objc_method_list'
Incomplete definition of type 'struct objc_method_list'
Incomplete definition of type 'struct objc_method_list'
Incomplete definition of type 'struct objc_method_list'
Incomplete definition of type 'struct objc_method_list'
Incomplete definition of type 'struct objc_method'
Incomplete definition of type 'struct objc_method'
Incomplete definition of type 'struct objc_method'
Incomplete definition of type 'struct objc_method'
Instance method '-descriptionForInstanceMethod:' not found (return type defaults to 'id')
Incompatible pointer types assigning to 'struct objc_method_description *' from 'id'
Instance method '-descriptionForClassMethod:' not found (return type defaults to 'id')
Incompatible pointer types assigning to 'struct objc_method_description *' from 'id'

The errors are not in the GHUnitIOS (version 0.4.33 here) itself, but in the GTM library:

GTMObjC2Runtime.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
#import "objc/Protocol.h"
#import <libkern/OSAtomic.h>

OBJC_EXPORT Class object_getClass(id obj);
OBJC_EXPORT const char *class_getName(Class cls);
OBJC_EXPORT BOOL class_conformsToProtocol(Class cls, Protocol *protocol);
OBJC_EXPORT Class class_getSuperclass(Class cls);
OBJC_EXPORT Method *class_copyMethodList(Class cls, unsigned int *outCount);
OBJC_EXPORT SEL method_getName(Method m);
OBJC_EXPORT void method_exchangeImplementations(Method m1, Method m2);
OBJC_EXPORT IMP method_getImplementation(Method method);
OBJC_EXPORT IMP method_setImplementation(Method method, IMP imp);

// …skipped…

#endif  // MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5

When you compile an iOS application for simulator, its architecture is i386, not an armv{6,7}. Apparently, that’s why the MAC_OS_X_VERSION_MIN_REQUIRED macro gets defined in the AvailabilityMacros.h file, which triggers the compiler to build the object_getClass(), class_getName(), etc. methods, even though they’re already defined in the objc/runtime.h file. So my solution is to wrap that piece of code in #if !GTM_IPHONE_SDK / #endif directives. Here’s my patch:

(0001-GTMObjC2Runtime.patch) download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
---
 Pods/GHUnitIOS/Libraries/GTM/Foundation/GTMObjC2Runtime.h  | 2 ++
 Pods/GHUnitIOS/Libraries/GTM/Foundation/GTMObjC2Runtime.m  | 3 ++-
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/Pods/GHUnitIOS/Libraries/GTM/Foundation/GTMObjC2Runtime.h b/Pods/GHUnitIOS/Libraries/GTM/Foundation/GTMObjC2Runtime.h
index 8d62abf..4705cac 100644
--- a/Pods/GHUnitIOS/Libraries/GTM/Foundation/GTMObjC2Runtime.h
+++ b/Pods/GHUnitIOS/Libraries/GTM/Foundation/GTMObjC2Runtime.h
@@ -47,6 +47,7 @@
 #import <objc/Object.h>
 #endif

+#if !GTM_IPHONE_SDK
 #if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
 #import "objc/Protocol.h"
 #import <libkern/OSAtomic.h>
@@ -103,3 +104,4 @@ GTM_INLINE BOOL objc_atomicCompareAndSwapInstanceVariableBarrier(id predicate,
 #endif

 #endif  // OBJC2_UNAVAILABLE
+#endif
diff --git a/Pods/GHUnitIOS/Libraries/GTM/Foundation/GTMObjC2Runtime.m b/Pods/GHUnitIOS/Libraries/GTM/Foundation/GTMObjC2Runtime.m
index 9835654..cc88c58 100644
--- a/Pods/GHUnitIOS/Libraries/GTM/Foundation/GTMObjC2Runtime.m
+++ b/Pods/GHUnitIOS/Libraries/GTM/Foundation/GTMObjC2Runtime.m
@@ -18,6 +18,7 @@

 #import "GTMObjC2Runtime.h"

+#if !GTM_IPHONE_SDK
 #if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
 #import <stdlib.h>
 #import <string.h>
@@ -152,5 +153,5 @@ struct objc_method_description protocol_getMethodDescription(Protocol *p,


 #endif
-
+#endif

-- 
1.7.12.1

Those errors disappeared after the fix, but a new one came during the app linking stage:

1
2
3
4
5
"_GHU_GTMStackTraceFromException", referenced from:
_GHUStackTraceFromException in libPods-test.a(GHTesting.o)
+[GHTesting descriptionForException:] in libPods-test.a(GHTesting.o)
Symbol(s) not found for architecture i386
Linker command failed with exit code 1 (use -v to see invocation)

It has to do with the same MAC_OS_X_VERSION_MIN_REQUIRED macro:

GTMStackTrace.m
1
2
3
4
5
6
7
#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5
// Returns a string containing a nicely formatted stack trace from the
// exception.  Only available on 10.5 or later, uses 
// -[NSException callStackReturnAddresses].
//
NSString *GHU_GTMStackTraceFromException(NSException *e);
#endif

This isn’t compiled into the Pods library for simulator. Here’s the second patch:

(0002-GTMStackTrace.patch) download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
---
 Pods/GHUnitIOS/Libraries/GTM/Foundation/GTMStackTrace.h | 2 +-
 Pods/GHUnitIOS/Libraries/GTM/Foundation/GTMStackTrace.m | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/Pods/GHUnitIOS/Libraries/GTM/Foundation/GTMStackTrace.h b/Pods/GHUnitIOS/Libraries/GTM/Foundation/GTMStackTrace.h
index dc0e489..a053b34 100644
--- a/Pods/GHUnitIOS/Libraries/GTM/Foundation/GTMStackTrace.h
+++ b/Pods/GHUnitIOS/Libraries/GTM/Foundation/GTMStackTrace.h
@@ -54,7 +54,7 @@ struct GHU_GTMAddressDescriptor {

 NSString *GHU_GTMStackTrace(void);

-#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5
+#if (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5) || GTM_IPHONE_SDK
 // Returns a string containing a nicely formatted stack trace from the
 // exception.  Only available on 10.5 or later, uses
 // -[NSException callStackReturnAddresses].
diff --git a/Pods/GHUnitIOS/Libraries/GTM/Foundation/GTMStackTrace.m b/Pods/GHUnitIOS/Libraries/GTM/Foundation/GTMStackTrace.m
index 7a32bdc..c86acb9 100644
--- a/Pods/GHUnitIOS/Libraries/GTM/Foundation/GTMStackTrace.m
+++ b/Pods/GHUnitIOS/Libraries/GTM/Foundation/GTMStackTrace.m
@@ -324,7 +324,7 @@ NSString *GHU_GTMStackTrace(void) {
   return result;
 }

-#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5
+#if (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5) || GTM_IPHONE_SDK

 NSString *GHU_GTMStackTraceFromException(NSException *e) {
   NSString *trace = @"";
-- 
1.7.12.1

Finally, the whole project gets built, linked, and run fine on the iOS Simulators and devices. Of course, it’s a hack to patch the library like this, but better than nothing until an official fix is made.

iOS

Don't hesitate to leave a comment below. NB! If you don't see a comment form under the post, it's most likely that an extension (such as Ghostery, NoScript, or AdBlock) of your browser blocks the scripts from disqus.com, and you can unblock that.

« jmp Log to UITextView on iOS »

Comments