Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

static library function name conflict between Rdio and Google Core library

Problem

This is happening with two static libraries where I don't have access to the source code.

I'm trying to install the Rdio SDK into my project (using these instructions). My project already uses a lot of Google's services, and there seems to be a C function naming conflict between Rdio and Google:

duplicate symbol _CreateDispatchTimer in:
    /Users/abdullahbakhach/dev/ios/Vibereel_IOS/Vibereel/Pods/Google/Libraries/libGGLCore.a(GMRAlarm.o)
    /Users/abdullahbakhach/dev/ios/Vibereel_IOS/Vibereel/Vibereel/rdio-ios-3.1.0/Rdio.framework/Rdio(RDPlayer.o)
ld: 1 duplicate symbol for architecture armv7
Google Core is installed on my project using cocoapods, on my podfile I have:
pod 'Google/SignIn'

and in the Podfile.lock I have:

  - Google/Core (1.1.0):        
    - GoogleInterchangeUtilities (~> 1.0)
    - GoogleNetworkingUtilities (~> 1.0)       
    - GoogleSymbolUtilities (~> 1.0)        
    - GoogleUtilities (~> 1.1)        
  - Google/SignIn (1.1.0):        
    - Google/Core        
    - GoogleSignIn (~> 2.0)        
  - GoogleAppUtilities (1.0.0):        
    - GoogleSymbolUtilities (~> 1.0)        
  - GoogleAuthUtilities (1.0.1):        
    - GoogleNetworkingUtilities (~> 1.0)        
    - GoogleSymbolUtilities (~> 1.0)        
  - GoogleInterchangeUtilities (1.0.0):        
    - GoogleSymbolUtilities (~> 1.0)        
  - GoogleNetworkingUtilities (1.0.0):        
    - GoogleSymbolUtilities (~> 1.0)        
  - GoogleSignIn (2.2.0):        
    - GoogleAppUtilities (~> 1)        
    - GoogleAuthUtilities (~> 1)        
    - GoogleNetworkingUtilities (~> 1)        
    - GoogleUtilities (~> 1)        
  - GoogleSymbolUtilities (1.0.0)
- GoogleUtilities (1.1.0):
  - GoogleSymbolUtilities (~> 1.0.0)

What I tried/researched

I've done some research and tried to see if i could somehow change/remove/hide that method name in either of those two libraries.. but then I can across this apple documentation:

There is no mechanism for hiding an Objective-C class or method defined in a dynamic library from the clients of that library.

So I'm kind of stuck.. any ideas?

like image 428
abbood Avatar asked Oct 20 '15 09:10

abbood


2 Answers

If you have access to a source code you could modify the name of the conflicted variable or visibility scope (e.g. make it static).

If you don't have access to a source code of using libraries you could contact the contributors to ask to change the name / add the prefix / change the visibility of function/variable.

If you aren't satisfied with that option you could modify the symbol table on the one of libraries to avoid the conflict. You could modify the symbol table by changing the visibility of conflicting function or renaming the function.

Because you're using OS X you need to have objconv by Agner Fog (analog of objcopy) on your local machine (see documentation).

The following are steps for modifying symbol table for a library:

  1. Open Terminal and locate your library
  2. path/to/rdio/rdio-ios-3.1.0/Rdio.framework/Rdio
  3. List architectures for what build the fat library
  4. lipo -info Rdio
  5. Extract the first architecture (armv7)
  6. lipo Rdio -thin armv7 -output Rdio_armv7
  7. Extract conflicting object file (RDPlayer.o)
  8. ar x Rdio_armv7 RDPlayer.o
  9. List symbols from object file to ensure conflicting function there
  10. nm -gU RDPlayer.o
  11. Change visibility of function from global to local
  12. objconv -nl:_CreateDispatchTimer RDPlayer.o RDPlayer_new.o
  13. Delete old RDPlayer.o and rename RDPLayer_new.o to RDPlayer.o
  14. rm RDPLayer.o && mv RDPLayer_new.o RDPlayer.o
  15. Ensure the function is no longer visible on object file
  16. nm -gU RDPlayer.o
  17. Replace new object file with old one in archived library and rebuild symbol table
  18. ar r -s Rdio_armv7 RDPlayer.o
  19. Repeat steps 5-18 for other architectures
  20. Combine all architectures back into fat library
  21. lipo Rdio_arm64 Rdio_armv7 Rdio_armv7s Rdio_i386 Rdio_x86_64 -create -output Rdio
  22. ...
  23. PROFIT
like image 103
Dmitry Fantastik Avatar answered Sep 20 '22 01:09

Dmitry Fantastik


The problematic symbol is a plain C function, not a method (Objective-C methods don't clash on the linker level).

If you have access to the source code you can put a static if front of the function definition, which looks probably like this:

static dispatch_source_t CreateDispatchTimer(double interval, dispatch_queue_t queue, dispatch_block_t block)

The function is very likely local to the compilation unit, so this will work. If it's not, you have to rename it in the whole library project.

like image 24
Nikolai Ruhe Avatar answered Sep 21 '22 01:09

Nikolai Ruhe