Repository navigation
rootcling crashes (SIGSEGV) on Xcode 27 when SDKROOT is set to an empty string #23712
Description
Check duplicate issues.
- Checked for duplicates
Description
Summary
rootcling crashes with a segmentation fault (exit 139) when the environment
variable SDKROOT is present but empty, on macOS 27 / Xcode 27. The same
command succeeds when SDKROOT is unset, or set to a real SDK path.
Root cause is in cling's macOS sysroot discovery,
interpreter/cling/lib/Interpreter/CIFactory.cpp:383:
if (!llvm::sys::fs::exists(cling_osx_sysroot_directory)) { // no -isysroot passed
if (!::getenv("SDKROOT")) { // ← BUG
// fallback: run `xcrun --show-sdk-path`, add it as -isysroot
}
}getenv returns non-NULL for the empty string, so cling assumes the driver
"handles SDKROOT internally" (per the comment) and skips the xcrun
fallback. But the driver rejects an empty SDKROOT
(clang/lib/Driver/ToolChains/Darwin.cpp:2369 requires
is_absolute(env) && exists(env)), so the process ends up with no sysroot
at all. Xcode 27's restructured libc++ headers (__new/, __stdlib/,
__configuration/ layout) require the SDK C headers to be chained in via the
sysroot; without it, ldiv_t / __BYTE_ORDER__ errors cascade and rootcling
segfaults. (With the pre-Xcode-27 libc++ layout the missing sysroot happened
to be harmless, which is why this only surfaced after upgrading Xcode.)
This breaks dictionary generation for any downstream project that uses
ROOT_GENERATE_DICTIONARY without setting CMAKE_OSX_SYSROOT, because
ROOT's own RootMacros.cmake (line 676) unconditionally passes
SDKROOT=${CMAKE_OSX_SYSROOT} to rootcling:
set(command ${CMAKE_COMMAND} -E env SDKROOT=${CMAKE_OSX_SYSROOT} ${rootcling_exe})With an empty CMAKE_OSX_SYSROOT this becomes cmake -E env SDKROOT= rootcling ...
— exactly the failing case.
Environment
| component | version |
|---|---|
| macOS | 27.0.1 (Darwin 27.0.0, arm64) |
| Xcode | 27.0 (Apple clang 21.0.0 / SDK MacOSX27.0) |
| ROOT | 6.41.01, self-built from master, builtin_llvm=ON, builtin_clang=ON |
| CMake | 4.4.4 |
Worked before upgrading macOS/Xcode (same ROOT build recipe, Xcode 16 era).
Minimal reproducer
mkdir /tmp/repro && cd /tmp/repro
printf '#pragma once\nstruct Dummy_t { double x; };\n' > dummy.hh
printf '#pragma link C++ class Dummy_t;\n' > LinkDef.h
# 1) SDKROOT unset -> PASS
env -u SDKROOT rootcling -f d1.cxx dummy.hh LinkDef.h
# 2) SDKROOT empty string -> FAIL, exit 139 (SIGSEGV)
env SDKROOT= rootcling -f d2.cxx dummy.hh LinkDef.h
# 3) SDKROOT = real SDK path -> PASS
env SDKROOT=$(xcrun --show-sdk-path) rootcling -f d3.cxx dummy.hh LinkDef.hOnly case 2 fails.
Observed output (case 2)
Header search breaks inside the Xcode 27 libc++ headers — the C library
symbols/types never get pulled in, then the __BYTE_ORDER__ check trips, and
rootcling finally segfaults (stack through cling::IncrementalParser /
TCling / TROOT::InitInterpreter):
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/c++/v1/stdlib.h:126:30: error: unknown type name 'ldiv_t'
/Applications/Xcode.app/.../c++/v1/stdlib.h:126:82: error: no member named 'ldiv' in the global namespace; did you mean 'div'?
/Applications/Xcode.app/.../c++/v1/stdlib.h:128:30: error: unknown type name 'lldiv_t'
/Applications/Xcode.app/.../c++/v1/__configuration/platform.h:46:4: error: "Your compiler doesn't seem to define __BYTE_ORDER__, which is required by libc++ to know the endianness of your target platform"
... (cling call stack, "no debug info") ...
Segmentation fault: rootcling exits with 139
Control experiment
The system compiler is NOT affected by an empty SDKROOT, so this is
specific to the clang bundled with ROOT:
printf '#include <new>\nint main(){}\n' > t.cpp
env SDKROOT= clang++ -std=c++23 -fsyntax-only t.cpp # PASS (Apple clang 21.0.0)Suggested fixes (either layer fixes it)
-
interpreter/cling/lib/Interpreter/CIFactory.cpp:383: treat an empty
SDKROOTas unset, e.g.const char *env = ::getenv("SDKROOT"); if (!env || !*env) { // xcrun --show-sdk-path fallback }
-
RootMacros.cmake(ROOT_GENERATE_DICTIONARY): only inject
SDKROOT=...into the env whenCMAKE_OSX_SYSROOTis non-empty.
Workaround for downstream projects
Configure with an explicit sysroot so the injected value is never empty:
cmake -S . -B build -DCMAKE_OSX_SYSROOT="$(xcrun --show-sdk-path)"Reproducer
Minimal reproducer
mkdir /tmp/repro && cd /tmp/repro
printf '#pragma once\nstruct Dummy_t { double x; };\n' > dummy.hh
printf '#pragma link C++ class Dummy_t;\n' > LinkDef.h
# 1) SDKROOT unset -> PASS
env -u SDKROOT rootcling -f d1.cxx dummy.hh LinkDef.h
# 2) SDKROOT empty string -> FAIL, exit 139 (SIGSEGV)
env SDKROOT= rootcling -f d2.cxx dummy.hh LinkDef.h
# 3) SDKROOT = real SDK path -> PASS
env SDKROOT=$(xcrun --show-sdk-path) rootcling -f d3.cxx dummy.hh LinkDef.hOnly case 2 fails.
Observed output (case 2)
Header search breaks inside the Xcode 27 libc++ headers — the C library
symbols/types never get pulled in, then the __BYTE_ORDER__ check trips, and
rootcling finally segfaults (stack through cling::IncrementalParser /
TCling / TROOT::InitInterpreter):
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/c++/v1/stdlib.h:126:30: error: unknown type name 'ldiv_t'
/Applications/Xcode.app/.../c++/v1/stdlib.h:126:82: error: no member named 'ldiv' in the global namespace; did you mean 'div'?
/Applications/Xcode.app/.../c++/v1/stdlib.h:128:30: error: unknown type name 'lldiv_t'
/Applications/Xcode.app/.../c++/v1/__configuration/platform.h:46:4: error: "Your compiler doesn't seem to define __BYTE_ORDER__, which is required by libc++ to know the endianness of your target platform"
... (cling call stack, "no debug info") ...
Segmentation fault: rootcling exits with 139
ROOT version
6.40.01
Installation method
build from source
Operating system
macos 27
Additional context
xcode 27
Metadata
Metadata
Assignees
Type
Projects
- StatusShow more project fieldsNo status
Activity
[cling] treat empty SDKROOT as unset
[cling] treat empty SDKROOT as unset
treat empty SDKROOT as unset
[cling] treat empty SDKROOT as unset
[cling] treat empty SDKROOT as unset