When cross-compiling to aarch64-pc-windows-msvc from a Linux host, psm selects the GAS assembly file (aarch_aapcs64.s) but skips the preprocessor flag (-xassembler-with-cpp) and platform defines (CFG_TARGET_OS_windows, etc.) because the compiler is detected as MSVC-like (clang-cl).
This causes the assembly to fall into the #else (Linux/ELF) path in aarch_aapcs64.s, which emits .type and .size directives that COFF targets reject.
Root Cause
In build.rs, line 84:
let masm = msvc && var("HOST").expect("HOST env not set").contains("windows");
This correctly detects that MASM isn't available when cross-compiling from Linux. The GAS .s file is selected as the fallback (line 30-36).
However, lines 101-106 skip preprocessing for all MSVC compilers:
if !msvc {
cfg.flag("-xassembler-with-cpp");
cfg.define(&*format!("CFG_TARGET_OS_{}", os), None);
cfg.define(&*format!("CFG_TARGET_ARCH_{}", arch), None);
cfg.define(&*format!("CFG_TARGET_ENV_{}", env), None);
}
When msvc is true but masm is false (cross-compiling from Linux), the .s file is used but doesn't get the preprocessor or CFG_TARGET_OS_windows define. The macros in aarch_aapcs64.s (lines 13-17) don't match, falling through to the ELF code path which emits directives incompatible with COFF.
Reproduction
# On a Linux host with clang, lld, and Rust nightly:
rustup target add aarch64-pc-windows-msvc
cargo install cargo-xwin
cargo xwin build --target aarch64-pc-windows-msvc
Any crate depending on stacker (which depends on psm) will fail with:
src/arch/aarch_aapcs64.s:32:7: error: expected absolute expression
src/arch/aarch_aapcs64.s:38:1: error: unknown directive
The x86_64-pc-windows-msvc target is not affected because it uses a separate x86_64_windows_gnu.s file that doesn't rely on these preprocessor macros.
Suggested Fix
Change line 101 from:
to:
When cross-compiling to
aarch64-pc-windows-msvcfrom a Linux host, psm selects the GAS assembly file (aarch_aapcs64.s) but skips the preprocessor flag (-xassembler-with-cpp) and platform defines (CFG_TARGET_OS_windows, etc.) because the compiler is detected as MSVC-like (clang-cl).This causes the assembly to fall into the
#else(Linux/ELF) path inaarch_aapcs64.s, which emits.typeand.sizedirectives that COFF targets reject.Root Cause
In
build.rs, line 84:This correctly detects that MASM isn't available when cross-compiling from Linux. The GAS
.sfile is selected as the fallback (line 30-36).However, lines 101-106 skip preprocessing for all MSVC compilers:
When
msvcis true butmasmis false (cross-compiling from Linux), the.sfile is used but doesn't get the preprocessor orCFG_TARGET_OS_windowsdefine. The macros inaarch_aapcs64.s(lines 13-17) don't match, falling through to the ELF code path which emits directives incompatible with COFF.Reproduction
# On a Linux host with clang, lld, and Rust nightly: rustup target add aarch64-pc-windows-msvc cargo install cargo-xwin cargo xwin build --target aarch64-pc-windows-msvcAny crate depending on
stacker(which depends onpsm) will fail with:The
x86_64-pc-windows-msvctarget is not affected because it uses a separatex86_64_windows_gnu.sfile that doesn't rely on these preprocessor macros.Suggested Fix
Change line 101 from:
to: