How I solved the duplicate symbols issue when integrating google frameworks SDK for iOS ?

Recently I was integrating the new google sign in SDK into my project. https://developers.google.com/identity/sign-in/ios/sdk This was a new version and I was integrating it after a couple of months.

I followed the usual, and when I compiled my project, I started getting these compile errors.

duplicate symbol 'OBJC_IVAR$_GTMAppAuthFetcherAuthorizationArgs.request' in: pathInBuildDebug.build/Objects-normal/arm64/GTMAppAuthFetcherAuthorization.o pathInGoogleFolder/GoogleSignInDependencies.framework/GoogleSignInDependencies(GTMAppAuthFetcherAuthorization_8eb40aa9262502d90d50b6a28bea1d68.o) duplicate symbol '_OBJC_IVAR$_GTMAppAuthFetcherAuthorization._shouldAuthorizeAllRequests' in:
pathInBuildDebug.build/Objects-normal/arm64/GTMAppAuthFetcherAuthorization.o

duplicate symbol 'OBJC_IVAR$_OIDExternalUserAgentIOSCustomBrowser.canOpenURLScheme' in: pathInBuildDebug.build/Objects-normal/arm64/OIDExternalUserAgentIOSCustomBrowser.o pathInGoogleFolder/GoogleSignInDependencies.framework/GoogleSignInDependencies(OIDExternalUserAgentIOSCustomBrowser_0ecc41f590539d34b9efeb9577094ab4.o) duplicate symbol '_OBJC_IVAR$_OIDExternalUserAgentIOSCustomBrowser._appStoreURL' in:
pathInBuildDebug.build/Objects-normal/arm64/OIDExternalUserAgentIOSCustomBrowser.o
pathInGoogleFolder/GoogleSignInDependencies.framework/GoogleSignInDependencies(OIDExternalUserAgentIOSCustomBrowser_0ecc41f590539d34b9efeb9577094ab4.o)

There were a lot of errors, but I have pasted only a subset. Most errors said duplicate symbols. That gave me a idea that I might be already including these header files. So I went ahead and searched for OIDExternalUserAgentIOSCustomBrowser and GTMAppAuthFetcherAuthorization. Luckily I found a hit inside my project. Just to be frank my project has over 150 subprojects and those have tons of other dependencies. At least over 200 developers touch the main project.

As expected, there were similar header files included by a youtube export helper project. These can be downloaded from https://github.com/openid/AppAuth-iOS and https://github.com/google/GTMAppAuth. These include the same files as the google sign in sdk.

So, the next question was, how do I solve this ? I didn’t want to alter the already existing YouTube helper project, since that would cause a lot of regressions and more testing. So I did the next best step thing, investigate how to remove these duplicate symbols from the google signin sdk.

If you open the google signin sdk, you will see the below files:

I found the dependencies of this file

lipo -info GoogleSignInDependencies.framework/GoogleSignInDependencies
Architectures in the fat file: GoogleSignInDependencies.framework/GoogleSignInDependencies are: armv7 i386 x86_64 arm64

First thing, my project is only 64 bit, I went ahead and removed all other architectures except the arm64.

lipo -thin arm64 GoogleSignInDependencies -output arm64.a

Next you will be getting a arm64.a file. Create a new folder called arm64. Move this file arm64.a into that file. Next lets use the ar tool to extract all the archived files from its archive. The ar utility creates and maintains groups of files combined into an archive. Once an archive has been created, new files can be added and existing files can be extracted, deleted, or replaced.

Files are named in the archive by a single component, i.e., if a file referenced by a path containing a slash (“/”) is archived it will be named by the last component of that path. When matching paths listed on the command line against file names stored in the archive, only the last component of the path will be compared.

ar -x arm64.a

You will get a list of files as shown below:

