Xcode 14.2

Bitcode is actually just the LLVM intermediate language. When you compile source code using the LLVM toolchain, source code is translated into an intermediate language, named Bitcode. This Bitcode is then analyzed, optimized and finally translated to CPU instructions for the desired target CPU.

The advantage of doing it that way is that all LLVM based frontends (like clang) only need to translate source code to Bitcode, from there on it works the same regardless the source language as the LLVM toolchain doesn't care if the Bitcode was generated from C, C++, Obj-C, Rust, Swift or any other source language; once there is Bitcode, the rest of the workflow is always the same.

One benefit of Bitcode is that you can later on generate instructions for another CPU without having to re-compile the original source code. E.g. I may compile a C code to Bitcode and have LLVM generate a running binary for x86 CPUs in the end. If I save the Bitcode, however, I can later on tell LLVM to also create a running binary for an ARM CPU from that Bitcode, without having to compile anything and without access to the original C code. And the generated ARM code will be as good as if I had compiled to ARM from the very start.

Without the Bitcode, I would have to convert x86 code to ARM code and such a translation produces way worse code as the original intent of the code is often lost in the final compilation step to CPU code, which also involves CPU specific optimizations that make no sense for other CPUs, whereas Bitcode retains the original intent pretty well and only performs optimization that all CPUs will benefit from.

Having the Bitcode of all apps allowed Apple to re-compile that Bitcode for a specific CPU, either to make an App compatible with a different kind of CPU or an entirely different architecture or just to benefit from better optimizations of newer compiler versions. E.g. if Apple had tomorrow shiped an iPhone that uses a RISC-V instead of an ARM CPU, all apps with Bitcode could have been re-compiled to RISC-V and would natively support that new CPU architecture despite the author of the app having never even heard of RISC-V.

I think that was the idea why Apple wanted all Apps in Bitcode format. But that approach had issues to begin with. One issue is that Bitcode is not a frozen format, LLVM updates it with every release and they do not guarantee full backward compatibility. Bitcode has never been intended to be a stable representation for permanent storage or archival. Another problem is that you cannot use assembly code as no Bitcode is emitted for assembly code. Also you cannot use pre-built third party libraries that come without Bitcode.

And last but not least: AFAIK Apple has never used any of the Bitcode advantages so far. Despite requiring all apps to contain Bitcode in the past, the apps also had to contain pre-build fat binaries for all supported CPUs and Apple would always only just ship that pre-build code. E.g. for iPhones you used to once have a 32 Bit ARMv7 and a 64 Bit ARM64 version, as well as the Bitcode and during app thinning, Apple would remove either the 32 Bit or the 64 Bit version, as well as the Bitcode, and then ship whats left over. Fine, but they could have done so also if no Bitcode was there. Bitcode is not required to thin out architectures of a fat binary!

Bitcode would be required to re-build for a different architecture but Apple has never done that. No 32 Bit app magically became 64 bit by Apple re-compiling the Bitcode. And no 64 bit only app was magically available for 32 bit systems as Apple re-compiled the Bitcode on demand. As a developer, I can assure you, the iOS App Store always delivered exactly the binary code that you have built and signed yourself and never any code that Apple has themselves created from the Bitcode, so nothing was server side optimized. Even when Apple switched from Intel to M1, no macOS app magically got converted to native ARM, despite that would have been possible for all x86 apps in the app store for that Apple had the Bitcode. Instead Apple still shipped the x86 version and let it run in Rosetta 2.

So imposing various disadvantages onto developers by forcing all code to be available as Bitcode and then not using any of the advantages Bitcode would give you kinda makes the whole thing pointless. And now that all platforms migrated to ARM64 and in a couple of years there won't even be fat binaries anymore (once x86 support for Mac has been dropped), what's the point of continuing with that stuff? I guess Apple took the chance to bury that idea once and for all. Even if they one day add RISC-V to their platforms, developers can still ship fat binaries containing ARM64 and RISC-V code at the same time. This concept works well enough, is way simpler, and has no downsides other than "bigger binaries" and that's something server side app thinning can fix, as during download only the code for the current platform needs to be included.
Google 翻译:
Bitccode 实际上只是 LLVM 中间语言。 当您使用 LLVM 工具链编译源代码时,源代码会被翻译成一种名为 Bitcode 的中间语言。 然后分析、优化此 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 都将从中受益的优化。

拥有所有应用程序的 Bitcode 允许 Apple 为特定的 CPU 重新编译该 Bitcode,要么使应用程序与不同类型的 CPU 或完全不同的架构兼容,要么只是为了从新编译器版本的更好优化中受益。 例如。 如果 Apple 明天推出了使用 RISC-V 而不是 ARM CPU 的 iPhone,那么所有带有 Bitcode 的应用程序都可以重新编译为 RISC-V,并且会原生支持新的 CPU 架构,尽管应用程序的作者甚至从未 听说过RISC-V。

我认为这就是为什么 Apple 希望所有应用程序都采用 Bitcode 格式的原因。 但这种方法一开始就存在问题。 一个问题是 Bitcode 不是固定格式,LLVM 会在每次发布时更新它,并且它们不保证完全向后兼容。 Bitcode 从未打算成为永久存储或存档的稳定表示。 另一个问题是您不能使用汇编代码,因为没有为汇编代码发出 Bitcode。 您也不能使用没有 Bitcode 的预建第三方库。

最后但同样重要的是:AFAIK Apple 迄今为止从未使用过任何 Bitcode 优势。 尽管过去要求所有应用程序都包含 Bitcode,但这些应用程序还必须包含所有支持的 CPU 的预构建胖二进制文件,而 Apple 总是只会发布预构建代码。 例如。 对于曾经拥有 32 位 ARMv7 和 64 位 ARM64 版本以及 Bitcode 的 iPhone,Apple 会删除 32 位或 64 位版本以及 Bitcode,然后发布 还剩下什么。 很好,但如果没有 Bitcode,他们也可以这样做。 不需要位码来精简胖二进制文件的体系结构!

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

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

也可以参考:理解iOS开发中BitCode功能 https://www.jianshu.com/p/8eff48e5c010 一文