简体   繁体   中英

Can't compile Simulator build with Universal (fat) Framework built with Xcode 10.2+

I can't compile application for Simulator (Device compiles successfully) which use Universal (fat) Framework built with Xcode 10.2+. Application use the Framework from Objective-C code. When switching from build for Device to build for Simulator Xcode stops to recognize any classes and other entities from the Framework so it doesn't compile (but in Swift files Framework classes recognized properly).

My script to create Universal Framework is similar to https://gist.github.com/sundeepgupta/3ad9c6106e2cd9f51c68cf9f475191fa (in general all such scripts use almost same logic and mostly differs by variable naming).

REASON

The real reason for this issue is in Xcode compiler. Starting Xcode 10.2 Apple changed generator of Framework swift header (MyFramework.framework/Headers/MyFramework-Swift.h). Now it adds lines like

#elif defined(__x86_64__) && __x86_64__
#elif defined(__i386__) && __i386__

to simulator header and

#elif defined(__arm64__) && __arm64__
#elif defined(__ARM_ARCH_7A__) && __ARM_ARCH_7A__

to device header.

So headers for simulator and device become different. Because general script for universal framework building copy header from device build directory then such framework works fine with device build but fails with Simulator builds.

Apple discover this issue in the Xcode 10.2 release notes Known Issues chapter and suggests a solution.

SOLUTION

Solution to resolve the issue mentioned by Apple is to create combined header which should include both original headers from device and simulator:

#include <TargetConditionals.h>
#if TARGET_OS_SIMULATOR
<contents of original iOS Simulator/Framework.framework/Framework-Swift.h>
#else
<contents of original iOS/Framework.framework/Framework-Swift.h>
#endif

Regarding mentioned script to make fat Framework you could modify it in next way:

# Step 5. Convenience step to copy the framework to the project's directory
cp -R "${UNIVERSAL_OUTPUT_DIR}/${PRODUCT_NAME}.framework" "${RELEASE_DIR}"

# Step 6. Combine PRODUCT_NAME-Swift.h from device and simulator architectures (Xcode 10.2 issue: 48635615)
UNIVERSAL_SWIFT_HEADER=${UNIVERSAL_OUTPUT_DIR}/${PRODUCT_NAME}.framework/Headers/${PRODUCT_NAME}-Swift.h

> ${UNIVERSAL_SWIFT_HEADER}
echo "#include <TargetConditionals.h>" >> ${UNIVERSAL_SWIFT_HEADER}
echo "#if TARGET_OS_SIMULATOR" >> ${UNIVERSAL_SWIFT_HEADER}
cat ${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${PRODUCT_NAME}.framework/Headers/${PRODUCT_NAME}-Swift.h >> ${UNIVERSAL_SWIFT_HEADER}
echo "#else" >> ${UNIVERSAL_SWIFT_HEADER}
cat ${BUILD_DIR}/${CONFIGURATION}-iphoneos/${PRODUCT_NAME}.framework/Headers/${PRODUCT_NAME}-Swift.h >> ${UNIVERSAL_SWIFT_HEADER}
echo "#endif" >> ${UNIVERSAL_SWIFT_HEADER}    

# Step 7. Convenience step to open the project's directory in Finder
open "${RELEASE_DIR}"

Line > ${UNIVERSAL_SWIFT_HEADER} needed to clear copied header in step 2 before combine started.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM