如何解决ios中第3方框架中的重复符号?
Posted
技术标签:
【中文标题】如何解决ios中第3方框架中的重复符号?【英文标题】:How to resolve the duplicate symbol in 3rd party Framework in ios? 【发布时间】:2014-07-16 13:12:27 【问题描述】:我正在我的项目中开发 Amazon 登录和 Google Plus 共享。我在我的项目中添加了 Amazon 和 Google plus 框架。当我尝试构建项目时,它显示“GooglePlus 和 Amazon 框架中的重复符号”错误。
错误信息
duplicate symbol _kClientId in:
/Users/test/Amazon/Apps-SDK/ios/LoginWithAmazon/LoginWithAmazon.framework/LoginWithAmazon(AIConstants.o)
/Users/test/GooglePlus/google-plus-ios-sdk-1.5.1/GooglePlus.framework/GooglePlus(GPPOzLogger.o)
ld: 1 duplicate symbol for architecture i386
clang: error: linker command failed with exit code 1 (use -v to see invocation)
如何解决此类错误?
【问题讨论】:
【参考方案1】:你真正能做的就是联系谷歌和/或亚马逊,告诉他们修复他们的冲突框架。当使用这样的名称发生冲突的可能性非常高时,在他们的框架中使用像_kClientId
这样的全局符号名称对他们来说有点愚蠢。对于每个框架,名称确实应该像 _kGooglePlus_iOS_Framework_ClientId
和 _kAmazon_iOS_Framework_ClientId
这样长,以减少符号名称冲突的机会。
如果可以的话,要么这样做,要么为 Google Plus 或 Amazon 使用不同的框架或库。或者,如果您不能这样做,请使用 HEX 编辑器手动更改其中一个框架中对 _kClientId
符号的所有引用。
【讨论】:
有没有其他框架或者其他方式来实现google+分享? @harigharan 我不知道,不。你可能只需要谷歌它。或者 Bing 它——随你喜欢。【参考方案2】:我之前也遇到过同样的问题。最后我想出了如何解决这个问题。 作为图书馆的客户,我们无法避免它,但我们仍然有机会处理它。 我的答案包括两部分,一是描述问题,一是作为框架的客户解决这个问题(这意味着我们必须自己解决这个问题,而不是要求框架的开发人员来解决这个问题)。
1) 碰撞是如何发生的,链接错误是什么意思?
framework其实就是一个文件夹,进入framework你会发现一个lib文件。有时,lib 文件的扩展名是 *.a,或者只是没有扩展名。 lib 文件的结构如下所示:
libFoo.a / i386 /
hello.o
world.o
arm64 /
hello.o
world.o
在这种情况下,libFoo.a 是一个胖库,这意味着它包含多个架构。链接错误告诉您,您有两个库在同一架构中包含相同的 .o(symbols) 文件。
以您的情况为例:
duplicate symbol _kClientId in:
/Users/test/Amazon/Apps-SDK/iOS/LoginWithAmazon/LoginWithAmazon.framework/LoginWithAmazon(AIConstants.o)
/Users/test/GooglePlus/google-plus-ios-sdk-1.5.1/GooglePlus.framework/GooglePlus(GPPOzLogger.o)
ld: 1 duplicate symbol for architecture i386
clang: error: linker command failed with exit code 1 (use -v to see invocation)
这意味着在这两个框架中,您在 i386 架构中有重复的 .o 文件。
2) 如何解决问题。
我们需要一些工具来解决这个问题。幸运的是,您应该在计算机中安装了这些工具。 我们需要做的是打开一个框架并进行一些手术以删除重复的符号并将其关闭。
我这里演示i386架构下LoginWithAmazon去除重复符号AIConstants.o的过程:
lipo -info LoginWithAmazon //this is going to show us the architectures in the fat library
lipo LoginWithAmazon -thin i386 -output LoginWithAmazon-i386 //we extract the i386 architecture as xxx-i386 from fat library
//use the same command to extract every architecture from fat libraray as xxx-archname
ar -t LoginWithAmazon-i386 // list of symbols in this architecture, we should see AIConstants.o in it
ar -d LoginWithAmazon-i386 AIConstants.o // delete AIConstants.o from LoginWithAmazon-i386
//now work is done, we put everything back to the fat library
lipo LoginWithAmazon-i386 LoginWithAmazon-arm64 <every architecture you extracted from the fat library> -create -output LoginWithAmazon-new
ranlib -s LoginWithAmazon-new //sometime we need to rebuild the symbol table
//now you have done the work, use LoginWithAmazon-new to replace the old LoginWithAmazon, and try to compile your program again
参考:
http://blog.sigmapoint.pl/avoiding-dependency-collisions-in-ios-static-library-managed-by-cocoapods/
【讨论】:
很好的描述,但这不起作用,因为您还从 AIConstants.o 中删除了所有其他常量,这将使所有其他 _k* 引用的链接器失败 我假设两个版本的 AIConstants.o 具有相同的内容。如果不是这样,您需要框架源代码来重建不太可能发生的整个事情。【参考方案3】:似乎这个问题对于亚马逊团队的登录来说不是高优先级。
作为临时解决方案(信不信由你),您可以使用文本编辑器并将 LoginWithAmazon 二进制文件中所有出现的“_kClientId”替换为其他内容(如“_kClientIe”)。
也可以在这里查看我的回答:
https://github.com/aws/aws-sdk-ios/issues/18
【讨论】:
以上是关于如何解决ios中第3方框架中的重复符号?的主要内容,如果未能解决你的问题,请参考以下文章