Skip to content

Symbol mangling fails when a pod has both a class and a macro with the same name #31

Description

@IAmConorNolan

Description

When a pod defines both a class and a macro with the same name, cocoapods-mangle's preprocessor-based approach causes compilation failures. The -D flag replaces ALL occurrences of the symbol, breaking macro definitions.

Concrete Example: Ably Pod

The Ably pod (v1.2.33) has both:

  1. A class named ARTLog:
// Source/include/Ably/ARTLog.h
@interface ARTLog : NSObject
@property (nonatomic) ARTLogLevel logLevel;
- (void)log:(NSString *)message withLevel:(ARTLogLevel)level;
@end
  1. A macro named ARTLog:
// Source/PrivateHeaders/Ably/ARTInternalLog.h
#define ARTLog(_logger, _level, _format, ...) \
    [_logger logWithLevel:_level file:__FILE__ line:__LINE__ format:_format, ##__VA_ARGS__]

The Problem

When cocoapods-mangle generates -DARTLog=MySDKSDK_ARTLog, the preprocessor replaces BOTH:

What happens to the class (✅ This is desired):

@interface MySDKSDK_ARTLog : NSObject  // Good - class gets renamed

What happens to the macro (❌ This breaks):

#define MySDKSDK_ARTLog(_logger, _level, _format, ...) \  // Bad - invalid macro name!
    [_logger logWithLevel:_level file:__FILE__ line:__LINE__ format:_format, ##__VA_ARGS__]

The macro definition becomes invalid because MySDKSDK_ARTLog(...) is not valid preprocessor syntax for a function-like macro definition.

Compilation Error

/Users/.../Pods/Ably/Source/include/Ably/ARTClientOptions.h:55:34: error: unknown type name 'ARTLog'
@property (nonatomic, readwrite) ARTLog *logHandler;
                                 ^

This happens because the broken macro definition prevents proper compilation of the headers.

Why This Is Challenging

Preprocessor defines (-D) operate at the text substitution level before the compiler understands the difference between classes and macros. There's no way to tell the preprocessor "only replace ARTLog when it's a class reference, not when it's a macro definition."

Workaround

We have to monkey-patch the pod to rename the macro:

# In Podfile
post_install do |installer|
  header_path = "#{__dir__}/Pods/Ably/Source/PrivateHeaders/Ably/ARTInternalLog.h"

  if File.exist?(header_path)
    content = File.read(header_path)
    # Rename macro from ARTLog to ARTLogMacro
    content.gsub!(/^#define ARTLog\(/, '#define ARTLogMacro(')
    content.gsub!(/\bARTLog\(logger, ARTLogLevel/, 'ARTLogMacro(logger, ARTLogLevel')
    File.write(header_path, content)
  end
end

This is a fundamental limitation of using preprocessor defines for symbol mangling. The issue cannot be fully solved without either:

  • Changing the mangling implementation approach
  • Requiring source modifications to affected pods
  • Providing robust detection and workaround mechanisms

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions