iOS问题记录 - Building for iOS Simulator, but linking in dylib built for iOS, for architecture arm64

这篇具有很好参考价值的文章主要介绍了iOS问题记录 - Building for iOS Simulator, but linking in dylib built for iOS, for architecture arm64。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


前言

最近用了一个第三方的Flutter插件,刚开始用项目运行到iOS模拟器就失败了。这个报错在老早以前出现的比较频繁,但是现在还出现属实不应该。

开发环境

  • Flutter: 3.7.11
  • Xcode: 14.3

问题描述

Flutter项目引入第三方插件后,在iOS模拟器运行项目报错:

Building for iOS Simulator, but linking in dylib built for iOS, file 'xxx' for architecture arm64

通过第三方插件ios目录下的xxx.podspec文件可知,这个插件依赖了一个Pod库(已编译的非开源库),插件的作用就是对Pod库进行二次封装。

问题分析

在XCFramework出来之前,第三方库(已编译的非开源库)不区分真机和模拟,都是通过lipo命令将真机库和模拟器库合并为一个库,合并后的库中,arm64架构的属于真机,x86_64架构的属于模拟器。

Apple Silicon M1芯片出来前不区分真机和模拟器没什么问题,因为iOS模拟器确实都是x86_64架构的。M系列芯片出来后,Xcode 12支持了arm64架构的iOS模拟器。然后问题来了,在M系列芯片电脑上,Xcode会默认使用arm64架构的iOS模拟器,项目构建时会链接第三方库中arm64架构的二进制文件,又由于arm64架构的二进制文件是属于真机的,如果第三方库是动态库,那么就会出现问题描述中的错误,如果第三方库是静态库,那么出现的错误是这样的:

building for iOS Simulator, but linking in object file built for iOS, file 'xxx' for architecture arm64

这问题已经出来很久了,第三方库的作者早已经做了处理。要么去支持XCFramework,要么在Podspec文件中加上:

# Pod库的构建设置排除arm64架构模拟器
s.pod_target_xcconfig = { 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'arm64' }
# 主工程的构建设置排除arm64架构模拟器
s.user_target_xcconfig = { 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'arm64' }

按道理来说,现在只要项目依赖的第三方库不是特别老的版本,基本不会遇到这种问题。不过我就是一个例外,同一个Flutter项目,连续在Intel芯片的Mac和M系列芯片的Mac遇到这个问题。

注意,以下分析基于Flutter插件,如果你是纯iOS开发,不了解也没有关系。因为Flutter插件只看iOS相关部分的话,就是一个Pod库,所以以下凡是涉及Flutter插件的都可以看作是Pod库。

1. Intel芯片的Mac上报错

首先对比已经引入的Flutter插件,没发现新引入的有什么问题。接着排查项目中涉及架构的构建设置,还真让我发现了一个问题,Pods工程中的Build Active Architecture Only设置有问题。正常情况下,多环境配置中的Dev环境(属于Debug环境)应该设为Yes,但是实际是No:

iOS问题记录 - Building for iOS Simulator, but linking in dylib built for iOS, for architecture arm64,问题记录,iOS,ios,flutter,xcode

那么问题的原因是这个吗?当Build Active Architecture Only设为No时,Xcode构建项目不会局限于当前设备所支持的架构,通常用于Release环境,毕竟打的正式包一般不可能只在当前设备运行;设为Yes时,Xcode构建项目只会基于当前设备所支持的架构。

当前电脑是x86_64架构的,也就是说只支持x86_64架构的iOS模拟器,Build Active Architecture Only设为No意味着Xcode项目构建时将不限于x86_64架构,还会构建arm64架构的。这么一分析,好像确实如此。手动修改设置为Yes,项目重新运行到模拟器,一切正常!

手动修改肯定是不靠谱的,一开始遇到这个问题的时候,没想那么多,直接像这样在Podfile文件中通过Hook匹配构建配置名称将ONLY_ACTIVE_ARCH的值设为YES

post_install do |installer|
  installer.pods_project.build_configurations.each do |config|
    if config.name == 'Dev'
      config.build_settings['ONLY_ACTIVE_ARCH'] = 'YES'
      break
    end
  end
end

后来研究Flutter & iOS问题记录 - 多环境配置下Pod库的宏定义失效问题时,发现完全没必要用Hook,在Podfile文件中给多环境配置映射正确的配置类型才是正常的做法:

project 'app', {
  'Dev' => :debug,
  'Pre' => :release,
  'Prod' => :release,
}

这里有一个很重要的问题当时被我忽略了,在引入这个第三方Flutter插件之前已经引入了不少其他第三方Flutter插件,但是之前都没有报错,所以这个新引入的Flutter插件还是可能有问题的。如果后面没有再次遇到这个问题,我还真以为这个问题已经被彻底解决。

2. M系列芯片的Mac上报错

为了方便调试和分析,新建一个Flutter项目,同时参考报错的第三方Flutter插件也新建一个,就叫test_plugin。运行测试项目到iOS模拟器,问题成功复现,找到构建日志:

iOS问题记录 - Building for iOS Simulator, but linking in dylib built for iOS, for architecture arm64,问题记录,iOS,ios,flutter,xcode

咦,怪不得报错,竟然会针对arm64架构进行编译链接。针对arm64架构编译不报错是因为这是源码编译,无所谓什么架构,链接报错是因为被链接的库(Flutter插件依赖的第三方库)不支持arm64架构的iOS模拟器。

找到test_plugin的构建设置:

iOS问题记录 - Building for iOS Simulator, but linking in dylib built for iOS, for architecture arm64,问题记录,iOS,ios,flutter,xcode

模拟器竟然没有排除arm64架构,这是怎么回事?打开test_plugin.podspec文件发现了问题:

s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'VALID_ARCHS[sdk=iphonesimulator*]' => 'x86_64' }

VALID_ARCHS设置已经过时失效,现在应该用EXCLUDED_ARCHS设置。关于这些构建设置的使用可以参考文档:TN3117: Resolving architecture build errors on Apple silicon。

iOS问题记录 - Building for iOS Simulator, but linking in dylib built for iOS, for architecture arm64,问题记录,iOS,ios,flutter,xcode

看来这报错的Flutter插件的创建时间有点久远了,从Flutter框架项目的提交记录看,在2020年Podspec文件模板已经开始改用EXCLUDED_ARCHS设置:

iOS问题记录 - Building for iOS Simulator, but linking in dylib built for iOS, for architecture arm64,问题记录,iOS,ios,flutter,xcode

不过,改用新模板的设置能解决问题吗?看这也没排除arm64架构。

s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' }

改为这个实测不行。在设置中的i386的后面加上arm64

s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386 arm64' }

再次运行,弹出了这个:

iOS问题记录 - Building for iOS Simulator, but linking in dylib built for iOS, for architecture arm64,问题记录,iOS,ios,flutter,xcode

点击Build for Rosetta确实也能正常运行,如果想切换回原来的目标设备列表,按这个步骤[Xcode菜单栏] -> [Product] -> [Destination] -> [Destination Architectures] -> [Show Apple Silicon Destinations]操作。

虽然能运行,但是不想用Rosetta怎么办?很好解决,在主工程的构建设置中设置排除arm64架构的模拟器。有两种设置方式:

  1. 手动设置

iOS问题记录 - Building for iOS Simulator, but linking in dylib built for iOS, for architecture arm64,问题记录,iOS,ios,flutter,xcode

  1. 通过Flutter插件的Podspec文件设置
s.user_target_xcconfig = { 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'arm64' }

注意,低版本的iOS模拟器只支持Rosetta,至于具体到多低的版本,推测是低于iOS 14的版本,因为iOS 14/Xcode 12/M1芯片都是2020年发布的。

可以通过file命令查看iOS模拟器支持的架构,例如查看Xcode 14.3内置的iOS模拟器:

file /Applications/Xcode.app/Contents/Developer/Applications/Simulator.app/Contents/MacOS/Simulator

执行输出:

