Skip to content

Commit e1dc224

Browse files
Jake-Shadlenagisa
authored andcommitted
Fix cross compilation for Windows
1 parent 6d3e250 commit e1dc224

File tree

1 file changed

+78
-17
lines changed

1 file changed

+78
-17
lines changed

psm/build.rs

+78-17
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,39 @@
11
extern crate cc;
22

3-
fn find_assembly(arch: &str, endian: &str, os: &str, env: &str) -> Option<(&'static str, bool)> {
3+
fn find_assembly(
4+
arch: &str,
5+
endian: &str,
6+
os: &str,
7+
env: &str,
8+
is_windows_host: bool,
9+
) -> Option<(&'static str, bool)> {
410
match (arch, endian, os, env) {
511
// The implementations for stack switching exist, but, officially, doing so without Fibers
612
// is not supported in Windows. For x86_64 the implementation actually works locally,
713
// but failed tests in CI (???). Might want to have a feature for experimental support
814
// here.
9-
("x86", _, "windows", "msvc") => Some(("src/arch/x86_msvc.asm", false)),
10-
("x86_64", _, "windows", "msvc") => Some(("src/arch/x86_64_msvc.asm", false)),
15+
("x86", _, "windows", "msvc") => {
16+
if is_windows_host {
17+
Some(("src/arch/x86_msvc.asm", false))
18+
} else {
19+
Some(("src/arch/x86_windows_gnu.s", false))
20+
}
21+
}
22+
("x86_64", _, "windows", "msvc") => {
23+
if is_windows_host {
24+
Some(("src/arch/x86_64_msvc.asm", false))
25+
} else {
26+
Some(("src/arch/x86_64_windows_gnu.s", false))
27+
}
28+
}
1129
("arm", _, "windows", "msvc") => Some(("src/arch/arm_armasm.asm", false)),
12-
("aarch64", _, "windows", "msvc") => Some(("src/arch/aarch64_armasm.asm", false)),
30+
("aarch64", _, "windows", "msvc") => {
31+
if is_windows_host {
32+
Some(("src/arch/aarch64_armasm.asm", false))
33+
} else {
34+
Some(("src/arch/aarch_aapcs64.s", false))
35+
}
36+
}
1337
("x86", _, "windows", _) => Some(("src/arch/x86_windows_gnu.s", false)),
1438
("x86_64", _, "windows", _) => Some(("src/arch/x86_64_windows_gnu.s", false)),
1539

@@ -37,21 +61,58 @@ fn main() {
3761
let env = ::std::env::var("CARGO_CFG_TARGET_ENV").unwrap();
3862
let os = ::std::env::var("CARGO_CFG_TARGET_OS").unwrap();
3963
let endian = ::std::env::var("CARGO_CFG_TARGET_ENDIAN").unwrap();
40-
let asm = if let Some((asm, canswitch)) = find_assembly(&arch, &endian, &os, &env) {
41-
println!("cargo:rustc-cfg=asm");
42-
if canswitch {
43-
println!("cargo:rustc-cfg=switchable_stack")
44-
}
45-
asm
46-
} else {
47-
println!(
48-
"cargo:warning=Target {}-{}-{} has no assembly files!",
49-
arch, os, env
50-
);
51-
return;
52-
};
64+
// Handle cross compilation scenarios where we're using eg clang-cl
65+
// from a non-windows host, as by default cc will automatically try and
66+
// run the appropriate Microsoft assembler for the target architecture
67+
// if we give it a .asm file
68+
let is_windows_host = std::env::var("HOST")
69+
.unwrap_or_default()
70+
.contains("-windows-");
71+
72+
let asm =
73+
if let Some((asm, canswitch)) = find_assembly(&arch, &endian, &os, &env, is_windows_host) {
74+
println!("cargo:rustc-cfg=asm");
75+
if canswitch {
76+
println!("cargo:rustc-cfg=switchable_stack")
77+
}
78+
asm
79+
} else {
80+
println!(
81+
"cargo:warning=Target {}-{}-{} has no assembly files!",
82+
arch, os, env
83+
);
84+
return;
85+
};
86+
87+
// We are only assembling a single file and any flags in the environment probably
88+
// don't apply in this case, so we don't want to use them. Unfortunately, cc
89+
// doesn't provide a way to clear/ignore flags set from the environment, so
90+
// we manually remove them instead
91+
for key in
92+
std::env::vars().filter_map(|(k, _)| if k.contains("CFLAGS") { Some(k) } else { None })
93+
{
94+
std::env::remove_var(key);
95+
}
5396

5497
let mut cfg = cc::Build::new();
98+
99+
// There seems to be a bug with clang-cl where using
100+
// `/clang:-xassembler-with-cpp` is apparently accepted (ie no warnings
101+
// about unused/unknown arguments), but results in the same exact error
102+
// as if the flag was not present, so instead we take advantage of the
103+
// fact that we're not actually compiling any C/C++ code, only assembling
104+
// and can just use clang directly
105+
if cfg
106+
.get_compiler()
107+
.path()
108+
.file_name()
109+
.and_then(|f| f.to_str())
110+
.map(|fname| fname.contains("clang-cl"))
111+
.unwrap_or(false)
112+
{
113+
cfg.compiler("clang");
114+
}
115+
55116
let msvc = cfg.get_compiler().is_like_msvc();
56117

57118
if !msvc {

0 commit comments

Comments
 (0)