Infer fails with iOS SDK 26 (Xcode 26)
- Dominant language
- OCaml
- Stars
- 15.7k
- Forks
- 2.1k
- Avg merge
- 19h 36m
- Merged PRs (30d)
- 13
Description
# Infer fails with iOS SDK 26 (Xcode 26) with Objective-C
## Summary
Infer currently fails to analyze iOS projects built with **Xcode 26 / iOS SDK 26** with **Objective-C**.
The failures originate from multiple incompatibilities between Infer's **bundled clang toolchain** and the **new Apple SDK headers**.
Typical results include:
- `xcodebuild` failing with **exit code 65**
- Infer capture aborting before compilation finishes
- missing `.o` files
- extremely low analysis coverage
---
## Environment
- Infer: v1.2.0-f37905523e
- Xcode: **26**
- iOS SDK: **26.0**
- macOS: 15.7.4
- LLVM bundled with Infer: **20.1.1** (from `facebook-clang-plugins/clang/install/bin/clang`)
- **Command run**: `infer capture -- xcodebuild -project YourProject.xcodeproj -scheme YourScheme -sdk iphoneos`
---
## 1. Bundled Clang Incompatible with SDK 26 Headers
Infer uses its **bundled clang** (upstream LLVM 20.1.1), not the Xcode clang.
Location: `facebook-clang-plugins/clang/install/bin/clang`
Apple SDK 26 headers rely on **Apple clang extensions** including:
- `__attribute__((swift_name))`
- `__attribute__((diagnose_if))`
- `API_UNAVAILABLE(...)`
- `NS_SWIFT_NAME(...)`
- `@import` modules (Photos, AVFoundation, UIKit, etc.)
When Infer clang parses SDK headers (Foundation, UIKit, UserNotifications, etc.), it fails with errors such as:
- `error: use of '@import' when modules are disabled`
- `error: unknown attribute`
- `error: expected identifier`
- `error: invalid availability attribute`
- `module 'UIKit' not found` / `could not build module 'Foundation'`
### Impact
Capture fails before Apple clang runs → object file not produced → xcodebuild exits with code 65.
---
## 2. Hard-coded SDK Path Assumptions
Infer assumes **non-versioned SDK names** in `Makefile.config`, e.g.:
- `iPhoneSimulator.sdk`
- `MacOSX.sdk`
Xcode 26 uses **versioned SDK directories**:
- `iPhoneOS26.0.sdk`
- `iPhoneSimulator26.0.sdk`
- `MacOSX15.0.sdk`
This can result in invalid sysroots such as `.../SDKs/iPhoneSimulator.sdk` which no longer exist.
### Impact
Clang fails with `fatal error: 'Foundation/Foundation.h' file not found`.
---
## 3. SDKROOT Not Passed to xcodebuild Environment
Infer launches `xcodebuild` from `infer/src/integration/XcodeBuild.ml` but does not guarantee `SDKROOT` is exported.
Because SDK directory names changed in Xcode 26, the wrapper cannot reliably infer the correct sysroot.
### Impact
Incorrect system include resolution: `error: 'UIKit/UIKit.h' file not found`.
---
## 4. Fatal Exit on Clang Failure During Capture
In `infer/src/clang/Capture.ml`, when Infer clang fails, it executes `L.exit exit_code`, which terminates the worker immediately.
In an Xcode parallel build graph this prevents the real compile step from running.
### Result
Apple clang never executes → object file missing → xcodebuild fails with exit code 65.
---
## 5. Clang Wrapper Can Abort Before Apple Clang Runs
In `infer/src/clang/ClangWrapper.ml`, Infer runs `exec_all_commands` which performs:
1. Infer clang (AST capture)
2. Apple clang (real compilation)
Exceptions such as `ClangCompileError`, Unix errors, or `SIGINT` can abort the wrapper before the real compile step runs.
### Impact
Real clang never executes → compilation fails.
---
## 6. Hardcoded Internal Clang Include Version
In `infer/src/clang/ClangCommand.ml`, Infer constructs builtin include paths such as:
clang/install/lib/clang//include
The version is hardcoded (e.g. `"20"` for LLVM 20.1.1). If it drifts from the actual bundled clang version, builtin headers (`stddef.h`, `stdint.h`, `stdarg.h`) may be wrong and cause parsing failures.
---
## 7. Apple SDK Modules Not Properly Supported
Apple SDKs rely heavily on **Clang modules** defined in `System/Library/Frameworks/.../Modules/module.modulemap`.
Infer clang frequently fails with:
- `module 'UIKit' not found`
- `could not build module 'Foundation'`
or falls back to textual includes that expose unsupported macros.
---
## 8. AST Exporter Plugin Must Be Updated for New Clang/SDK
The **BiniouASTExporter** plugin in `facebook-clang-plugins/libtooling/` is built against Infer's bundled Clang. It produces the AST that Infer's OCaml frontend consumes.
**Files involved:**
- `facebook-clang-plugins/libtooling/ASTExporter.h` – visitor over Decl/Stmt/Type/Attr
- `facebook-clang-plugins/libtooling/ASTExporter.cpp` – plugin entry points
- `facebook-clang-plugins/libtooling/SimplePluginASTAction.cpp`
- `facebook-clang-plugins/libtooling/AttrParameterVectorStream.h`
- `facebook-clang-plugins/libtooling/atdlib/*`
**Why updates are needed:**
1. **API compatibility:** Clang's C++ APIs (visitors, `Decl::getKind()`, `SourceLocation`, etc.) change between versions. If the bundled Clang is upgraded, the plugin will not compile without fixes.
2. **New AST constructs:** SDK 26 / newer Clang may introduce Decl/Stmt kinds the current exporter does not handle, leading to crashes or incomplete AST.
3. **Build against Apple Clang:** To analyze `@import` SDK 26 code, the plugin must be built against **Apple's Clang** (from Xcode 26), not upstream LLVM. That requires adapting `facebook-clang-plugins/Makefile.config` to use Apple's headers and libraries.
See `facebook-clang-plugins/libtooling/ATD_GUIDELINES.md` for how ATD annotations in the exporter map to the OCaml AST.
---
## 9. Swift Interop Macros in SDK 26
SDK 26 headers introduce more Swift bridging annotations:
- `NS_SWIFT_NAME(...)`
- `SWIFT_COMPILE_NAME(...)`
Combined with availability attributes, these often cause parsing failures in older clang builds.
---
## 10. New Availability Macros
New macros include:
- `API_AVAILABLE(...)`
- `API_UNAVAILABLE(...)`
- `API_DEPRECATED(...)`
These expand to attributes that may not be recognized by Infer's bundled clang.
---
## 11. Upstream LLVM vs Apple LLVM
Infer builds its clang from **upstream LLVM**, while Apple SDK headers depend on **Apple clang extensions**, including:
- Objective-C runtime attributes
- availability syntax
- module flags
- Apple-specific target attributes
Upstream LLVM frequently lags behind these extensions. There is no newer upstream LLVM release that fully supports Apple's SDK 26 format; the format is Apple-specific.
---
## Result in Practice
Typical build flow:
1. Infer clang attempts AST capture
2. It fails parsing SDK headers (modules, attributes, etc.)
3. Capture stage aborts (or wrapper exits on exception)
4. Apple clang never runs
5. `.o` file missing
6. `xcodebuild` fails with **exit code 65**
Or, if errors are swallowed: analysis completes but most files are skipped → **near-zero analysis coverage**.
---
## Suggested Fix Directions
| Fix | Description |
|-----|-------------|
| **1. Dynamic SDK paths** | Resolve SDK paths via `xcrun --sdk iphoneos --show-sdk-path` instead of hardcoded names. |
| **2. Inject SDKROOT** | Ensure `SDKROOT` is set in the xcodebuild environment when `-sdk` is used. |
| **3. Non-fatal capture failures** | When Infer clang fails in xcodebuild mode, do not exit; allow Apple clang to run so `.o` files are produced. |
| **4. Wrapper exception handling** | Catch exceptions (ClangCompileError, SIGINT) in the clang wrapper and still run Apple clang. |
| **5. Builtin include path** | Ensure the hardcoded clang version in `ClangCommand.ml` matches the bundled clang (e.g. `"20"` for LLVM 20.1.1). |
| **6. Update bundled clang** | *Limited:* Infer already uses LLVM 20.1.1. Upgrading to a newer upstream LLVM will not add support for Apple's SDK 26 module format. |
| **7. Build plugin against Apple Clang** | To analyze `@import` SDK 26 code, build the BiniouASTExporter plugin against **Apple's Clang** (Xcode 26 toolchain) and update `facebook-clang-plugins/Makefile.config` accordingly. |
| **8. Update libtooling C++ code** | When changing the Clang version (bundled or Apple), update `ASTExporter.h`, `ASTExporter.cpp`, and related files in `facebook-clang-plugins/libtooling/` for API compatibility and new AST constructs. See `ATD_GUIDELINES.md`. |
---
## Full Output
```bash
XCODEBUILD: ** BUILD FAILED **
XCODEBUILD:
XCODEBUILD: The following build commands failed:
XCODEBUILD: CompileC /Users/[USER]/Library/Developer/Xcode/DerivedData/[PROJECT]-[HASH]/Build/Intermediates.noindex/[PROJECT].build/Release-iphoneos/[PROJECT].build/Objects-normal/arm64/[FILE1].o [PROJECT]/Classes/Core/[FILE1].m normal arm64 objective-c com.apple.compilers.llvm.clang.1_0.compiler (in target '[PROJECT]' from project '[PROJECT]')
XCODEBUILD: CompileC /Users/[USER]/Library/Developer/Xcode/DerivedData/[PROJECT]-[HASH]/Build/Intermediates.noindex/[PROJECT].build/Release-iphoneos/[PROJECT].build/Objects-normal/arm64/[FILE2].o [PROJECT]/Classes/Core/[FILE2].m normal arm64 objective-c com.apple.compilers.llvm.clang.1_0.compiler (in target '[PROJECT]' from project '[PROJECT]')
XCODEBUILD: CompileC /Users/[USER]/Library/Developer/Xcode/DerivedData/[PROJECT]-[HASH]/Build/Intermediates.noindex/[PROJECT].build/Release-iphoneos/[PROJECT].build/Objects-normal/arm64/[FILE3].o [PROJECT]/Classes/Core/[FILE3].m normal arm64 objective-c com.apple.compilers.llvm.clang.1_0.compiler (in target '[PROJECT]' from project '[PROJECT]')
XCODEBUILD: CompileC /Users/[USER]/Library/Developer/Xcode/DerivedData/[PROJECT]-[HASH]/Build/Intermediates.noindex/[PROJECT].build/Release-iphoneos/[PROJECT].build/Objects-normal/arm64/[FILE4].o [PROJECT]/Classes/Core/[FILE4].m normal arm64 objective-c com.apple.compilers.llvm.clang.1_0.compiler (in target '[PROJECT]' from project '[PROJECT]')
XCODEBUILD: CompileC /Users/[USER]/Library/Developer/Xcode/DerivedData/[PROJECT]-[HASH]/Build/Intermediates.noindex/[PROJECT].build/Release-iphoneos/[PROJECT].build/Objects-normal/arm64/[FILE5].o [PROJECT]/Classes/Core/[FILE5].m normal arm64 objective-c com.apple.compilers.llvm.clang.1_0.compiler (in target '[PROJECT]' from project '[PROJECT]')
XCODEBUILD: CompileC /Users/[USER]/Library/Developer/Xcode/DerivedData/[PROJECT]-[HASH]/Build/Intermediates.noindex/[PROJECT].build/Release-iphoneos/[PROJECT].build/Objects-normal/arm64/[FILE6].o [PROJECT]/Classes/Core/[FILE6].m normal arm64 objective-c com.apple.compilers.llvm.clang.1_0.compiler (in target '[PROJECT]' from project '[PROJECT]')
XCODEBUILD: CompileC /Users/[USER]/Library/Developer/Xcode/DerivedData/[PROJECT]-[HASH]/Build/Intermediates.noindex/[PROJECT].build/Release-iphoneos/[PROJECT].build/Objects-normal/arm64/[FILE7].o [PROJECT]/Classes/Core/[FILE7].m normal arm64 objective-c com.apple.compilers.llvm.clang.1_0.compiler (in target '[PROJECT]' from project '[PROJECT]')
XCODEBUILD: CompileC /Users/[USER]/Library/Developer/Xcode/DerivedData/[PROJECT]-[HASH]/Build/Intermediates.noindex/[PROJECT].build/Release-iphoneos/[PROJECT].build/Objects-normal/arm64/[FILE8].o [PROJECT]/Classes/Core/[FILE8].m normal arm64 objective-c com.apple.compilers.llvm.clang.1_0.compiler (in target '[PROJECT]' from project '[PROJECT]')
XCODEBUILD: Building project [PROJECT] with scheme [PROJECT] and configuration Release
XCODEBUILD: (9 failures)
External Error: *** capture failed to execute: exited with code 65
Error backtrace:
Raised at Stdlib.input_line.scan in file "stdlib.ml", line 456, characters 14-31
Called from Stdio__In_channel.input_line_exn in file "src/in_channel.ml" (inlined), line 64, characters 13-32
Called from IBase__Utils.with_channel_in in file "src/base/Utils.ml", line 257, characters 11-44
Re-raised at IBase__Die.raise_error.do_raise in file "src/base/Die.ml", line 26, characters 8-58
Called from Integration__Driver.capture in file "src/integration/Driver.ml", line 223, characters 10-40
Called from Integration__Driver.capture.(fun) in file "src/integration/Driver.ml", line 267, characters 2-29
Called from IBase__Utils.timeit in file "src/base/Utils.ml", line 400, characters 16-20
Called from IBase__StatsLogging.execute_with_time_logging in file "src/base/StatsLogging.ml", line 103, characters 26-41
Called from Backend__GCStats.log_f in file "src/backend/GCStats.ml", line 93, characters 10-14
Called from Integration__Driver.run in file "src/integration/Driver.ml", line 591, characters 2-36
Called from IBase__Utils.timeit in file "src/base/Utils.ml", line 400, characters 16-20
Called from IBase__StatsLogging.execute_with_time_logging in file "src/base/StatsLogging.ml", line 103, characters 26-41
Called from Integration__Driver.run in file "src/integration/Driver.ml", line 597, characters 2-74
Called from Dune__exe__Infer in file "src/infer.ml", line 136, characters 6-59
Run the command again with `--keep-going` to try and ignore this error.
❌ Failed to run 'infer capture' with build cmd: xcodebuild clean build -sdk iphoneos -project [PROJECT].xcodeproj -configuration Release -j 8 BUILD_DIR=.tmp CONFIGURATION_BUILD_DIR=.tmp/Release FRAMEWORK_SEARCH_PATHS="\$(FRAMEWORK_SEARCH_PATHS) \$(inherited) \$(PROJECT_DIR)/.deps" OTHER_CFLAGS="\$(OTHER_CFLAGS) -D NS_BLOCK_ASSERTIONS=1" ENABLE_BITCODE=NO ONLY_ACTIVE_ARCH=NO BUILD_LIBRARY_FOR_DISTRIBUTION=YES DEAD_CODE_STRIPPING=YES STRIP_STYLE=debugging GCC_OPTIMIZATION_LEVEL=s VALID_ARCHS='arm64' COMPILER_INDEX_STORE_ENABLE=NO SKIP_INSTALL=NO MACH_O_TYPE=staticlib IPHONEOS_DEPLOYMENT_TARGET=15.1 GCC_GENERATE_DEBUGGING_SYMBOLS=NO -scheme [PROJECT]
make: *** [infer] Error 1
```
---
## Test with new project
I created new project with ObjC, no additional code and run the infer v.1.2.0 and the error code 65 happens similarly
```bash
➜ ~ /usr/local/bin/infer run -- xcodebuild -sdk iphoneos -project /Users/[USER]/Documents/[PROJECT_PATH]/[PROJECT].xcodeproj -scheme [SCHEME] -configuration Debug clean build
Capturing in xcodebuild mode...
XCODEBUILD: Command line invocation:
XCODEBUILD: /Applications/Xcode26.app/Contents/Developer/usr/bin/xcodebuild \
XCODEBUILD: -sdk iphoneos \
XCODEBUILD: -project /Users/[USER]/Documents/[PROJECT_PATH]/[PROJECT].xcodeproj \
XCODEBUILD: -scheme [SCHEME] \
XCODEBUILD: configuration Debug clean build \
XCODEBUILD: CC=/usr/local/lib/infer/infer/lib/wrappers/clang \
XCODEBUILD: CPLUSPLUS=/usr/local/lib/infer/infer/lib/wrappers/clang++ \
XCODEBUILD: GCC_PRECOMPILE_PREFIX_HEADER=NO
XCODEBUILD:
XCODEBUILD: Build settings from command line:
XCODEBUILD: CC = /usr/local/lib/infer/infer/lib/wrappers/clang
XCODEBUILD: CPLUSPLUS = /usr/local/lib/infer/infer/lib/wrappers/clang++
XCODEBUILD: GCC_PRECOMPILE_PREFIX_HEADER = NO
XCODEBUILD: SDKROOT = iphoneos26.2
XCODEBUILD:
XCODEBUILD: Writing error result bundle to /var/folders/[TEMP_PATH]/ResultBundle.xcresult
XCODEBUILD: xcodebuild: error: Unknown build action 'configuration'.
External Error: *** capture failed to execute: exited with code 65
Error backtrace:
Raised at Stdlib.input_line.scan in file "stdlib.ml", line 456
Called from Stdio__In_channel.input_line_exn in file "src/in_channel.ml", line 64
Called from IBase__Utils.with_channel_in in file "src/base/Utils.ml", line 257
Re-raised at IBase__Die.raise_error.do_raise in file "src/base/Die.ml", line 26
Called from Integration__Driver.capture in file "src/integration/Driver.ml", line 223
Called from Integration__Driver.capture.(fun) in file "src/integration/Driver.ml", line 267
Called from IBase__Utils.timeit in file "src/base/Utils.ml", line 400
Called from IBase__StatsLogging.execute_with_time_logging in file "src/base/StatsLogging.ml", line 103
Called from Backend__GCStats.log_f in file "src/backend/GCStats.ml", line 93
Called from Integration__Driver.run in file "src/integration/Driver.ml", line 591
Called from IBase__Utils.timeit in file "src/base/Utils.ml", line 400
Called from IBase__StatsLogging.execute_with_time_logging in file "src/base/StatsLogging.ml", line 103
Called from Integration__Driver.run in file "src/integration/Driver.ml", line 597
Called from Dune__exe__Infer in file "src/infer.ml", line 136
Run the command again with `--keep-going` to try and ignore this error.
```
Contributor guide
Assessment
This issue has not been assessed yet.