如何使用启用Bitcode的xcodebuild构建静态库?

93

Xcode 7 推出了Bitcode,它是一种 LLVM 中间二进制文件,这意味着苹果的服务器可以在没有我的参与下为不同的架构重新编译我的应用程序。

在 Lookback,我使用一个静态存档框架来分发我们的库。似乎当你使用除“Build & Archive”以外的任何东西进行构建时,实际上并没有将 bitcode 发送到我的库中。任何链接我们库并尝试启用 Bitcode 进行“Build & Archive”的人将会收到以下两个警告之一:

  • ld:“Lookback(Lookback.o)”不包含位码。您必须使用启用了位码的Xcode设置ENABLE_BITCODE重新构建它,从供应商处获取更新的库,或者为此目标禁用位码。(如果使用Xcode 6构建库)
  • ld:警告:无法生成完整的位码捆绑包,因为“Lookback(Lookback.o)”仅使用位码标记构建。该库必须从启用位码的Xcode存档构建中生成(Xcode设置ENABLE_BITCODE)(如果使用普通xcodebuild在Xcode 7中构建库)

我有一个构建脚本,可以构建设备+模拟器通用二进制文件,因此我不能使用Build&Archive,而是从我的脚本中通过命令行运行xcodebuild。如何使xcodebuild生成适当的启用位码的库?


嗨 @nevyn,我正在尝试在使用位码的应用程序中编译您的SDK。有没有办法? - Stoff81
@Stoff81 抱歉,我正在处理中。我需要先让所有的依赖项与 Bitcode 兼容,这需要花费相当多的工作量。 - nevyn
4个回答

142

Bitcode是一种编译时功能(而非链接时间功能),这意味着当使用bitcode创建.o文件时,每个文件应包含一个名为__bitcode的额外部分。您可以通过运行otool -l (我的.o或.a文件)| grep __LLVM来确认二进制文件是否兼容于bitcode。

在正常构建时,Xcode会将-fembed-bitcode-marker构建标志添加到任何clang调用中。这似乎是某种“如果启用了bitcode,则会放置bitcode的位置”,并且实际上没有启用bitcode。

当您进行“构建和存档”操作时,该标志被替换为-fembed-bitcode,这确实构建了一个启用Bitcode的二进制文件。

有两种方法可以使xcodebuild使用-fembed-bitcode:

  • 使用“存档”操作,例如xcodebuild-target LookbackSDK archive而不是xcodebuild-target LookbackSDK build。这会导致将二进制文件放入您的Xcode Organizer而不是build/文件夹中,尽管您可以通过使用-exportArchive-archivePath ./build来解决此问题(感谢@JensAyton
  • 通过添加其他C标志OTHER_CFLAGS="-fembed-bitcode"来强制使用该标志。您的xcodebuild调用将类似于xcodebuild OTHER_CFLAGS="-fembed-bitcode" -target LookbackSDK build

我选择后者,这样就无需更改构建系统,但它将为每个文件生成警告,因为现在将-fembed-bitcode-marker-fembed-bitcode发送到clang。幸运的是,后者胜出,生成了一个启用Bitcode的库!

资源

  • 苹果开发者论坛:Bitcode和汇编语言?
  • SO:iOS库转为BitCode

  • 9
    顺带一提,你可以通过添加"-Qunused-arguments"来消除有关忽略"-fembed-bitcode-marker"的警告。这样不会改变原意,同时使句子更加通俗易懂。 - mstorsjo
    @nevyn 我仍然无法构建我的主应用程序,该应用程序具有自定义框架文件,该文件又包含具有上述标志的构建脚本。 - ravoorinandan
    1
    @MikeM 不是实际上 otool -l myfile.o | grep __LLVM,因为即使只有位码标记而不是真正的位码,也会有一个 __bitcode 段。 - nevyn
    @nevyn 这是bash脚本:https://www.snip2code.com/Snippet/115398/Script-for-iOS-Universal-Framework-compi - 2cupsOfTech
    这似乎不再适用于.a静态库档案。现在,otool -l似乎只显示mylib.a(xxx.c.o):是LLVM位代码文件 - Will
    显示剩余8条评论

    44

    在使用Xcode 8时,我无法让OTHER_CFLAGS="-fembed-bitcode"起作用。当我尝试创建包含静态框架的应用程序的归档构建时,总是遇到类似于没有完整的位码构建。所有用于位码的框架和dylibs必须从Xcode Archive或Install Build生成的问题。

    我真正需要的是这个:

    BITCODE_GENERATION_MODE=bitcode
    

    实际上我正在使用一个聚合目标内的运行脚本,完整的xcodebuild命令如下(仅供参考):

    xcodebuild BITCODE_GENERATION_MODE=bitcode OTHER_CFLAGS="-fembed-bitcode" -target "${PROJECT_NAME}" ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphoneos BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build


    3
    +1,似乎首选BITCODE_GENERATION_MODE = bitcode方法,正如此答案中所建议的一样。 - William Denniss
    这也解决了我的问题,而默认答案已经不再适用。 - Kamchatka
    救命稻草!谢谢你! - vidalbenjoe
    +1。 接受的答案对我没用,但包括 BITCODE_GENERATION_MODE=bitcode 就解决了问题。谢谢! - brian_schick

    17
    一旦您为静态库添加了位码支持,它将无法与Xcode 6兼容。 应用程序将无法归档。
    我想清楚地提到有关位码设置的设置,因为@nevyn的答案有点让我困惑。
    转到生成设置,搜索“自定义编译器标志”。 添加-fembed-bitcode。 这将使用位码构建您的库。

    7

    选择项目 在构建设置->其他C标志中,将Debug设置为-fembed-bitcode-marker,并将Release设置为-fembed-bitcode

    在构建设置中,点击顶部的+号以添加一个名为BITCODE_GENERATION_MODE的用户定义的构建设置,并将Debug设置为marker,将Release设置为bitcode

    编辑模式为Release 然后单击所需的库。 获取构建路径的文件。 从Release文件夹中获取库。


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