无法使用 Xcode 10.2+ 构建的通用(胖)框架编译模拟器构建
Can't compile Simulator build with Universal (fat) Framework built with Xcode 10.2+
我无法为使用 Xcode 10.2+ 构建的通用(胖)框架的模拟器(设备编译成功)编译应用程序。应用程序使用 Objective-C 代码中的框架。当从设备构建切换到模拟器构建时 Xcode 停止识别框架中的任何 类 和其他实体,因此它不会编译(但在 Swift 文件中框架 类正确识别)。
我创建 Universal Framework 的脚本类似于 https://gist.github.com/sundeepgupta/3ad9c6106e2cd9f51c68cf9f475191fa(一般来说,所有此类脚本都使用几乎相同的逻辑,并且主要因变量命名而不同)。
原因
此问题的真正原因在于 Xcode 编译器。开始 Xcode 10.2 Apple 更改了 Framework swift header (MyFramework.framework/Headers/MyFramework-Swift.h) 的生成器。现在它添加了像
这样的行
#elif defined(__x86_64__) && __x86_64__
#elif defined(__i386__) && __i386__
到模拟器 header 和
#elif defined(__arm64__) && __arm64__
#elif defined(__ARM_ARCH_7A__) && __ARM_ARCH_7A__
到设备 header。
所以 header 模拟器和设备变得不同。
因为通用框架构建的通用脚本从设备构建目录复制 header,所以这样的框架在设备构建时工作正常,但在模拟器构建时失败。
Apple 在 Xcode 10.2 release notes 已知问题章节中发现了这个问题并提出了解决方案。
解决方案
解决 Apple 提到的问题的方法是创建组合 header,其中应包括来自设备和模拟器的原始 header:
#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
关于上面提到的制作 fat Framework 的脚本,您可以通过以下方式修改它:
# 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}"
第 > ${UNIVERSAL_SWIFT_HEADER}
行需要清除在步骤 2 中复制的 header
在联合收割机开始之前。
我无法为使用 Xcode 10.2+ 构建的通用(胖)框架的模拟器(设备编译成功)编译应用程序。应用程序使用 Objective-C 代码中的框架。当从设备构建切换到模拟器构建时 Xcode 停止识别框架中的任何 类 和其他实体,因此它不会编译(但在 Swift 文件中框架 类正确识别)。
我创建 Universal Framework 的脚本类似于 https://gist.github.com/sundeepgupta/3ad9c6106e2cd9f51c68cf9f475191fa(一般来说,所有此类脚本都使用几乎相同的逻辑,并且主要因变量命名而不同)。
原因
此问题的真正原因在于 Xcode 编译器。开始 Xcode 10.2 Apple 更改了 Framework swift header (MyFramework.framework/Headers/MyFramework-Swift.h) 的生成器。现在它添加了像
这样的行#elif defined(__x86_64__) && __x86_64__
#elif defined(__i386__) && __i386__
到模拟器 header 和
#elif defined(__arm64__) && __arm64__
#elif defined(__ARM_ARCH_7A__) && __ARM_ARCH_7A__
到设备 header。
所以 header 模拟器和设备变得不同。 因为通用框架构建的通用脚本从设备构建目录复制 header,所以这样的框架在设备构建时工作正常,但在模拟器构建时失败。
Apple 在 Xcode 10.2 release notes 已知问题章节中发现了这个问题并提出了解决方案。
解决方案
解决 Apple 提到的问题的方法是创建组合 header,其中应包括来自设备和模拟器的原始 header:
#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
关于上面提到的制作 fat Framework 的脚本,您可以通过以下方式修改它:
# 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}"
第 > ${UNIVERSAL_SWIFT_HEADER}
行需要清除在步骤 2 中复制的 header
在联合收割机开始之前。