文章目录
  1. 1. 解决步骤
  2. 2. 常用方法
  3. 3. 完整命令

最近项目组在做一些第三方功能的集成,不止一次的遇到第三方库冲突的问题,报错如下:

1
2
3
4
5
duplicate symbol _OBJC_METACLASS_$_XMPPElement in:
/Users/test/Xcode/XXXProject/Vendors/MiPush/libMiPushSDK.a(XMPPElement.o)
/Users/test/Xcode/XXXProject/Vendors/EaseMobSDK/lib/libEaseMobClientSDKLite.a(XMPPElement.o)
ld: 186 duplicate symbols for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

在这个报错中,原因是两个第三方库都使用了XMPPFrameWork这个库。这种情况需要我们把其中一个第三方SDK中冲突的库移除掉,即将它拆包后重打包处理。

解决步骤

首先按照上述错误中提到的路径找到库文件:/Users/test/Xcode/XXXProject/Vendors/MiPush/libMiPushSDK.a,将它拷贝一份出来做进一步处理。

1
2
cd ~/ && mkdir librepack && cd librepack
cp /Users/test/Xcode/XXXProject/Vendors/MiPush/libMiPushSDK.a ./libx.a

查看包信息:lipo -info libx.a

如果提示fat file,那么代表这个包是支持多平台的,例如 armv7s armv7 i386 x86_64 arm64 等,这需要我们逐一做解包重打包操作。否则我们只需要做一次[1-6]操作即可

  1. 创建临时文件夹,用于存放armv7平台解压后的.o文件:mkdir armv7

  2. 取出armv7平台的包:lipo libx.a -thin armv7 -output armv7/libx-armv7.a

  3. 查看库中所包含的文件列表:ar -t armv7/libx-armv7.a

  4. 解压出object file(即.o后缀文件):cd armv7 && ar xv libx-armv7.a

  5. 找到冲突的包(报错信息里列出来的.o文件),删除掉 rm `ls XMPPElement.o`

  6. 重新打包object file:cd .. && ar rcs libx-armv7.a armv7/*.o,可以再次使用[2]中命令确认是否已成功将文件去除

  7. 将其他几个平台(armv7s, i386, x86_64, arm64)包逐一做上述[1-6]操作

  8. 重新合并为fat file的.a文件:lipo -create libx-armv7.a libx-armv7s.a libx-i386.a libx-x86_64.a libx-arm64.a -output libMiPushSDK-new.a

  9. 拷贝到项目中覆盖源文件:cp libMiPushSDK-new.a /Users/test/Xcode/XXXProject/Vendors/MiPush/libMiPushSDK.a

常用方法

查找.a文件中是否包含相关信息,如苹果禁用的 unique Identifier。

1
2
3
4
find . -name *.a |xargs grep uniqueIdentifier
查看object file文件信息:
nm xxx.a | grep ".o:" | sed "s/.(//g" | sed "s/).//g" | uniq

完整命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
cd ~/ && mkdir librepack && cd librepack
cp /Users/test/Xcode/XXXProject/Vendors/MiPush/libMiPushSDK.a ./libx.a
mkdir armv7
lipo libx.a -thin armv7 -output armv7/libx-armv7.a
cd armv7 && ar xv libx-armv7.a
rm `ls DD* && ls TURNSocket.o && ls RFImageToDataTransformer.o && ls XMPP*|egrep -v XMPPTransports.o`
cd .. && ar rcs libx-armv7.a armv7/*.o
mkdir armv7s
lipo libx.a -thin armv7s -output armv7s/libx-armv7s.a
cd armv7s && ar xv libx-armv7s.a
rm `ls DD* && ls TURNSocket.o && ls RFImageToDataTransformer.o && ls XMPP*|egrep -v XMPPTransports.o`
cd .. && ar rcs libx-armv7s.a armv7s/*.o
mkdir i386
lipo libx.a -thin i386 -output i386/libx-i386.a
cd i386 && ar xv libx-i386.a
rm `ls DD* && ls TURNSocket.o && ls RFImageToDataTransformer.o && ls XMPP*|egrep -v XMPPTransports.o`
cd .. && ar rcs libx-i386.a i386/*.o
mkdir x86_64
lipo libx.a -thin x86_64 -output x86_64/libx-x86_64.a
cd x86_64 && ar xv libx-x86_64.a
rm `ls DD* && ls TURNSocket.o && ls RFImageToDataTransformer.o && ls XMPP*|egrep -v XMPPTransports.o`
cd .. && ar rcs libx-x86_64.a x86_64/*.o
mkdir arm64
lipo libx.a -thin arm64 -output arm64/libx-arm64.a
cd arm64 && ar xv libx-arm64.a
rm `ls DD* && ls TURNSocket.o && ls RFImageToDataTransformer.o && ls XMPP*|egrep -v XMPPTransports.o`
cd .. && ar rcs libx-arm64.a arm64/*.o
lipo -create libx-armv7.a libx-armv7s.a libx-i386.a libx-x86_64.a libx-arm64.a -output libMiPushSDK-new.a
cp libMiPushSDK-new.a /Users/test/Xcode/XXXProject/Vendors/MiPush/libMiPushSDK.a