GTMAppAuthFetcherAuthorization+Keychain_fab36ccc489133f182944cdd021e0396.o OIDExternalUserAgentIOSCustomBrowser_0ecc41f590539d34b9efeb9577094ab4.o
GTMAppAuthFetcherAuthorization_8eb40aa9262502d90d50b6a28bea1d68.o OIDExternalUserAgentIOS_72d27a6b1ff725ce310d91d91741a793.o
GTMKeychain_iOS_5d4700a3d7a9649807c6487123348c2e.o OIDFieldMapping_c6cbe4ecdb6b8ec00b781c6273c2ea04.o
GTMOAuth2KeychainCompatibility_658422c699cb1f3d3565ee4fc55f133d.o OIDGrantTypes_450d94e32e5c578c129072b006be80b6.o
GTMSessionFetcherLogging_0c15a56b1796eced66382c6b87b8d7d1.o OIDIDToken_8fcb137354b4958b1112fbd878cbdd46.o
GTMSessionFetcherService_2e227824097119dae0a3dbbaed733920.o OIDRegistrationRequest_be06b466f1ff5a81a240012efa002c77.o
GTMSessionFetcher_7b8c8ffae413e42bbca43e4d46d92bd0.o OIDRegistrationResponse_a8c2c78bc55cdc361bc12b46e6ba9652.o
GTMSessionUploadFetcher_5c2f6ad357282a9f2e25f97426ae07c9.o OIDResponseTypes_49d7abf89c8a5a80ebd7aeee9407e55d.o
OIDAuthState+IOS_2c005ab214184220c1748b12b46e41e6.o OIDScopeUtilities_83f170892eb498fc7f958ae5e42fbfd9.o
OIDAuthState_2bcb3c37e8a27b7c34150a281b2a35c9.o OIDScopes_3a21415e82e3935086d06897aaa2c503.o
OIDAuthorizationRequest_926c5f812d4312375e94c9c73b6cc0bb.o OIDServiceConfiguration_578b99bd11b635dcf73d0171db43cc3e.o
OIDAuthorizationResponse_105383697c28b534bd0c62ff87d891fc.o OIDServiceDiscovery_996730ac554113bc333a0c89e923dfee.o
OIDAuthorizationService+IOS_1b2646ab57c2bf47bb54ce7cb39cc970.o OIDTokenRequest_1e3fc996eed392893fdc2627c7e9f9b6.o
OIDAuthorizationService_21c721262e37de8f248b08819688d31a.o OIDTokenResponse_06f192be068a7fec00368a1bdbf32580.o
OIDClientMetadataParameters_760f6996144fbd551c38a200838c7cea.o OIDTokenUtilities_e791d21b7439dc9304706d3743516127.o
OIDEndSessionRequest_4515938045f0e2f4ee98de69e949a9c8.o OIDURLQueryComponent_e4f728325570885b1afd9a869f318e55.o
OIDEndSessionResponse_d96694ad574be291108ad3639ee6e79e.o OIDURLSessionProvider_e46deda52541c789dcad662d6921d0e2.o
OIDErrorUtilities_9543da3ed98596d79ffad728103912a2.o __.SYMDEF
OIDError_7fe8a9517470df735e382d24138b75f3.o arm64.a

Now go to your error log, and pull out all the duplicate symbols. My duplicate symbols are as shown below

GTMAppAuthFetcherAuthorization_8eb40aa9262502d90d50b6a28bea1d68.o
GTMOAuth2KeychainCompatibility_658422c699cb1f3d3565ee4fc55f133d.o
GTMKeychain_iOS_5d4700a3d7a9649807c6487123348c2e.o
OIDAuthState_2bcb3c37e8a27b7c34150a281b2a35c9.o
OIDAuthorizationRequest_926c5f812d4312375e94c9c73b6cc0bb.o
OIDAuthorizationResponse_105383697c28b534bd0c62ff87d891fc.o
OIDAuthorizationService_21c721262e37de8f248b08819688d31a.o
OIDEndSessionRequest_4515938045f0e2f4ee98de69e949a9c8.o
OIDEndSessionResponse_d96694ad574be291108ad3639ee6e79e.o
OIDErrorUtilities_9543da3ed98596d79ffad728103912a2.o
OIDFieldMapping_c6cbe4ecdb6b8ec00b781c6273c2ea04.o
OIDIDToken_8fcb137354b4958b1112fbd878cbdd46.o
OIDRegistrationRequest_be06b466f1ff5a81a240012efa002c77.o
OIDRegistrationResponse_a8c2c78bc55cdc361bc12b46e6ba9652.o
OIDScopeUtilities_83f170892eb498fc7f958ae5e42fbfd9.o
OIDServiceConfiguration_578b99bd11b635dcf73d0171db43cc3e.o
OIDServiceDiscovery_996730ac554113bc333a0c89e923dfee.o
OIDTokenRequest_1e3fc996eed392893fdc2627c7e9f9b6.o
OIDTokenResponse_06f192be068a7fec00368a1bdbf32580.o
OIDTokenUtilities_e791d21b7439dc9304706d3743516127.o
OIDURLQueryComponent_e4f728325570885b1afd9a869f318e55.o
OIDURLSessionProvider_e46deda52541c789dcad662d6921d0e2.o
OIDExternalUserAgentIOS_72d27a6b1ff725ce310d91d91741a793.o
OIDExternalUserAgentIOSCustomBrowser_0ecc41f590539d34b9efeb9577094ab4.o
end

Next I wrote a small script to delete all these files from the folder.

while read p; do  echo "/Users/tester/Downloads/update_csdk_google/google_signin_sdk_5_0_1/GoogleSignInDependencies.framework/arm64"."$p"  rm "/Users/tester/Downloads/update_csdk_google/google_signin_sdk_5_0_1/GoogleSignInDependencies.framework/arm64/$p"done </Users/tester/Downloads/update_csdk_google/removal_symbols

Next step, combine all the remaining files with the command shown. I will using libtool to do this. The libtool command takes the specified input object files and creates a library for use with the link editor, ld(1). The library’s name is specified by output (the argument to the -o flag). The input object files may be in any correct format that contains object files (“universal” files, archives, object files). Libtool will not put any non-object input file into the output library (unlike ranlib, which allows this in the archives it operates on).

cd ../arm64
$ libtool -static *.o -o arm64-new.a

Final step, combine them into the google dependency framework file

lipo -create arm64-new.a -output GoogleSignInDependencies-new

Now you are ready to replace this file with the original file and you should be good to go. No compile issues.

Leave a Reply

Your email address will not be published. Required fields are marked *