You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Command Line Tools: 26.6 (installed via Software Update, independent of Xcode.app)
Bug description
On macOS, node-gyp rebuild invokes clang++ without either -isysroot or --sdk. This makes the clang driver fall back to its own internal call to xcrun --show-sdk-path (with no --sdk argument). Verified via xcrun -v that this specific call variant resolves via a cache key hard-coded to /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk -- independent of xcode-select/DEVELOPER_DIR, and independent of whichever Xcode toolchain actually supplies the invoked clang++ binary. (By contrast, xcrun --sdk macosx --show-sdk-path -- i.e. with an explicit SDK name -- does respect DEVELOPER_DIR/xcode-select.)
On systems where the OS has been updated (bumping the standalone CommandLineTools SDK) but the selected Xcode.app has not, this pairs a newer SDK's libc++ headers (which reference builtins like __builtin_ctzg/__builtin_clzg, requiring Clang >= 19) with an older embedded clang (16.0.0 from Xcode 16.2), producing:
error: use of undeclared identifier '__builtin_ctzg'
Root cause in gyp's own code
gyp/pylib/gyp/xcode_emulation.py already contains logic that avoids this, by explicitly naming the SDK when querying xcrun, and by passing -isysroot:
# GetSDKVersionInfoItemreturnGetStdoutQuiet(["xcrun", "--sdk", sdk, infoitem]) # explicit --sdk, respects DEVELOPER_DIR# GetCflagsif"SDKROOT"inself._Settings() andsdk_root:
cflags.append("-isysroot %s"%sdk_root) # only appended if SDKROOT is explicitly set in xcode_settings
(Line numbers 525 / 581-582 in the 9.4.1 tag I actually hit this on; confirmed the exact same structure -- same gating -- is still present at line 522 / 578-579 in the current latest release, v13.0.1, published 2026-07-02. Also checked that release's CHANGELOG for any macOS SDK/clang-related fix; found none.)
This mirrors what CMake does (Modules/Platform/Darwin-Initialize.cmake: xcrun --sdk macosx --show-sdk-path), which correctly resolves the SDK paired with the active developer directory, and does not hit this issue on the same machine/OS update.
However, -isysroot is only emitted if the target's binding.gyp (or a shared .gypi) sets SDKROOT under xcode_settings. Neither node-gyp's own addon.gypi, node's cached common.gypi, nor common third-party native modules (checked diskusage, better-sqlite3, node-pty) set SDKROOT. As a result, no -isysroot is passed for ordinary builds, and clang falls through to the SDK-resolution path described above.
Steps to reproduce
On a Mac where the standalone CommandLineTools SDK has been updated (via Software Update) to a version requiring Clang >= 19 builtins, while xcode-select still points at an older Xcode with an older embedded clang.
npm install / yarn install any package with a native addon (e.g. diskusage, better-sqlite3, node-pty).
node-gyp rebuild fails with __builtin_ctzg/__builtin_clzg undeclared identifier errors, even though xcodebuild/CMake-based builds on the same machine succeed.
Expected behavior
The SDK-resolution path gyp uses by default (when SDKROOT is not explicitly configured) should pair the SDK with the actual compiler in use -- e.g. by always querying xcrun --sdk macosx --show-sdk-path instead of the no---sdk variant -- rather than relying on a system-wide default that can silently drift out of sync with the selected Xcode/CLT compiler.
Same root cause, labeled bug and fixed upstream: terasakisatoshi/CxxFork.jl#24 -- "Avoid blindly preferring MacOSX.sdk / latest SDK symlinks when their libc++ headers are incompatible with the embedded Clang path."
Environment
xcode-select -p->/Applications/Xcode-16.2.0.app/Contents/DeveloperBug description
On macOS,
node-gyp rebuildinvokesclang++without either-isysrootor--sdk. This makes the clang driver fall back to its own internal call toxcrun --show-sdk-path(with no--sdkargument). Verified viaxcrun -vthat this specific call variant resolves via a cache key hard-coded to/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk-- independent ofxcode-select/DEVELOPER_DIR, and independent of whichever Xcode toolchain actually supplies the invokedclang++binary. (By contrast,xcrun --sdk macosx --show-sdk-path-- i.e. with an explicit SDK name -- does respectDEVELOPER_DIR/xcode-select.)On systems where the OS has been updated (bumping the standalone CommandLineTools SDK) but the selected Xcode.app has not, this pairs a newer SDK's libc++ headers (which reference builtins like
__builtin_ctzg/__builtin_clzg, requiring Clang >= 19) with an older embedded clang (16.0.0 from Xcode 16.2), producing:Root cause in gyp's own code
gyp/pylib/gyp/xcode_emulation.pyalready contains logic that avoids this, by explicitly naming the SDK when querying xcrun, and by passing-isysroot:(Line numbers 525 / 581-582 in the 9.4.1 tag I actually hit this on; confirmed the exact same structure -- same gating -- is still present at line 522 / 578-579 in the current latest release,
v13.0.1, published 2026-07-02. Also checked that release's CHANGELOG for any macOS SDK/clang-related fix; found none.)This mirrors what CMake does (
Modules/Platform/Darwin-Initialize.cmake:xcrun --sdk macosx --show-sdk-path), which correctly resolves the SDK paired with the active developer directory, and does not hit this issue on the same machine/OS update.However,
-isysrootis only emitted if the target'sbinding.gyp(or a shared.gypi) setsSDKROOTunderxcode_settings. Neither node-gyp's ownaddon.gypi, node's cachedcommon.gypi, nor common third-party native modules (checkeddiskusage,better-sqlite3,node-pty) setSDKROOT. As a result, no-isysrootis passed for ordinary builds, and clang falls through to the SDK-resolution path described above.Steps to reproduce
xcode-selectstill points at an older Xcode with an older embedded clang.npm install/yarn installany package with a native addon (e.g.diskusage,better-sqlite3,node-pty).node-gyp rebuildfails with__builtin_ctzg/__builtin_clzgundeclared identifier errors, even thoughxcodebuild/CMake-based builds on the same machine succeed.Expected behavior
The SDK-resolution path gyp uses by default (when
SDKROOTis not explicitly configured) should pair the SDK with the actual compiler in use -- e.g. by always queryingxcrun --sdk macosx --show-sdk-pathinstead of the no---sdkvariant -- rather than relying on a system-wide default that can silently drift out of sync with the selected Xcode/CLT compiler.Workaround (confirmed working)
Pin toolchain and SDK together, either direction:
DEVELOPER_DIR=/Library/Developer/CommandLineTools npm install # newer clang + newer SDK, pairedSDKROOT=/Applications/Xcode-16.2.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.2.sdk npm install # older clang + older SDK, pairedRelated
bugand fixed upstream: terasakisatoshi/CxxFork.jl#24 -- "Avoid blindly preferringMacOSX.sdk/ latest SDK symlinks when their libc++ headers are incompatible with the embedded Clang path."builtin_ctzg,isysroot,SDKROOT,DEVELOPER_DIR,CommandLineTools,Tahoe/"macOS 26" -- closest existing issues (node-gyp fails on Sonoma with CLI only and not XCode (Mac M1 / Apple Silicon) #2992, node-gyp build fails obscurely if no Xcode or CLT are found #3064, Xcode detection issue #3137) are about detecting the Xcode/CLT version, not this SDK/compiler pairing mismatch, so this appears to be a distinct report.