【问题标题】:Is it possible to create a universal iOS framework using bitcode?是否可以使用位码创建通用 iOS 框架?
【发布时间】:2016-02-23 19:33:09
【问题描述】:

据我了解,bitcode 允许生成具有中间二进制格式的二进制文件。所以这是编译到 ARM 或 x64 架构之前的步骤。

从 iOS 8 开始,可以为 iOS 创建“真实的”.framework 文件。但是,默认情况下,框架文件仅针对一种架构(模拟器、iPhone)进行编译。当一个人想要分发.framework 文件时,最好提供一个与iOS 模拟器兼容并且也可以部署到iPhone 的文件。可以找到不同的脚本示例来使用lipo 创建这样的胖文件。

但是,是否可以只分发编译为位码的.framework 而不必创建具有不同架构的胖文件?

不幸的是,即使为我的.framework 启用了位码:

  • 根据目标架构默认创建不同的文件
  • 即使似乎为框架目标启用了“归档”菜单,我也找不到结果,即使在我的管理器视图中也是如此

我对bitcode的概念有什么误解,还是我错过了什么?

【问题讨论】:

    标签: ios xcode bitcode


    【解决方案1】:

    您需要提供一个通用的平面框架。由lipo创建。

    • 启用位码,Targets->Build Setting->Enable BitcodeYes
    • 添加构建目标以创建通用框架

      创建一个Aggregate 目标并将以下脚本复制到Build Phrase -> Run Script

    ###################### # 选项 ###################### #详细 设置-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" ###################### # 构建框架 ###################### # 为模拟器构建 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 # 为设备构建 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 ###################### # 创建通用目录 ###################### rm -rf "${UNIVERSAL_LIBRARY_DIR}" mkdir "${UNIVERSAL_LIBRARY_DIR}" mkdir "${FRAMEWORK}" ###################### # 复制文件框架 ###################### cp -r "${DEVICE_LIBRARY_PATH}/." “${框架}” ###################### # 制作通用二进制 ###################### lipo "${SIMULATOR_LIBRARY_PATH}/${FRAMEWORK_NAME}" "${DEVICE_LIBRARY_PATH}/${FRAMEWORK_NAME}" -create -output "${FRAMEWORK}/${FRAMEWORK_NAME}" |回声 # 对于 Swift 框架,需要将 Swiftmodule 复制到通用框架中 if [ -d "${SIMULATOR_LIBRARY_PATH}/Modules/${FRAMEWORK_NAME}.swiftmodule/" ];然后 cp -f ${SIMULATOR_LIBRARY_PATH}/Modules/${FRAMEWORK_NAME}.swiftmodule/* "${FRAMEWORK}/Modules/${FRAMEWORK_NAME}.swiftmodule/" |回声 菲 if [ -d "${DEVICE_LIBRARY_PATH}/Modules/${FRAMEWORK_NAME}.swiftmodule/" ];然后 cp -f ${DEVICE_LIBRARY_PATH}/Modules/${FRAMEWORK_NAME}.swiftmodule/* "${FRAMEWORK}/Modules/${FRAMEWORK_NAME}.swiftmodule/" |回声 菲 ###################### # 在发布时,将结果复制到发布目录 ###################### 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 ];然后 打开“${OUTPUT_DIR}/” 菲

    注意

    • bitcode 仅打包在archive iphoneos sdk 构建上

    • otool -l -arch arm64 <yourframework_binary>|grep __LLVM检查是否包含bitcode,如果不指定arch参数,则不会有__LLVM,因为otool只打印一个主机arch(模拟器)。

    【讨论】:

    • 请再读一遍问题。这正是我想避免的(我在我的问题中提到了lipo)。如果我无论如何都需要创建通用二进制文件,我不明白将某些东西编译为位码的目的。而且我找不到使用archive 构建创建的框架文件。
    • bitcode 是由 Xcode 编译的中间 LLVM IR,并且依赖于 arch,不像 java 字节码,因此每个 slice 都需要自己的 bitcode 部分。既然是中间代码,所以苹果以后不用上传新版本就可以用它优化到最终的机器码,这是主要目的
    • 并且使用脚本中的archive 创建的框架位于${DEVICE_LIBRARY_PATH}/Modules/${FRAMEWORK_NAME} 上,参见here
    • 非常感谢这个脚本!还应添加“跳过安装 = 是”以避免从 Build/Products/Release-iphoneos 中删除设备版本
    【解决方案2】:

    我花了很多时间修复/更改 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
    
    

    以防万一它可以帮助你们中的一些人:)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-16
      • 2014-11-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多