Skip to content

Infer fails with iOS SDK 26 (Xcode 26) #2016

@khoilecontact

Description

@khoilecontact

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

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

~ /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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions