Search code examples
objective-cxcodecompiler-flags

How to disable XCode compiler defines "-DXXX" in the Objective-C source code files


Tried #undef with NS_BLOCK_ASSERTIONS, but it looks like the Release default option from settings is welded brutally into the build process. The trick is to use only .m source code file directives (maybe pragmas) to disable it, because I'm in a situation where I have no control on XCode project settings and they are set as default for me in Release builds.

#undef NS_BLOCK_ASSERTIONS

#import <Foundation/Foundation.h>
#include <stdio.h>

@interface LoggingAssertionHandler : NSAssertionHandler
@end

@implementation LoggingAssertionHandler

- (void)handleFailureInMethod:(SEL)selector
                       object:(id)object
                         file:(NSString *)fileName
                   lineNumber:(NSInteger)line
                  description:(NSString *)format, ...
{
    NSString *failureMessageDescription = [NSString stringWithFormat:@"NSAssert Failure: Method %@ for object %@ in %@#%li. Reason: \"%@\"", NSStringFromSelector(selector), object, fileName, (long)line, format];
    printf("%s\n", [failureMessageDescription UTF8String]);
}

- (void)handleFailureInFunction:(NSString *)functionName
                           file:(NSString *)fileName
                     lineNumber:(NSInteger)line
                    description:(NSString *)format, ...
{
    NSString *failureMessageDescription = [NSString stringWithFormat:@"NSCAssert Failure: Function (%@) in %@#%li. Reason: \"%@\"", functionName, fileName, (long)line, format];
    printf("%s\n", [failureMessageDescription UTF8String]);
}

@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSAssertionHandler *assertionHandler = [[LoggingAssertionHandler alloc] init];
        [[[NSThread currentThread] threadDictionary] setValue:assertionHandler forKey:NSAssertionHandlerKey];
        NSCAssert(true == false, @"Impossible.");
        NSLog(@"Hello, World!");
    }
    return 0;
}

Solution

  • The problem is that the macros are part of the system files added at project creation, which are precompiled (pre-preprocessed). Your #undef is compiled later, therefore it cannot change the already preprocessed makros.

    To change this, put the #undef in the .pch (precompiled headers) file ahead of the include of the system headers. It might look like this:

    #ifdef __OBJC__
      #undef NS_BLOCK_ASSERTIONS
      #import <Cocoa/Cocoa.h>
    #endif