iOS: 由第三方SDK引起 duplicate symbol 的思考

本文建立在 xcode6.4 的基础之上.

开发 App, 难免要接第三方的 SDK. 按照 SDK 文档接入, 理论上说不会有什么错误.

~

但是, 现实还是没那么的理想~

~

第三方 SDK 一般不会写文档告诉你, 我使用了哪些第三方库, 你们在接入的时候要注意啊类似的话.

可能说出这样的话, 无法体现自己的逼格, 呵呵!

这样就苦逼了程序员们了.

不过, 魔高一尺道高一丈!

~

今天讨论一下接入 SDK 引起的 duplicate symbol 问题.

拿百度地图来说吧. 

不是黑百度地图, 确实是自己亲身经历.

~

按照百度地图的接入文档, 顺利的完成了开发!

后面随着项目的完善, 自己也加入了一些开源库, 比如 Reachability.

加入之后, 项目编译链接就失败了.

~

这时, 我就开始怀疑是百度地图 SDK 引起的. 于是开始了下面的旅程.

~

这里会用到 ar 和 lipo 工具.不知道他们用法的可以自行 google.

ar 工具可以列出库文件中的相关文件.

ar -t BaiduMapAPI.framework

提示信息(失败``)

ar: BaiduMapAPI.framework: Inappropriate file type or format

提示的意思是, 无法识别(不兼容).

cd BaiduMapAPI.framework/

ar -t BaiduMapAPI

还是提示失败

ar: BaiduMapAPI is a fat file (use libtool(1) or lipo(1) and ar(1) on it)
ar: BaiduMapAPI: Inappropriate file type or format

这次的提示给了一条明路: is a fat file.

既然他是 fat 的, 那么如何 thin 下来呢?

我在这里找到了答案, 你可以点击看看.

~

使用 lipo 将其瘦身.

首先, 看一下 BaiduMapAPI.framework 支持哪些架构.

如果你像下面这样操作的话

 lipo -info BaiduMapAPI.framework

出现一个错误提示

can't map input file: BaiduMapAPI.framework (Invalid argument)

答案在这里:iOS Framework lipo报错 lipo: can't map input file

cd BaiduMapAPI.framwork

lipo -info BaiduMapAPI

成功的输出信息

Architectures in the fat file: BaiduMapAPI are: armv7 armv7s i386 x86_64 arm64 

说明, 这个库既支持模拟器(i386 | x86_64), 又支持真机(armv7 | armv7s | arm64).

关于 iphone 和 ipad 的CPU架构, 可以参考这张(叼炸天)的图.



原图来源自这里:点击打开链接.

~

接下来, 我们开始提取其中一种架构来分析.

lipo BaiduMapAPI -thin armv7 -output bmap.armv7
在当前路径下, 生成了 bmp.armv7文件.

ar -t bmap.armv7 
可以看一下 list

__.SYMDEF
Animation.o
AppLocation.o
AppMan.o
BGLBase.o
BGLLine.o
BGLModel.o
BGLSurface.o
BGLTextrue.o
BMAddrList.o
BMAddressInfo.o
BMAppTools.o
BMAreaSearchResult.o
BMAroundInfo.o
BMBase.o
BMBusLine.o
BMBusLineElement.o
BMBusRoute.o
BMCarRoute.o
BMCityInfo.o
BMCityList.o
BMCloudEngine.o
BMCloudSerail.o
BMDictionary.o
BMEspecialQuery.o
BMGEOResult.o
BMHeatMapOverlay.o
BMHeatMapService.o
BMHistoryKeyWords.o
BMKActionPaopaoView.o
BMKAnnotationView.o
BMKAnnotationViewInternal.o
BMKArcline.o
BMKArclineView.o
BMKBaseCloudSearchInfo+Interval.o
BMKBusLineSearch.o
BMKBusLineSearchOption.o
BMKCircle.o
BMKCircleView.o
BMKCloudPOIList.o
BMKCloudSearch.o
BMKCloudSearchInfo.o
BMKGeocodeSearch.o
BMKGeocodeSearchOption.o
BMKGeocodeType.o
BMKGeometry.o
BMKGradient+Interval.o
BMKGradient.o
BMKGroundOverlay.o
BMKGroundOverlayView.o
BMKHeatMap.o
BMKLocationService.o
BMKLocationServiceInternal.o
BMKLocationViewDisplayParam.o
BMKManager.o
BMKMapStatus.o
BMKMapView.o
BMKMultiPoint.o
BMKNavigation.o
BMKNotificationCenter.o
BMKNotifier.o
BMKOfflineMap.o
BMKOfflineMapType.o
BMKOverlayGLBasicView.o
BMKOverlayPathView.o
BMKOverlayView.o
BMKOverlayViewInternal.o
BMKPinAnnotationView.o
BMKPoiSearch.o
BMKPoiSearchOption.o
BMKPoiSearchType.o
BMKPointAnnotation.o
BMKPolygon.o
BMKPolygonView.o
BMKPolyline.o
BMKPolylineView.o
BMKRouteInternal.o
BMKRouteSearch.o
BMKRouteSearchOption.o
BMKRouteSearchType.o
BMKShape.o
BMKShareURLSearch.o
BMKShareUrlSearchOption.o
BMKSuggestionSearch.o
BMKSuggestionSearchOption.o
BMKTypes.o
BMKUserLocation.o
BMKUserLocationInternal.o
BMLogService.o
BMMapMsgObserver.o
BMMapViewManager.o
BMOfflineCityInfo.o
BMOnlineUpData.o
BMPOIDetail.o
BMPOIInfo.o
BMPOIList.o
BMPlaceParameterInfo.o
BMPoiBkgData.o
BMPointQuadTree.o
BMReachability.o
BMReverseGEOResult.o
BMSDKDeviceInfo.o
BMSDKKeychainItemWrapper.o
BMSDKUDID.o
BMSearchEngine.o
BMSerail.o
BMSubwayLineInfo.o
BMTile.o
BVDBBase.o
BVDBBuffer.o
BVDBLog.o
BVDBMission.o
BVDBToolkit.o
BVDBUrl.o
BVDDBase.o
BVDDCache.o
BVDDDataTMP.o
BVDDDataset.o
BVDDToolkit.o
BVDEDataCfg.o
BVDEDataDOM.o
BVDEDataEngine.o
BVDEDataHEM.o
BVDEDataITS.o
BVDEDataMap.o
BVDHBase.o
BVDHCache.o
BVDHDataTMP.o
BVDHDataset.o
BVDHToolkit.o
BVHEMMission.o
BVIDBase.o
BVIDCache.o
BVIDDataEVT.o
BVIDDataTMP.o
BVIDDataVMP.o
BVIDDataset.o
BVIDOfflineFrame.o
BVIDToolkit.o
BVMDBase.o
BVMDCache.o
BVMDDataTMP.o
BVMDDataVMP.o
BVMDDataset.o
BVMDFrame.o
BVMDIndex.o
BVMDToolkit.o
BaiduMapView.o
Baidu_Reachability.o
BaseFramework_vers.o
BaseLayer.o
BaseLayerData.o
BaseMapFactory.o
BaseMapScaleView.o
BaseOverlay.o
BundleUtil.o
CRT.o
CVDatabase.o
CVNetworkStatusMonitor.o
CVResultSet.o
CVStatement.o
CloudControl.o
CloudSearch.o
CloudSearcher.o
CommonMemCacheEngine.o
CommonToolJsonPharser.o
CommonToolSearch.o
CommonToolSearchUrl.o
CompassOverlay.o
CompassView.o
ComplexPt.o
DataStorage.o
DetailJsonObjParser.o
DetailSearch.o
DetailSearchUrl.o
DrawUnit.o
EAGLView.o
FrameControl.o
GDI_Bitmap.o
GDI_FontMan.o
GDI_FontTrueType.o
GDI_Line.o
GDI_Res.o
GDI_Surface.o
GDI_Util.o
GZipHelper.o
GZipUtil.o
GridData.o
GridDataCache.o
GridDataFileCache.o
GridLayer.o
GroundData.o
GroundLayer.o
GroundOverlay.o
HardwareInfo.o
HeatmapData.o
HeatmapLayer.o
HttpClientPool.o
IphoneBaiduMaps.o
IphoneGPSMan.o
JsonPharser.o
LBSSearchFramework_vers.o
LocalCityInfo.o
LocalMap.o
LocalMapElement.o
LocalMapEngine.o
LocalMapImport.o
LocalMapImportElemInfo.o
LocalMapInfo.o
LocationController.o
LocationEngine.o
LocationFramework_vers.o
LocationView.o
MapController.o
MapDefine.o
MapFramework_vers.o
MapGesture.o
MapModeEngine.o
MapModel.o
MapView.o
MyUIDeviceIdentifierAddition.o
NSStringMD5Addition.o
NetworkDetectEngine.o
PaopaoBaseView.o
PoiJsonPharser.o
PoiMarkData.o
PoiMarkExtData.o
PoiMarkExtLayer.o
PoiMarkLayer.o
PoiSearch.o
PoiSearchUrl.o
ResPackFile.o
RoutePlanJsonPharser.o
RoutePlanSearch.o
RoutePlanSearchUrl.o
SDKHeatMapLayer.o
SDKHeatMapLayerData.o
SDKHeatMapLayerDataModel.o
SearchControl.o
SearchFramework_vers.o
Searcher.o
SpatialUtil.o
StretchImageUtil.o
Style.o
SugSearchJsonObjParser.o
SuggestionResult.o
SuggestionSearch.o
SuggestionSearchUrl.o
SysConfig.o
SysConfigMan.o
TapDetectingView.o
TrafficData.o
TrafficEventData.o
TrafficEventLayer.o
TrafficLayer.o
UIDeviceHelper.o
UIDeviceScreen.o
UtilsFramework_vers.o
VBGL.o
VBase.o
VBaseMapLayerFactory.o
VBaseMapPoiLayerFactory.o
VBundle.o
VCMMap.o
VComServer.o
VCommonMemCacheFactory.o
VCommonToolSearchFactory.o
VDNSCache.o
VDataEngineFactory.o
VDataStorageFactory.o
VDetailSearchFactory.o
VDeviceAPI.o
VException.o
VF_Face.o
VF_Glyph.o
VF_Module.o
VF_Render.o
VF_TT_Outline.o
VF_TT_Table.o
VFile.o
VGDI.o
VGroundLayerFactory.o
VHeatmapLayerFactory.o
VHttpClient.o
VHttpClientPoolFactory.o
VHttpGet.o
VHttpPost.o
VHttpRequestBase.o
VHttpResponse.o
VHttpSocket.o
VLocationFactory.o
VLog.o
VMapControl.o
VMapSimple.o
VMem.o
VMemAlloc.o
VMemPool.o
VMsg.o
VNetStateObservable.o
VNetStateObserver.o
VNetworkDetectFactory.o
VOSJpeg.o
VOSPng.o
VPoiSearchFactory.o
VRoutePlanSearchFactory.o
VSDKHeatMapLayerFactory.o
VSearchFactory.o
VServerForwardFailOverFactory.o
VServerForwardFailover.o
VSocket.o
VString.o
VStyleFactory.o
VSuggestionSearchFactory.o
VSysConfigFactory.o
VThread.o
VTimer.o
VTrafficEventLayerFactory.o
VTrafficLayerFactory.o
VUrlUtility.o
VVos.o
VWnd.o
adler32.o
cJSON.o
compress.o
crc32.o
deflate.o
des.o
encrypt.o
envpostmsg.o
fcrypt.o
gpc.o
gzclose.o
gzgpst.o
gzlib.o
gzread.o
gzwrite.o
infback.o
inffast.o
inflate.o
inftrees.o
ioapi.o
jaricom.o
jcapimin.o
jcapistd.o
jcarith.o
jccoefct.o
jccolor.o
jcdctmgr.o
jchuff.o
jcinit.o
jcmainct.o
jcmarker.o
jcmaster.o
jcomapi.o
jcparam.o
jcprepct.o
jcsample.o
jctrans.o
jdapimin.o
jdapistd.o
jdarith.o
jdatadst.o
jdatasrc.o
jdcoefct.o
jdcolor.o
jddctmgr.o
jdhuff.o
jdinput.o
jdmainct.o
jdmarker.o
jdmaster.o
jdmerge.o
jdpostct.o
jdsample.o
jdtrans.o
jerror.o
jfdctflt.o
jfdctfst.o
jfdctint.o
jidctflt.o
jidctfst.o
jidctint.o
jmemansi.o
jmemmgr.o
jmemnobs.o
jpegtran.o
jquant1.o
jquant2.o
jutils.o
md5.o
minixml.o
mztools.o
png.o
pngerror.o
pngget.o
pngmem.o
pngpread.o
pngread.o
pngrio.o
pngrtran.o
pngrutil.o
pngset.o
pngtrans.o
pngwio.o
pngwrite.o
pngwtran.o
pngwutil.o
rdbmp.o
rdcolmap.o
rdgif.o
rdjpgcom.o
rdppm.o
rdrle.o
rdswitch.o
rdtarga.o
sqlite3.o
systemConfigModel.o
transupp.o
trees.o
uncompr.o
unzip.o
util.o
wrbmp.o
wrgif.o
wrjpgcom.o
wrppm.o
wrrle.o
wrtarga.o
zip.o
zutil.o

