【问题标题】:Xcode 12.3: Building for iOS Simulator, but the linked and embedded framework was built for iOS + iOS Simulator [duplicate]Xcode 12.3:为 iOS 模拟器构建,但链接和嵌入式框架是为 iOS + iOS 模拟器构建的 [重复]
【发布时间】:2020-12-15 09:39:08
【问题描述】:

我有一个使用链接和嵌入式自定义框架的应用。在 Xcode 12.2 之前,该应用程序为 iOS 设备和模拟器正确构建。但是,从 Xcode 12.3 开始,我收到以下错误:

Building for iOS Simulator, but the linked and embedded framework 'My.framework' was built for iOS + iOS Simulator.

该框架是为设备和模拟器构建的(正如错误实际上所说)并使用lipo 合并,因此它应该能够在任何地方运行而不会出现问题。

我在这里遗漏了什么吗? Xcode 12.3 有什么相关变化吗?

【问题讨论】:

  • 一个临时的解决方法(对我有用)是使用旧的构建系统stackoverflow.com/a/54058682
  • 另一种解决方法是将 BuildSettings ->"Validate Workspace" 设置为 Yes。它仍然会显示警告,但会构建项目。
  • “验证工作区”为 YES 对我有用!但是当我再次更改为 NO 时,它仍然有效。有什么想法吗?
  • @o15a3d4l11s2 使用此选项有什么影响?
  • @NicHubbard,这是一个相当棘手的案例。将其切换为“是”会导致预构建验证过程。在这种特殊情况下,它发现框架是“胖的”(内部包含 iOS 和模拟器架构)并产生验证警告。为什么这会有所帮助 - 因为现在这个问题是一个警告,它不会再次显示为错误。只有错误才会停止构建过程。总的来说,我建议将其作为临时解决方法,而不是永久解决方案。

标签: ios xcode12 lipo


【解决方案1】:

恐怕这实际上是正确的错误,框架不应该同时包含 iOS 和 iOS Simulator 代码。苹果试图强迫我们为此目的使用XCFrameworks。他们从 XCode 11 开始,只是收紧了限制。

解决此问题的唯一正确方法是将框架重建为XCFramework。这很容易做到:

$ xcrun xcodebuild -create-xcframework \
    -framework /path/to/ios.framework \
    -framework /path/to/sim.framework \
    -output combined.xcframework

您可以从组合 .framework 开始制作框架的两个副本,然后使用 lipo 从二进制文件中删除与不同 SDK 关联的切片。

基于 Apple here 的原始答案。

我的特殊情况是使用生成这些框架的 Rome 时遇到此错误(可能的解决方案是 here)。此外,Carthage side 上也有很多挣扎。

希望有所帮助;)

【讨论】:

  • 太好了,非常感谢。我目前正在使用一种解决方法,但我会在第一时间将我的框架重建为XCFramework。如果一切正常,我也会接受答案:)
  • 请查看我的回答 stackoverflow.com/a/65613941/1431182 以获得我现在使用的构建脚本,而不是旧的基于 lipo 的方法
  • xcrun xcodebuild -create-xcframework -framework /path/to/ios.framework -framework /path/to/sim.framework -output combined.xcframework
  • @alex-shubin 我面临下面提到的问题,我同时使用架构 arm64 和 armv7。 ravihmalviya@Mac-mini linphone-sdk % xcrun xcodebuild -create-xcframework \ -framework x86_64-apple-darwin.ios/Frameworks/bctoolbox-ios.framework \ -framework arm64-apple-darwin.ios/Frameworks/bctoolbox-ios。 framework \ -framework armv7-apple-darwin.ios/Frameworks/bctoolbox-ios.framework \ -output bctoolbox-ios.xcframework 错误 -> ios-arm64 和 ios-armv7 都代表两个等效的库定义。
  • 收到此错误:不支持具有多个平台的二进制文件
【解决方案2】:

在为模拟器构建时必须排除设备架构,在为设备构建时必须排除模拟器的架构。

为此,导航到您项目的Build Settings -> Excluded Architectures -> 选择配置(调试/发布/等...) -> 点击 + -> Any iOS Simulator SDK -> 添加arm64 , arm64e, armv7

同样,将x86_64i386 添加到Any iOS SDK

PS:您可以通过运行file <path_to_framework_binary>lipo -info <path_to_framework_binary> 来检查框架中存在的所有架构。

例如。 file /Users/srikanth.kv/MyProject/MyLibrary.framework/MyLibrary

