Xcode 12.3: Building for iOS Simulator, but the linked and embedded framework was built for iOS + iOS Simulator [duplicate]

二次信任 提交于 2020-12-27 07:52:28

问题


I have an app using a linked and embedded custom framework. The app built properly for iOS devices and simulators until Xcode 12.2. Starting from Xcode 12.3 however, I'm getting the following error:

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

The framework is built for both devices and simulators (as the error actually says) and merged using lipo, so it should be able to run everywhere without issues.

Am I missing something here? Is there any relevant change on Xcode 12.3?


回答1:


I'm afraid that this is actually the correct error and the framework shouldn't contain iOS and iOS Simulator code at the same time. Apple tries to force us to use XCFramework for this purpose. They started it in XCode 11 and just tightened up the restrictions.

The only correct way to resolve this is to rebuild the framework as an XCFramework.

Based on the original answer from Apple here.

My particular case is that I'm getting this error using Rome, which produces these frameworks. Also, a lot of struggling is going on the Carthage side.

Hope that helps ;)




回答2:


You have to exclude device architectures while building for simulator and while building for the device you have to exclude simulator's architectures.

To do that, navigate to Build Settings of your project -> Excluded Architectures -> Select the configuration(Debug/Release/Etc...) -> Tap + -> Any iOS Simulator SDK -> Add arm64, arm64e, armv7

Similarly, add x86_64, i386 to Any iOS SDK.

PS: You can check all the architectures which are present in your framework by running file <path_to_framework_binary> or lipo -info <path_to_framework_binary>.

Ex. file /Users/srikanth.kv/MyProject/MyLibrary.framework/MyLibrary




回答3:


I have a framework with universal binary that contains x86_64 and arm64 which I merge with lipo with a custom script at framework build time. I encountered this same issue for XCode 12.3 and have created a work around for now. Hopefully this will get fix in XCode quickly, but until then, one quick fix would be to thin the architectures and use the framework that you need.

For instance, let's assume I'm in a terminal in the working directory where my universal framework some_framework.framework is. If I want to run on an actual physical device, I execute the following command:

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

With the above command, you extract the arm64 binary. Afterwards, replace the current some_framework.framework/some_framework with the newly generated arm64 only binary

mv some_framework some_framework.framework

If you have a universal framework built only from Objective-C sources, your job is done. But if you've got swift code too, then you would need to update some_framework.framework/Modules/some_framework.swiftmodule so that it does not contain any references to architectures that are not arm64.

You would follow a similar process for running on the simulator except that you need x86_64. I'm currently now maintaining two versions of my framework until this is fixed. Whenever I switch between the simulator and the device, I simply switch out which framework is in my project.




回答4:


In addition to @mistahenry answer you can handle this automatically in yout project with this workaround.

  1. Set your Universal framework that does not work in XCode 12.3 to Do not embed (in General > Frameworks, Libraries and Embedded Content)
  2. Add this "new run script phase" in "Build Phases"
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
  • Replace MY_WONDERFUL_UNIVERSAL_FRAMEWORK by the name of your framework and be sure that it is located at SRCROOT


来源:https://stackoverflow.com/questions/65303304/xcode-12-3-building-for-ios-simulator-but-the-linked-and-embedded-framework-wa

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!