Bitcode is an intermediate representation of a program at the compilation stage of an iOS application. Unlike machine code, Bitcode is not tied to a specific processor architecture. According to Apple Developer Documentation, the App Store can recompile Bitcode for the target architecture, improving performance and reducing the installation file size. The developer submits Bitcode to the App Store, and the store itself generates an optimized binary file for each device type.
Key Takeaways
Bitcode is an intermediate representation of a program (Intermediate Representation, IR) generated by the LLVM compiler infrastructure. Apple introduced Bitcode support starting with Xcode 7 and iOS 9 as a mandatory requirement for watchOS applications and optional for iOS and tvOS. Starting with Xcode 14, the requirement was removed for all platforms except watchOS.
The concept of intermediate code representation has existed since the 2000s as part of the LLVM project, founded by Chris Lattner at the University of Illinois. Apple adapted LLVM for Xcode in 2011, and in 2015 introduced Bitcode as a way to update applications without resubmitting to the App Store. The technology was announced at WWDC 2015 in the session "What's New in Xcode".
Machine code consists of binary instructions for a specific processor: arm64, armv7, or x86_64. Bitcode is stored in a hardware-independent format, allowing the App Store to generate optimized binary files for different architectures from a single source representation. This key difference defines all the advantages of the technology.
| Characteristic | Bitcode | Machine Code |
|---|---|---|
| Architecture Dependency | Independent | Tied to CPU |
| Binary File Size | Compact | Larger |
| Recompilation Capability | Yes | No |
| App Store Support | Recompiled | Used as-is |
| Debugging | Limited | Full support |
Bitcode is not an executable file. It is LLVM IR in binary format that the developer submits to the App Store along with project metadata. The App Store runs the recompilation process, adapting the code for each target platform and operating system version.
The Bitcode generation process begins with the compiler frontend, which converts Swift or Objective-C source code into LLVM IR. At the linking stage, Xcode packages the IR into .bc (Bitcode) format files, which are then submitted to the App Store along with the .xcarchive. The App Store, in turn, runs the recompilation process on its end.
The LLVM infrastructure consists of three parts: the frontend (Clang for C/ObjC, Swift Frontend for Swift), the Middle-End optimizer, and the backend (machine code generator). Bitcode is the result of the first two stages without proceeding to assembly instruction generation. The Middle-End performs platform-independent optimizations: dead code elimination, inlining, and constant folding.
// Swift source code example
func calculateSum(a: Int, b: Int) -> Int {
return a + b
}
// LLVM IR after compilation (simplified)
; define i32 @calculateSum(i32 %a, i32 %b)
; %result = add i32 %a, %b
; ret i32 %result
After IR generation, the compiler performs a series of optimizations at the representation level: dead code elimination, function inlining, and constant folding. These optimizations are architecture-independent and are preserved in Bitcode. During recompilation in the App Store, architecture-dependent optimizations are added, such as instruction reordering for a specific processor.
App Store Connect receives the archive with Bitcode and runs its own compilation infrastructure. The system determines the target architecture of the user's device and generates machine code, further optimizing it for the specific processor characteristics. For arm64e (A12+ and M-series processors), additional security optimizations are applied.
This process is called App Thinning — a technology that delivers only the resources and code necessary for a device's architecture to that device. A user with an iPhone running an A17 Pro processor receives a binary file optimized for arm64e, without unnecessary instructions for older architectures. This reduces download time and saves space on the device.
Bitcode provides several key advantages for iOS application developers. The main one is automatic optimization for new Apple processors without requiring a re-submission of an update to the App Store. This is especially relevant when transitioning to new architectures, such as the move from armv7 to arm64.
When Apple releases a processor with a new architecture, applications submitted with Bitcode are automatically recompiled for it. The developer does not need to rebuild the project and publish an update — the App Store does this on its end when the user first downloads it. This is particularly important for long-lived applications that are maintained for years.
App Thinning combined with Bitcode can reduce the installed application size by 15–40%. The App Store generates only the machine instructions needed by a specific device, eliminating code for other architectures and variations for different iOS versions. In practice, this means a user with a new iPhone gets a compact binary file.
According to Apple WWDC 2015 Session 102, using Bitcode and App Thinning can reduce the downloaded application size by an average of 25% compared to a universal binary file containing all architectures. For a 100 MB application, the savings can amount to up to 40 MB on the user's device.
Bitcode configuration is done in the Xcode build settings. The Enable Bitcode parameter is located in the Build Settings and is enabled by default for new projects, but developers can disable it for debugging or when using third-party libraries without Bitcode support.
// Build Settings -> Apple Clang - Code Generation
// Enable Bitcode = YES
// Or via Info.plist for individual targets
@property (nonatomic, assign) BOOL enableBitcode;
- (void)configureBuildSettings {
// Checking Bitcode status in configuration
if (self.enableBitcode) {
NSLog(@"Bitcode is enabled for this target");
} else {
NSLog(@"Bitcode is disabled");
}
}
To verify whether the archive contains Bitcode, open the .xcarchive file via Xcode Organizer or run the otool -l command in the Terminal. The presence of a __LLVM section in the binary file confirms that Bitcode is enabled and packaged correctly. If the section is missing, Bitcode was not generated during the build.
# Checking Bitcode presence in the archive
otool -l YourApp.app/YourApp | grep __LLVM
# Output: if there is a __LLVM section — Bitcode is present
# If output is empty — Bitcode is not enabled or not generated
# You can also check using the size command
size -m -l YourApp.app/YourApp | grep __LLVM
When using third-party libraries via CocoaPods or SPM, make sure all dependencies are built with Bitcode. If at least one library does not support Bitcode, Xcode will generate a linking error during archiving. For CocoaPods, check the bitcode_enabled flag in subspecs or use use_frameworks! with enable_bitcode.
Bitcode is not a universal solution for all types of iOS projects. The technology has limitations that the developer should consider before enabling the option in the build configuration. Understanding these limitations helps avoid problems during archiving and publication.
Not all third-party libraries come with Bitcode support. If a library is distributed only as a compiled binary file without Bitcode, a project with the option enabled will not build. In this case, the developer will have to either disable Bitcode or request a Bitcode-enabled version from the vendor. This is especially relevant for older libraries that are no longer updated.
Crash reports from applications built with Bitcode require additional processing. Symbols (dSYM) for recompiled code are generated by the App Store and are available for download via Xcode Organizer. Without loading the corresponding dSYM files, the call stack in crash reports will be unreadable, making problem diagnosis difficult.
As of iOS 17 and Xcode 15, Apple does not require mandatory Bitcode enabling for publication on the App Store. However, for watchOS applications, Bitcode remains a mandatory requirement established at the App Store Connect policy level. Developers are recommended to enable Bitcode for new projects if all dependencies support it.
Frequently Asked Questions
For iOS and tvOS applications, Bitcode is not mandatory starting from Xcode 14. For watchOS, Bitcode support remains mandatory. Apple recommends enabling Bitcode for new projects but does not block publication without it.
Bitcode allows the App Store to apply App Thinning — generating machine code only for the user's device architecture. This reduces the downloaded binary file size by 15–40% depending on the number of supported architectures in the project.
Yes, dSYM files are necessary for symbolizing crash reports from recompiled binary files. The App Store provides the ability to download dSYM via Xcode Organizer after processing the archive. Without them, the call stack in Crashlytics and the console will contain only memory addresses.
SPM supports Bitcode if dependencies are distributed in source code rather than as binary files. Binary dependencies via SPM must provide a version with Bitcode, otherwise a project with the option enabled will not compile.
Bitcode is a hardware-independent intermediate LLVM IR representation that cannot be directly executed by a processor. Machine code contains ready-made instructions for a specific architecture (arm64, x86_64) and executes without additional compilation.
Summary
We will develop a mobile application turnkey
IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.
Read also