Xcode14, Library not loaded: /usr/lib/swift/libswiftCoreGraphics.dylib

1,510 阅读2分钟

起因:

最近为了适配 iOS 16,把 Xcode 升级到了14.0版本,测试人员反馈在 iOS 12.1 的测试机上启动app就会闪退,而在高版本的测试机上是启动正常的(我们还要兼容iOS12😢)。

问题排查:

重现bug:

使用出现问题的测试机,用 Xcode 运行程序,app启动的时候崩溃了,错误信息如下:

dyld: Library not loaded: /usr/lib/swift/libswiftCoreGraphics.dylib
Referenced from: /private/var/containers/Bundle/Application/44A87AEC-6AA2-4377-9C82-9C3AB2D7794C/Demo.app/Frameworks/HandyJSON.framework/HandyJSON
Reason: image not found
Message from debugger: failed to send the k packet

提供的信息是:
HandyJSON 引用了 libswiftCoreGraphics.dylib 这个库,而动态链接库在 /usr/lib/swift/libswiftCoreGraphics.dylib 这个路径下找不到 libswiftCoreGraphics 库

bug分析:

既然说是 HandyJSON 引用了 libswiftCoreGraphics,那么先通过 otool 查看 HandyJSON 引用的库以及加载路径

otool -L HandyJSON二进制路径

42DE5612-8677-4BE2-84D2-9330C7F73200.png

找到了 libswiftCoreGraphics 项,也发现一个奇怪的现象,其它的Swift的标准库都是从 @rpath 路径加载的,而 libswiftCoreGraphics 是从 /usr/lib/swift/ 加载的,很显然现在问题是这个路径下没有这个库。
实际上,在 iOS 12.1 中,通过 @rpath 加载运行时库才是正常的,因为Swift的运行时库是在 Swift ABI稳定,在 iOS 12.2 之后才放在iOS系统内,而在之前都是需要把Swift运行时库嵌在app包内的。

image.png
那么解决方案应该就是让 libswiftCoreGraphics 加载路径变为和其它库一样,大概就是@rpath/libswiftCoreGraphics.dylib
这个看起来感觉应该是苹果的bug,于是我去苹果论坛搜了一下,找到了同样的问题 developer.apple.com/forums/thre…
同时Apple也给出了解决建议:

Apple.png

问题处理:

方案有了,就是在 Build Setting 的 Other Linker Flags 里加上-Wl,-weak-lswiftCoreGraphics
但是我们的工程的第三方库是通过CocoaPods管理的,CocoaPods是通过在xcconfig文件里设置OTHER_LDFLAGS来设置 Other Linker Flags ,如果直接手动改每个库的 Other Linker Flags,那么既费劲,而且无效,因为下次 pod install 又会还原。所以需要通过修改 pod install 的过程来在 OTHER_LDFLAGS里插入 -Wl,-weak-lswiftCoreGraphics。
于是网上搜了一下怎么修改 pod install,最终用的方法是在 Podfile 里面加上hook

def update_xcconfig(xcconfig_path, key, value)
  # read from xcconfig to build_settings dictionary
  build_settings = Hash[*File.read(xcconfig_path).lines.map{|x| x.delete!("\n").split(/\s*=\s*/, 2)}.flatten]
  
  # modify key
  if build_settings.has_key?(key)
    if build_settings[key].index(value) == nil
      build_settings[key] << value
    end
  else
    build_settings[key] = value
  end
  
  # write build_settings dictionary to xcconfig
  File.open(xcconfig_path, "w+") {|file|
    build_settings.each do |k, v|
      file.puts "#{k} = #{v}"
    end
  }
end

# post_install hook
post_install do |installer|
  installer.pods_project.targets.each do |target|
    target.build_configurations.each do |config|
      xcconfig_path = config.base_configuration_reference.real_path
      update_xcconfig(xcconfig_path, 'OTHER_LDFLAGS', ' -Wl,-weak-lswiftCoreGraphics')
    end
  end
end

重新 pod install,app能正常运行。再用otool查看库,加载路径也是正确的,问题解决。

after.png