fix: override host-specific variables when reading headers config.gypi#3303
Open
iFwu wants to merge 1 commit intonodejs:mainfrom
Open
fix: override host-specific variables when reading headers config.gypi#3303iFwu wants to merge 1 commit intonodejs:mainfrom
iFwu wants to merge 1 commit intonodejs:mainfrom
Conversation
The official Node release headers tarball is a single universal artifact shipped to all platforms, but its embedded config.gypi reflects the build host of the Node release-engineering machine (currently Linux x64 / GCC). When a consumer on a different host inherits it verbatim via --disturl or --nodedir (PR nodejs#2497), host-specific fields end up wrong: * host_arch is x64 even on arm64 hosts * clang is 0 even when the local toolchain is clang * llvm_version, xcode_version, arm_fpu, gas_version, shlib_suffix similarly reflect the build farm rather than the local host The most visible symptom is on macOS arm64, where clang=0 silently drops the `clang==1` branches in common.gypi (notably -std=gnu++20). C++ compilation then falls back to C++03 and node-addon-api/napi.h fails with "no template named initializer_list", "unknown type name constexpr", etc. Affected scope: anyone with disturl set in .npmrc or env (China mirrors such as npmmirror/taobao, self-hosted Nexus/JFrog with disturl rewriting, Electron projects via electron-rebuild). See electron/rebuild#1209 for the original report. Override only the host-specific variables from process.config after parsing the headers' config.gypi. PR nodejs#2497's intent is preserved: target build config (v8 features, bundled vs shared deps, node_module_version, etc.) still comes from the headers tarball; only host fields are corrected. Verified that the fix is a no-op on Linux x64 (all 7 fields already match between cache and process.config) and necessary on macOS arm64 (all 7 fields mismatched). Refs: nodejs#2497, electron/rebuild#1209 Signed-off-by: iFwu <blanu@live.com> Made-with: Cursor
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Background
getBaseConfigGypireads\$nodedir/include/node/config.gypiverbatim whenever--disturl,--dist-url, or--nodediris set (and--force-process-configis not). This was introduced in #2497 to let Electron / NW.js builds pick up target build config from custom headers.The official Node release headers tarball is, however, a single universal artifact shipped to all platforms, and its embedded
config.gypireflects the build host of the Node release-engineering machine (currently a Linux x64 / GCC box). When a consumer on a different host inherits it verbatim, host-specific fields end up wrong.Symptom on macOS arm64
Field-by-field diff between the cached headers'
config.gypiandprocess.config.variableson darwin/arm64 with Node v24.13.1:The killer is
clang=0: Node'scommon.gypigates-std=gnu++20(and several other flags) onclang==1. Withclang=0those branches never fire, C++ compilation falls back to C++03, and any addon usingnode-addon-apiimmediately fails with:```
node-addon-api/napi.h: error: a space is required between consecutive right angle brackets (use '> >')
node-addon-api/napi.h: error: no template named 'initializer_list' in namespace 'std'
node-addon-api/napi.h: error: unknown type name 'constexpr'
```
For comparison, on Linux x64 / Node v24.13.1 the same diff shows all 7 host-specific fields are identical between cache and process.config (the cache literally is a Linux x64 build farm fingerprint), so the fix in this PR is a strict no-op there.
Minimal repro (no Electron required)
```bash
mkdir /tmp/repro && cd /tmp/repro
cat > package.json <<'EOF'
{"name":"r","dependencies":{"node-addon-api":"^8.0.0"}}
EOF
cat > binding.gyp <<'EOF'
{"targets":[{"target_name":"r","sources":["r.cc"],
"include_dirs":["<!@(node -p \"require('node-addon-api').include\")"],
"dependencies":["<!(node -p \"require('node-addon-api').gyp\")"]}]}
EOF
echo '#include <napi.h>' > r.cc
npm install --ignore-scripts
Works:
npx node-gyp rebuild
Fails (anywhere disturl is set):
npm_config_disturl=https://npmmirror.com/mirrors/node npx node-gyp rebuild
```
Affected scope
Anyone with `disturl` set in `~/.npmrc`, project `.npmrc`, or as `npm_config_disturl` env var. Common cases:
Why `--force-process-config` is not a real fix
node_module_versionmismatch — Electron then refuses to load the addon. See Revert setting of--force-process-config… pulsar-edit/ppm#162 (2025-12, reverting--force-process-configafter exactly this).Fix
Override only the host-specific variables from
process.config.variablesafter parsing the headers'config.gypi:```js
const HOST_SPECIFIC_VARIABLES = [
'host_arch',
'clang',
'llvm_version',
'xcode_version',
'arm_fpu',
'gas_version',
'shlib_suffix'
]
```
PR #2497's intent is preserved — target build config (v8 features, bundled vs shared deps,
node_module_version, etc.) still comes from the headers tarball; only host (build machine) fields are corrected.Verification
npm test: 108 passing, 6 pending — unchanged from main).test/test-create-config-gypi.jscovering the override behaviour and--force-process-configback-compat, with a new fixturetest/fixtures/nodedir-mismatched-host/that mimics a Linux x64 build farm headers tarball.npm run lintclean for changed files.Open questions for maintainers
HOST_SPECIFIC_VARIABLESset complete? It was derived from a full diff on macOS arm64; would appreciate a sanity check on Windows arm64 / FreeBSD / AIX.Related
--force-process-config… pulsar-edit/ppm#162 —--force-process-configside-effect on Electron module_versionMade with Cursor