objc: Class MyClass is implemented in both dylibs

I have a static library staticLib.a which is witten mostly in C++ with one additional obj-C class MyClass. There are two dynamic libs, dynamicLib_A. dylib and dynamicLib_B.dylib are linked with the static lib.

When starting the application which loads the dynamic libs at runtime it comes out the following warning: objc[15078]: Class MyClass is implemented in both /path/to/libdynamicLib_A.dylib (0x104f03f90) and /path/to/libdynamicLib_B.dylib (0x10dbf3f48). One of the two will be used. Which one is undefined.

It can be found that the C++ names are mangled. For instance, both libdynamicLib_A.dylib and libdynamicLib_B contains string: __ZN18MyClassBC2Ev

It looks like the obj-c class name is not mangled. Both libdynamicLib_A.dylib and libdynamicLib_B contains string:

00000000012b7f48 S OBJC_CLASS$_MyClass

Question: How to avoid this warning? Why it complains only about the obj-c class but not the C++ class? Is this issue related to name mangling?

Answered by DTS Engineer in 760717022

It looks like the obj-c class name is not mangled.

Correct. Objective-C classes live in a single flat namespace. This is why, for example, it’s traditional to prefix them (two letter prefixes, like NS, for Apple classes, and longer prefix for third-party ones).

How to avoid this warning?

The best way to avoid this warning is to rework how you do your linking, so that you only have one instance of the class.

This makes sense anyway. Shipping two copies of this code is wasteful.

The alternative is to build the static library twice, with different names in each case. That’ll fix this problem, but you still end up wasting space with two copies of the code.

Why it complains only about the obj-c class but not the C++ class?

That’s quite a subtle question (-:

Is this issue related to name mangling?

No. If you dump the C++ names you’ll probably see them mangled in the same way.

What saves you with C++ is that:

  • The names don’t collide. There are two potentials reasons for that. The first is that the names might be private to your dynamic libraries. However, even if that’s not the case, the two-level namespace prevents name collisions like this. For more on that, see An Apple Library Primer.

  • The C++ runtime is largely distributed [1]. In contrast, the Objective-C runtime is very centralised, and it requires that your class names be unique. This supports functionality like NSClassFromString, which is fundamental to how Cocoa apps work.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] Until you start looking One Definition Rule!

Accepted Answer

It looks like the obj-c class name is not mangled.

Correct. Objective-C classes live in a single flat namespace. This is why, for example, it’s traditional to prefix them (two letter prefixes, like NS, for Apple classes, and longer prefix for third-party ones).

How to avoid this warning?

The best way to avoid this warning is to rework how you do your linking, so that you only have one instance of the class.

This makes sense anyway. Shipping two copies of this code is wasteful.

The alternative is to build the static library twice, with different names in each case. That’ll fix this problem, but you still end up wasting space with two copies of the code.

Why it complains only about the obj-c class but not the C++ class?

That’s quite a subtle question (-:

Is this issue related to name mangling?

No. If you dump the C++ names you’ll probably see them mangled in the same way.

What saves you with C++ is that:

  • The names don’t collide. There are two potentials reasons for that. The first is that the names might be private to your dynamic libraries. However, even if that’s not the case, the two-level namespace prevents name collisions like this. For more on that, see An Apple Library Primer.

  • The C++ runtime is largely distributed [1]. In contrast, the Objective-C runtime is very centralised, and it requires that your class names be unique. This supports functionality like NSClassFromString, which is fundamental to how Cocoa apps work.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] Until you start looking One Definition Rule!

@eskimo Thanks for detailed explanation.

I solved the issue in this way: Instead of static linking with MyClass in the shared library, the shared library gets the referece of MyClass which is initiated in the loader.

objc: Class MyClass is implemented in both dylibs
 
 
Q