Xcode 12.3:为 iOS 模拟器构建,但链接和嵌入式框架是为 iOS + iOS 模拟器构建的

spa*_*sas 152 ios lipo xcode12

我有一个使用链接和嵌入式自定义框架的应用程序。该应用程序在 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 是否有任何相关更改?

Ale*_*bin 60

恐怕这实际上是正确的错误,框架不应同时包含 iOS 和 iOS 模拟器代码。Apple 试图强迫我们为此使用XCFrameworks。他们在 XCode 11 中启动了它,只是收紧了限制。

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

$ xcrun xcodebuild -create-xcframework \
    -framework /path/to/ios.framework \
    -framework /path/to/sim.framework \
    -output combined.xcframework
Run Code Online (Sandbox Code Playgroud)

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

基于 Apple here的原始答案。

我的特殊情况是我在使用 Rome 时遇到了这个错误,它产生了这些框架(一个可能的解决方案是here)。此外,迦太基方面正在发生很多挣扎。

希望有帮助;)


Sri*_*nth 25

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

要做到这一点,导航到Build Settings你的项目- > Excluded Architectures- >选择配置(调试/发布/等) - >点击+ - > Any iOS Simulator SDK- >添加arm64arm64earmv7

同样,将x86_64,添加i386Any iOS SDK

在此处输入图片说明

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

前任。 file /Users/srikanth.kv/MyProject/MyLibrary.framework/MyLibrary

  • 看起来很有希望并且有意义,但在实现此解决方案时我仍然遇到相同的错误:-( (17认同)
  • ...并在“构建设置”下的“项目”下搜索“验证工作区”,将“调试”设置为“是”。 (7认同)
  • 只需选择“任何 iOS 模拟器 SDK”,而不在“目标”(不是“项目”)部分插入任何值,就可以解决我的问题。 (3认同)
  • 对我不起作用。我猜当我同时运行 xcode 12.3 和 12.2 时,还会发生其他事情。我可以在 12.2 上构建设备和模拟器,但在代码 12.3 上构建设备或模拟器时出现错误。 (2认同)

mis*_*nry 23

我有一个包含通用二进制的框架x86_64arm64我与合并lipo与框架构建时自定义脚本。我在 XCode 12.3 中遇到了同样的问题,现在已经创建了一个解决方法。希望这会很快在 XCode 中得到修复,但在那之前,一个快速的修复方法是精简架构并使用您需要的框架。编辑:请在此处查看我关于如何开始生成 .xcframeworks 的答案,这是框架作者的长期解决方案

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

lipo -thin arm64 some_framework.framework/some_framework -output some_framework
Run Code Online (Sandbox Code Playgroud)

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

mv some_framework some_framework.framework
Run Code Online (Sandbox Code Playgroud)

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

除了需要x86_64. 我目前正在维护我的框架的两个版本,直到这个问题得到解决。每当我在模拟器和设备之间切换时,我只需切换出我的项目中的框架。


小智 21

除了@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
Run Code Online (Sandbox Code Playgroud)
  • 替换MY_WONDERFUL_UNIVERSAL_FRAMEWORK为您的框架的名称,并确保它位于SRCROOT

  • 我现在使用这个解决方案,它更简单、更方便:/sf/answers/4571482051/ (8认同)