Skip to content

Commit 8fc2eb6

Browse files
inoway46aduh95
authored andcommitted
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: #66897 Refs: #66803 Assisted-by: Codex Signed-off-by: inoway46 <[email protected]> PR-URL: #66823 Reviewed-By: Chengzhong Wu <[email protected]>
1 parent ee779f1 commit 8fc2eb6

3 files changed

Lines changed: 92 additions & 2 deletions

File tree

‎BUILDING.md‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1075,6 +1075,12 @@ a warning is printed and Temporal support is disabled.
10751075

10761076
Passing both options to `configure.py` is an error.
10771077

1078+
For non-Windows cross builds with bundled Temporal, set `CARGO_BUILD_TARGET`
1079+
to the Rust target triple when running `configure.py` (for example,
1080+
`aarch64-unknown-linux-gnu`). Otherwise, Temporal support is disabled with a
1081+
warning, or `configure.py` stops with an error when
1082+
`--v8-enable-temporal-support` is passed.
1083+
10781084
## Building Node.js with external core modules
10791085

10801086
It is possible to specify one or more JavaScript text files to be bundled in

‎configure.py‎

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1620,6 +1620,55 @@ def get_rustc_version(rustc):
16201620
warn(f'Could not recognize `rustc`: {rustc_ret}')
16211621
return '0.0'
16221622

1623+
# Prefixes of Rust target triple architectures for each GYP architecture.
1624+
rust_arch_prefixes = {
1625+
'arm': ('arm', 'thumb'),
1626+
'arm64': ('aarch64',),
1627+
'ia32': ('i386', 'i586', 'i686'),
1628+
'loong64': ('loongarch64',),
1629+
'mips64el': ('mips64el',),
1630+
'mipsel': ('mipsel',),
1631+
'ppc64': ('powerpc64',),
1632+
'riscv64': ('riscv64',),
1633+
's390x': ('s390x',),
1634+
'x64': ('x86_64',),
1635+
}
1636+
1637+
def get_rust_cross_targets(host_arch, default_target):
1638+
"""Returns (host triple, target triple, problem). problem is non-empty when
1639+
the triples for a bundled Temporal cross build cannot be determined."""
1640+
rust_target = os.environ.get('CARGO_BUILD_TARGET', '') or default_target
1641+
if not rust_target:
1642+
return '', '', 'Cross compilation with bundled Temporal requires CARGO_BUILD_TARGET.'
1643+
1644+
rust_host_target = ''
1645+
rustc = os.environ.get('RUSTC', 'rustc')
1646+
try:
1647+
version = subprocess.check_output(shlex.split(rustc) + ['-vV'],
1648+
stderr=subprocess.PIPE, text=True)
1649+
except (OSError, subprocess.CalledProcessError):
1650+
version = ''
1651+
match = re.search(r'^host: (\S+)$', version, re.MULTILINE)
1652+
if match:
1653+
rust_host_target = match.group(1)
1654+
if not rust_host_target:
1655+
return '', '', 'Cannot determine the Rust host triple from `rustc -vV`.'
1656+
1657+
# The host toolset follows CC_host, which may build 32-bit host tools for
1658+
# 32-bit targets (e.g. CC_host="gcc -m32") on a 64-bit Rust host.
1659+
rust_host_arch, _, rust_host_rest = rust_host_target.partition('-')
1660+
if not rust_host_arch.startswith(rust_arch_prefixes.get(host_arch, ('',))):
1661+
if host_arch == 'ia32' and rust_host_arch == 'x86_64':
1662+
rust_host_target = f'i686-{rust_host_rest}'
1663+
else:
1664+
return '', '', (f'Rust host triple {rust_host_target} does not match '
1665+
f'the host toolset architecture {host_arch} (CC_host).')
1666+
1667+
for triple in (rust_host_target, rust_target):
1668+
if not re.fullmatch(r'[A-Za-z0-9_]+(?:-[A-Za-z0-9_]+)+', triple):
1669+
error('Rust targets must be target triples, not paths to target JSON files')
1670+
return rust_host_target, rust_target, ''
1671+
16231672
# Note: Apple clang self-reports as clang 4.2.0 and gcc 4.2.1. It passes
16241673
# the version check more by accident than anything else but a more rigorous
16251674
# check involves checking the build number against an allowlist. I'm not
@@ -1957,6 +2006,23 @@ def configure_node(o):
19572006
os.environ['GYP_CROSSCOMPILE'] = "1"
19582007

