creating two frameworks with different name for same cpp classes in xcode

Created two frameworks with the same cpp file name and classes name in Xcode,

Actually, I have to duplicate our codebase using the framework and need to use both the framework in application target which uses objc.


I am able to generate both the frameworks without duplication symbol error and also link with the application target.


But when accessing framework class from application it links to the incorrect framework. below I have explained it.


Let say Framework Name A and B, I am importing framework A in objc class and calling its class and method but it redirects to framework B class and when import framework B in objc class, it redirects correctly to framework B.

Since both the file name and class name are same but I created a saperate project and folder structure to generate the framework.

Accepted Reply

Apple systems use a two-level namespace. When a client Mach-O image imports a symbol from a shared library, the symbol is referenced by name within that shared library.

When you export a C++ class from a Mach-O image, it exports various symbols that are mangled to embed the name of the class.

These two factoids combine to determine how C++ linkage works. When you link the client Mach-O image, the linker finds the first library that exports the class’s symbols. It then embeds into the client a reference to that library and references to the symbols that make up the class.

Note This is in stark contrast to Objective-C, where all classes within a process live within a single flat namespace.

The critical thing here is that this resolution happens when you link the client. After that, the client has a reference to the shared library containing the symbols and that’s what will be used when you load the client.

There are two standard tools used for investigating this:

  • otool -L
    will show you a list of shared libraries being imported by the client. For example, this:
    $ otool -L MyTestTool
    MyTestTool:
        /System/Library/Frameworks/Foundation.framework/Versions/C/Foundation (compatibility version 300.0.0, current version 1570.15.0)
        /usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0)
        /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.250.1)

    shows that

    MyTestTool
    is importing the shared libraries
    Foundation
    ,
    libobjc
    and
    libSystem
    .
  • nm
    will show you a list of symbols being imported by the client library. Pass the
    -m
    option to see which shared library these are coming from. For example, in the following:
    $ nm -m MyTestTool
                     (undefined) external ___stderrp (from libSystem)
    0000000100000000 (__TEXT,__text) [referenced dynamically] external __mh_execute_header
                     (undefined) external _fprintf (from libSystem)
                     (undefined) external _getprogname (from libSystem)
    0000000100000ee0 (__TEXT,__text) external _main
                     (undefined) external _objc_autoreleasePoolPop (from libobjc)
                     (undefined) external _objc_autoreleasePoolPush (from libobjc)
                     (undefined) external dyld_stub_binder (from libSystem)

    imported symbols are those without an address, and for each imported symbol there is both the symbol name and the library in which it’s expected to be found. As you can see, the

    fprintf
    function is being imported from
    libSystem
    .

You can see this info to confirm which shared library is being referenced by your client. Once you do that, you can try various things to change that, the most likely candidate being the order in which A and B are presented to the linker.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Replies

Are the classes in these framework C++ classes? Or Objective-C classes?

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Thanks for the reply.

All classes are CPP classes inside the framework.

Apple systems use a two-level namespace. When a client Mach-O image imports a symbol from a shared library, the symbol is referenced by name within that shared library.

When you export a C++ class from a Mach-O image, it exports various symbols that are mangled to embed the name of the class.

These two factoids combine to determine how C++ linkage works. When you link the client Mach-O image, the linker finds the first library that exports the class’s symbols. It then embeds into the client a reference to that library and references to the symbols that make up the class.

Note This is in stark contrast to Objective-C, where all classes within a process live within a single flat namespace.

The critical thing here is that this resolution happens when you link the client. After that, the client has a reference to the shared library containing the symbols and that’s what will be used when you load the client.

There are two standard tools used for investigating this:

  • otool -L
    will show you a list of shared libraries being imported by the client. For example, this:
    $ otool -L MyTestTool
    MyTestTool:
        /System/Library/Frameworks/Foundation.framework/Versions/C/Foundation (compatibility version 300.0.0, current version 1570.15.0)
        /usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0)
        /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.250.1)

    shows that

    MyTestTool
    is importing the shared libraries
    Foundation
    ,
    libobjc
    and
    libSystem
    .
  • nm
    will show you a list of symbols being imported by the client library. Pass the
    -m
    option to see which shared library these are coming from. For example, in the following:
    $ nm -m MyTestTool
                     (undefined) external ___stderrp (from libSystem)
    0000000100000000 (__TEXT,__text) [referenced dynamically] external __mh_execute_header
                     (undefined) external _fprintf (from libSystem)
                     (undefined) external _getprogname (from libSystem)
    0000000100000ee0 (__TEXT,__text) external _main
                     (undefined) external _objc_autoreleasePoolPop (from libobjc)
                     (undefined) external _objc_autoreleasePoolPush (from libobjc)
                     (undefined) external dyld_stub_binder (from libSystem)

    imported symbols are those without an address, and for each imported symbol there is both the symbol name and the library in which it’s expected to be found. As you can see, the

    fprintf
    function is being imported from
    libSystem
    .

You can see this info to confirm which shared library is being referenced by your client. Once you do that, you can try various things to change that, the most likely candidate being the order in which A and B are presented to the linker.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"