/Applications/Xcode.app/Contents/Developer/Applications/Simulator.app/Contents/MacOS/Simulator: Mach-O universal binary with 2 architectures: [x86_64:Mach-O 64-bit executable x86_64] [arm64]
/Applications/Xcode.app/Contents/Developer/Applications/Simulator.app/Contents/MacOS/Simulator (for architecture x86_64):	Mach-O 64-bit executable x86_64
/Applications/Xcode.app/Contents/Developer/Applications/Simulator.app/Contents/MacOS/Simulator (for architecture arm64):	Mach-O 64-bit executable arm64

从输出内容可以看到, iOS 16.4模拟器同时支持x86_64和arm64架构。如果是 iOS 12.4模拟器,输出是这样的:

/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 12.4.simruntime/Contents/MacOS/iOS 12.4: Mach-O 64-bit bundle x86_64

iOS 12.4模拟器只支持x86_64架构,如果只显示Apple Silicon Destinations列表会出现找不到iOS 12.4模拟器的情况。建议按这个步骤[Xcode菜单栏] -> [Product] -> [Destination] -> [Destination Architectures] -> [Show Both]操作,显示全部iOS模拟器。

问题分析到这还没完,为什么其他还用着VALID_ARCHS设置的Flutter插件没报错呢?

3. 动态库引起的报错

对比多个Flutter插件的构建日志,我发现了报错的另一个原因,竟然是因为动态库。

Flutter插件报错时的构建日志:

iOS问题记录 - Building for iOS Simulator, but linking in dylib built for iOS, for architecture arm64,问题记录,iOS,ios,flutter,xcode

test_plugin.podspec文件中加上这行代码指定为静态库:

s.static_framework = true

重新构建的日志:

iOS问题记录 - Building for iOS Simulator, but linking in dylib built for iOS, for architecture arm64,问题记录,iOS,ios,flutter,xcode

一切正常!构建静态库时只编译不链接,避免了链接报错。等到构建APP时,由于主工程的构建设置中已经排除了arm64架构,所以只会基于x86_64架构构建,这时链接也不会报错。

虽然可以通过将动态库修改为静态库这种方式来解决问题,但这个问题本质还是架构相关的问题,所以还是围绕架构来解决。

解决方案

这里提供三个解决方法,请根据需要任选一个即可:

  1. iOS模拟器排除arm64架构(设置Pods项目的构建设置)

Podfile文件中加上:

post_install do |installer|
  installer.pods_project.build_configurations.each do |config|
    config.build_settings['EXCLUDED_ARCHS[sdk=iphonesimulator*]'] = 'arm64'
  end
end

这个方法只适用于解决因为使用过时VALID_ARCHS设置导致的报错。如果本身使用的是EXCLUDED_ARCHS设置,又没有加上$(inherited),会导致这个方法失效。例如Podspec文件这样设置:

s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' }

会因为优先级问题,无法生效:

iOS问题记录 - Building for iOS Simulator, but linking in dylib built for iOS, for architecture arm64,问题记录,iOS,ios,flutter,xcode

  1. iOS模拟器排除arm64架构(设置Target的构建设置)
  • iOS项目在Podfile文件中加上:
post_install do |installer|
  installer.pods_project.targets.each do |target|
    target.build_configurations.each do |config|
      excluded_archs = config.build_settings['EXCLUDED_ARCHS[sdk=iphonesimulator*]']
      excluded_archs = excluded_archs.nil? ? '' : excluded_archs
      if !excluded_archs.include?('arm64')
        excluded_archs = "#{excluded_archs} arm64"
      end
      config.build_settings['EXCLUDED_ARCHS[sdk=iphonesimulator*]'] = excluded_archs
    end
  end
end
  • Flutter项目在Podfile文件中加上:
post_install do |installer|
  installer.pods_project.targets.each do |target|
    flutter_additional_ios_build_settings(target)
    target.build_configurations.each do |config|
      excluded_archs = config.build_settings['EXCLUDED_ARCHS[sdk=iphonesimulator*]']
      excluded_archs = excluded_archs.nil? ? '' : excluded_archs
      if !excluded_archs.include?('arm64')
        excluded_archs = "#{excluded_archs} arm64"
      end
      config.build_settings['EXCLUDED_ARCHS[sdk=iphonesimulator*]'] = excluded_archs
    end
  end
end