【讨论】:

  • 看起来很有希望并且很有意义,但是在实施此解决方案时我仍然遇到相同的错误:-(
  • 对我不起作用。我猜在我同时运行 xcode 12.3 和 12.2 时还会发生其他事情。我可以在 12.2 上为设备和模拟器构建,但在代码 12.3 上构建设备或模拟器时出现错误。
  • 在将我的 iOS 应用程序构建为目标“我的 Mac 为 iPad 设计”的 M1 Mac 上对我不起作用,但验证工作区技巧是一个很好的解决方法。这个排除架构技巧确实适用于我基于 Intel 的 iMac Pro 上的同一个项目。
  • 只需选择 Any iOS Simulator SDK 而不在 TARGET(不是 PROJECT)部分插入任何值,就为我做了诀窍。
  • ...并在构建设置下的项目下搜索验证工作区,将调试设置为是。
【解决方案3】:

我有一个包含x86_64arm64 的通用二进制框架,我在框架构建时将其与lipo 与自定义脚本合并。我在 XCode 12.3 中遇到了同样的问题,现在已经创建了一个解决方法。希望这将很快在 XCode 中得到修复,但在那之前,一个快速的修复方法是精简架构并使用您需要的框架。编辑:请参阅my answer here on how to start producing .xcframeworks which is the long term solution for framework authors

例如,假设我在我的通用框架some_framework.framework 所在的工作目录中的终端中。如果我想在实际的物理设备上运行,我执行以下命令:

lipo -thin arm64 some_framework.framework/some_framework -output some_framework

使用上述命令,您可以提取 arm64 二进制文件。之后,将当前的some_framework.framework/some_framework 替换为新生成的arm64 only binary

mv some_framework some_framework.framework

如果您有一个仅由 Objective-C 源代码构建的通用框架,那么您的工作就完成了。但是,如果您也有 swift 代码,那么您需要更新 some_framework.framework/Modules/some_framework.swiftmodule,使其不包含对非 arm64 架构的任何引用。

除了需要x86_64 之外,您将遵循类似的过程在模拟器上运行。我目前正在维护我的框架的两个版本,直到这个问题得到修复。每当我在模拟器和设备之间切换时,我只需切换出我的项目中的框架。

【讨论】:

  • 感谢您的回答,这基本上就是我目前所做的。但是,这是一种有很多限制的解决方法...
  • @spass 好吧,直到导致不相信,我将假设这是最新 Xcode 中的一个错误,将在相对较短的时间内解决。除了不便之外,您认为其他“许多限制”是什么?
  • 是的,我也认为这是一个 Xcode 错误。第一个重要限制是,当不同的团队在框架和主应用程序上并行工作并且对代码具有隔离访问权限时,协调变得非常麻烦。另一个是它破坏了 CI 测试和分发管道
  • 很公平,如果我也有这些限制,那肯定是很差的限制。让我们希望 Apple 能快速解决问题:)
  • 这是对我有用的答案。在我的项目中,我正在导入一个 iOS+iOS 模拟器都支持的名为 Intercom 的框架。令人失望的是,这就是答案.. 新的 Xcode 更新集绝对可怕。无论如何谢谢@mistahenry
【解决方案4】:

除了@mistahenry 回答之外,您还可以使用此解决方法在您的项目中自动处理此问题。

  1. 将在 XCode 12.3 中不起作用的通用框架设置为 Do not embed(在常规 > 框架、库和嵌入式内容中)
  2. 在“构建阶段”中添加这个“新的运行脚本阶段”
FRAMEWORK_APP_PATH="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"

# 1. Copying FRAMEWORK to FRAMEWORK_APP_PATH
find "$SRCROOT" -name '*.framework' -type d | while read -r FRAMEWORK
do
if [[ $FRAMEWORK == *"MY_WONDERFUL_UNIVERSAL_FRAMEWORK.framework" ]]
then
    echo "Copying $FRAMEWORK into $FRAMEWORK_APP_PATH"
    cp -r $FRAMEWORK "$FRAMEWORK_APP_PATH"
fi
done
# 2. Loops through the frameworks embedded in the application and removes unused architectures.
find "$FRAMEWORK_APP_PATH" -name '*.framework' -type d | while read -r FRAMEWORK
do
if [[ $FRAMEWORK == *"MY_WONDERFUL_UNIVERSAL_FRAMEWORK.framework" ]]
then
     
    echo "Strip invalid archs on: $FRAMEWORK"
    FRAMEWORK_EXECUTABLE_NAME=$(/usr/libexec/PlistBuddy -c "Print CFBundleExecutable" "$FRAMEWORK/Info.plist")
    FRAMEWORK_EXECUTABLE_PATH="$FRAMEWORK/$FRAMEWORK_EXECUTABLE_NAME"
    echo "Executable is $FRAMEWORK_EXECUTABLE_PATH"
    EXTRACTED_ARCHS=()
    for ARCH in $ARCHS
    do
    echo "Extracting $ARCH from $FRAMEWORK_EXECUTABLE_NAME"
    lipo -extract "$ARCH" "$FRAMEWORK_EXECUTABLE_PATH" -o "$FRAMEWORK_EXECUTABLE_PATH-$ARCH"
    EXTRACTED_ARCHS+=("$FRAMEWORK_EXECUTABLE_PATH-$ARCH")
    done
    echo "Merging extracted architectures: ${ARCHS}"
    lipo -o "$FRAMEWORK_EXECUTABLE_PATH-merged" -create "${EXTRACTED_ARCHS[@]}"
    rm "${EXTRACTED_ARCHS[@]}"
    echo "Replacing original executable with thinned version"
    rm "$FRAMEWORK_EXECUTABLE_PATH"
    mv "$FRAMEWORK_EXECUTABLE_PATH-merged" "$FRAMEWORK_EXECUTABLE_PATH"
    codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS:-} --preserve-metadata=identifier,entitlements $FRAMEWORK_EXECUTABLE_PATH
else
    echo "Ignored strip on: $FRAMEWORK"
fi
done
  • MY_WONDERFUL_UNIVERSAL_FRAMEWORK 替换为您的框架名称,并确保它位于SRCROOT

【讨论】:

  • 酷!有没有办法自动执行第 1 步?
  • 有没有办法为 Xcode 12.3 中的所有(以前的)嵌入式框架执行此操作,而不是为每个框架单独设置这些变通运行脚本?
  • 我现在用这个方案,简单多了:stackoverflow.com/a/65306886/2003634
  • 为什么不直接通过input files list绑定框架名称?
猜你喜欢
  • 2021-05-30
  • 1970-01-01
  • 2020-07-07
  • 1970-01-01
  • 2022-01-08
  • 2020-11-25
  • 2022-06-23
  • 2021-04-09
  • 2022-07-02
相关资源
最近更新 更多