问题描述:opencv2.framework与BaiduMapAPI_Base.framework中部分.o文件冲突,导致编译不能通过
背景
某些通用处理库被百度BaiduMapAPI_Base.framework和opencv2.framework 都引用进去 ,这样导致的问题就是当接入百度地图的app再次引入opencv.framework的时候,就会报duplicate symbol … in的错误。
解决思路
- 对比BaiduMapAPI_Base.framework和opencv2.framework中的.o文件
- 把两个framework中重复部分从opencv2.framework中“剔除”,然后再将处理后的opencv2.framework加入项目中去进行编译
工具
- ar -- 查看framework中的相关文件
- lipo -- 删除framework中“多余”的.o文件以及重新合成新的framework包
步骤
- 在opencv2.framework所在的目录下,利用下面两个命令,进入opencv2.framework,查看它支持的CPU架构
cd opencv2.framework
lipo -info opencv2
执行完之后输出如下:
Architectures in the fat file: opencv2 are: armv7 armv7s i386 x86_64 arm64
从CPU的架构可以看出该framework同时支持真机和模拟器
2. 把每种架构对应的文件提取出来进行分析处理,首先以armv7架构为例,运行下面命令解压armv7架构下对应的文件
lipo opencv -thin armv7 -output cv.armv7
运行成功之后在当前路径下生成一个cv.armv7文件,现在用ar命令来查看该文件中的.o文件
ar -t cv.armv7
world_init.o
algorithm.o
alloc.o
arithm.o
array.o
cmdparser.o
convert.o
copy.o
datastructs.o
drawing.o
dxt.o
gl_core_3_1.o
glob.o
gpumat.o
lapack.o
mathfuncs.o
matmul.o
matop.o
matrix.o
opengl_interop.o
opengl_interop_deprecated.o
out.o
parallel.o
persistence.o
rand.o
stat.o
system.o
tables.o
flann.o
miniflann.o
accum.o
approx.o
canny.o
clahe.o
color.o
contours.o
convhull.o
corner.o
cornersubpix.o
deriv.o
.......
同样方法分析BaiduMapAPI_Base.framework, 发现重复的文件如下
adler32.o
compress.o
crc32.o
deflate.o
inflate.o
执行删除操作,依次删除这五个文件
ar d cv.armv7 adler32.o
...
至此,armv7架构下的文件“清理”完毕!
3. 重复步骤2,将其他CPU架构文件夹下的内容做相同操作。此步骤结束之后,会有cv.armv7、cv.armv7s、cv.arm64、cv.i386和cv.x86_64五个删除重复.o后的文件。
4. 运行下面命令合成新的opencv2包
lipo -create -output opencv2 cv.armv7 cv.armv7s cv.arm64 cv.i386 cv.x86_64
命令运行成功之后大功告成,此时将新的opencv2.framework引入工程中,在模拟器和真机上分别进行测试,均可通过编译。
总结
- Google了一下,我并不是第一个踩百度坑的人,有人在接入百度地图之后再次接入Reachability的时候也会出现类似情况。我们以后给别人提供sdk的时候要把一些公共库抽出来单独打包,但这种方案也并不完美,可能涉及到版本不统一问题,后续多做一些调研,制定一套通用的解决方案。
- iOS: 由第三方SDK引起 duplicate symbol 的思考描述了lipo、ar使用过程工具出现的一些坑,让我少走了很多弯路。
- 本文还参考了 Avoiding duplicate symbol errors during linking by removing classes from static libraries
- 最后感谢adamschen,在思路上给了我很多帮助!!!