是否可以使用位码创建通用的iOS框架?

10
据我所了解,位码允许生成带有中介二进制格式的二进制文件。 因此,它是编译为ARM或x64架构之前的步骤。
自iOS 8以来,可以创建“真实”的.framework 文件。但是,默认情况下,框架文件仅为一个体系结构编译而成(模拟器,iPhone)。当想要分发.framework 文件时,最好提供适用于iOS模拟器并可部署到iPhone的文件。可以找到不同的脚本示例来使用lipo 创建这样的fat文件。
但是,是否可能仅分发作为位码编译的.framework 而无需创建具有不同架构的fat文件?
不幸的是,即使启用了我的.framework 的位码:
  • 默认情况下根据目标架构创建不同的文件
  • 即使框架目标似乎启用了“存档”菜单,我也找不到结果,即使在我的组织者视图中
我在位码的概念上有什么误解,还是我错过了什么?
2个回答

10
您需要提供一个通用的平面框架,该框架是由lipo创建的。
  • 启用位代码:目标->构建设置->启用位代码
  • 添加构建目标以创建通用框架

    创建一个聚合目标,并将以下脚本复制到构建阶段->运行脚本

    ######################
    # Options
    ######################
#verbose set -x
REVEAL_ARCHIVE_IN_FINDER=false FRAMEWORK_NAME="${PROJECT_NAME}"
SIMULATOR_LIBRARY_PATH="${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${FRAMEWORK_NAME}.framework"
DEVICE_LIBRARY_PATH="${BUILD_DIR}/${CONFIGURATION}-iphoneos/${FRAMEWORK_NAME}.framework"
UNIVERSAL_LIBRARY_DIR="${BUILD_DIR}/${CONFIGURATION}-iphoneuniversal"
FRAMEWORK="${UNIVERSAL_LIBRARY_DIR}/${FRAMEWORK_NAME}.framework"
###################### # Build Frameworks ###################### # Build for simulator xcodebuild -target ${PROJECT_NAME} -sdk iphonesimulator -configuration ${CONFIGURATION} ARCHS="i386 x86_64" ONLY_ACTIVE_ARCH=NO clean build CONFIGURATION_BUILD_DIR=${BUILD_DIR}/${CONFIGURATION}-iphonesimulator # Build for device xcodebuild -scheme ${PROJECT_NAME} -sdk iphoneos -configuration ${CONFIGURATION} ARCHS="armv7 armv7s arm64" ONLY_ACTIVE_ARCH=NO clean archive CONFIGURATION_BUILD_DIR=${BUILD_DIR}/${CONFIGURATION}-iphoneos
###################### # Create directory for universal ######################
rm -rf "${UNIVERSAL_LIBRARY_DIR}"
mkdir "${UNIVERSAL_LIBRARY_DIR}"
mkdir "${FRAMEWORK}"
###################### # Copy files Framework ######################
cp -r "${DEVICE_LIBRARY_PATH}/." "${FRAMEWORK}"
###################### # Make an universal binary ######################
lipo "${SIMULATOR_LIBRARY_PATH}/${FRAMEWORK_NAME}" "${DEVICE_LIBRARY_PATH}/${FRAMEWORK_NAME}" -create -output "${FRAMEWORK}/${FRAMEWORK_NAME}" | echo
# 对于Swift框架,需要将Swiftmodule复制到通用框架中如果 [ -d "${SIMULATOR_LIBRARY_PATH}/Modules/${FRAMEWORK_NAME}.swiftmodule/" ]; then cp -f ${SIMULATOR_LIBRARY_PATH}/Modules/${FRAMEWORK_NAME}.swiftmodule/* "${FRAMEWORK}/Modules/${FRAMEWORK_NAME}.swiftmodule/" | echo fi
如果 [ -d "${DEVICE_LIBRARY_PATH}/Modules/${FRAMEWORK_NAME}.swiftmodule/" ]; then cp -f ${DEVICE_LIBRARY_PATH}/Modules/${FRAMEWORK_NAME}.swiftmodule/* "${FRAMEWORK}/Modules/${FRAMEWORK_NAME}.swiftmodule/" | echo fi
###################### # 单侧发布,将结果复制到发布目录中 ###################### OUTPUT_DIR="${PROJECT_DIR}/build/${FRAMEWORK_NAME}-${CONFIGURATION}-iphoneuniversal/"
rm -rf "$OUTPUT_DIR" mkdir -p "$OUTPUT_DIR"
cp -r "${FRAMEWORK}" "$OUTPUT_DIR"
如果 [ ${REVEAL_ARCHIVE_IN_FINDER} = true ]; then open "${OUTPUT_DIR}/" fi

注意事项

  • 位码仅在 archive 构建 iphoneos sdk 时打包。

  • otool -l -arch arm64 <yourframework_binary>|grep __LLVM 用于检查是否包括位码,如果您不指定 arch 参数,则不会出现 __LLVM,因为 otool 只会打印一个主机架构(模拟器)。


1
请再次阅读问题。这正是我想要避免的(我在问题中提到了“lipo”)。如果我需要创建通用二进制文件,我不明白将某些东西编译为位码的目的是什么。而且我找不到使用“archive”构建创建的框架文件。 - Vincent Hiribarren
1
Bitcode是由Xcode编译的中间LLVM IR,与Java字节码不同,它是与架构相关的,因此每个切片都需要自己的Bitcode部分。由于它是中间代码,因此苹果可以在未来使用它来优化最终的机器代码,而无需上传新版本,这是主要目的。 - xfdai
使用脚本创建的框架位于 ${DEVICE_LIBRARY_PATH}/Modules/${FRAMEWORK_NAME},具体请参见此处 - xfdai
非常感谢这个脚本!还应该添加“Skip Install = yes”以避免从Build/Products/Release-iphoneos中删除设备版本。 - Vadim

1

我花费了很多时间来修复/更改xfaid答案的设置,最终得到了一个可以在XCode 10上使用位码的通用包。

我无法让"xcodebuild archive"命令工作,所以我使用了在此链接中描述的设置进行构建:http://iosre.com/t/enable-bitcode-for-frameworks-in-xcode/12581

然后我稍微更改了脚本:

# Fix for bitcode:
unset TOOLCHAINS

######################
# Options
######################

#verbose
#set -x

REVEAL_ARCHIVE_IN_FINDER=true

FRAMEWORK_NAME="${PROJECT_NAME}"

SIMULATOR_LIBRARY_PATH="${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${FRAMEWORK_NAME}.framework"

DEVICE_LIBRARY_PATH="${BUILD_DIR}/${CONFIGURATION}-iphoneos/${FRAMEWORK_NAME}.framework"

UNIVERSAL_LIBRARY_DIR="${BUILD_DIR}/${CONFIGURATION}-iphoneuniversal"

FRAMEWORK="${UNIVERSAL_LIBRARY_DIR}/${FRAMEWORK_NAME}.framework"


######################
# Build Frameworks
######################
# Build for simulator
xcodebuild -target ${PROJECT_NAME} -sdk iphonesimulator -configuration ${CONFIGURATION} ARCHS="i386 x86_64" ONLY_ACTIVE_ARCH=NO clean build CONFIGURATION_BUILD_DIR=${BUILD_DIR}/${CONFIGURATION}-iphonesimulator
# Build for device
xcodebuild -scheme ${PROJECT_NAME} -sdk iphoneos -configuration ${CONFIGURATION} ARCHS="armv7 armv7s arm64" ONLY_ACTIVE_ARCH=NO build  ENABLE_BITCODE=YES OTHER_CFLAGS="-fembed-bitcode"  OBJROOT="${OBJROOT}/DependantBuilds" CONFIGURATION_BUILD_DIR=${BUILD_DIR}/${CONFIGURATION}-iphoneos

######################
# Create directory for universal
######################

rm -rf "${UNIVERSAL_LIBRARY_DIR}"

mkdir "${UNIVERSAL_LIBRARY_DIR}"

mkdir "${FRAMEWORK}"


######################
# Copy files Framework
######################

cp -r "${DEVICE_LIBRARY_PATH}/." "${FRAMEWORK}"


######################
# Make an universal binary
######################

lipo "${SIMULATOR_LIBRARY_PATH}/${FRAMEWORK_NAME}" "${DEVICE_LIBRARY_PATH}/${FRAMEWORK_NAME}" -create -output "${FRAMEWORK}/${FRAMEWORK_NAME}" | echo

# For Swift framework, Swiftmodule needs to be copied in the universal framework
if [ -d "${SIMULATOR_LIBRARY_PATH}/Modules/${FRAMEWORK_NAME}.swiftmodule/" ]; then
cp -f ${SIMULATOR_LIBRARY_PATH}/Modules/${FRAMEWORK_NAME}.swiftmodule/* "${FRAMEWORK}/Modules/${FRAMEWORK_NAME}.swiftmodule/" | echo
fi

if [ -d "${DEVICE_LIBRARY_PATH}/Modules/${FRAMEWORK_NAME}.swiftmodule/" ]; then
cp -f ${DEVICE_LIBRARY_PATH}/Modules/${FRAMEWORK_NAME}.swiftmodule/* "${FRAMEWORK}/Modules/${FRAMEWORK_NAME}.swiftmodule/" | echo
fi

######################
# On Release, copy the result to release directory
######################
OUTPUT_DIR="${PROJECT_DIR}/build/${FRAMEWORK_NAME}-${CONFIGURATION}-iphoneuniversal/"

rm -rf "$OUTPUT_DIR"
mkdir -p "$OUTPUT_DIR"

cp -r "${FRAMEWORK}" "$OUTPUT_DIR"

if [ ${REVEAL_ARCHIVE_IN_FINDER} = true ]; then
open "${OUTPUT_DIR}/"
fi


只是以防万一,这可能会对你们中的一些人有所帮助 :)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接