~

可以看出果然有 Baidu_Reachability.o和 BMReachability.o.

解决方案就是, 删除自己项目中引用的 Reachability 这个库.

~

当然, 你也可以解压出这些文件, 使用下面命令

ar xv bmp.armv7

到此为止, 解决了其中一个错误, 希望大家初步清楚使用 lipo 和 ar 这两个工具.

另外还有一个错误, 也是 duplicate symbol.

跟大家分享一下.

这个错误的原因在于自己写的代码, 把一个结构体指针命名为 p, 和百度地图也重复了.

我修改了这个命名, 就编译成功了.

~

这里也暴露了几个问题:

1. 在写 sdk 的时候, 命名一定要加前缀.

2. 自己写的代码, 命名不要那么的随性.

3. sdk 使用了哪些第三方库, 最好告诉开发者.

~

不想看下面的, 就浏览完成了.

~

在此特别感谢: How to fix a "Duplicated Symbols" error on binary files 的作者!


附录:


* 了解 xcode 中关于 Architecture 和 valid architecture 的, 可以参考

1. 官方文档Build Setting Reference

2. Xcode设置项之Architectures和Valid Architectures


* 了解 xcode6 默认不支持 armv7s 和制作静态库注意事项的, 可以参考

1. Xcode 6 默认不再构建 Armv7s 指令集的代码

2. xCode6制作动态及静态Framework


* 学习 lipo, 可以借鉴

1. lipo 命令

2. lipo命令使用

3. lipo 制作通用版本静态库



©️2020 CSDN 皮肤主题: 酷酷鲨 设计师:CSDN官方博客 返回首页