根据EXCLUDED_ARCHS设置的值决定要不要追加排除arm64架构,如果值中已经有了arm64便不做改动。由于是设置Target的构建设置,优先级高,所以不会出现第一个方法中的问题。注意,尽量不要整个直接复制粘贴,请根据项目的实际情况修改。如有疑问,欢迎留言评论。

  1. 设置需要构建的架构(终极方法

Podfile文件中加上:

post_install do |installer|
  installer.pods_project.build_configurations.each do |config|
    config.build_settings['ARCHS[sdk=iphonesimulator*]'] = 'x86_64'
  end
end

这段代码的作用是设置iOS模拟器只构建x86_64架构,专治各种关于架构的问题,你值得拥有。

注意:修改Podfile文件后,需要重新执行pod install命令让改动生效。

2023/08/14更新:

如果以上三个解决方法都没能解决你的问题,请检查主工程的构建设置中是否设置了排除arm64架构的模拟器:

iOS问题记录 - Building for iOS Simulator, but linking in dylib built for iOS, for architecture arm64,问题记录,iOS,ios,flutter,xcode

如果没有设置,手动设置即可。

补充内容1

你可能还会遇到以下问题:

  • Undefined symbol: _OBJC_CLASS_$_xxx

出现这个问题的原因有两种。一是被链接的库(开源库)没有排除arm64架构,默认只编译了arm64架构,而第三方库排除了arm64架构,只编译x86_64架构;二是被链接的库(开源库)排除了arm64架构,只编译x86_64架构,但是第三方库没排除arm64架构。这叫什么?这叫互相错过,爱而不得。

  • Unsupported Swift architecture

根据构建日志,可以找到报错的文件xxx-Swift.h,内容是这样的:

#if 0
#elif defined(__arm64__) && __arm64__
...
#else
#error unsupported Swift architecture
#endif

看到__arm64__,基本可以确定也是架构的问题。找到报错库的Podspec文件修改为排除arm64架构,重新构建不再报错,文件xxx-Swift.h的内容变为这样:

#if 0
#elif defined(__x86_64__) && __x86_64__
...
#else
#error unsupported Swift architecture
#endif

以上问题都是关于架构的同一类问题,具体解决方法请看前面。

补充内容2

从前面的问题分析可知,现在的iOS模拟器同时支持x86_64和arm64架构,那么该如何判断当前运行的模拟器是哪个架构的呢?可以通过打印设备型号判断:

  • Objective-C
#import <sys/utsname.h>
struct utsname systemInfo;
uname(&systemInfo);
NSLog(@"machine: %@", @(systemInfo.machine));
  • Swift
var systemInfo = utsname()
uname(&systemInfo)
let machine = withUnsafePointer(to: &systemInfo.machine.0) { ptr in
    return String(cString: ptr)
}
print("machine: \(machine)")

如果打印结果为machine: x86_64,说明当前运行的是x86_64架构的iOS模拟器;如果打印结果为machine: arm64,说明是arm64架构的iOS模拟器。

补充内容3

如果运行项目时遇到以下问题:

/xxx/Pods-xxx-frameworks.sh: line 132: ARCHS[@]: unbound variable

可能是因为在[Build Settings] -> [Architectures] -> [Excluded Architectures]设置中将目标设备支持的架构排除了,例如运行项目到真机,但是排除了arm64架构,修改设置可以解决该问题。

最后

如果这篇文章对你有所帮助,点赞👍收藏🌟支持一下吧,谢谢~


本篇文章由@crasowas发布于CSDN。文章来源地址https://www.toymoban.com/news/detail-611658.html

到了这里,关于iOS问题记录 - Building for iOS Simulator, but linking in dylib built for iOS, for architecture arm64的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 记录mybatis插件奇怪报错问题There is no getter for property named ‘delegate‘ in ‘class com.sun.proxy.$Proxy的排查

    一、背景描述 项目要求update/delete必须要有where条件(因为出了一次生产上把一张表的数据全表删除的严重生产事故),并且要打印出where中的条件,所以考虑用mybatis拦截器处理 mybatis拦截器实现原理简述 在Mybatis中,拦截器可拦截如上图中四种相关操作类的操作方法。通过阅读源

    2024年01月16日
    浏览(52)
  • MySQL启动时出现initialize specified but the data directory has files in it. Aborting问题

    你是否遇见以下问题在MySQL重启时出现问题,报出了以下的错误,现在我将告诉你遇见以下错误怎么处理。 当出现了上面的错误,我们可以看出它提供了两条命令“systemctl status mysqld.service”和“journalctl -xe”来帮助我们来查看错误的详情。 使用“systemctl status mysqld.service”命

    2024年02月16日
    浏览(41)
  • 【IOS】Xcode 15.2版本下载 iOS_17 Simulator失败

    Xcode更新15.2自身不带iOS_17 Simulator模拟器的,然而在使用自带的get下载安装会一直在40进度左右出现因为网络问题安装失败的情况,一般这种情况在断点处重试安装也还好,但是每次重试都是需要重新下载,因为本身下载又很慢,又总是在40左右出现此问题,所以只能尝试自行

    2024年02月20日
    浏览(75)
  • iOS学习 --- Xcode 15 下载iOS_17.0.1_Simulator失败解决方法

    1.去开发者官网下载安装包 https://developer.apple.com/download/all/?q=iOS%2017 使用浏览器下载。 2.打开终端通过命令添加到xcode 命令如下: sudo xcode-select -s /Applications/Xcode.app(输入开始密码) xcodebuild -runFirstLaunch (等待一小会) xcrun simctl runtime add \\\"/Users/xxxxx/Downloads/iOS_17.0.1_Simulator_Runtime

    2024年02月05日
    浏览(47)
  • xcode iOS 17.2 not install, Simulator 手动安装

    参考文档 xcode又又又升级了,升级完成之后不下载最新的 iOS 17 Simulator就不能编译运行了,只能静静的等他下载。但是离谱的是这个居然没有断点续下,每次都要重新下载,眼睁睁的看着下载了4个G然后断掉了从头再来。 自动挡不太行还是要切回手动档模式了。 苹果有个下载

    2024年02月04日
    浏览(54)
  • mac使用Simulator打开IOS模拟器(不使用Xcode打开IOS模拟器)

    提示:打开模拟器的前提必须是安装了Xcode。 在mac电脑上有Xcode可以用来模拟不同类型的手机进行来解决ios兼容问题,这里记录一下不使用Xcode打开ios模拟器的方法 快捷键:command+空格。搜索simulator,第一个就是模拟器 使用以下命令打开模拟器 结果如下图

    2024年02月15日
    浏览(54)
  • 解决更新Xcode 15.2后,下载 iOS_17 Simulator失败

    更新到最新的xcode后,自动下载Simulator总是失败。 解决方法如下: 从官网直接下载: 打开https://developer.apple.com/download/all/?q=ios 下载:IOS 17.2 Simulator Runtime.dmg安装文件 手动安装

    2024年01月20日
    浏览(45)
  • Xcode15 iOS 17 Simulator 离线安装,模拟器安装

    Xcode 15 安装包的大小相比之前更小,因为除了 macOS 的 Components,其他都需要动态下载安装,否则提示 iOS 17 Simulator Not Installed。 如果不安装对应的运行模拟库 无法真机和模拟器运行,更无法新建项目。但是由于模拟器安装包过大且不支持断点续传,在经历了在线安装 N 次失败

    2024年02月03日
    浏览(49)
  • 关于ios Universal Links apple-app-site-association文件 Not Found的问题

    Support Universal Links 里面有说到 Universal Links 是什么、注意点、以及如何配置的。简单来说就是 当您支持通用链接时,iOS 用户可以点击指向您网站的链接,并无缝重定向到您安装的应用程序 大白话就是说,用户通过点击某个链接,可以直接唤起对应的app。提供这样功能的目的

    2024年02月11日
    浏览(42)
  • swsim: A C++ Simulator for Digital Circuits

    Swsim is an open-source digital circuit simulator written in C++. It allows users to design, simulate and verify digital circuits using a simple and intuitive graphical interface. The project is available on GitCode. Swsim is a software tool that enables users to simulate the behavior of digital circuits. It supports various digital logic gates, flip-flops,

    2024年03月10日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包