iOS中如何处理SDK中重复.o文件

 ###  iOS中如何处理SDK中重复.o文件
  1. 在iOS开发中经常会使用到第三方的SDK,有些SDK中有应用的相同的类,如下图所示:Demo工程中有A跟B两个静态库,A跟B中又有相同的YTLog类


    Demo工程目录
  2. 该Demo在编译时会报重复.o文件错误,报错如下图所示:


    Demo报错

ld: warning: directory not found for option '-L/Users/z_yt/Desktop/ /Personal_file/5/TestDemo/StaticLibraryDemo/Library'
duplicate symbol OBJC_CLASS$_YTLog in:
/Users/z_yt/Library/Developer/Xcode/DerivedData/StaticLibraryDemoWorkspace-byqglqkcbrjzljfrqjqzzmgrbuvz/Build/Products/Debug-iphonesimulator/libLibraryB.a(YTLog.o)
/Users/z_yt/Library/Developer/Xcode/DerivedData/StaticLibraryDemoWorkspace-byqglqkcbrjzljfrqjqzzmgrbuvz/Build/Products/Debug-iphonesimulator/libLibraryA.a(YTLog.o)
duplicate symbol OBJC_METACLASS$_YTLog in:
/Users/z_yt/Library/Developer/Xcode/DerivedData/StaticLibraryDemoWorkspace-byqglqkcbrjzljfrqjqzzmgrbuvz/Build/Products/Debug-iphonesimulator/libLibraryB.a(YTLog.o)
/Users/z_yt/Library/Developer/Xcode/DerivedData/StaticLibraryDemoWorkspace-byqglqkcbrjzljfrqjqzzmgrbuvz/Build/Products/Debug-iphonesimulator/libLibraryA.a(YTLog.o)
ld: 2 duplicate symbols for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

  1. 由报错的信息我们可以很明显知道LibraryA跟LibraryB中有相同的类冲突,解决这种冲突的最好方法肯定是把其中一个SDK中相同的类修改名称,但是实际开发中我们使用的SDK可能是没有源码,且也无法修改类名,这时可以通过删除相同的.o文件来解决这个问题;

  2. 使用lipo命令可以查看到LibraryA的信息,命令为 lipo -info libLibraryA.a,

    lipo查看SDK信息

    由图可以看出该SDK是no fat file,也就是只有x86_64模拟器版本,如果查看的结果为fat file,那么还需要做逐一解包的操作,操作命令为lipo LibraryA.a -thin armv7 -output userPath/xxx,userPath/xxx为你想存放的路径;

  3. 查看libLibraryA.a x86_64包中所包含的文件列表,其操作命令为ar -t libLibraryA.a

    libLibraryA.a x86_64包文件列表

由图中我们可以看到其中就有YTLog.o文件

  1. 从libLibraryA.a x86_64包中解压出所包含的文件,其操作命令为ar xv libLibraryA.a
    此处解压出来的文件是在你的当前路径下(pwd可查看你的当前路径),而不是libLibraryA.a所在的路径
    libLibraryA.a x86_64解压出objc file
  1. 删除YTLog.o文件,rm YTLog.o

  2. 重新打包.a文件,其操作命令为ar rcs libLibraryA.a *.o,执行完该命令则会生成一个新的libLibraryA库

  3. 如果你的库为fat file的话则每个平台的包都要执行上面6-8的动作,然后再执行合并各平台包的操作lipo -create libLibraryA-armv7.a libLibraryA-armv7s.a libLibraryA-i386.a -output libLibraryA.a

  4. 把重新打包出来的库导入工程中就可以正常运行起来了;

注意事项

  1. Demo工程中可能有人能够成功run起来而不用删除重复的.o文件,这是因为没有把两个sdk中的所有文件导入工程中,要把sdk的所有文件导入工程中要在工程的build Settings中设置Other Linker Flags,如图所示


    设置Other Linker Flags
  2. Other Linker Flags几个参数 -ObjC -all_load -force_load的意义

-ObjC:加了这个参数后,编译器会把静态库中所有的OC类和分类都导入到最后的可执行文件中。注意该参数的O是大写的。

-all_load:编译器会把所有找到的目标文件都加载到可执行文件中。该参数的出现的是为解决静态库中只有Category时,-Objc参数失效的bug。但正常情况下不要轻易使用该参数。要解决-Objc失效的问题也可以使用下面的参数-force_load

-force_load:所做的事情跟-all_load是一样的,但是-force_load要指定需要加载的静态库的文件路径,这中设置就可以仅仅完全加载一个库文件,而不影响其他静态库。

  1. 该方法只能删除名称相同且实现相同的类,加入该类仅仅是类名相同,但是实现不一样,这样删除任意一个类都会导致编译失败;

你可能感兴趣的:(iOS中如何处理SDK中重复.o文件)