Commit eb3ae472b68 for nodejs
commit eb3ae472b68dccff74f96233dfa3701558b4dd9e
Author: Yuya Inoue <65857152+inoway46@users.noreply.github.com>
Date: Tue Nov 10 05:46:30 2026 +0900
build: separate host and target Rust artifacts in cross builds
Capture the Rust target and host triples during configure for bundled
Temporal cross builds. Use explicit Cargo targets and separate output
directories so host and target archives do not share a build rule.
If the triples cannot be determined, disable Temporal with a warning
unless it was explicitly enabled.
Fixes: https://github.com/nodejs/node/issues/66897
Refs: https://github.com/nodejs/node/issues/66803
Assisted-by: Codex
Signed-off-by: inoway46 <inoueyuya416@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/66823
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
diff --git a/BUILDING.md b/BUILDING.md
index e66d1974617..5ab3b7bb971 100644
--- a/BUILDING.md
+++ b/BUILDING.md
@@ -1071,6 +1071,12 @@ a warning is printed and Temporal support is disabled.
Passing both options to `configure.py` is an error.
+For non-Windows cross builds with bundled Temporal, set `CARGO_BUILD_TARGET`
+to the Rust target triple when running `configure.py` (for example,
+`aarch64-unknown-linux-gnu`). Otherwise, Temporal support is disabled with a
+warning, or `configure.py` stops with an error when
+`--v8-enable-temporal-support` is passed.
+
## Building Node.js with external core modules
It is possible to specify one or more JavaScript text files to be bundled in
diff --git a/configure.py b/configure.py
index d9d75443e7c..c6916b093cf 100755
--- a/configure.py
+++ b/configure.py
@@ -1597,6 +1597,55 @@ def get_rustc_version(rustc):
warn(f'Could not recognize `rustc`: {rustc_ret}')
return '0.0'
+# Prefixes of Rust target triple architectures for each GYP architecture.
+rust_arch_prefixes = {
+ 'arm': ('arm', 'thumb'),
+ 'arm64': ('aarch64',),
+ 'ia32': ('i386', 'i586', 'i686'),
+ 'loong64': ('loongarch64',),
+ 'mips64el': ('mips64el',),
+ 'mipsel': ('mipsel',),
+ 'ppc64': ('powerpc64',),
+ 'riscv64': ('riscv64',),
+ 's390x': ('s390x',),
+ 'x64': ('x86_64',),
+}
+
+def get_rust_cross_targets(host_arch, default_target):
+ """Returns (host triple, target triple, problem). problem is non-empty when
+ the triples for a bundled Temporal cross build cannot be determined."""
+ rust_target = os.environ.get('CARGO_BUILD_TARGET', '') or default_target
+ if not rust_target:
+ return '', '', 'Cross compilation with bundled Temporal requires CARGO_BUILD_TARGET.'
+
+ rust_host_target = ''
+ rustc = os.environ.get('RUSTC', 'rustc')
+ try:
+ version = subprocess.check_output(shlex.split(rustc) + ['-vV'],
+ stderr=subprocess.PIPE, text=True)
+ except (OSError, subprocess.CalledProcessError):
+ version = ''
+ match = re.search(r'^host: (\S+)$', version, re.MULTILINE)
+ if match:
+ rust_host_target = match.group(1)
+ if not rust_host_target:
+ return '', '', 'Cannot determine the Rust host triple from `rustc -vV`.'
+
+ # The host toolset follows CC_host, which may build 32-bit host tools for
+ # 32-bit targets (e.g. CC_host="gcc -m32") on a 64-bit Rust host.
+ rust_host_arch, _, rust_host_rest = rust_host_target.partition('-')
+ if not rust_host_arch.startswith(rust_arch_prefixes.get(host_arch, ('',))):
+ if host_arch == 'ia32' and rust_host_arch == 'x86_64':
+ rust_host_target = f'i686-{rust_host_rest}'
+ else:
+ return '', '', (f'Rust host triple {rust_host_target} does not match '
+ f'the host toolset architecture {host_arch} (CC_host).')
+
+ for triple in (rust_host_target, rust_target):
+ if not re.fullmatch(r'[A-Za-z0-9_]+(?:-[A-Za-z0-9_]+)+', triple):
+ error('Rust targets must be target triples, not paths to target JSON files')
+ return rust_host_target, rust_target, ''
+
# Note: Apple clang self-reports as clang 4.2.0 and gcc 4.2.1. It passes
# the version check more by accident than anything else but a more rigorous
# check involves checking the build number against an allowlist. I'm not
@@ -1934,6 +1983,23 @@ def configure_node(o):
os.environ['GYP_CROSSCOMPILE'] = "1"
o['variables']['want_separate_host_toolset'] = int(cross_compiling)
+ o['variables']['cargo_cross_compiling'] = 0
+ if (flavor != 'win' and cross_compiling and
+ not options.v8_disable_temporal_support and not options.shared_temporal_capi):
+ # Only bundled Temporal cross builds need explicit per-toolset Rust targets.
+ rust_host_target, rust_target, problem = get_rust_cross_targets(
+ host_arch, o['variables']['cargo_rust_target'])
+ if problem:
+ # Like a missing Rust toolchain, this is only fatal when Temporal support
+ # was explicitly requested.
+ if options.v8_enable_temporal_support:
+ error(problem)
+ warn(f'{problem} Support for Temporal will be disabled.')
+ options.v8_disable_temporal_support = True
+ else:
+ o['variables']['cargo_cross_compiling'] = 1
+ o['variables']['cargo_rust_target_target'] = rust_target
+ o['variables']['cargo_rust_target_host'] = rust_host_target
if target_arch == 'arm64':
o['variables']['arm_fpu'] = options.arm_fpu or 'neon'
diff --git a/deps/crates/crates.gyp b/deps/crates/crates.gyp
index 702e661f4d3..4961aca6f75 100644
--- a/deps/crates/crates.gyp
+++ b/deps/crates/crates.gyp
@@ -6,14 +6,18 @@
'zoneinfo64_dir': 'zoneinfo64-v0_3',
'temporal_zoneinfo64_data_output': '<(SHARED_INTERMEDIATE_DIR)/src/builtins/builtins-temporal-zoneinfo64-data.cc',
'cargo_rust_target%': '',
+ 'cargo_cross_compiling%': 0,
+ 'cargo_rust_target_host%': '',
+ 'cargo_rust_target_target%': '',
},
'conditions': [
['build_type == "Release"', {
'variables': {
'cargo_build_flags': ['--release'],
+ 'cargo_profile': 'release',
},
'conditions': [
- ['cargo_rust_target!=""', {
+ ['cargo_rust_target!="" and cargo_cross_compiling==0', {
'variables': {
'cargo_build_flags': ['--target', '<(cargo_rust_target)'],
}
@@ -31,6 +35,7 @@
}, {
'variables': {
'cargo_build_flags': [],
+ 'cargo_profile': 'debug',
},
'conditions': [
['OS=="win"', {
@@ -50,6 +55,18 @@
'target_name': 'node_crates',
'type': 'none',
'toolsets': ['host', 'target'],
+ 'variables': {
+ 'cargo_output_dir': '<(SHARED_INTERMEDIATE_DIR)',
+ 'cargo_cross_target_flags': [],
+ 'conditions': [
+ ['cargo_cross_compiling==1', {
+ 'cargo_output_dir': '<(SHARED_INTERMEDIATE_DIR)/cargo/<(_toolset)',
+ 'cargo_cross_target_flags': ['--target', '<(cargo_rust_target_<(_toolset))'],
+ # Referencing cargo_output_dir here would use its pre-condition value.
+ 'node_crates_libpath': '<(SHARED_INTERMEDIATE_DIR)/cargo/<(_toolset)/<(cargo_rust_target_<(_toolset))/<(cargo_profile)/<(STATIC_LIB_PREFIX)node_crates<(STATIC_LIB_SUFFIX)',
+ }],
+ ],
+ },
'hard_dependency': 1,
'sources': [
'Cargo.toml',
@@ -103,10 +120,11 @@
'action': [
'<(cargo)',
'rustc',
+ '<@(cargo_cross_target_flags)',
'<@(cargo_build_flags)',
'--frozen',
'--target-dir',
- '<(SHARED_INTERMEDIATE_DIR)'
+ '<(cargo_output_dir)'
],
}
],