19592008
o['variables']['want_separate_host_toolset'] = int(cross_compiling)
2009+
o['variables']['cargo_cross_compiling'] = 0
2010+
if (flavor != 'win' and cross_compiling and
2011+
not options.v8_disable_temporal_support and not options.shared_temporal_capi):
2012+
# Only bundled Temporal cross builds need explicit per-toolset Rust targets.
2013+
rust_host_target, rust_target, problem = get_rust_cross_targets(
2014+
host_arch, o['variables']['cargo_rust_target'])
2015+
if problem:
2016+
# Like a missing Rust toolchain, this is only fatal when Temporal support
2017+
# was explicitly requested.
2018+
if options.v8_enable_temporal_support:
2019+
error(problem)
2020+
warn(f'{problem} Support for Temporal will be disabled.')
2021+
options.v8_disable_temporal_support = True
2022+
else:
2023+
o['variables']['cargo_cross_compiling'] = 1
2024+
o['variables']['cargo_rust_target_target'] = rust_target
2025+
o['variables']['cargo_rust_target_host'] = rust_host_target
19602026

19612027
if target_arch == 'arm64':
19622028
o['variables']['arm_fpu'] = options.arm_fpu or 'neon'

‎deps/crates/crates.gyp‎

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,18 @@
66
'zoneinfo64_dir': 'zoneinfo64-v0_3',
77
'temporal_zoneinfo64_data_output': '<(SHARED_INTERMEDIATE_DIR)/src/builtins/builtins-temporal-zoneinfo64-data.cc',
88
'cargo_rust_target%': '',
9+
'cargo_cross_compiling%': 0,
10+
'cargo_rust_target_host%': '',
11+
'cargo_rust_target_target%': '',
912
},
1013
'conditions': [
1114
['build_type == "Release"', {
1215
'variables': {
1316
'cargo_build_flags': ['--release'],
17+
'cargo_profile': 'release',
1418
},
1519
'conditions': [
16-
['cargo_rust_target!=""', {
20+
['cargo_rust_target!="" and cargo_cross_compiling==0', {
1721
'variables': {
1822
'cargo_build_flags': ['--target', '<(cargo_rust_target)'],
1923
}
@@ -31,6 +35,7 @@
3135
}, {
3236
'variables': {
3337
'cargo_build_flags': [],
38+
'cargo_profile': 'debug',
3439
},
3540
'conditions': [
3641
['OS=="win"', {
@@ -50,6 +55,18 @@
5055
'target_name': 'node_crates',
5156
'type': 'none',
5257
'toolsets': ['host', 'target'],
58+
'variables': {
59+
'cargo_output_dir': '<(SHARED_INTERMEDIATE_DIR)',
60+
'cargo_cross_target_flags': [],
61+
'conditions': [
62+
['cargo_cross_compiling==1', {
63+
'cargo_output_dir': '<(SHARED_INTERMEDIATE_DIR)/cargo/<(_toolset)',
64+
'cargo_cross_target_flags': ['--target', '<(cargo_rust_target_<(_toolset))'],
65+
# Referencing cargo_output_dir here would use its pre-condition value.
66+
'node_crates_libpath': '<(SHARED_INTERMEDIATE_DIR)/cargo/<(_toolset)/<(cargo_rust_target_<(_toolset))/<(cargo_profile)/<(STATIC_LIB_PREFIX)node_crates<(STATIC_LIB_SUFFIX)',
67+
}],
68+
],
69+
},
5370
'hard_dependency': 1,
5471
'sources': [
5572
'Cargo.toml',
@@ -103,10 +120,11 @@
103120
'action': [
104121
'<(cargo)',
105122
'rustc',
123+
'<@(cargo_cross_target_flags)',
106124
'<@(cargo_build_flags)',
107125
'--frozen',
108126
'--target-dir',
109-
'<(SHARED_INTERMEDIATE_DIR)'
127+
'<(cargo_output_dir)'
110128
],
111129
}
112130
],

0 commit comments

Comments
 (0)