Xcode 12.3:为 iOS 模拟器构建,但链接和嵌入式框架是为 iOS + iOS 模拟器构建的
Xcode 12.3: Building for iOS Simulator, but the linked and embedded framework was built for iOS + iOS Simulator
我有一个使用链接和嵌入式自定义框架的应用程序。在 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 是否有任何相关变化?
我有一个包含通用二进制文件的框架,其中包含 x86_64
和 arm64
,我在框架构建时使用自定义脚本将其与 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
之外,您将在模拟器上对 运行ning 执行类似的过程。在修复之前,我目前正在维护我的框架的两个版本。每当我在模拟器和设备之间切换时,我只需切换出我项目中的框架。
在为模拟器构建时必须排除设备架构,而在为设备构建时必须排除模拟器的架构。
为此,导航到项目的 Build Settings
-> Excluded Architectures
-> Select 配置(Debug/Release/Etc...) -> 点击 + - > Any iOS Simulator SDK
-> 添加 arm64
、arm64e
、armv7
同样,将x86_64
、i386
添加到Any iOS SDK
。
PS:您可以通过 运行 file <path_to_framework_binary>
或 lipo -info <path_to_framework_binary>
.
检查框架中存在的所有架构
例如。 file /Users/srikanth.kv/MyProject/MyLibrary.framework/MyLibrary
除了@mistahenry 的回答之外,您还可以使用此解决方法在您的项目中自动处理此问题。
- 将在 XCode 12.3 中不起作用的通用框架设置为
Do not embed
(在常规 > 框架、库和嵌入式内容中)
- 在“构建阶段”中添加此“新 运行 脚本阶段”
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
恐怕这实际上是正确的错误,框架不应同时包含 iOS 和 iOS 模拟器代码。 Apple 试图强迫我们为此目的使用 XCFramework
s。他们在 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). Also, a lot of struggling is going on on the Carthage side。
希望对您有所帮助 ;)
我有一个使用链接和嵌入式自定义框架的应用程序。在 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 是否有任何相关变化?
我有一个包含通用二进制文件的框架,其中包含 x86_64
和 arm64
,我在框架构建时使用自定义脚本将其与 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
之外,您将在模拟器上对 运行ning 执行类似的过程。在修复之前,我目前正在维护我的框架的两个版本。每当我在模拟器和设备之间切换时,我只需切换出我项目中的框架。
在为模拟器构建时必须排除设备架构,而在为设备构建时必须排除模拟器的架构。
为此,导航到项目的 Build Settings
-> Excluded Architectures
-> Select 配置(Debug/Release/Etc...) -> 点击 + - > Any iOS Simulator SDK
-> 添加 arm64
、arm64e
、armv7
同样,将x86_64
、i386
添加到Any iOS SDK
。
PS:您可以通过 运行 file <path_to_framework_binary>
或 lipo -info <path_to_framework_binary>
.
例如。 file /Users/srikanth.kv/MyProject/MyLibrary.framework/MyLibrary
除了@mistahenry 的回答之外,您还可以使用此解决方法在您的项目中自动处理此问题。
- 将在 XCode 12.3 中不起作用的通用框架设置为
Do not embed
(在常规 > 框架、库和嵌入式内容中) - 在“构建阶段”中添加此“新 运行 脚本阶段”
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
恐怕这实际上是正确的错误,框架不应同时包含 iOS 和 iOS 模拟器代码。 Apple 试图强迫我们为此目的使用 XCFramework
s。他们在 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). Also, a lot of struggling is going on on the Carthage side。
希望对您有所帮助 ;)