Xcode 14 弃用了位码 - 但为什么呢?

Isa*_*erg 131 xcode ios bitcode xcode14

Xcode 14 Beta 发行说明已经发布,这一切都归功于一年一度的 WWDC。

可惜的是,Bitcode 现已被弃用,如果您尝试启用它,您将收到一条警告消息。

我想知道为什么会发生这种情况?使用 Bitcode 有什么缺点吗?苹果维护它是否有些痛苦?现在每个 iPhone 型号的编译将如何运行?

Mec*_*cki 266

Bitccode实际上只是LLVM中间语言。当您使用 LLVM 工具链编译源代码时,源代码将被翻译为一种名为 Bitcode 的中间语言。然后,该位码经过分析、优化并最终转换为所需目标 CPU 的 CPU 指令。

这样做的优点是,所有基于 LLVM 的前端(如 clang)只需要将源代码转换为 Bitcode,从那里开始,无论源语言是什么,它的工作原理都是一样的,因为 LLVM 工具链不关心 Bitcode 是否生成来自 C、C++、Obj-C、Rust、Swift 或任何其他源语言;一旦有了 Bitcode,其余的工作流程总是相同的。

Bitcode 的好处之一是您稍后可以为另一个 CPU 生成指令,而无需重新编译原始源代码。例如,我可以将 C 代码编译为 Bitcode,并最终让 LLVM 为 x86 CPU 生成运行二进制文件。然而,如果我保存 Bitcode,我稍后可以告诉 LLVM 从该 Bitcode 为 ARM CPU 创建一个正在运行的二进制文件,而无需编译任何内容,也无需访问原始 C 代码。生成的 ARM 代码就像我从一开始就编译为 ARM 一样好。

如果没有 Bitcode,我将不得不将 x86 代码转换为 ARM 代码,这样的转换会产生更糟糕的代码,因为代码的原始意图常常在最终编译为 CPU 代码的步骤中丢失,这还涉及 CPU 特定的优化,这使得对于其他 CPU 来说是有意义的,而 Bitcode 很好地保留了最初的意图,并且只执行所有 CPU 都会受益的优化。

拥有所有应用程序的位码后,Apple 就可以针对特定 CPU 重新编译该位码,从而使应用程序与不同类型的 CPU 或完全不同的架构兼容,或者只是为了从新编译器版本的更好优化中受益。例如,如果 Apple 明天发布一款使用 RISC-V 而不是 ARM CPU 的 iPhone,则所有具有 Bitcode 的应用程序都可以重新编译为 RISC-V,并且原生支持新的 CPU 架构,尽管该应用程序的作者从未这样做过。甚至听说过 RISC-V。

我认为这就是苹果希望所有应用程序都采用位码格式的原因。但这种方法一开始就存在问题。一个问题是 Bitcode 不是一种冻结格式,LLVM 在每个版本中都会更新它,并且它们不保证完全向后兼容性。位码从来就没有打算成为永久存储或存档的稳定表示。另一个问题是您无法使用汇编代码,因为不会为汇编代码发出位码。此外,您不能使用没有 Bitcode 的预构建第三方库。

最后但并非最不重要的一点是:据我所知,苹果迄今为止从未使用过 Bitcode 的任何优势。尽管过去要求所有应用程序都包含 Bitcode,但应用程序还必须包含所有支持的 CPU 的预构建胖二进制文件,并且 Apple 始终只提供预构建代码。例如,对于 iPhone,您曾经拥有 32 位 ARMv7 和 64 位 ARM64 版本,以及 Bitcode,在应用程序精简期间,Apple 会删除 32 位或 64 位版本以及 Bitcode,然后运送剩下的东西。很好,但如果没有 Bitcode,他们也可以这样做。不需要位码来精简胖二进制文件的架构!

需要为不同的架构重新构建位码,但苹果从未这样做过。没有任何 32 位应用程序会通过 Apple 重新编译 Bitcode 神奇地变成 64 位。而且,随着 Apple 按需重新编译 Bitcode,任何 64 位应用程序都无法神奇地适用于 32 位系统。作为一名开发人员,我可以向您保证,iOS App Store 始终准确地提供您自己构建和签名的二进制代码,而不是 Apple 自己根据 Bitcode 创建的任何代码,因此没有任何内容经过服务器端优化。即使苹果从 Intel 切换到 M1,也没有 macOS 应用程序神奇地转换为原生 ARM,尽管应用商店中的所有 x86 应用程序都可以实现这一点,因为苹果有 Bitcode。相反,Apple 仍然提供 x86 版本并让它在 Rosetta 2 中运行。

因此,通过强制所有代码都以 Bitcode 形式提供,然后不使用 Bitcode 会给您带来的任何优势,从而给开发人员带来各种缺点,这会让整个事情变得毫无意义。现在所有平台都迁移到 ARM64,几年后甚至不再有胖二进制文件(一旦 Mac 的 x86 支持被放弃),继续这些东西还有什么意义呢?我想苹果借此机会一劳永逸地埋葬了这个想法。即使有一天他们将 RISC-V 添加到他们的平台中,开发人员仍然可以同时发布包含 ARM64 和 RISC-V 代码的胖二进制文件。这个概念工作得很好,更简单,除了“更大的二进制文件”之外没有任何缺点,这是服务器端应用程序精简可以解决的问题,因为在下载过程中只需要包含当前平台的代码。

  • 有趣的。所以他们多年来一直用这些比特代码的麻烦让我们烦恼——完全没有任何意义?有趣的。我刚刚在这里看到这篇文章,因为 Xcode 14 希望“强制”我为现有 Unity 项目的 Pod 启用 Bitcode。否则,构建失败。如果他们“放弃”了位码支持,我不知道为什么会出现这种情况。对我来说没有任何意义。在 Xcode 13 中,该项目构建得很好。 (43认同)
  • “苹果从未使用过位码”是不正确的。向 64 位 watchOS 的过渡涉及使用位码将所有现有的armv7应用程序重新编译为古怪的过渡arm64_32架构(它是arm64,但具有32位指针)。他们还尝试使用位码为使用 Xcode 13.1 构建的应用程序启用 Swift Concurrency 反向部署,但这仅适用于 TestFlight,因为它大多只会引起问题。还值得注意的是,Apple 的位码格式与 LLVM 位码不是一回事,实际上是被冻结的。 (12认同)
  • @waldgeist 在应用程序商店中提供 CPU 中立形式的应用程序的想法并不是一个坏主意;这就是 Android 选择 Java 字节码 (JBC) 的原因。然而,JBC 是一种非常稳定的表示形式,有很好的文档记录和理解,而 Bitcode 则不然。此外,在 Android 上,设备本身将 JBC 转换为 CPU 代码(现在是 AOT),这是 Apple 不希望发生的情况,因此他们的服务器必须执行该任务,我可以看到该概念的各种陷阱。至于您的具体问题,创建一个新问题并在那里提供一些日志输出,有人可能知道您问题的答案。 (6认同)
  • Apple 的位码格式仅进行了附加更改。较旧的编译器生成的位码可以被较新的编译器使用,但反之则不然。相比之下,LLVM 的格式只能由与其创建时相同的版本使用,因为它们改变了现有事物的含义。我怀疑将所有内容表达为纯粹附加更改的困难可能是他们放弃位码的一个因素。 (3认同)
  • @ThomasGoyne Apple的位码格式不能被冻结,就好像LLVM引入了一个新功能,这需要改变他们的位码格式,他们只是改变它;现在,如果冻结,该功能将如何转换为苹果的位码格式?然后苹果根本无法提供该功能,因为他们无法表达它,但据我所知,这种情况从未发生过;LLVM 位码格式的此类变化在过去几年中确实发生过几次。 (2认同)

Byo*_*Lee 11

Apple Watch Series 3 是最后一款不支持 64 位的设备。(即i386或armv7)

Apple 现已停止支持 Apple Watch Series 3。 [1] 他们本来很乐意放弃对位码的支持。

[1] https://www.xda-developers.com/watchos-9-not-coming-apple-watch-series-3


jac*_*son 5

xcode 删除了 armv7/armv7s/i386 目标支持。位码用于构建不同的 cpu 目标。但现在所有设备可能都是arm64。现在没有更多的开发人员使用这项技术。所以不赞成也许是一个明智的选择